mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-08 11:42:01 +00:00
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.
This commit is contained in:
parent
c78048bc25
commit
682ae32f6f
2 changed files with 71 additions and 3 deletions
|
@ -81,9 +81,12 @@ enum
|
||||||
{
|
{
|
||||||
ARG_0,
|
ARG_0,
|
||||||
ARG_METADATA,
|
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",
|
static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
|
@ -168,6 +171,12 @@ static void gst_matroska_demux_reset (GstElement * element);
|
||||||
static gboolean perform_seek_to_offset (GstMatroskaDemux * demux,
|
static gboolean perform_seek_to_offset (GstMatroskaDemux * demux,
|
||||||
guint64 offset);
|
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);
|
GType gst_matroska_demux_get_type (void);
|
||||||
GST_BOILERPLATE (GstMatroskaDemux, gst_matroska_demux, GstElement,
|
GST_BOILERPLATE (GstMatroskaDemux, gst_matroska_demux, GstElement,
|
||||||
GST_TYPE_ELEMENT);
|
GST_TYPE_ELEMENT);
|
||||||
|
@ -223,6 +232,15 @@ gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass)
|
||||||
|
|
||||||
gobject_class->finalize = gst_matroska_demux_finalize;
|
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 =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_matroska_demux_change_state);
|
GST_DEBUG_FUNCPTR (gst_matroska_demux_change_state);
|
||||||
gstelement_class->send_event =
|
gstelement_class->send_event =
|
||||||
|
@ -262,6 +280,9 @@ gst_matroska_demux_init (GstMatroskaDemux * demux,
|
||||||
|
|
||||||
demux->common.adapter = gst_adapter_new ();
|
demux->common.adapter = gst_adapter_new ();
|
||||||
|
|
||||||
|
/* property defaults */
|
||||||
|
demux->max_gap_time = DEFAULT_MAX_GAP_TIME;
|
||||||
|
|
||||||
/* finish off */
|
/* finish off */
|
||||||
gst_matroska_demux_reset (GST_ELEMENT (demux));
|
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
|
/* handle gaps, e.g. non-zero start-time, or an cue index entry
|
||||||
* that landed us with timestamps not quite intended */
|
* that landed us with timestamps not quite intended */
|
||||||
GST_OBJECT_LOCK (demux);
|
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) {
|
demux->common.segment.rate > 0.0) {
|
||||||
GstClockTimeDiff diff;
|
GstClockTimeDiff diff;
|
||||||
GstEvent *event1, *event2;
|
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
|
* otherwise if these go back and forth downstream (sinks) increase
|
||||||
* accumulated time and running_time */
|
* accumulated time and running_time */
|
||||||
diff = GST_CLOCK_DIFF (demux->last_stop_end, lace_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)
|
&& (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)
|
||||||
|| lace_time < demux->common.segment.stop)) {
|
|| lace_time < demux->common.segment.stop)) {
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
|
@ -5412,6 +5435,48 @@ gst_matroska_demux_change_state (GstElement * element,
|
||||||
return ret;
|
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
|
gboolean
|
||||||
gst_matroska_demux_plugin_init (GstPlugin * plugin)
|
gst_matroska_demux_plugin_init (GstPlugin * plugin)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,6 +91,9 @@ typedef struct _GstMatroskaDemux {
|
||||||
/* reverse playback */
|
/* reverse playback */
|
||||||
GArray *seek_index;
|
GArray *seek_index;
|
||||||
gint seek_entry;
|
gint seek_entry;
|
||||||
|
|
||||||
|
/* gap handling */
|
||||||
|
guint64 max_gap_time;
|
||||||
} GstMatroskaDemux;
|
} GstMatroskaDemux;
|
||||||
|
|
||||||
typedef struct _GstMatroskaDemuxClass {
|
typedef struct _GstMatroskaDemuxClass {
|
||||||
|
|
Loading…
Reference in a new issue