From 67c4ec55b12c9c397838e3cf3392b66cbd4c142a Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Tue, 4 Dec 2018 19:27:14 +0100 Subject: Gstreamer: Set custom pipeline using url MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced possibility to set custom pipeline using url. Now the pipeline should be set only via QMediaPlayer::setMedia using url with scheme "gst-pipeline". For example, "gst-pipeline: videotestsrc ! autovideosink" Since setting the media should be done after renderer in QML, hence a surface is ready to be used and "qtvideosink" is available in pipelines. To use it with QVideoWidget, setting the pipeline should be done after passing video output. Change-Id: Id43f8681069e4bca2eafb154df2c5d446a0ca498 Reviewed-by: Andy Shaw Reviewed-by: Christian Strømme --- src/gsttools/qgstreamerplayersession.cpp | 88 +++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 30 deletions(-) (limited to 'src/gsttools') diff --git a/src/gsttools/qgstreamerplayersession.cpp b/src/gsttools/qgstreamerplayersession.cpp index 485556275..bd402fb3c 100644 --- a/src/gsttools/qgstreamerplayersession.cpp +++ b/src/gsttools/qgstreamerplayersession.cpp @@ -272,33 +272,6 @@ GstElement *QGstreamerPlayerSession::playbin() const return m_playbin; } -void QGstreamerPlayerSession::setPipeline(GstElement *pipeline) -{ - GstBus *bus = pipeline ? gst_element_get_bus(pipeline) : nullptr; - if (!bus) - return; - - gst_object_unref(GST_OBJECT(m_pipeline)); - m_pipeline = pipeline; - gst_object_unref(GST_OBJECT(m_bus)); - m_bus = bus; - delete m_busHelper; - m_busHelper = new QGstreamerBusHelper(m_bus, this); - m_busHelper->installMessageFilter(this); - - if (m_videoOutput) - m_busHelper->installMessageFilter(m_videoOutput); - - if (m_playbin) { - gst_element_set_state(m_playbin, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(m_playbin)); - } - - m_playbin = nullptr; - m_volumeElement = nullptr; - m_videoIdentity = nullptr; -} - #if QT_CONFIG(gstreamer_app) void QGstreamerPlayerSession::configureAppSrcElement(GObject* object, GObject *orig, GParamSpec *pspec, QGstreamerPlayerSession* self) { @@ -364,6 +337,22 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request) } #endif + if (m_request.url().scheme() == QLatin1String("gst-pipeline")) { + QString url = m_request.url().toString(QUrl::RemoveScheme); + QString pipeline = QUrl::fromPercentEncoding(url.toLatin1().constData()); + GError *err = nullptr; + GstElement *element = gst_parse_launch(pipeline.toLatin1().constData(), &err); + if (err) { + auto errstr = QLatin1String(err->message); + qWarning() << "Error:" << pipeline << ":" << errstr; + emit error(QMediaPlayer::FormatError, errstr); + g_clear_error(&err); + } + + setPipeline(element); + return; + } + if (m_playbin) { m_tags.clear(); emit tagsChanged(); @@ -379,6 +368,48 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request) } } +void QGstreamerPlayerSession::setPipeline(GstElement *pipeline) +{ + GstBus *bus = pipeline ? gst_element_get_bus(pipeline) : nullptr; + if (!bus) + return; + + gst_object_unref(GST_OBJECT(m_pipeline)); + m_pipeline = pipeline; + gst_object_unref(GST_OBJECT(m_bus)); + m_bus = bus; + delete m_busHelper; + m_busHelper = new QGstreamerBusHelper(m_bus, this); + m_busHelper->installMessageFilter(this); + + if (m_videoOutput) + m_busHelper->installMessageFilter(m_videoOutput); + + if (m_playbin) { + gst_element_set_state(m_playbin, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(m_playbin)); + } + + m_playbin = nullptr; + m_volumeElement = nullptr; + m_videoIdentity = nullptr; + + if (m_renderer) { + auto it = gst_bin_iterate_sinks(GST_BIN(pipeline)); + GValue data = { 0, 0 }; + while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) { + auto child = static_cast(g_value_get_object(&data)); + if (QLatin1String(GST_OBJECT_NAME(child)) == QLatin1String("qtvideosink")) { + m_renderer->setVideoSink(child); + break; + } + } + gst_iterator_free(it); + } + + emit pipelineChanged(); +} + qint64 QGstreamerPlayerSession::duration() const { return m_duration; @@ -581,9 +612,6 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) QGstreamerVideoRendererInterface* renderer = qobject_cast(videoOutput); m_renderer = renderer; - - // If custom pipeline is considered to use video sink from the renderer - // need to create the pipeline when the renderer is ready. emit rendererChanged(); // No sense to continue if custom pipeline requested. -- cgit v1.2.3