matroska: implement preliminary support for the bitrate query
authorMatthew Waters <matthew@centricular.com>
Thu, 17 May 2018 11:58:25 +0000 (21:58 +1000)
committerEdward Hervey <bilboed@bilboed.com>
Wed, 7 Nov 2018 15:07:18 +0000 (15:07 +0000)
Return the size / total duration as a ballpark estimate.

https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/issues/60

gst/matroska/matroska-demux.c

index 4318a2f..2362c97 100644 (file)
@@ -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;