summaryrefslogtreecommitdiffstats
path: root/src/gsttools
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-06-03 15:34:21 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-06-03 15:34:21 +0200
commit58a304824abbff8f1bf3d5031c1799de91869190 (patch)
treea092b1400a82b86acee4e2771bfc2f27630f0261 /src/gsttools
parentafca8928ce8e4113a224e57fa30a3b4bc5a2db47 (diff)
parent293566a1841151cf0a374af7016a396c943ab96e (diff)
Merge remote-tracking branch 'origin/5.13' into dev
Diffstat (limited to 'src/gsttools')
-rw-r--r--src/gsttools/qgstreamerplayersession.cpp136
-rw-r--r--src/gsttools/qgstreamerplayersession_p.h3
-rw-r--r--src/gsttools/qgstvideorenderersink.cpp3
3 files changed, 87 insertions, 55 deletions
diff --git a/src/gsttools/qgstreamerplayersession.cpp b/src/gsttools/qgstreamerplayersession.cpp
index 24f9b788b..2f89d2a1a 100644
--- a/src/gsttools/qgstreamerplayersession.cpp
+++ b/src/gsttools/qgstreamerplayersession.cpp
@@ -61,9 +61,9 @@
#include <QtCore/qdir.h>
#include <QtCore/qstandardpaths.h>
#include <qvideorenderercontrol.h>
+#include <QUrlQuery>
//#define DEBUG_PLAYBIN
-//#define DEBUG_VO_BIN_DUMP
QT_BEGIN_NAMESPACE
@@ -319,7 +319,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();
@@ -351,28 +351,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();
@@ -387,17 +366,61 @@ 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;
gst_object_unref(GST_OBJECT(m_bus));
m_bus = bus;
- delete m_busHelper;
+ m_busHelper->deleteLater();
m_busHelper = new QGstreamerBusHelper(m_bus, this);
m_busHelper->installMessageFilter(this);
@@ -414,24 +437,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
@@ -642,12 +672,6 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
if (!m_playbin)
return;
-#ifdef DEBUG_VO_BIN_DUMP
- gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
- "playbin_set");
-#endif
-
GstElement *videoSink = 0;
if (m_renderer && m_renderer->isReady())
videoSink = m_renderer->videoSink();
@@ -908,11 +932,6 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
gst_object_unref(GST_OBJECT(srcPad));
-#ifdef DEBUG_VO_BIN_DUMP
- gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* | GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES */),
- "playbin_finish");
-#endif
}
#if !GST_CHECK_VERSION(1,0,0)
@@ -975,6 +994,9 @@ bool QGstreamerPlayerSession::isSeekable() const
bool QGstreamerPlayerSession::play()
{
+ static bool dumpDot = qEnvironmentVariableIsSet("GST_DEBUG_DUMP_DOT_DIR");
+ if (dumpDot)
+ gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_pipeline), GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL), "session.play");
#ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO;
#endif
@@ -1650,6 +1672,14 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo
self->m_sourceType = UDPSrc;
//The udpsrc is always a live source.
self->m_isLiveSource = true;
+
+ QUrlQuery query(self->m_request.url());
+ const QString var = QLatin1String("udpsrc.caps");
+ if (query.hasQueryItem(var)) {
+ GstCaps *caps = gst_caps_from_string(query.queryItemValue(var).toLatin1().constData());
+ g_object_set(G_OBJECT(source), "caps", caps, NULL);
+ gst_caps_unref(caps);
+ }
} else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstSoupHTTPSrc") == 0) {
//souphttpsrc timeout unit = second
g_object_set(G_OBJECT(source), "timeout", guint(timeout), NULL);
diff --git a/src/gsttools/qgstreamerplayersession_p.h b/src/gsttools/qgstreamerplayersession_p.h
index b613793c4..d4b050272 100644
--- a/src/gsttools/qgstreamerplayersession_p.h
+++ b/src/gsttools/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;
diff --git a/src/gsttools/qgstvideorenderersink.cpp b/src/gsttools/qgstvideorenderersink.cpp
index 49016b952..5f71d342c 100644
--- a/src/gsttools/qgstvideorenderersink.cpp
+++ b/src/gsttools/qgstvideorenderersink.cpp
@@ -686,7 +686,8 @@ void QGstVideoRendererSink::handleShowPrerollChange(GObject *o, GParamSpec *p, g
if (!showPrerollFrame) {
GstState state = GST_STATE_VOID_PENDING;
- gst_element_get_state(GST_ELEMENT(sink), &state, NULL, GST_CLOCK_TIME_NONE);
+ GstClockTime timeout = 10000000; // 10 ms
+ gst_element_get_state(GST_ELEMENT(sink), &state, NULL, timeout);
// show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means
// the QMediaPlayer was stopped from the paused state.
// We need to flush the current frame.