summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVaL Doroshchuk <valentyn.doroshchuk@qt.io>2018-12-04 19:27:14 +0100
committerVaL Doroshchuk <valentyn.doroshchuk@qt.io>2019-01-23 12:08:40 +0000
commit67c4ec55b12c9c397838e3cf3392b66cbd4c142a (patch)
treea3d14df2412868a00d3f34c3ea88df220bcc8dcb
parent4e8e47989d96f8d60feec2187e4d9c85adb19c2a (diff)
Gstreamer: Set custom pipeline using url
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 <andy.shaw@qt.io> Reviewed-by: Christian Strømme <christian.stromme@qt.io>
-rw-r--r--src/gsttools/qgstreamerplayersession.cpp88
-rw-r--r--src/multimedia/gsttools_headers/qgstreamerplayersession_p.h3
2 files changed, 60 insertions, 31 deletions
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<GstElement*>(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<QGstreamerVideoRendererInterface*>(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.
diff --git a/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h b/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h
index 447b9816a..b613793c4 100644
--- a/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h
+++ b/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h
@@ -94,7 +94,6 @@ public:
virtual ~QGstreamerPlayerSession();
GstElement *playbin() const;
- void setPipeline(GstElement *pipeline);
GstElement *pipeline() const { return m_pipeline; }
QGstreamerBusHelper *bus() const { return m_busHelper; }
@@ -178,6 +177,7 @@ signals:
void invalidMedia();
void playbackRateChanged(qreal);
void rendererChanged();
+ void pipelineChanged();
private slots:
void getStreamsInfo();
@@ -208,6 +208,7 @@ private:
void addAudioBufferProbe();
void flushVideoProbes();
void resumeVideoProbes();
+ void setPipeline(GstElement *pipeline);
QNetworkRequest m_request;
QMediaPlayer::State m_state;