diff options
author | Tim Blechmann <tim@klingt.org> | 2024-03-26 12:53:18 +0800 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-03-29 06:25:34 +0000 |
commit | a8e366d222f46c014246c8b0292403f439ef18d3 (patch) | |
tree | cf92a0202d141ff805f0f7be2780a905543e5356 | |
parent | 2f4af94229dadf454fedb92f754a5b9b88a1bf4b (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)
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(); }; |