summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-02-14 11:33:21 +0100
committerLars Knoll <lars.knoll@qt.io>2021-03-02 14:49:56 +0000
commiteb98dd37047de88f8eefcae5c3ef651da1a260df (patch)
tree75c6f353cec37d8b0ed13d5a9031446b62f47a4a
parent3c59d3c008665c7075ad6fb3e7f89a295518036d (diff)
Move the Gst wrapper API into it's own file
And extend it with support for GstObject, GstElement and GstBin. Change-Id: Ia4e3887076d7b91ff6d3dcb5f24d832943795f38 Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/multimedia/CMakeLists.txt1
-rw-r--r--src/multimedia/platform/gstreamer/common/common.pri1
-rw-r--r--src/multimedia/platform/gstreamer/common/qgst_p.h450
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h1
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamerplayersession.cpp33
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamerplayersession_p.h1
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils_p.h127
7 files changed, 456 insertions, 158 deletions
diff --git a/src/multimedia/CMakeLists.txt b/src/multimedia/CMakeLists.txt
index 34aecfd34..dcd12585a 100644
--- a/src/multimedia/CMakeLists.txt
+++ b/src/multimedia/CMakeLists.txt
@@ -191,6 +191,7 @@ qt_internal_extend_target(Multimedia CONDITION QT_FEATURE_gstreamer
platform/gstreamer/audio/qaudioinput_gstreamer.cpp platform/gstreamer/audio/qaudioinput_gstreamer_p.h
platform/gstreamer/audio/qaudiooutput_gstreamer.cpp platform/gstreamer/audio/qaudiooutput_gstreamer_p.h
platform/gstreamer/audio/qgstreameraudiodecodercontrol.cpp platform/gstreamer/audio/qgstreameraudiodecodercontrol_p.h
+ platform/gstreamer/common/qgst_p.h
platform/gstreamer/common/qgstappsrc.cpp platform/gstreamer/common/qgstappsrc_p.h
platform/gstreamer/common/qgstreamerbufferprobe.cpp platform/gstreamer/common/qgstreamerbufferprobe_p.h
platform/gstreamer/common/qgstreamerbushelper.cpp platform/gstreamer/common/qgstreamerbushelper_p.h
diff --git a/src/multimedia/platform/gstreamer/common/common.pri b/src/multimedia/platform/gstreamer/common/common.pri
index 944e0ed60..afb383d00 100644
--- a/src/multimedia/platform/gstreamer/common/common.pri
+++ b/src/multimedia/platform/gstreamer/common/common.pri
@@ -1,4 +1,5 @@
HEADERS += \
+ $$PWD/qgst_p.h \
$$PWD/qgstappsrc_p.h \
$$PWD/qgstreamerbushelper_p.h \
$$PWD/qgstreamermessage_p.h \
diff --git a/src/multimedia/platform/gstreamer/common/qgst_p.h b/src/multimedia/platform/gstreamer/common/qgst_p.h
new file mode 100644
index 000000000..5e95ebe0c
--- /dev/null
+++ b/src/multimedia/platform/gstreamer/common/qgst_p.h
@@ -0,0 +1,450 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGST_P_H
+#define QGST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtmultimediaglobal_p.h>
+
+#include <QtCore/qlist.h>
+
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/qvideoframe.h>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSize;
+
+template <typename T> struct QGRange
+{
+ T min;
+ T max;
+};
+
+class QGString
+{
+ char *str;
+public:
+ QGString(char *string) : str(string) {}
+ ~QGString() { g_free(str); }
+ operator QByteArray() { return QByteArray(str); }
+ operator const char *() { return str; }
+};
+
+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>> toIntRange() 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) };
+ }
+
+ Q_MULTIMEDIA_EXPORT QList<QAudioFormat::SampleFormat> getSampleFormats() const;
+};
+
+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;
+
+ QByteArray toString() const { return gst_structure_to_string(structure); }
+};
+
+class QGstCaps {
+ const GstCaps *caps;
+public:
+ QGstCaps(const GstCaps *c) : caps(c) {}
+
+ 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); }
+ const GstCaps *get() const { return caps; }
+ QByteArray toString() const
+ {
+ gchar *c = gst_caps_to_string(caps);
+ QByteArray b(c);
+ g_free(c);
+ return b;
+ }
+};
+
+class QGstMutableCaps {
+ GstCaps *caps;
+public:
+ enum RefMode { HasRef, NeedsRef };
+ QGstMutableCaps(GstCaps *c, RefMode mode = HasRef)
+ : caps(c)
+ {
+ if (mode == NeedsRef)
+ gst_caps_ref(caps);
+ }
+ QGstMutableCaps(const QGstMutableCaps &other)
+ : caps(other.caps)
+ {
+ if (caps)
+ gst_caps_ref(caps);
+ }
+ QGstMutableCaps &operator=(const QGstMutableCaps &other)
+ {
+ if (other.caps)
+ gst_caps_ref(other.caps);
+ if (caps)
+ gst_caps_unref(caps);
+ caps = other.caps;
+ return *this;
+ }
+ ~QGstMutableCaps() {
+ if (caps)
+ gst_caps_unref(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); }
+ GstCaps *get() { return caps; }
+ QByteArray toString() const
+ {
+ gchar *c = gst_caps_to_string(caps);
+ QByteArray b(c);
+ g_free(c);
+ return b;
+ }
+};
+
+class QGstObject
+{
+protected:
+ GstObject *m_object = nullptr;
+public:
+ enum RefMode { HasRef, NeedsRef };
+
+ QGstObject() = default;
+ QGstObject(GstObject *o, RefMode mode = HasRef)
+ : m_object(o)
+ {
+ if (mode == NeedsRef)
+ // Use ref_sink to remove any floating references
+ gst_object_ref_sink(m_object);
+ }
+ QGstObject(const QGstObject &other)
+ : m_object(other.m_object)
+ {
+ if (m_object)
+ gst_object_ref(m_object);
+ }
+ QGstObject &operator=(const QGstObject &other)
+ {
+ if (other.m_object)
+ gst_object_ref(other.m_object);
+ if (m_object)
+ gst_object_unref(m_object);
+ m_object = other.m_object;
+ return *this;
+ }
+ ~QGstObject() {
+ if (m_object)
+ gst_object_unref(m_object);
+ }
+
+ friend bool operator==(const QGstObject &a, const QGstObject &b)
+ { return a.m_object == b.m_object; }
+ friend bool operator!=(const QGstObject &a, const QGstObject &b)
+ { return a.m_object != b.m_object; }
+
+ bool isNull() const { return !m_object; }
+
+ void set(const char *property, const char *str) { g_object_set(m_object, property, str, nullptr); }
+ void set(const char *property, bool b) { g_object_set(m_object, property, gboolean(b), nullptr); }
+ void set(const char *property, uint i) { g_object_set(m_object, property, guint(i), nullptr); }
+ void set(const char *property, int i) { g_object_set(m_object, property, gint(i), nullptr); }
+ void set(const char *property, qint64 i) { g_object_set(m_object, property, gint64(i), nullptr); }
+ void set(const char *property, quint64 i) { g_object_set(m_object, property, guint64(i), nullptr); }
+ void set(const char *property, double d) { g_object_set(m_object, property, gdouble(d), nullptr); }
+
+ QGString getString(const char *property) const
+ { char *s = nullptr; g_object_get(m_object, property, &s, nullptr); return s; }
+ bool getBool(const char *property) const { gboolean b = false; g_object_get(m_object, property, &b, nullptr); return b; }
+ uint getUInt(const char *property) const { guint i = 0; g_object_get(m_object, property, &i, nullptr); return i; }
+ int getInt(const char *property) const { gint i = 0; g_object_get(m_object, property, &i, nullptr); return i; }
+ quint64 getUInt64(const char *property) const { guint64 i = 0; g_object_get(m_object, property, &i, nullptr); return i; }
+ qint64 getInt64(const char *property) const { gint64 i = 0; g_object_get(m_object, property, &i, nullptr); return i; }
+ double getDouble(const char *property) const { gdouble d = 0; g_object_get(m_object, property, &d, nullptr); return d; }
+
+ GstObject *object() const { return m_object; }
+ const char *name() const { return GST_OBJECT_NAME(m_object); }
+};
+
+class QGstPad : public QGstObject
+{
+public:
+ QGstPad() = default;
+ QGstPad(const QGstObject &o)
+ : QGstPad(GST_PAD(o.object()), NeedsRef)
+ {}
+ QGstPad(GstPad *pad, RefMode mode)
+ : QGstObject(&pad->object, mode)
+ {}
+
+ QGstMutableCaps currentCaps() const
+ { return QGstMutableCaps(gst_pad_get_current_caps(pad())); }
+
+ bool isLinked() const { return gst_pad_is_linked(pad()); }
+ bool link(const QGstPad &sink) const { return gst_pad_link(pad(), sink.pad()) == GST_PAD_LINK_OK; }
+
+ GstPad *pad() const { return GST_PAD_CAST(object()); }
+
+ template<auto Member, typename T>
+ void addProbe(T *instance, GstPadProbeType type) {
+ struct Impl {
+ static GstPadProbeReturn callback(GstPad * pad, GstPadProbeInfo */*info*/, gpointer userData) {
+ (static_cast<T *>(userData)->*Member)(QGstPad(pad, NeedsRef));
+ return GST_PAD_PROBE_REMOVE;
+ };
+ };
+
+ gst_pad_add_probe (pad(), type, Impl::callback, instance, NULL);
+ }
+};
+
+class QGstElement : public QGstObject
+{
+public:
+ QGstElement() = default;
+ QGstElement(const QGstObject &o)
+ : QGstElement(GST_ELEMENT(o.object()), NeedsRef)
+ {}
+ QGstElement(GstElement *element, RefMode mode)
+ : QGstObject(&element->object, mode)
+ {}
+
+ QGstElement(const char *factory, const char *name = nullptr)
+ : QGstElement(gst_element_factory_make(factory, name), NeedsRef)
+ {
+ }
+
+ bool link(const QGstElement &next)
+ { return gst_element_link(element(), next.element()); }
+ bool link(const QGstElement &n1, const QGstElement &n2)
+ { return gst_element_link_many(element(), n1.element(), n2.element(), nullptr); }
+ bool link(const QGstElement &n1, const QGstElement &n2, const QGstElement &n3)
+ { return gst_element_link_many(element(), n1.element(), n2.element(), n3.element(), nullptr); }
+ bool link(const QGstElement &n1, const QGstElement &n2, const QGstElement &n3, const QGstElement &n4)
+ { return gst_element_link_many(element(), n1.element(), n2.element(), n3.element(), n4.element(), nullptr); }
+
+ QGstPad staticPad(const char *name) { return QGstPad(gst_element_get_static_pad(element(), name), HasRef); }
+ QGstPad getRequestPad(const char *name) { return QGstPad(gst_element_get_request_pad(element(), name), HasRef); }
+
+ GstState state() const
+ {
+ GstState state;
+ gst_element_get_state(element(), &state, nullptr, 0);
+ return state;
+ }
+ GstStateChangeReturn setState(GstState state) { return gst_element_set_state(element(), state); }
+ bool setStateSync(GstState state)
+ {
+ auto change = gst_element_set_state(element(), state);
+ if (change == GST_STATE_CHANGE_ASYNC) {
+ change = gst_element_get_state(element(), nullptr, &state, 100*1e6 /*100ms*/);
+ }
+ return change == GST_STATE_CHANGE_SUCCESS;
+ }
+
+ bool seek(qint64 pos, double rate)
+ {
+ return gst_element_seek(element(), rate, GST_FORMAT_TIME,
+ GstSeekFlags(GST_SEEK_FLAG_FLUSH),
+ GST_SEEK_TYPE_SET, pos,
+ GST_SEEK_TYPE_SET, -1);
+ }
+ qint64 duration() const
+ {
+ gint64 d;
+ if (!gst_element_query_duration(element(), GST_FORMAT_TIME, &d))
+ return 0.;
+ return d;
+ }
+ qint64 position() const
+ {
+ gint64 pos;
+ if (!gst_element_query_position(element(), GST_FORMAT_TIME, &pos))
+ return 0.;
+ return pos;
+ }
+
+ template<auto Member, typename T>
+ void onPadAdded(T *instance) {
+ struct Impl {
+ static void callback(GstElement *e, GstPad *pad, gpointer userData) {
+ (static_cast<T *>(userData)->*Member)(QGstElement(e, NeedsRef), QGstPad(pad, NeedsRef));
+ };
+ };
+
+ g_signal_connect (element(), "pad-added", G_CALLBACK(Impl::callback), instance);
+ }
+
+ GstElement *element() const { return GST_ELEMENT_CAST(m_object); }
+};
+
+class QGstBin : public QGstElement
+{
+public:
+ QGstBin(const QGstObject &o)
+ : QGstBin(GST_BIN(o.object()), NeedsRef)
+ {}
+ QGstBin(const char *name = nullptr)
+ : QGstElement(gst_bin_new(name), NeedsRef)
+ {
+ }
+ QGstBin(GstBin *bin, RefMode mode)
+ : QGstElement(&bin->element, mode)
+ {}
+
+ void add(const QGstElement &element)
+ { gst_bin_add(bin(), element.element()); }
+ void add(const QGstElement &e1, const QGstElement &e2)
+ { gst_bin_add_many(bin(), e1.element(), e2.element(), nullptr); }
+ void add(const QGstElement &e1, const QGstElement &e2, const QGstElement &e3)
+ { gst_bin_add_many(bin(), e1.element(), e2.element(), e3.element(), nullptr); }
+ void add(const QGstElement &e1, const QGstElement &e2, const QGstElement &e3, const QGstElement &e4)
+ { gst_bin_add_many(bin(), e1.element(), e2.element(), e3.element(), e4.element(), nullptr); }
+ void add(const QGstElement &e1, const QGstElement &e2, const QGstElement &e3, const QGstElement &e4, const QGstElement &e5)
+ { gst_bin_add_many(bin(), e1.element(), e2.element(), e3.element(), e4.element(), e5.element(), nullptr); }
+ void remove(const QGstElement &element)
+ { gst_bin_remove(bin(), element.element()); }
+
+ GstBin *bin() const { return GST_BIN_CAST(m_object); }
+};
+
+class QGstBus : public QGstObject
+{
+public:
+ QGstBus() = default;
+ QGstBus(GstBus *bus) : QGstObject(&bus->object, HasRef) {}
+
+ GstBus *bus() { return GST_BUS_CAST(object()); }
+};
+
+class QGstPipeline : public QGstBin
+{
+public:
+ QGstPipeline(const QGstObject &o)
+ : QGstPipeline(GST_PIPELINE(o.object()), NeedsRef)
+ {}
+ QGstPipeline(const char *name = nullptr)
+ : QGstBin(GST_BIN(gst_pipeline_new(name)), NeedsRef)
+ {
+ }
+ QGstPipeline(GstPipeline *p, RefMode mode)
+ : QGstBin(&p->bin, mode)
+ {}
+
+ GstPipeline *pipeline() const { return GST_PIPELINE_CAST(m_object); }
+ QGstBus bus() { return gst_element_get_bus(element()); }
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h
index dfd57bc59..48c7f8c37 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h
@@ -55,6 +55,7 @@
#include <qplatformmediaplayer_p.h>
#include <private/qtmultimediaglobal_p.h>
#include <qurl.h>
+#include <private/qgstutils_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamerplayersession.cpp b/src/multimedia/platform/gstreamer/common/qgstreamerplayersession.cpp
index 15c7da302..f165d632f 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamerplayersession.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstreamerplayersession.cpp
@@ -247,7 +247,7 @@ void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIO
m_appSrc = new QGstAppSrc(this);
m_appSrc->setStream(appSrcStream);
- if (!parsePipeline() && m_playbin) {
+ if (m_playbin) {
m_metaData.clear();
emit metaDataChanged();
@@ -279,7 +279,7 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request)
}
#endif
- if (!parsePipeline() && m_playbin) {
+ if (m_playbin) {
m_metaData.clear();
emit metaDataChanged();
@@ -294,35 +294,6 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request)
}
}
-bool QGstreamerPlayerSession::parsePipeline()
-{
- if (m_request.url().scheme() != QLatin1String("gst-pipeline")) {
- if (!m_playbin) {
- resetElements();
- initPlaybin();
- updateVideoRenderer();
- }
- return false;
- }
-
- // Set current surface to video sink before creating a pipeline.
- if (m_videoOutput)
- QGstVideoRendererSink::setSurface(m_videoOutput->surface());
-
- QString url = m_request.url().toString(QUrl::RemoveScheme);
- QString desc = QUrl::fromPercentEncoding(url.toLatin1().constData());
- GError *err = nullptr;
- GstElement *pipeline = gst_parse_launch(desc.toLatin1().constData(), &err);
- if (err) {
- auto errstr = QLatin1String(err->message);
- qWarning() << "Error:" << desc << ":" << errstr;
- emit error(QMediaPlayer::FormatError, errstr);
- g_clear_error(&err);
- }
-
- return setPipeline(pipeline);
-}
-
static void gst_foreach(GstIterator *it, const std::function<bool(GstElement *)> &cmp)
{
GValue value = G_VALUE_INIT;
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamerplayersession_p.h b/src/multimedia/platform/gstreamer/common/qgstreamerplayersession_p.h
index 4a2124aa5..839ca4226 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamerplayersession_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstreamerplayersession_p.h
@@ -196,7 +196,6 @@ private:
static GstPadProbeReturn change_audio_sink_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data);
void updateAudioSink();
- bool parsePipeline();
bool setPipeline(GstElement *pipeline);
void resetElements();
void initPlaybin();
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils_p.h b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
index d22734e43..6d7f83f5e 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
@@ -55,7 +55,7 @@
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
-#include <gst/gst.h>
+#include <private/qgst_p.h>
#include <gst/video/video.h>
#include <qaudioformat.h>
#include <qcamera.h>
@@ -99,131 +99,6 @@ 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>> toIntRange() 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) };
- }
-
- Q_MULTIMEDIA_EXPORT QList<QAudioFormat::SampleFormat> getSampleFormats() const;
-};
-
-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;
-
- QByteArray toString() const { return gst_structure_to_string(structure); }
-};
-
-class QGstCaps {
- const GstCaps *caps;
-public:
- QGstCaps(const GstCaps *c) : caps(c) {}
-
- 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); }
- const GstCaps *get() const { return caps; }
-};
-
-class QGstMutableCaps {
- GstCaps *caps;
-public:
- enum RefMode { HasRef, NeedsRef };
- QGstMutableCaps(GstCaps *c, RefMode mode = HasRef)
- : caps(c)
- {
- if (mode == NeedsRef)
- gst_caps_ref(caps);
- }
- QGstMutableCaps(const QGstMutableCaps &other)
- : caps(other.caps)
- {
- if (caps)
- gst_caps_ref(caps);
- }
- QGstMutableCaps &operator=(const QGstMutableCaps &other)
- {
- if (other.caps)
- gst_caps_ref(other.caps);
- if (caps)
- gst_caps_unref(const_cast<GstCaps *>(caps));
- caps = other.caps;
- return *this;
- }
- ~QGstMutableCaps() {
- if (caps)
- gst_caps_unref(const_cast<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); }
- GstCaps *get() { return caps; }
-};
-
Q_MULTIMEDIA_EXPORT const gchar *qt_gst_element_get_factory_name(GstElement *element);
Q_MULTIMEDIA_EXPORT GList *qt_gst_video_sinks();
QPair<int,int> qt_gstRateAsRational(qreal frameRate);