From: David Svensson Fors Date: Wed, 14 Sep 2011 12:46:00 +0000 (+0200) Subject: matroskademux: configurable timestamp gap handling X-Git-Tag: 1.19.3~509^2~7136^2~363 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fupstream%2Fgstreamer.git;a=commitdiff_plain;h=682ae32f6f8a81e4c3cb164bb285c3d5f1069fa5 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. --- 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 {