summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Blechmann <tim@klingt.org>2024-03-26 12:53:18 +0800
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-29 06:25:34 +0000
commita8e366d222f46c014246c8b0292403f439ef18d3 (patch)
treecf92a0202d141ff805f0f7be2780a905543e5356
parent2f4af94229dadf454fedb92f754a5b9b88a1bf4b (diff)
GStreamer: use glib to resolve/reference `QGstPipelinePrivate`
We attach `QGstPipelinePrivate` to the the `QGstPipeline`, which means that we cannot cast from base classes to the pipeline. So we rework this code a bit to use glib's `g_object_set_data` to attach the private data to pipelines constructed by us. Pick-to: 6.5 Change-Id: I09e60af4ef566d87483f318ac6b9b573325ed155 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> (cherry picked from commit 63d629446ecd2a2c8e0ee86c4c363455d454f6f9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 147c77a3c01514e96305c076db8068da927895ae)
-rw-r--r--src/plugins/multimedia/gstreamer/audio/qgstreameraudiodecoder.cpp3
-rw-r--r--src/plugins/multimedia/gstreamer/common/qgst.cpp26
-rw-r--r--src/plugins/multimedia/gstreamer/common/qgst_p.h28
-rw-r--r--src/plugins/multimedia/gstreamer/common/qgstpipeline.cpp76
-rw-r--r--src/plugins/multimedia/gstreamer/common/qgstpipeline_p.h13
5 files changed, 98 insertions, 48 deletions
diff --git a/src/plugins/multimedia/gstreamer/audio/qgstreameraudiodecoder.cpp b/src/plugins/multimedia/gstreamer/audio/qgstreameraudiodecoder.cpp
index 9c7f52e28..d286ceb3a 100644
--- a/src/plugins/multimedia/gstreamer/audio/qgstreameraudiodecoder.cpp
+++ b/src/plugins/multimedia/gstreamer/audio/qgstreameraudiodecoder.cpp
@@ -44,7 +44,8 @@ QMaybe<QPlatformAudioDecoder *> QGstreamerAudioDecoder::create(QAudioDecoder *pa
return errorMessageCannotFindElement("audioconvert");
QGstPipeline playbin(
- GST_PIPELINE_CAST(QGstElement::createFromFactory("playbin", "playbin").element()));
+ GST_PIPELINE_CAST(QGstElement::createFromFactory("playbin", "playbin").element()),
+ QGstPipeline::NeedsRef);
if (!playbin)
return errorMessageCannotFindElement("playbin");
diff --git a/src/plugins/multimedia/gstreamer/common/qgst.cpp b/src/plugins/multimedia/gstreamer/common/qgst.cpp
index bd951d11a..0aafd6499 100644
--- a/src/plugins/multimedia/gstreamer/common/qgst.cpp
+++ b/src/plugins/multimedia/gstreamer/common/qgst.cpp
@@ -3,6 +3,7 @@
#include <common/qgst_p.h>
#include <common/qgst_debug_p.h>
+#include <common/qgstpipeline_p.h>
#include <common/qgstreamermessage_p.h>
#include <QtCore/qdebug.h>
@@ -852,6 +853,31 @@ GstElement *QGstElement::element() const
return GST_ELEMENT_CAST(get());
}
+QGstElement QGstElement::getParent() const
+{
+ return QGstElement{
+ qGstCheckedCast<GstElement>(gst_element_get_parent(object())),
+ QGstElement::HasRef,
+ };
+}
+
+QGstPipeline QGstElement::getPipeline() const
+{
+ QGstElement ancestor = *this;
+ for (;;) {
+ QGstElement greatAncestor = ancestor.getParent();
+ if (greatAncestor) {
+ ancestor = std::move(greatAncestor);
+ continue;
+ }
+
+ return QGstPipeline{
+ qGstSafeCast<GstPipeline>(ancestor.element()),
+ QGstPipeline::NeedsRef,
+ };
+ }
+}
+
// QGstBin
QGstBin QGstBin::create(const char *name)
diff --git a/src/plugins/multimedia/gstreamer/common/qgst_p.h b/src/plugins/multimedia/gstreamer/common/qgst_p.h
index 3123af7b2..5db195c17 100644
--- a/src/plugins/multimedia/gstreamer/common/qgst_p.h
+++ b/src/plugins/multimedia/gstreamer/common/qgst_p.h
@@ -80,6 +80,27 @@ QGST_DEFINE_CAST_TRAITS(GstElement, ELEMENT);
QGST_DEFINE_CAST_TRAITS(GstBin, BIN);
QGST_DEFINE_CAST_TRAITS(GstPad, PAD);
+template <>
+struct GstObjectTraits<GObject>
+{
+ using Type = GObject;
+ template <typename U>
+ static bool isObjectOfType(U *arg)
+ {
+ return G_IS_OBJECT(arg);
+ }
+ template <typename U>
+ static Type *cast(U *arg)
+ {
+ return G_OBJECT(arg);
+ }
+ template <typename U>
+ static Type *checked_cast(U *arg)
+ {
+ return G_OBJECT(arg);
+ }
+};
+
#undef QGST_DEFINE_CAST_TRAITS
} // namespace QGstImpl
@@ -315,8 +336,6 @@ public:
QGstObject(const QGstObject &) = default;
QGstObject(QGstObject &&) noexcept = default;
- virtual ~QGstObject() = default;
-
QGstObject &operator=(const QGstObject &) = default;
QGstObject &operator=(QGstObject &&) noexcept = default;
@@ -435,6 +454,8 @@ public:
GstClockTime time() const;
};
+class QGstPipeline;
+
class QGstElement : public QGstObject
{
public:
@@ -503,6 +524,9 @@ public:
void setBaseTime(GstClockTime time) const;
GstElement *element() const;
+
+ QGstElement getParent() const;
+ QGstPipeline getPipeline() const;
};
template <typename... Ts>
diff --git a/src/plugins/multimedia/gstreamer/common/qgstpipeline.cpp b/src/plugins/multimedia/gstreamer/common/qgstpipeline.cpp
index e81bb0d1a..7ac6debd6 100644
--- a/src/plugins/multimedia/gstreamer/common/qgstpipeline.cpp
+++ b/src/plugins/multimedia/gstreamer/common/qgstpipeline.cpp
@@ -166,90 +166,74 @@ void QGstPipelinePrivate::removeMessageFilter(QGstreamerBusMessageFilter *filter
busFilters.removeAll(filter);
}
-QGstPipeline::QGstPipeline(const QGstPipeline &o)
- : QGstBin(o.bin(), NeedsRef),
- d(o.d)
+QGstPipeline QGstPipeline::create(const char *name)
{
- if (d)
- d->ref();
-}
+ GstPipeline *pipeline = qGstCheckedCast<GstPipeline>(gst_pipeline_new(name));
-QGstPipeline &QGstPipeline::operator=(const QGstPipeline &o)
-{
- if (this == &o)
- return *this;
- if (o.d)
- o.d->ref();
- if (d)
- d->deref();
- QGstBin::operator=(o);
- d = o.d;
- return *this;
-}
+ QGstPipelinePrivate *d = new QGstPipelinePrivate(gst_pipeline_get_bus(pipeline));
+ g_object_set_data_full(qGstCheckedCast<GObject>(pipeline), "pipeline-private", d,
+ [](gpointer ptr) {
+ delete reinterpret_cast<QGstPipelinePrivate *>(ptr);
+ return;
+ });
-QGstPipeline QGstPipeline::create(const char *name)
-{
return QGstPipeline{
- GST_PIPELINE(gst_pipeline_new(name)),
+ pipeline,
+ QGstPipeline::NeedsRef,
};
}
-QGstPipeline::QGstPipeline(GstPipeline *p)
- : QGstBin(&p->bin, NeedsRef)
+QGstPipeline::QGstPipeline(GstPipeline *p, RefMode mode) : QGstBin(qGstCheckedCast<GstBin>(p), mode)
{
- d = new QGstPipelinePrivate(gst_pipeline_get_bus(pipeline()));
- d->ref();
}
-QGstPipeline::~QGstPipeline()
-{
- if (d)
- d->deref();
-}
+QGstPipeline::~QGstPipeline() = default;
bool QGstPipeline::inStoppedState() const
{
- Q_ASSERT(d);
+ QGstPipelinePrivate *d = getPrivate();
return d->inStoppedState;
}
void QGstPipeline::setInStoppedState(bool stopped)
{
- Q_ASSERT(d);
+ QGstPipelinePrivate *d = getPrivate();
d->inStoppedState = stopped;
}
void QGstPipeline::setFlushOnConfigChanges(bool flush)
{
+ QGstPipelinePrivate *d = getPrivate();
d->m_flushOnConfigChanges = flush;
}
void QGstPipeline::installMessageFilter(QGstreamerSyncMessageFilter *filter)
{
- Q_ASSERT(d);
+ QGstPipelinePrivate *d = getPrivate();
d->installMessageFilter(filter);
}
void QGstPipeline::removeMessageFilter(QGstreamerSyncMessageFilter *filter)
{
- Q_ASSERT(d);
+ QGstPipelinePrivate *d = getPrivate();
d->removeMessageFilter(filter);
}
void QGstPipeline::installMessageFilter(QGstreamerBusMessageFilter *filter)
{
- Q_ASSERT(d);
+ QGstPipelinePrivate *d = getPrivate();
d->installMessageFilter(filter);
}
void QGstPipeline::removeMessageFilter(QGstreamerBusMessageFilter *filter)
{
- Q_ASSERT(d);
+ QGstPipelinePrivate *d = getPrivate();
d->removeMessageFilter(filter);
}
GstStateChangeReturn QGstPipeline::setState(GstState state)
{
+ QGstPipelinePrivate *d = getPrivate();
auto retval = gst_element_set_state(element(), state);
if (d->m_pendingFlush) {
d->m_pendingFlush = false;
@@ -268,8 +252,7 @@ void QGstPipeline::dumpGraph(const char *fileName)
void QGstPipeline::beginConfig()
{
- if (!d)
- return;
+ QGstPipelinePrivate *d = getPrivate();
Q_ASSERT(!isNull());
++d->m_configCounter;
@@ -283,8 +266,7 @@ void QGstPipeline::beginConfig()
void QGstPipeline::endConfig()
{
- if (!d)
- return;
+ QGstPipelinePrivate *d = getPrivate();
Q_ASSERT(!isNull());
--d->m_configCounter;
@@ -300,11 +282,13 @@ void QGstPipeline::endConfig()
void QGstPipeline::flush()
{
+ QGstPipelinePrivate *d = getPrivate();
seek(position(), d->m_rate);
}
bool QGstPipeline::seek(qint64 pos, double rate)
{
+ QGstPipelinePrivate *d = getPrivate();
// always adjust the rate, so it can be set before playback starts
// setting position needs a loaded media file that's seekable
d->m_rate = rate;
@@ -323,6 +307,7 @@ bool QGstPipeline::seek(qint64 pos, double rate)
bool QGstPipeline::setPlaybackRate(double rate)
{
+ QGstPipelinePrivate *d = getPrivate();
if (rate == d->m_rate)
return false;
@@ -343,17 +328,20 @@ bool QGstPipeline::setPlaybackRate(double rate)
double QGstPipeline::playbackRate() const
{
+ QGstPipelinePrivate *d = getPrivate();
return d->m_rate;
}
bool QGstPipeline::setPosition(qint64 pos)
{
+ QGstPipelinePrivate *d = getPrivate();
return seek(pos, d->m_rate);
}
qint64 QGstPipeline::position() const
{
gint64 pos;
+ QGstPipelinePrivate *d = getPrivate();
if (gst_element_query_position(element(), GST_FORMAT_TIME, &pos))
d->m_position = pos;
return d->m_position;
@@ -367,6 +355,14 @@ qint64 QGstPipeline::duration() const
return d;
}
+QGstPipelinePrivate *QGstPipeline::getPrivate() const
+{
+ gpointer p = g_object_get_data(qGstCheckedCast<GObject>(object()), "pipeline-private");
+ auto *d = reinterpret_cast<QGstPipelinePrivate *>(p);
+ Q_ASSERT(d);
+ return d;
+}
+
QT_END_NAMESPACE
#include "qgstpipeline.moc"
diff --git a/src/plugins/multimedia/gstreamer/common/qgstpipeline_p.h b/src/plugins/multimedia/gstreamer/common/qgstpipeline_p.h
index d73467b06..c13196d12 100644
--- a/src/plugins/multimedia/gstreamer/common/qgstpipeline_p.h
+++ b/src/plugins/multimedia/gstreamer/common/qgstpipeline_p.h
@@ -41,13 +41,14 @@ class QGstPipelinePrivate;
class QGstPipeline : public QGstBin
{
- QGstPipelinePrivate *d = nullptr;
public:
constexpr QGstPipeline() = default;
- QGstPipeline(const QGstPipeline &o);
- QGstPipeline &operator=(const QGstPipeline &o);
- explicit QGstPipeline(GstPipeline *p);
- ~QGstPipeline() override;
+ QGstPipeline(const QGstPipeline &) = default;
+ QGstPipeline(QGstPipeline &&) = default;
+ QGstPipeline &operator=(const QGstPipeline &) = default;
+ QGstPipeline &operator=(QGstPipeline &&) noexcept = default;
+ QGstPipeline(GstPipeline *, RefMode mode);
+ ~QGstPipeline();
static QGstPipeline create(const char *name);
@@ -92,6 +93,8 @@ public:
qint64 duration() const;
private:
+ QGstPipelinePrivate *getPrivate() const;
+
void beginConfig();
void endConfig();
};