From 8e45fd27d14affe8fb77eae268d7c52422575f74 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 11 Mar 2020 17:18:56 +0900 Subject: [PATCH] mpegdemux: Add ignore-scr property to ignore broken SCR Some MPEG-PS streams might not be compliant but the SCR can be ignored if PTS/DTS in PES header is consistently increased. --- gst/mpegdemux/gstmpegdemux.c | 78 +++++++++++++++++++++++++++++++++++++++++--- gst/mpegdemux/gstmpegdemux.h | 3 ++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index 9e58d0a..e900377 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -91,9 +91,12 @@ enum enum { PROP_0, + PROP_IGNORE_SCR, /* FILL ME */ }; +#define DEFAULT_IGNORE_SCR FALSE + static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -140,6 +143,10 @@ static void gst_ps_demux_base_init (GstPsDemuxClass * klass); static void gst_ps_demux_class_init (GstPsDemuxClass * klass); static void gst_ps_demux_init (GstPsDemux * demux); static void gst_ps_demux_finalize (GstPsDemux * demux); +static void gst_ps_demux_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_ps_demux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); static void gst_ps_demux_reset (GstPsDemux * demux); static gboolean gst_ps_demux_sink_event (GstPad * pad, GstObject * parent, @@ -247,8 +254,24 @@ gst_ps_demux_class_init (GstPsDemuxClass * klass) gstelement_class = (GstElementClass *) klass; gobject_class->finalize = (GObjectFinalizeFunc) gst_ps_demux_finalize; + gobject_class->set_property = gst_ps_demux_set_property; + gobject_class->get_property = gst_ps_demux_get_property; gstelement_class->change_state = gst_ps_demux_change_state; + + /** + * GstPsDemux:ignore-scr: + * + * Ignore SCR (System Clock Reference) data from MPEG-PS Pack Header. + * This can help with playback of some broken files. + * + * Since: 1.18 + */ + g_object_class_install_property (gobject_class, PROP_IGNORE_SCR, + g_param_spec_boolean ("ignore-scr", "Ignore SCR data for timing", + "Ignore SCR data for timing", DEFAULT_IGNORE_SCR, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY | + G_PARAM_STATIC_STRINGS)); } static void @@ -279,6 +302,8 @@ gst_ps_demux_init (GstPsDemux * demux) demux->flowcombiner = gst_flow_combiner_new (); gst_ps_demux_reset (demux); + + demux->ignore_scr = DEFAULT_IGNORE_SCR; } static void @@ -296,6 +321,36 @@ gst_ps_demux_finalize (GstPsDemux * demux) } static void +gst_ps_demux_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPsDemux *demux = GST_PS_DEMUX (object); + + switch (prop_id) { + case PROP_IGNORE_SCR: + demux->ignore_scr = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_ps_demux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstPsDemux *demux = GST_PS_DEMUX (object); + + switch (prop_id) { + case PROP_IGNORE_SCR: + g_value_set_boolean (value, demux->ignore_scr); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void gst_ps_demux_reset (GstPsDemux * demux) { /* Clean up the streams and pads we allocated */ @@ -1736,6 +1791,20 @@ gst_ps_demux_parse_pack_start (GstPsDemux * demux) data += 8; } + + if (demux->ignore_scr) { + /* update only first/current_scr with raw scr value to start streaming + * after parsing 2 seconds long data with no-more-pad */ + if (demux->first_scr == G_MAXUINT64) { + demux->first_scr = scr; + demux->first_scr_offset = demux->cur_scr_offset; + } + + demux->current_scr = scr; + + goto out; + } + new_rate *= MPEG_MUX_RATE_MULT; /* scr adjusted is the new scr found + the colected adjustment */ @@ -1851,15 +1920,16 @@ gst_ps_demux_parse_pack_start (GstPsDemux * demux) * adapter */ demux->bytes_since_scr = avail; - gst_adapter_unmap (demux->adapter); - gst_adapter_flush (demux->adapter, length); - ADAPTER_OFFSET_FLUSH (length); - /* Now check for all streams if they're behind the new SCR and if * they are then move them forward to the SCR position */ gst_ps_demux_send_gap_updates (demux, MPEGTIME_TO_GSTTIME (demux->current_scr - demux->first_scr)); +out: + gst_adapter_unmap (demux->adapter); + gst_adapter_flush (demux->adapter, length); + ADAPTER_OFFSET_FLUSH (length); + return GST_FLOW_OK; lost_sync: diff --git a/gst/mpegdemux/gstmpegdemux.h b/gst/mpegdemux/gstmpegdemux.h index 9e4501d..e2af68b 100644 --- a/gst/mpegdemux/gstmpegdemux.h +++ b/gst/mpegdemux/gstmpegdemux.h @@ -156,6 +156,9 @@ struct _GstPsDemux /* Indicates an MPEG-2 stream */ gboolean is_mpeg2_pack; + + /* properties */ + gboolean ignore_scr; }; struct _GstPsDemuxClass -- 2.7.4