[0.11] gst-plugins-good: matroskademux: configurable timestamp gap handling

Wim Taymans wtay at kemper.freedesktop.org
Wed Sep 28 03:45:28 PDT 2011


Module: gst-plugins-good
Branch: 0.11
Commit: 682ae32f6f8a81e4c3cb164bb285c3d5f1069fa5
URL:    http://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=682ae32f6f8a81e4c3cb164bb285c3d5f1069fa5

Author: David Svensson Fors <davidsf at axis.com>
Date:   Wed Sep 14 14:46:00 2011 +0200

matroskademux: configurable timestamp gap handling

matroskademux performs segment tricks to skip gaps in streams,
notably at start for non 0 based files.  There may however be
cases when full presentation (including intermediate gaps) is
desired, so a property allows to configure as of which gap
to act (or not at all).

API: GstMatroskaDemux::max-gap-time

Fixes #659009.

---

 gst/matroska/matroska-demux.c |   71 +++++++++++++++++++++++++++++++++++++++--
 gst/matroska/matroska-demux.h |    3 ++
 2 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index 7fb4071..4b39dc9 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -81,9 +81,12 @@ enum
 {
   ARG_0,
   ARG_METADATA,
-  ARG_STREAMINFO
+  ARG_STREAMINFO,
+  ARG_MAX_GAP_TIME
 };
 
+#define  DEFAULT_MAX_GAP_TIME      (2 * GST_SECOND)
+
 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
@@ -168,6 +171,12 @@ static void gst_matroska_demux_reset (GstElement * element);
 static gboolean perform_seek_to_offset (GstMatroskaDemux * demux,
     guint64 offset);
 
+/* gobject functions */
+static void gst_matroska_demux_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_matroska_demux_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
 GType gst_matroska_demux_get_type (void);
 GST_BOILERPLATE (GstMatroskaDemux, gst_matroska_demux, GstElement,
     GST_TYPE_ELEMENT);
@@ -223,6 +232,15 @@ gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass)
 
   gobject_class->finalize = gst_matroska_demux_finalize;
 
+  gobject_class->get_property = gst_matroska_demux_get_property;
+  gobject_class->set_property = gst_matroska_demux_set_property;
+
+  g_object_class_install_property (gobject_class, ARG_MAX_GAP_TIME,
+      g_param_spec_uint64 ("max-gap-time", "Maximum gap time",
+          "The demuxer sends out newsegment events for skipping "
+          "gaps longer than this (0 = disabled).", 0, G_MAXUINT64,
+          DEFAULT_MAX_GAP_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_matroska_demux_change_state);
   gstelement_class->send_event =
@@ -262,6 +280,9 @@ gst_matroska_demux_init (GstMatroskaDemux * demux,
 
   demux->common.adapter = gst_adapter_new ();
 
+  /* property defaults */
+  demux->max_gap_time = DEFAULT_MAX_GAP_TIME;
+
   /* finish off */
   gst_matroska_demux_reset (GST_ELEMENT (demux));
 }
@@ -3364,7 +3385,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         /* handle gaps, e.g. non-zero start-time, or an cue index entry
          * that landed us with timestamps not quite intended */
         GST_OBJECT_LOCK (demux);
-        if (GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) &&
+        if (demux->max_gap_time &&
+            GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) &&
             demux->common.segment.rate > 0.0) {
           GstClockTimeDiff diff;
           GstEvent *event1, *event2;
@@ -3373,7 +3395,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
            * otherwise if these go back and forth downstream (sinks) increase
            * accumulated time and running_time */
           diff = GST_CLOCK_DIFF (demux->last_stop_end, lace_time);
-          if (diff > 2 * GST_SECOND && lace_time > demux->common.segment.start
+          if (diff > demux->max_gap_time
+              && lace_time > demux->common.segment.start
               && (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)
                   || lace_time < demux->common.segment.stop)) {
             GST_DEBUG_OBJECT (demux,
@@ -5412,6 +5435,48 @@ gst_matroska_demux_change_state (GstElement * element,
   return ret;
 }
 
+static void
+gst_matroska_demux_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstMatroskaDemux *demux;
+
+  g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
+  demux = GST_MATROSKA_DEMUX (object);
+
+  switch (prop_id) {
+    case ARG_MAX_GAP_TIME:
+      GST_OBJECT_LOCK (demux);
+      demux->max_gap_time = g_value_get_uint64 (value);
+      GST_OBJECT_UNLOCK (demux);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_matroska_demux_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstMatroskaDemux *demux;
+
+  g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
+  demux = GST_MATROSKA_DEMUX (object);
+
+  switch (prop_id) {
+    case ARG_MAX_GAP_TIME:
+      GST_OBJECT_LOCK (demux);
+      g_value_set_uint64 (value, demux->max_gap_time);
+      GST_OBJECT_UNLOCK (demux);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
 gboolean
 gst_matroska_demux_plugin_init (GstPlugin * plugin)
 {
diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h
index c9ab2fc..192189f 100644
--- a/gst/matroska/matroska-demux.h
+++ b/gst/matroska/matroska-demux.h
@@ -91,6 +91,9 @@ typedef struct _GstMatroskaDemux {
   /* reverse playback */
   GArray                  *seek_index;
   gint                     seek_entry;
+
+  /* gap handling */
+  guint64                  max_gap_time;
 } GstMatroskaDemux;
 
 typedef struct _GstMatroskaDemuxClass {



More information about the gstreamer-commits mailing list