mpegtsparse: parse TDT table in mpegts.

Some tables in MPEG-TS do not have a crc in the spec, so also mpegtsparse
is not calculating crc for sections with table_id 0x70 - 0x72 because they
do not have a CRC in the spec. See EN300468. Parse Time and Date table and
output bus message.
This commit is contained in:
Zaheer Abbas Merali 2010-05-12 13:00:16 +02:00
parent ea0fb9a3ee
commit d2bd939899
3 changed files with 97 additions and 4 deletions

View file

@ -1940,6 +1940,75 @@ error:
return NULL;
}
GstStructure *
mpegts_packetizer_parse_tdt (MpegTSPacketizer * packetizer,
MpegTSPacketizerSection * section)
{
GstStructure *tdt = NULL;
guint16 mjd;
guint year, month, day, hour, minute, second;
guint8 *data, *end, *utc_ptr;
GST_DEBUG ("TDT");
/* length always 8 */
if (G_UNLIKELY (GST_BUFFER_SIZE (section->buffer) != 8)) {
GST_WARNING ("PID %d invalid TDT size %d",
section->pid, section->section_length);
goto error;
}
data = GST_BUFFER_DATA (section->buffer);
end = data + GST_BUFFER_SIZE (section->buffer);
section->table_id = *data++;
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
data += 2;
if (data + section->section_length != end) {
GST_WARNING ("PID %d invalid TDT section length %d expected %d",
section->pid, section->section_length, (gint) (end - data));
goto error;
}
mjd = GST_READ_UINT16_BE (data);
data += 2;
utc_ptr = data;
if (mjd == G_MAXUINT16) {
year = 1900;
month = day = hour = minute = second = 0;
} else {
/* See EN 300 468 Annex C */
year = (guint32) (((mjd - 15078.2) / 365.25));
month = (guint8) ((mjd - 14956.1 - (guint) (year * 365.25)) / 30.6001);
day = mjd - 14956 - (guint) (year * 365.25) - (guint) (month * 30.6001);
if (month == 14 || month == 15) {
year++;
month = month - 1 - 12;
} else {
month--;
}
year += 1900;
hour = ((utc_ptr[0] & 0xF0) >> 4) * 10 + (utc_ptr[0] & 0x0F);
minute = ((utc_ptr[1] & 0xF0) >> 4) * 10 + (utc_ptr[1] & 0x0F);
second = ((utc_ptr[2] & 0xF0) >> 4) * 10 + (utc_ptr[2] & 0x0F);
}
tdt = gst_structure_new ("tdt",
"year", G_TYPE_UINT, year,
"month", G_TYPE_UINT, month,
"day", G_TYPE_UINT, day,
"hour", G_TYPE_UINT, hour,
"minute", G_TYPE_UINT, minute, "second", G_TYPE_UINT, second, NULL);
return tdt;
error:
if (tdt)
gst_structure_free (tdt);
return NULL;
}
void
mpegts_packetizer_clear (MpegTSPacketizer * packetizer)
{
@ -2199,6 +2268,7 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
/* flush stuffing bytes */
mpegts_packetizer_clear_section (packetizer, stream);
} else {
GST_DEBUG ("section not complete");
/* section not complete yet */
section->complete = FALSE;
}
@ -2209,6 +2279,7 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
out:
packet->data = data;
GST_DEBUG ("result: %d complete: %d", res, section->complete);
return res;
}

View file

@ -148,6 +148,8 @@ GstStructure *mpegts_packetizer_parse_sdt (MpegTSPacketizer *packetizer,
MpegTSPacketizerSection *section);
GstStructure *mpegts_packetizer_parse_eit (MpegTSPacketizer *packetizer,
MpegTSPacketizerSection *section);
GstStructure *mpegts_packetizer_parse_tdt (MpegTSPacketizer *packetizer,
MpegTSPacketizerSection *section);
G_END_DECLS

View file

@ -1095,16 +1095,28 @@ mpegts_parse_apply_eit (MpegTSParse * parse,
gst_structure_copy (eit_info)));
}
static void
mpegts_parse_apply_tdt (MpegTSParse * parse,
guint16 tdt_pid, GstStructure * tdt_info)
{
gst_element_post_message (GST_ELEMENT_CAST (parse),
gst_message_new_element (GST_OBJECT (parse),
gst_structure_copy (tdt_info)));
}
static gboolean
mpegts_parse_handle_psi (MpegTSParse * parse, MpegTSPacketizerSection * section)
{
gboolean res = TRUE;
GstStructure *structure = NULL;
if (G_UNLIKELY (mpegts_parse_calc_crc32 (GST_BUFFER_DATA (section->buffer),
GST_BUFFER_SIZE (section->buffer)) != 0)) {
GST_WARNING_OBJECT (parse, "bad crc in psi pid 0x%x", section->pid);
return FALSE;
/* table ids 0x70 - 0x72 do not have a crc */
if (G_LIKELY (section->table_id < 0x70 || section->table_id > 0x72)) {
if (G_UNLIKELY (mpegts_parse_calc_crc32 (GST_BUFFER_DATA (section->buffer),
GST_BUFFER_SIZE (section->buffer)) != 0)) {
GST_WARNING_OBJECT (parse, "bad crc in psi pid 0x%x", section->pid);
return FALSE;
}
}
switch (section->table_id) {
@ -1186,6 +1198,14 @@ mpegts_parse_handle_psi (MpegTSParse * parse, MpegTSPacketizerSection * section)
else
res = FALSE;
break;
case 0x70:
/* TDT (Time and Date table) */
structure = mpegts_packetizer_parse_tdt (parse->packetizer, section);
if (G_LIKELY (structure))
mpegts_parse_apply_tdt (parse, section->pid, structure);
else
res = FALSE;
break;
default:
break;
}