summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVaL Doroshchuk <valentyn.doroshchuk@qt.io>2019-04-15 15:21:08 +0200
committerVaL Doroshchuk <valentyn.doroshchuk@qt.io>2019-05-15 12:29:36 +0000
commit7aeebc07b0566b2cf18f3f1f5656eac4d6386aaf (patch)
treef19544501e75bb90f3339775155f8e7dedcb5293 /src
parent19232dbe27521f60bdd265dbac0419d93c7ea5de (diff)
Gstreamer: Allow streams in custom pipelines
Introduced pushing buffers from QIODevice to appsrc gstreamer element: player->setMedia("gst-pipeline: appsrc ! ...", io_device); Also ported to gst 0.10. Change-Id: I1a84d22c0d5c56fe433d494413c5ab23da7c6bf3 Reviewed-by: Christian Strømme <christian.stromme@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/gsttools/qgstreamerplayersession.cpp110
-rw-r--r--src/multimedia/gsttools_headers/qgstreamerplayersession_p.h3
2 files changed, 72 insertions, 41 deletions
diff --git a/src/gsttools/qgstreamerplayersession.cpp b/src/gsttools/qgstreamerplayersession.cpp
index 1e099fc89..bd28afb91 100644
--- a/src/gsttools/qgstreamerplayersession.cpp
+++ b/src/gsttools/qgstreamerplayersession.cpp
@@ -306,7 +306,7 @@ void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIO
m_appSrc = new QGstAppSrc(this);
m_appSrc->setStream(appSrcStream);
- if (m_playbin) {
+ if (!parsePipeline() && m_playbin) {
m_tags.clear();
emit tagsChanged();
@@ -338,28 +338,7 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request)
}
#endif
- if (m_request.url().scheme() == QLatin1String("gst-pipeline")) {
- // Set current surface to video sink before creating a pipeline.
- auto renderer = qobject_cast<QVideoRendererControl*>(m_videoOutput);
- if (renderer)
- QVideoSurfaceGstSink::setSurface(renderer->surface());
-
- 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) {
+ if (!parsePipeline() && m_playbin) {
m_tags.clear();
emit tagsChanged();
@@ -374,11 +353,55 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request)
}
}
-void QGstreamerPlayerSession::setPipeline(GstElement *pipeline)
+bool QGstreamerPlayerSession::parsePipeline()
+{
+ if (m_request.url().scheme() != QLatin1String("gst-pipeline"))
+ return false;
+
+ // Set current surface to video sink before creating a pipeline.
+ auto renderer = qobject_cast<QVideoRendererControl *>(m_videoOutput);
+ if (renderer)
+ QVideoSurfaceGstSink::setSurface(renderer->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)
+{
+#if GST_CHECK_VERSION(1,0,0)
+ GValue value = G_VALUE_INIT;
+ while (gst_iterator_next (it, &value) == GST_ITERATOR_OK) {
+ auto child = static_cast<GstElement*>(g_value_get_object(&value));
+#else
+ GstElement *child = nullptr;
+ while (gst_iterator_next(it, reinterpret_cast<gpointer *>(&child)) == GST_ITERATOR_OK) {
+#endif
+ if (cmp(child))
+ break;
+ }
+
+ gst_iterator_free(it);
+#if GST_CHECK_VERSION(1,0,0)
+ g_value_unset(&value);
+#endif
+}
+
+bool QGstreamerPlayerSession::setPipeline(GstElement *pipeline)
{
GstBus *bus = pipeline ? gst_element_get_bus(pipeline) : nullptr;
if (!bus)
- return;
+ return false;
gst_object_unref(GST_OBJECT(m_pipeline));
m_pipeline = pipeline;
@@ -401,24 +424,31 @@ void QGstreamerPlayerSession::setPipeline(GstElement *pipeline)
m_videoIdentity = nullptr;
if (m_renderer) {
- auto it = gst_bin_iterate_sinks(GST_BIN(pipeline));
-#if GST_CHECK_VERSION(1,0,0)
- GValue data = { 0, 0 };
- while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) {
- auto child = static_cast<GstElement*>(g_value_get_object(&data));
-#else
- GstElement *child = nullptr;
- while (gst_iterator_next(it, reinterpret_cast<gpointer *>(&child)) == GST_ITERATOR_OK) {
-#endif
- if (QLatin1String(GST_OBJECT_NAME(child)) == QLatin1String("qtvideosink")) {
- m_renderer->setVideoSink(child);
- break;
- }
- }
- gst_iterator_free(it);
+ gst_foreach(gst_bin_iterate_sinks(GST_BIN(pipeline)),
+ [this](GstElement *child) {
+ if (qstrcmp(GST_OBJECT_NAME(child), "qtvideosink") == 0) {
+ m_renderer->setVideoSink(child);
+ return true;
+ }
+ return false;
+ });
}
+#if QT_CONFIG(gstreamer_app)
+ if (m_appSrc) {
+ gst_foreach(gst_bin_iterate_sources(GST_BIN(pipeline)),
+ [this](GstElement *child) {
+ if (qstrcmp(qt_gst_element_get_factory_name(child), "appsrc") == 0) {
+ m_appSrc->setup(child);
+ return true;
+ }
+ return false;
+ });
+ }
+#endif
+
emit pipelineChanged();
+ return true;
}
qint64 QGstreamerPlayerSession::duration() const
diff --git a/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h b/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h
index b613793c4..d4b050272 100644
--- a/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h
+++ b/src/multimedia/gsttools_headers/qgstreamerplayersession_p.h
@@ -208,7 +208,8 @@ private:
void addAudioBufferProbe();
void flushVideoProbes();
void resumeVideoProbes();
- void setPipeline(GstElement *pipeline);
+ bool parsePipeline();
+ bool setPipeline(GstElement *pipeline);
QNetworkRequest m_request;
QMediaPlayer::State m_state;