From aa3d7de98bb9ba00ea5bf66d3458e6f68bfda384 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Tue, 29 May 2018 01:06:09 +1000 Subject: [PATCH] tsdemux: implement preliminary support for the bitrate query Return the size / total duration as a ballpark estimate. https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/issues/60 --- gst/mpegtsdemux/mpegtsbase.c | 23 ++++++++++++++++++++++ gst/mpegtsdemux/mpegtsbase.h | 3 +++ gst/mpegtsdemux/tsdemux.c | 37 ++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index 5180c2ee50..1a68f8691d 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -83,6 +83,10 @@ static GstFlowReturn mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf); static gboolean mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event); +static gboolean mpegts_base_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean mpegts_base_default_sink_query (MpegTSBase * base, + GstQuery * query); static GstStateChangeReturn mpegts_base_change_state (GstElement * element, GstStateChange transition); static gboolean mpegts_base_get_tags_from_eit (MpegTSBase * base, @@ -138,6 +142,7 @@ mpegts_base_class_init (MpegTSBaseClass * klass) "Parse private sections", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + klass->sink_query = GST_DEBUG_FUNCPTR (mpegts_base_default_sink_query); } static void @@ -228,6 +233,7 @@ mpegts_base_init (MpegTSBase * base) mpegts_base_sink_activate_mode); gst_pad_set_chain_function (base->sinkpad, mpegts_base_chain); gst_pad_set_event_function (base->sinkpad, mpegts_base_sink_event); + gst_pad_set_query_function (base->sinkpad, mpegts_base_sink_query); gst_element_add_pad (GST_ELEMENT (base), base->sinkpad); base->disposed = FALSE; @@ -1356,6 +1362,23 @@ mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) return res; } +static gboolean +mpegts_base_default_sink_query (MpegTSBase * base, GstQuery * query) +{ + return gst_pad_query_default (base->sinkpad, GST_OBJECT (base), query); +} + +static gboolean +mpegts_base_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + MpegTSBase *base = GST_MPEGTS_BASE (parent); + + GST_DEBUG_OBJECT (base, "Got query %s", + gst_query_type_get_name (GST_QUERY_TYPE (query))); + + return GST_MPEGTS_BASE_GET_CLASS (base)->sink_query (base, query); +} + static GstFlowReturn mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { diff --git a/gst/mpegtsdemux/mpegtsbase.h b/gst/mpegtsdemux/mpegtsbase.h index 80a454f686..5775cdd66d 100644 --- a/gst/mpegtsdemux/mpegtsbase.h +++ b/gst/mpegtsdemux/mpegtsbase.h @@ -211,6 +211,9 @@ struct _MpegTSBaseClass { void (*nit_info) (GstStructure *nit); void (*sdt_info) (GstStructure *sdt); void (*eit_info) (GstStructure *eit); + + /* takes ownership of @query */ + gboolean (*sink_query) (MpegTSBase *base, GstQuery * query); }; #define MPEGTS_BIT_SET(field, offs) ((field)[(offs) >> 3] |= (1 << ((offs) & 0x7))) diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index e5c78e7add..64f9d0bb7e 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -322,6 +322,7 @@ static void gst_ts_demux_stream_flush (TSDemuxStream * stream, GstTSDemux * demux, gboolean hard); static gboolean push_event (MpegTSBase * base, GstEvent * event); +static gboolean sink_query (MpegTSBase * base, GstQuery * query); static void gst_ts_demux_check_and_sync_streams (GstTSDemux * demux, GstClockTime time); @@ -394,6 +395,7 @@ gst_ts_demux_class_init (GstTSDemuxClass * klass) ts_class->reset = GST_DEBUG_FUNCPTR (gst_ts_demux_reset); ts_class->push = GST_DEBUG_FUNCPTR (gst_ts_demux_push); ts_class->push_event = GST_DEBUG_FUNCPTR (push_event); + ts_class->sink_query = GST_DEBUG_FUNCPTR (sink_query); ts_class->program_started = GST_DEBUG_FUNCPTR (gst_ts_demux_program_started); ts_class->program_stopped = GST_DEBUG_FUNCPTR (gst_ts_demux_program_stopped); ts_class->update_program = GST_DEBUG_FUNCPTR (gst_ts_demux_update_program); @@ -1002,6 +1004,41 @@ push_event (MpegTSBase * base, GstEvent * event) return TRUE; } +static gboolean +sink_query (MpegTSBase * base, GstQuery * query) +{ + GstTSDemux *demux = (GstTSDemux *) base; + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_BITRATE:{ + gint64 size_bytes; + GstClockTime duration; + + if (gst_pad_peer_query_duration (base->sinkpad, GST_FORMAT_BYTES, + &size_bytes) && size_bytes > 0) { + if (gst_ts_demux_get_duration (demux, &duration) && duration > 0 + && duration != GST_CLOCK_TIME_NONE) { + guint bitrate = + gst_util_uint64_scale (8 * size_bytes, GST_SECOND, duration); + + GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GINT64_FORMAT + " duration %" GST_TIME_FORMAT " resulting in a bitrate of %u", + size_bytes, GST_TIME_ARGS (duration), bitrate); + gst_query_set_bitrate (query, bitrate); + res = TRUE; + } + } + break; + } + default: + res = GST_MPEGTS_BASE_CLASS (parent_class)->sink_query (base, query); + break; + } + + return res; +} + static inline void add_iso639_language_to_tags (TSDemuxStream * stream, gchar * lang_code) {