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; 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 void
mpegts_packetizer_clear (MpegTSPacketizer * packetizer) mpegts_packetizer_clear (MpegTSPacketizer * packetizer)
{ {
@ -2199,6 +2268,7 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
/* flush stuffing bytes */ /* flush stuffing bytes */
mpegts_packetizer_clear_section (packetizer, stream); mpegts_packetizer_clear_section (packetizer, stream);
} else { } else {
GST_DEBUG ("section not complete");
/* section not complete yet */ /* section not complete yet */
section->complete = FALSE; section->complete = FALSE;
} }
@ -2209,6 +2279,7 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
out: out:
packet->data = data; packet->data = data;
GST_DEBUG ("result: %d complete: %d", res, section->complete);
return res; return res;
} }

View file

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

View file

@ -1095,17 +1095,29 @@ mpegts_parse_apply_eit (MpegTSParse * parse,
gst_structure_copy (eit_info))); 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 static gboolean
mpegts_parse_handle_psi (MpegTSParse * parse, MpegTSPacketizerSection * section) mpegts_parse_handle_psi (MpegTSParse * parse, MpegTSPacketizerSection * section)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstStructure *structure = NULL; GstStructure *structure = NULL;
/* 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), if (G_UNLIKELY (mpegts_parse_calc_crc32 (GST_BUFFER_DATA (section->buffer),
GST_BUFFER_SIZE (section->buffer)) != 0)) { GST_BUFFER_SIZE (section->buffer)) != 0)) {
GST_WARNING_OBJECT (parse, "bad crc in psi pid 0x%x", section->pid); GST_WARNING_OBJECT (parse, "bad crc in psi pid 0x%x", section->pid);
return FALSE; return FALSE;
} }
}
switch (section->table_id) { switch (section->table_id) {
case 0x00: case 0x00:
@ -1186,6 +1198,14 @@ mpegts_parse_handle_psi (MpegTSParse * parse, MpegTSPacketizerSection * section)
else else
res = FALSE; res = FALSE;
break; 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: default:
break; break;
} }