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:
Edward Hervey 2013-07-06 10:36:33 +02:00
parent 20e9f0d139
commit a3b6b1a951
4 changed files with 134 additions and 106 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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. "