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.
This commit is contained in:
Seungha Yang 2020-03-11 17:18:56 +09:00
parent f6328cec89
commit 8e45fd27d1
2 changed files with 77 additions and 4 deletions

View file

@ -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
@ -295,6 +320,36 @@ gst_ps_demux_finalize (GstPsDemux * demux)
G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (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)
{
@ -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:

View file

@ -156,6 +156,9 @@ struct _GstPsDemux
/* Indicates an MPEG-2 stream */
gboolean is_mpeg2_pack;
/* properties */
gboolean ignore_scr;
};
struct _GstPsDemuxClass