diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 4318a2f346..2362c97734 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -151,6 +151,8 @@ static gboolean gst_matroska_demux_handle_src_query (GstPad * pad, static gboolean gst_matroska_demux_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event); +static gboolean gst_matroska_demux_handle_sink_query (GstPad * pad, + GstObject * parent, GstQuery * query); static GstFlowReturn gst_matroska_demux_chain (GstPad * pad, GstObject * object, GstBuffer * buffer); @@ -271,6 +273,8 @@ gst_matroska_demux_init (GstMatroskaDemux * demux) GST_DEBUG_FUNCPTR (gst_matroska_demux_chain)); gst_pad_set_event_function (demux->common.sinkpad, GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_sink_event)); + gst_pad_set_query_function (demux->common.sinkpad, + GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_sink_query)); gst_element_add_pad (GST_ELEMENT (demux), demux->common.sinkpad); /* init defaults for common read context */ @@ -3102,6 +3106,47 @@ gst_matroska_demux_handle_src_event (GstPad * pad, GstObject * parent, return res; } +static gboolean +gst_matroska_demux_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_BITRATE: + { + if (G_UNLIKELY (demux->cached_length == G_MAXUINT64 || + demux->common.offset >= demux->cached_length)) { + demux->cached_length = + gst_matroska_read_common_get_length (&demux->common); + } + + if (demux->cached_length < G_MAXUINT64 + && demux->common.segment.duration > 0) { + /* TODO: better results based on ranges/index tables */ + guint bitrate = + gst_util_uint64_scale (8 * demux->cached_length, GST_SECOND, + demux->common.segment.duration); + + GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT + " duration %" GST_TIME_FORMAT " resulting in a bitrate of %u", + demux->cached_length, + GST_TIME_ARGS (demux->common.segment.duration), bitrate); + + gst_query_set_bitrate (query, bitrate); + res = TRUE; + } + break; + } + default: + res = gst_pad_query_default (pad, (GstObject *) demux, query); + break; + } + + return res; +} + static GstFlowReturn gst_matroska_demux_seek_to_previous_keyframe (GstMatroskaDemux * demux) { @@ -4356,8 +4401,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, /* If we're doing a keyframe-only trickmode, only push keyframes on video * streams */ if (delta_unit - && demux->common. - segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS) { + && demux->common.segment. + flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS) { GST_LOG_OBJECT (demux, "Skipping non-keyframe on stream %d", stream->index); ret = GST_FLOW_OK;