mpegtsdemux: Handle registration descriptor for programs and streams
* Allows us to simplify some code and prepare for future cleanups. * Remove useless casts * Add some FIXME regarding VC1
This commit is contained in:
parent
20e9f0d139
commit
a3b6b1a951
@ -26,6 +26,19 @@
|
|||||||
|
|
||||||
#ifndef __GST_MPEG_DEFS_H__
|
#ifndef __GST_MPEG_DEFS_H__
|
||||||
#define __GST_MPEG_DEFS_H__
|
#define __GST_MPEG_DEFS_H__
|
||||||
|
#include <glib/gprintf.h>
|
||||||
|
|
||||||
|
#define SAFE_FOURCC_FORMAT "02x%02x%02x%02x (%c%c%c%c)"
|
||||||
|
#define SAFE_CHAR(a) (g_ascii_isalnum((gchar) (a)) ? ((gchar)(a)) : '.')
|
||||||
|
#define SAFE_FOURCC_ARGS(a) \
|
||||||
|
((guint8) ((a)>>24)), \
|
||||||
|
((guint8) ((a) >> 16 & 0xff)), \
|
||||||
|
((guint8) a >> 8 & 0xff), \
|
||||||
|
((guint8) a & 0xff), \
|
||||||
|
SAFE_CHAR((a)>>24), \
|
||||||
|
SAFE_CHAR((a) >> 16 & 0xff), \
|
||||||
|
SAFE_CHAR((a) >> 8 & 0xff), \
|
||||||
|
SAFE_CHAR(a & 0xff)
|
||||||
|
|
||||||
/* Stream type assignments */
|
/* Stream type assignments */
|
||||||
/* FIXME: Put these in mpegts lib separate stream type enums */
|
/* FIXME: Put these in mpegts lib separate stream type enums */
|
||||||
|
@ -390,6 +390,23 @@ mpegts_base_remove_program (MpegTSBase * base, gint program_number)
|
|||||||
g_hash_table_remove (base->programs, GINT_TO_POINTER (program_number));
|
g_hash_table_remove (base->programs, GINT_TO_POINTER (program_number));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
get_registration_from_descriptors (GArray * descriptors)
|
||||||
|
{
|
||||||
|
const GstMpegTsDescriptor *desc;
|
||||||
|
|
||||||
|
if ((desc =
|
||||||
|
gst_mpegts_find_descriptor (descriptors,
|
||||||
|
GST_MTS_DESC_REGISTRATION))) {
|
||||||
|
if (G_UNLIKELY (desc->descriptor_length < 4)) {
|
||||||
|
GST_WARNING ("Registration descriptor with length < 4. (Corrupted ?)");
|
||||||
|
} else
|
||||||
|
return GST_READ_UINT32_BE (desc->descriptor_data + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static MpegTSBaseStream *
|
static MpegTSBaseStream *
|
||||||
mpegts_base_program_add_stream (MpegTSBase * base,
|
mpegts_base_program_add_stream (MpegTSBase * base,
|
||||||
MpegTSBaseProgram * program, guint16 pid, guint8 stream_type,
|
MpegTSBaseProgram * program, guint16 pid, guint8 stream_type,
|
||||||
@ -410,6 +427,13 @@ mpegts_base_program_add_stream (MpegTSBase * base,
|
|||||||
bstream->pid = pid;
|
bstream->pid = pid;
|
||||||
bstream->stream_type = stream_type;
|
bstream->stream_type = stream_type;
|
||||||
bstream->stream = stream;
|
bstream->stream = stream;
|
||||||
|
if (stream) {
|
||||||
|
bstream->registration_id =
|
||||||
|
get_registration_from_descriptors (stream->descriptors);
|
||||||
|
GST_DEBUG ("PID 0x%04x, registration_id %" SAFE_FOURCC_FORMAT,
|
||||||
|
bstream->pid, SAFE_FOURCC_ARGS (bstream->registration_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
program->streams[pid] = bstream;
|
program->streams[pid] = bstream;
|
||||||
program->stream_list = g_list_append (program->stream_list, bstream);
|
program->stream_list = g_list_append (program->stream_list, bstream);
|
||||||
@ -562,6 +586,12 @@ mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program,
|
|||||||
program->pmt_pid = pmt_pid;
|
program->pmt_pid = pmt_pid;
|
||||||
program->pcr_pid = pmt->pcr_pid;
|
program->pcr_pid = pmt->pcr_pid;
|
||||||
|
|
||||||
|
/* extract top-level registration_id if present */
|
||||||
|
program->registration_id =
|
||||||
|
get_registration_from_descriptors (pmt->descriptors);
|
||||||
|
GST_DEBUG ("program 0x%04x, registration_id %" SAFE_FOURCC_FORMAT,
|
||||||
|
program->program_number, SAFE_FOURCC_ARGS (program->registration_id));
|
||||||
|
|
||||||
for (i = 0; i < pmt->streams->len; ++i) {
|
for (i = 0; i < pmt->streams->len; ++i) {
|
||||||
GstMpegTsPMTStream *stream = g_ptr_array_index (pmt->streams, i);
|
GstMpegTsPMTStream *stream = g_ptr_array_index (pmt->streams, i);
|
||||||
|
|
||||||
|
@ -57,21 +57,30 @@ typedef struct _MpegTSBaseProgram MpegTSBaseProgram;
|
|||||||
|
|
||||||
struct _MpegTSBaseStream
|
struct _MpegTSBaseStream
|
||||||
{
|
{
|
||||||
guint16 pid;
|
guint16 pid;
|
||||||
guint8 stream_type;
|
guint8 stream_type;
|
||||||
|
|
||||||
|
/* Content of the registration descriptor (if present) */
|
||||||
|
guint32 registration_id;
|
||||||
|
|
||||||
GstMpegTsPMTStream *stream;
|
GstMpegTsPMTStream *stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MpegTSBaseProgram
|
struct _MpegTSBaseProgram
|
||||||
{
|
{
|
||||||
gint program_number;
|
gint program_number;
|
||||||
guint16 pmt_pid;
|
guint16 pmt_pid;
|
||||||
guint16 pcr_pid;
|
guint16 pcr_pid;
|
||||||
GstMpegTsSection *section;
|
|
||||||
|
/* Content of the registration descriptor (if present) */
|
||||||
|
guint32 registration_id;
|
||||||
|
|
||||||
|
GstMpegTsSection *section;
|
||||||
const GstMpegTsPMT *pmt;
|
const GstMpegTsPMT *pmt;
|
||||||
MpegTSBaseStream **streams;
|
|
||||||
GList *stream_list;
|
MpegTSBaseStream **streams;
|
||||||
gint patcount;
|
GList *stream_list;
|
||||||
|
gint patcount;
|
||||||
|
|
||||||
/* Pending Tags for the program */
|
/* Pending Tags for the program */
|
||||||
GstTagList *tags;
|
GstTagList *tags;
|
||||||
|
@ -696,59 +696,50 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
GST_LOG ("Attempting to create pad for stream 0x%04x with stream_type %d",
|
GST_LOG ("Attempting to create pad for stream 0x%04x with stream_type %d",
|
||||||
bstream->pid, bstream->stream_type);
|
bstream->pid, bstream->stream_type);
|
||||||
|
|
||||||
/* FIXME : Extract the registration descriptor in mpegtsbase for each
|
|
||||||
* program and stream. This will help provide cleaner detection of all the
|
|
||||||
* mpeg-ts variants (Bluray, HDV, ...) and "private" types (dirac, vc1,
|
|
||||||
* ac3, eac3, ... */
|
|
||||||
|
|
||||||
/* First handle BluRay-specific stream types since there is some overlap
|
/* First handle BluRay-specific stream types since there is some overlap
|
||||||
* between BluRay and non-BluRay streay type identifiers */
|
* between BluRay and non-BluRay streay type identifiers */
|
||||||
desc =
|
if (program->registration_id == DRF_ID_HDMV) {
|
||||||
mpegts_get_descriptor_from_program (program, GST_MTS_DESC_REGISTRATION);
|
switch (bstream->stream_type) {
|
||||||
if (desc) {
|
case ST_BD_AUDIO_AC3:
|
||||||
if (DESC_REGISTRATION_format_identifier (desc) == DRF_ID_HDMV) {
|
{
|
||||||
switch (bstream->stream_type) {
|
const guint8 *ac3_desc;
|
||||||
case ST_BD_AUDIO_AC3:
|
|
||||||
{
|
|
||||||
const guint8 *ac3_desc;
|
|
||||||
|
|
||||||
/* ATSC ac3 audio descriptor */
|
/* ATSC ac3 audio descriptor */
|
||||||
ac3_desc =
|
ac3_desc =
|
||||||
mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
mpegts_get_descriptor_from_stream (bstream,
|
||||||
GST_MTS_DESC_AC3_AUDIO_STREAM);
|
GST_MTS_DESC_AC3_AUDIO_STREAM);
|
||||||
if (ac3_desc && DESC_AC_AUDIO_STREAM_bsid (ac3_desc) != 16) {
|
if (ac3_desc && DESC_AC_AUDIO_STREAM_bsid (ac3_desc) != 16) {
|
||||||
GST_LOG ("ac3 audio");
|
GST_LOG ("ac3 audio");
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
||||||
caps = gst_caps_new_empty_simple ("audio/x-ac3");
|
caps = gst_caps_new_empty_simple ("audio/x-ac3");
|
||||||
} else {
|
} else {
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
|
||||||
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
|
||||||
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ST_BD_AUDIO_EAC3:
|
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
||||||
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
||||||
break;
|
}
|
||||||
case ST_BD_AUDIO_AC3_TRUE_HD:
|
break;
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
|
||||||
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
|
||||||
caps = gst_caps_new_empty_simple ("audio/x-true-hd");
|
|
||||||
break;
|
|
||||||
case ST_BD_AUDIO_LPCM:
|
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
|
||||||
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
|
||||||
caps = gst_caps_new_empty_simple ("audio/x-private-ts-lpcm");
|
|
||||||
break;
|
|
||||||
case ST_BD_PGS_SUBPICTURE:
|
|
||||||
template = gst_static_pad_template_get (&subpicture_template);
|
|
||||||
name = g_strdup_printf ("subpicture_%04x", bstream->pid);
|
|
||||||
caps = gst_caps_new_empty_simple ("subpicture/x-pgs");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
case ST_BD_AUDIO_EAC3:
|
||||||
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
|
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
||||||
|
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
||||||
|
break;
|
||||||
|
case ST_BD_AUDIO_AC3_TRUE_HD:
|
||||||
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
|
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
||||||
|
caps = gst_caps_new_empty_simple ("audio/x-true-hd");
|
||||||
|
break;
|
||||||
|
case ST_BD_AUDIO_LPCM:
|
||||||
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
|
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
||||||
|
caps = gst_caps_new_empty_simple ("audio/x-private-ts-lpcm");
|
||||||
|
break;
|
||||||
|
case ST_BD_PGS_SUBPICTURE:
|
||||||
|
template = gst_static_pad_template_get (&subpicture_template);
|
||||||
|
name = g_strdup_printf ("subpicture_%04x", bstream->pid);
|
||||||
|
caps = gst_caps_new_empty_simple ("subpicture/x-pgs");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (template && name && caps)
|
if (template && name && caps)
|
||||||
@ -788,8 +779,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
/* FIXME: Move all of this into a common method (there might be other
|
/* FIXME: Move all of this into a common method (there might be other
|
||||||
* types also, depending on registratino descriptors also
|
* types also, depending on registratino descriptors also
|
||||||
*/
|
*/
|
||||||
desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
desc = mpegts_get_descriptor_from_stream (bstream, GST_MTS_DESC_DVB_AC3);
|
||||||
GST_MTS_DESC_DVB_AC3);
|
|
||||||
if (desc) {
|
if (desc) {
|
||||||
GST_LOG ("ac3 audio");
|
GST_LOG ("ac3 audio");
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
@ -798,7 +788,8 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
desc =
|
||||||
|
mpegts_get_descriptor_from_stream (bstream,
|
||||||
GST_MTS_DESC_DVB_ENHANCED_AC3);
|
GST_MTS_DESC_DVB_ENHANCED_AC3);
|
||||||
if (desc) {
|
if (desc) {
|
||||||
GST_LOG ("ac3 audio");
|
GST_LOG ("ac3 audio");
|
||||||
@ -807,7 +798,8 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
desc =
|
||||||
|
mpegts_get_descriptor_from_stream (bstream,
|
||||||
GST_MTS_DESC_DVB_TELETEXT);
|
GST_MTS_DESC_DVB_TELETEXT);
|
||||||
if (desc) {
|
if (desc) {
|
||||||
GST_LOG ("teletext");
|
GST_LOG ("teletext");
|
||||||
@ -817,7 +809,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
desc =
|
desc =
|
||||||
mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
mpegts_get_descriptor_from_stream (bstream,
|
||||||
GST_MTS_DESC_DVB_SUBTITLING);
|
GST_MTS_DESC_DVB_SUBTITLING);
|
||||||
if (desc) {
|
if (desc) {
|
||||||
GST_LOG ("subtitling");
|
GST_LOG ("subtitling");
|
||||||
@ -827,25 +819,21 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
switch (bstream->registration_id) {
|
||||||
GST_MTS_DESC_REGISTRATION);
|
case DRF_ID_DTS1:
|
||||||
if (desc) {
|
case DRF_ID_DTS2:
|
||||||
switch (DESC_REGISTRATION_format_identifier (desc)) {
|
case DRF_ID_DTS3:
|
||||||
case DRF_ID_DTS1:
|
/* SMPTE registered DTS */
|
||||||
case DRF_ID_DTS2:
|
GST_LOG ("subtitling");
|
||||||
case DRF_ID_DTS3:
|
template = gst_static_pad_template_get (&private_template);
|
||||||
/* SMPTE registered DTS */
|
name = g_strdup_printf ("private_%04x", bstream->pid);
|
||||||
GST_LOG ("subtitling");
|
caps = gst_caps_new_empty_simple ("audio/x-dts");
|
||||||
template = gst_static_pad_template_get (&private_template);
|
break;
|
||||||
name = g_strdup_printf ("private_%04x", bstream->pid);
|
case DRF_ID_S302M:
|
||||||
caps = gst_caps_new_empty_simple ("audio/x-dts");
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
break;
|
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
||||||
case DRF_ID_S302M:
|
caps = gst_caps_new_empty_simple ("audio/x-smpte-302m");
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
break;
|
||||||
name = g_strdup_printf ("audio_%04x", bstream->pid);
|
|
||||||
caps = gst_caps_new_empty_simple ("audio/x-smpte-302m");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (template)
|
if (template)
|
||||||
break;
|
break;
|
||||||
@ -914,34 +902,23 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
"alignment", G_TYPE_STRING, "nal", NULL);
|
"alignment", G_TYPE_STRING, "nal", NULL);
|
||||||
break;
|
break;
|
||||||
case ST_VIDEO_DIRAC:
|
case ST_VIDEO_DIRAC:
|
||||||
desc =
|
if (bstream->registration_id == 0x64726163) {
|
||||||
mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
GST_LOG ("dirac");
|
||||||
GST_MTS_DESC_REGISTRATION);
|
/* dirac in hex */
|
||||||
if (desc) {
|
template = gst_static_pad_template_get (&video_template);
|
||||||
if (DESC_LENGTH (desc) >= 4) {
|
name = g_strdup_printf ("video_%04x", bstream->pid);
|
||||||
if (DESC_REGISTRATION_format_identifier (desc) == 0x64726163) {
|
caps = gst_caps_new_empty_simple ("video/x-dirac");
|
||||||
GST_LOG ("dirac");
|
|
||||||
/* dirac in hex */
|
|
||||||
template = gst_static_pad_template_get (&video_template);
|
|
||||||
name = g_strdup_printf ("video_%04x", bstream->pid);
|
|
||||||
caps = gst_caps_new_empty_simple ("video/x-dirac");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ST_PRIVATE_EA: /* Try to detect a VC1 stream */
|
case ST_PRIVATE_EA: /* Try to detect a VC1 stream */
|
||||||
{
|
{
|
||||||
gboolean is_vc1 = FALSE;
|
gboolean is_vc1 = FALSE;
|
||||||
desc =
|
|
||||||
mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
/* Note/FIXME: RP-227 specifies that the registration descriptor
|
||||||
GST_MTS_DESC_REGISTRATION);
|
* for vc1 can also contain other information, such as profile,
|
||||||
if (desc) {
|
* level, alignment, buffer_size, .... */
|
||||||
if (DESC_LENGTH (desc) >= 4) {
|
if (bstream->registration_id == DRF_ID_VC1)
|
||||||
if (DESC_REGISTRATION_format_identifier (desc) == DRF_ID_VC1) {
|
is_vc1 = TRUE;
|
||||||
is_vc1 = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!is_vc1) {
|
if (!is_vc1) {
|
||||||
GST_WARNING ("0xea private stream type found but no descriptor "
|
GST_WARNING ("0xea private stream type found but no descriptor "
|
||||||
"for VC1. Assuming plain VC1.");
|
"for VC1. Assuming plain VC1.");
|
||||||
@ -956,7 +933,8 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
}
|
}
|
||||||
case ST_PS_AUDIO_AC3:
|
case ST_PS_AUDIO_AC3:
|
||||||
/* DVB_ENHANCED_AC3 */
|
/* DVB_ENHANCED_AC3 */
|
||||||
desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
desc =
|
||||||
|
mpegts_get_descriptor_from_stream (bstream,
|
||||||
GST_MTS_DESC_DVB_ENHANCED_AC3);
|
GST_MTS_DESC_DVB_ENHANCED_AC3);
|
||||||
if (desc) {
|
if (desc) {
|
||||||
template = gst_static_pad_template_get (&audio_template);
|
template = gst_static_pad_template_get (&audio_template);
|
||||||
@ -966,9 +944,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* DVB_AC3 */
|
/* DVB_AC3 */
|
||||||
desc =
|
desc = mpegts_get_descriptor_from_stream (bstream, GST_MTS_DESC_DVB_AC3);
|
||||||
mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
|
|
||||||
GST_MTS_DESC_DVB_AC3);
|
|
||||||
if (!desc)
|
if (!desc)
|
||||||
GST_WARNING ("AC3 stream type found but no corresponding "
|
GST_WARNING ("AC3 stream type found but no corresponding "
|
||||||
"descriptor to differentiate between AC3 and EAC3. "
|
"descriptor to differentiate between AC3 and EAC3. "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user