From 9d973d0f3527dfa05cc324bdf353db046e400e75 Mon Sep 17 00:00:00 2001 From: Andrew Voznytsa Date: Tue, 31 Mar 2020 21:26:22 +0300 Subject: [PATCH] Force parsebin to output frame aligned stream --- src/VideoReceiver/GstVideoReceiver.cc | 54 +++++++++++++++++++++++++++ src/VideoReceiver/GstVideoReceiver.h | 1 + 2 files changed, 55 insertions(+) diff --git a/src/VideoReceiver/GstVideoReceiver.cc b/src/VideoReceiver/GstVideoReceiver.cc index 6e6ea4085..857c6fef4 100644 --- a/src/VideoReceiver/GstVideoReceiver.cc +++ b/src/VideoReceiver/GstVideoReceiver.cc @@ -729,6 +729,8 @@ GstVideoReceiver::_makeSource(const QString& uri) break; } + g_signal_connect(parser, "autoplug-query", G_CALLBACK(_filterParserCaps), nullptr); + gst_bin_add_many(GST_BIN(bin), source, parser, nullptr); // FIXME: AV: Android does not determine MPEG2-TS via parsebin - have to explicitly state which demux to use @@ -1434,6 +1436,58 @@ GstVideoReceiver::_padProbe(GstElement* element, GstPad* pad, gpointer user_data return TRUE; } +gboolean +GstVideoReceiver::_filterParserCaps(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data) +{ + Q_UNUSED(bin) + Q_UNUSED(pad) + Q_UNUSED(element) + Q_UNUSED(data) + + if (GST_QUERY_TYPE(query) != GST_QUERY_CAPS) { + return FALSE; + } + + GstCaps* srcCaps; + + gst_query_parse_caps(query, &srcCaps); + + if (srcCaps == nullptr || gst_caps_is_any(srcCaps)) { + return FALSE; + } + + GstCaps* sinkCaps = nullptr; + + GstCaps* filter; + + if (sinkCaps == nullptr && (filter = gst_caps_from_string("video/x-h264")) != nullptr) { + if (gst_caps_can_intersect(srcCaps, filter)) { + sinkCaps = gst_caps_from_string("video/x-h264,stream-format=avc"); + } + + gst_caps_unref(filter); + filter = nullptr; + } else if (sinkCaps == nullptr && (filter = gst_caps_from_string("video/x-h265")) != nullptr) { + if (gst_caps_can_intersect(srcCaps, filter)) { + sinkCaps = gst_caps_from_string("video/x-h265,stream-format=hvc1"); + } + + gst_caps_unref(filter); + filter = nullptr; + } + + if (sinkCaps == nullptr) { + return FALSE; + } + + gst_query_set_caps_result(query, sinkCaps); + + gst_caps_unref(sinkCaps); + sinkCaps = nullptr; + + return TRUE; +} + gboolean GstVideoReceiver::_autoplugQueryCaps(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data) { diff --git a/src/VideoReceiver/GstVideoReceiver.h b/src/VideoReceiver/GstVideoReceiver.h index a16d96eaf..c59dbdab0 100644 --- a/src/VideoReceiver/GstVideoReceiver.h +++ b/src/VideoReceiver/GstVideoReceiver.h @@ -131,6 +131,7 @@ private: static void _wrapWithGhostPad(GstElement* element, GstPad* pad, gpointer data); static void _linkPadWithOptionalBuffer(GstElement* element, GstPad* pad, gpointer data); static gboolean _padProbe(GstElement* element, GstPad* pad, gpointer user_data); + static gboolean _filterParserCaps(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data); static gboolean _autoplugQueryCaps(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data); static gboolean _autoplugQueryContext(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data); static gboolean _autoplugQuery(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data); -- 2.22.0