mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
mpegtsdemux: Handle private section streams
Until now we simply ignored those streams (since we couldn't do anything with it anyway). Now that we have the mpegts library and we offload the section handling to the application side we can properly identify and extract them. By default it is disabled for tsparse and enabled for tsdemux, but there is a property to change that. This should open the way to properly handle all private section streams, including: * DSM-CC * MHEG * Carousel data * Metadata streams (though I haven't seen any of those in the wild) * ... And all other specs/protocols making use of those Partially fixes #560631
This commit is contained in:
parent
057d24811d
commit
1c96c79b88
3 changed files with 103 additions and 28 deletions
|
@ -64,12 +64,18 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
PROP_0,
|
||||
PROP_PARSE_PRIVATE_SECTIONS,
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
static void mpegts_base_dispose (GObject * object);
|
||||
static void mpegts_base_finalize (GObject * object);
|
||||
static void mpegts_base_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void mpegts_base_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void mpegts_base_free_program (MpegTSBaseProgram * program);
|
||||
static gboolean mpegts_base_sink_activate (GstPad * pad, GstObject * parent);
|
||||
static gboolean mpegts_base_sink_activate_mode (GstPad * pad,
|
||||
|
@ -115,8 +121,47 @@ mpegts_base_class_init (MpegTSBaseClass * klass)
|
|||
gobject_class = G_OBJECT_CLASS (klass);
|
||||
gobject_class->dispose = mpegts_base_dispose;
|
||||
gobject_class->finalize = mpegts_base_finalize;
|
||||
gobject_class->set_property = mpegts_base_set_property;
|
||||
gobject_class->get_property = mpegts_base_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_PARSE_PRIVATE_SECTIONS,
|
||||
g_param_spec_boolean ("parse-private-sections", "Parse private sections",
|
||||
"Parse private sections", FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
mpegts_base_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
MpegTSBase *base = GST_MPEGTS_BASE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PARSE_PRIVATE_SECTIONS:
|
||||
base->parse_private_sections = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mpegts_base_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
MpegTSBase *base = GST_MPEGTS_BASE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PARSE_PRIVATE_SECTIONS:
|
||||
g_value_set_boolean (value, base->parse_private_sections);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mpegts_base_reset (MpegTSBase * base)
|
||||
{
|
||||
|
@ -185,6 +230,7 @@ mpegts_base_init (MpegTSBase * base)
|
|||
base->programs = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
NULL, (GDestroyNotify) mpegts_base_free_program);
|
||||
|
||||
base->parse_private_sections = FALSE;
|
||||
base->is_pes = g_new0 (guint8, 1024);
|
||||
base->known_psi = g_new0 (guint8, 1024);
|
||||
base->program_size = sizeof (MpegTSBaseProgram);
|
||||
|
@ -544,10 +590,28 @@ mpegts_base_deactivate_program (MpegTSBase * base, MpegTSBaseProgram * program)
|
|||
|
||||
mpegts_base_program_remove_stream (base, program, stream->pid);
|
||||
|
||||
/* Only unset the is_pes bit if the PID isn't used in any other active
|
||||
/* Only unset the is_pes/known_psi bit if the PID isn't used in any other active
|
||||
* program */
|
||||
if (!mpegts_pid_in_active_programs (base, stream->pid))
|
||||
if (!mpegts_pid_in_active_programs (base, stream->pid)) {
|
||||
switch (stream->stream_type) {
|
||||
case GST_MPEG_TS_STREAM_TYPE_PRIVATE_SECTIONS:
|
||||
case GST_MPEG_TS_STREAM_TYPE_MHEG:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSM_CC:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_A:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_B:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_C:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_D:
|
||||
case GST_MPEG_TS_STREAM_TYPE_SL_FLEXMUX_SECTIONS:
|
||||
case GST_MPEG_TS_STREAM_TYPE_METADATA_SECTIONS:
|
||||
/* Set known PSI streams */
|
||||
if (base->parse_private_sections)
|
||||
MPEGTS_BIT_UNSET (base->known_psi, stream->pid);
|
||||
break;
|
||||
default:
|
||||
MPEGTS_BIT_UNSET (base->is_pes, stream->pid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* remove pcr stream */
|
||||
|
@ -595,8 +659,24 @@ mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program,
|
|||
for (i = 0; i < pmt->streams->len; ++i) {
|
||||
GstMpegTsPMTStream *stream = g_ptr_array_index (pmt->streams, i);
|
||||
|
||||
switch (stream->stream_type) {
|
||||
case GST_MPEG_TS_STREAM_TYPE_PRIVATE_SECTIONS:
|
||||
case GST_MPEG_TS_STREAM_TYPE_MHEG:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSM_CC:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_A:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_B:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_C:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_D:
|
||||
case GST_MPEG_TS_STREAM_TYPE_SL_FLEXMUX_SECTIONS:
|
||||
case GST_MPEG_TS_STREAM_TYPE_METADATA_SECTIONS:
|
||||
/* Set known PSI streams */
|
||||
if (base->parse_private_sections)
|
||||
MPEGTS_BIT_SET (base->known_psi, stream->pid);
|
||||
break;
|
||||
default:
|
||||
if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->is_pes, stream->pid)))
|
||||
GST_FIXME ("Refcounting issue. Setting twice a PID (0x%04x) as known PES",
|
||||
GST_FIXME
|
||||
("Refcounting issue. Setting twice a PID (0x%04x) as known PES",
|
||||
stream->pid);
|
||||
if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, stream->pid))) {
|
||||
GST_FIXME
|
||||
|
@ -606,6 +686,8 @@ mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program,
|
|||
}
|
||||
|
||||
MPEGTS_BIT_SET (base->is_pes, stream->pid);
|
||||
break;
|
||||
}
|
||||
mpegts_base_program_add_stream (base, program,
|
||||
stream->pid, stream->stream_type, stream);
|
||||
|
||||
|
|
|
@ -148,6 +148,9 @@ struct _MpegTSBase {
|
|||
|
||||
/* Upstream segment */
|
||||
GstSegment segment;
|
||||
|
||||
/* Whether to parse private section or not */
|
||||
gboolean parse_private_sections;
|
||||
};
|
||||
|
||||
struct _MpegTSBaseClass {
|
||||
|
|
|
@ -335,9 +335,11 @@ gst_ts_demux_reset (MpegTSBase * base)
|
|||
static void
|
||||
gst_ts_demux_init (GstTSDemux * demux)
|
||||
{
|
||||
GST_MPEGTS_BASE (demux)->stream_size = sizeof (TSDemuxStream);
|
||||
MpegTSBase *base = (MpegTSBase *) demux;
|
||||
|
||||
gst_ts_demux_reset ((MpegTSBase *) demux);
|
||||
base->stream_size = sizeof (TSDemuxStream);
|
||||
base->parse_private_sections = TRUE;
|
||||
gst_ts_demux_reset (base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -861,18 +863,6 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||
/* name = g_strdup_printf ("private_%04x", bstream->pid); */
|
||||
/* caps = gst_caps_new_simple ("hdv/aux-a", NULL); */
|
||||
break;
|
||||
case GST_MPEG_TS_STREAM_TYPE_PRIVATE_SECTIONS:
|
||||
case GST_MPEG_TS_STREAM_TYPE_MHEG:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSM_CC:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_A:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_B:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_C:
|
||||
case GST_MPEG_TS_STREAM_TYPE_DSMCC_D:
|
||||
/* FIXME: Unsetting them from the PES table makes sense since they
|
||||
* are sections .. but then why don't we set them as know PSI ?
|
||||
* Also: shouldn't this be handled in mpegtsbase ? */
|
||||
MPEGTS_BIT_UNSET (base->is_pes, bstream->pid);
|
||||
break;
|
||||
case GST_MPEG_TS_STREAM_TYPE_AUDIO_AAC_ADTS:
|
||||
template = gst_static_pad_template_get (&audio_template);
|
||||
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
||||
|
|
Loading…
Reference in a new issue