diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-01-27 19:30:58 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-01-29 08:54:31 +0000 |
commit | 3987aad97c74193db273f047a215f0921be35bb4 (patch) | |
tree | e864db657350fea4be37a6cb941b69d49782478a /src/multimedia | |
parent | 24a440a5c2b884285f384fbfddc2ba5637ce35fd (diff) |
Define some wrapper classes for Gstreamer structures
Define some wrapper classes for GstCaps, GstStructure and
GValue with a decent C++ API to use them. This will help
simplify our code within the gstreamer plugin.
Change-Id: Ifcae40f04030e89b2ae3fd73bf7ea2eb1db49d16
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/multimedia')
3 files changed, 114 insertions, 34 deletions
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils.cpp b/src/multimedia/platform/gstreamer/common/qgstutils.cpp index 4e96f523d..5f1c64333 100644 --- a/src/multimedia/platform/gstreamer/common/qgstutils.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstutils.cpp @@ -190,7 +190,7 @@ QSize QGstUtils::capsResolution(const GstCaps *caps) if (gst_caps_get_size(caps) == 0) return QSize(); - return structureResolution(gst_caps_get_structure(caps, 0)); + return QGstCaps(caps).at(0).resolution(); } /*! @@ -757,12 +757,14 @@ GstCaps *QGstUtils::videoFilterCaps() return gst_caps_make_writable(gst_static_caps_get(&staticCaps)); } -QSize QGstUtils::structureResolution(const GstStructure *s) +QSize QGstStructure::resolution() const { QSize size; int w, h; - if (s && gst_structure_get_int(s, "width", &w) && gst_structure_get_int(s, "height", &h)) { + if (structure && + gst_structure_get_int(structure, "width", &w) && + gst_structure_get_int(structure, "height", &h)) { size.rwidth() = w; size.rheight() = h; } @@ -770,7 +772,7 @@ QSize QGstUtils::structureResolution(const GstStructure *s) return size; } -QVideoFrame::PixelFormat QGstUtils::structurePixelFormat(const GstStructure *structure) +QVideoFrame::PixelFormat QGstStructure::pixelFormat() const { QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid; @@ -791,13 +793,13 @@ QVideoFrame::PixelFormat QGstUtils::structurePixelFormat(const GstStructure *str return pixelFormat; } -QSize QGstUtils::structurePixelAspectRatio(const GstStructure *s) +QSize QGstStructure::pixelAspectRatio() const { QSize ratio(1, 1); gint aspectNum = 0; gint aspectDenum = 0; - if (s && gst_structure_get_fraction(s, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) { + if (structure && gst_structure_get_fraction(structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) { if (aspectDenum > 0) { ratio.rwidth() = aspectNum; ratio.rheight() = aspectDenum; @@ -807,12 +809,12 @@ QSize QGstUtils::structurePixelAspectRatio(const GstStructure *s) return ratio; } -QPair<float, float> QGstUtils::structureFrameRateRange(const GstStructure *s) +QGRange<float> QGstStructure::frameRateRange() const { float minRate = 0.; float maxRate = 0.; - if (!s) + if (!structure) return {0.f, 0.f}; auto extractFraction = [] (const GValue *v) -> float { @@ -836,7 +838,7 @@ QPair<float, float> QGstUtils::structureFrameRateRange(const GstStructure *s) } }; - const GValue *gstFrameRates = gst_structure_get_value(s, "framerate"); + const GValue *gstFrameRates = gst_structure_get_value(structure, "framerate"); if (gstFrameRates) { if (GST_VALUE_HOLDS_LIST(gstFrameRates)) { guint nFrameRates = gst_value_list_get_size(gstFrameRates); @@ -847,8 +849,8 @@ QPair<float, float> QGstUtils::structureFrameRateRange(const GstStructure *s) extractFrameRate(gstFrameRates); } } else { - const GValue *min = gst_structure_get_value(s, "min-framerate"); - const GValue *max = gst_structure_get_value(s, "max-framerate"); + const GValue *min = gst_structure_get_value(structure, "min-framerate"); + const GValue *max = gst_structure_get_value(structure, "max-framerate"); if (min && max) { minRate = extractFraction(min); maxRate = extractFraction(max); diff --git a/src/multimedia/platform/gstreamer/common/qgstutils_p.h b/src/multimedia/platform/gstreamer/common/qgstutils_p.h index 8a94ac53c..bcc5ac4f4 100644 --- a/src/multimedia/platform/gstreamer/common/qgstutils_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstutils_p.h @@ -109,11 +109,6 @@ namespace QGstUtils { Q_MULTIMEDIA_EXPORT GstCaps *videoFilterCaps(); - Q_MULTIMEDIA_EXPORT QSize structureResolution(const GstStructure *s); - Q_MULTIMEDIA_EXPORT QVideoFrame::PixelFormat structurePixelFormat(const GstStructure *s); - Q_MULTIMEDIA_EXPORT QSize structurePixelAspectRatio(const GstStructure *s); - Q_MULTIMEDIA_EXPORT QPair<float, float> structureFrameRateRange(const GstStructure *s); - Q_MULTIMEDIA_EXPORT QString fileExtensionForMimeType(const QString &mimeType); Q_MULTIMEDIA_EXPORT QVariant fromGStreamerOrientation(const QVariant &value); @@ -122,6 +117,91 @@ namespace QGstUtils { Q_MULTIMEDIA_EXPORT bool useOpenGL(); } +template <typename T> struct QGRange +{ + T min; + T max; +}; + +class QGValue +{ +public: + QGValue(const GValue *v) : value(v) {} + const GValue *value; + + bool isNull() const { return !value; } + + std::optional<bool> toBool() const + { + if (!G_VALUE_HOLDS_BOOLEAN(value)) + return std::nullopt; + return g_value_get_boolean(value); + } + std::optional<int> toInt() const + { + if (!G_VALUE_HOLDS_INT(value)) + return std::nullopt; + return g_value_get_int(value); + } + const char *toString() const + { + return g_value_get_string(value); + } + std::optional<float> getFraction() const + { + if (!GST_VALUE_HOLDS_FRACTION(value)) + return std::nullopt; + return (float)gst_value_get_fraction_numerator(value)/(float)gst_value_get_fraction_denominator(value); + } + + std::optional<QGRange<float>> getFractionRange() const + { + if (!GST_VALUE_HOLDS_FRACTION_RANGE(value)) + return std::nullopt; + QGValue min = gst_value_get_fraction_range_min(value); + QGValue max = gst_value_get_fraction_range_max(value); + return QGRange<float>{ *min.getFraction(), *max.getFraction() }; + } + + std::optional<QGRange<int>> getIntRange() const + { + if (!GST_VALUE_HOLDS_INT_RANGE(value)) + return std::nullopt; + return QGRange<int>{ gst_value_get_int_range_min(value), gst_value_get_int_range_max(value) }; + } + +}; + +class QGstStructure { +public: + GstStructure *structure; + QGstStructure(GstStructure *s) : structure(s) {} + void free() { gst_structure_free(structure); structure = nullptr; } + + bool isNull() const { return !structure; } + + QByteArray name() const { return gst_structure_get_name(structure); } + + QGValue operator[](const char *name) const { return gst_structure_get_value(structure, name); } + + Q_MULTIMEDIA_EXPORT QSize resolution() const; + Q_MULTIMEDIA_EXPORT QVideoFrame::PixelFormat pixelFormat() const; + Q_MULTIMEDIA_EXPORT QSize pixelAspectRatio() const; + Q_MULTIMEDIA_EXPORT QGRange<float> frameRateRange() const; + +}; + +class QGstCaps { +public: + QGstCaps(const GstCaps *c) : caps(c) {} + const GstCaps *caps; + + bool isNull() const { return !caps; } + + int size() const { return gst_caps_get_size(caps); } + QGstStructure at(int index) { return gst_caps_get_structure(caps, index); } +}; + Q_MULTIMEDIA_EXPORT void qt_gst_object_ref_sink(gpointer object); Q_MULTIMEDIA_EXPORT GstCaps *qt_gst_pad_get_current_caps(GstPad *pad); Q_MULTIMEDIA_EXPORT GstCaps *qt_gst_pad_get_caps(GstPad *pad); diff --git a/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp b/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp index db175075c..f3707ffad 100644 --- a/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp +++ b/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp @@ -139,46 +139,44 @@ QList<QCameraInfo> QGstreamerDeviceManager::videoInputs() const QList<QCameraInfo> devices; for (auto *d : qAsConst(m_videoSources)) { - auto *properties = gst_device_get_properties(d); - if (properties) { + QGstStructure properties = gst_device_get_properties(d); + if (!properties.isNull()) { QCameraInfoPrivate *info = new QCameraInfoPrivate; auto *desc = gst_device_get_display_name(d); info->description = QString::fromUtf8(desc); g_free(desc); - auto *name = gst_structure_get_string(properties, "device.path"); - info->id = name; -// info->driver = gst_structure_get_string(properties, "v4l2.device.driver"); - gboolean def = false; - gst_structure_get_boolean(properties, "is-default", &def); - info->isDefault = def; + info->id = properties["device.path"].toString(); +// info->driver = properties["v4l2.device.driver"].getString(); + auto def = properties["is-default"].toBool(); + info->isDefault = *def; if (def) devices.prepend(info->create()); else devices.append(info->create()); - gst_structure_free(properties); - auto *caps = gst_device_get_caps(d); - if (caps) { + properties.free(); + QGstCaps caps = gst_device_get_caps(d); + if (!caps.isNull()) { QList<QCameraFormat> formats; QSet<QSize> photoResolutions; - int size = gst_caps_get_size(caps); + int size = caps.size(); for (int i = 0; i < size; ++i) { - auto *cap = gst_caps_get_structure(caps, i); + auto cap = caps.at(i); - QSize resolution = QGstUtils::structureResolution(cap); + QSize resolution = cap.resolution(); if (!resolution.isValid()) continue; - auto pixelFormat = QGstUtils::structurePixelFormat(cap); - auto frameRate = QGstUtils::structureFrameRateRange(cap); + auto pixelFormat = cap.pixelFormat(); + auto frameRate = cap.frameRateRange(); auto *f = new QCameraFormatPrivate{ QSharedData(), pixelFormat, resolution, - frameRate.first, - frameRate.second + frameRate.min, + frameRate.max }; formats << f->create(); photoResolutions.insert(resolution); |