diff options
author | Thiago Santos <ts.santos@sisa.samsung.com> | 2014-05-28 15:59:23 -0300 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2014-05-29 10:38:00 +0200 |
commit | 1cab60b7134f9ec2455a28fabefd938bd22ca7f1 (patch) | |
tree | d1d4491382105a0e499603358e130d99392d5f1b /gst-libs/gst/mpegts/gst-atsc-section.c | |
parent | 89fadbcfe433c7a6db3dac9093ffc4b7b6320227 (diff) | |
download | gstreamer-plugins-bad-1cab60b7134f9ec2455a28fabefd938bd22ca7f1.tar.gz |
mpegts: atsc: add atsc's EIT table parsing
ATSC has its own version of the EIT table (DVB also has one).
This patch adds parsing for the ATSC EIT table and also fixed
the section identification to mark it as the ATSC one.
The implementation aws refactored to reuse some common internal
structures from ETT.
Also adds its dumping function to ts-parser example
https://bugzilla.gnome.org/show_bug.cgi?id=730435
Diffstat (limited to 'gst-libs/gst/mpegts/gst-atsc-section.c')
-rw-r--r-- | gst-libs/gst/mpegts/gst-atsc-section.c | 296 |
1 files changed, 240 insertions, 56 deletions
diff --git a/gst-libs/gst/mpegts/gst-atsc-section.c b/gst-libs/gst/mpegts/gst-atsc-section.c index 5d02dbdb7..95de50f4f 100644 --- a/gst-libs/gst/mpegts/gst-atsc-section.c +++ b/gst-libs/gst/mpegts/gst-atsc-section.c @@ -397,6 +397,8 @@ gst_mpegts_section_get_atsc_mgt (GstMpegTsSection * section) return (const GstMpegTsAtscMGT *) section->cached_parsed; } +/* Multi string structure */ + static GstMpegTsAtscStringSegment * _gst_mpegts_atsc_string_segment_copy (GstMpegTsAtscStringSegment * seg) { @@ -491,72 +493,38 @@ G_DEFINE_BOXED_TYPE (GstMpegTsAtscMultString, gst_mpegts_atsc_mult_string, (GBoxedCopyFunc) _gst_mpegts_atsc_mult_string_copy, (GFreeFunc) _gst_mpegts_atsc_mult_string_free); -static GstMpegTsAtscETT * -_gst_mpegts_atsc_ett_copy (GstMpegTsAtscETT * ett) +static GPtrArray * +_parse_atsc_mult_string (guint8 * data, guint datasize) { - GstMpegTsAtscETT *copy; - - copy = g_slice_dup (GstMpegTsAtscETT, ett); - copy->messages = g_ptr_array_ref (ett->messages); - - return copy; -} - -static void -_gst_mpegts_atsc_ett_free (GstMpegTsAtscETT * ett) -{ - g_ptr_array_unref (ett->messages); - g_slice_free (GstMpegTsAtscETT, ett); -} - -G_DEFINE_BOXED_TYPE (GstMpegTsAtscETT, gst_mpegts_atsc_ett, - (GBoxedCopyFunc) _gst_mpegts_atsc_ett_copy, - (GFreeFunc) _gst_mpegts_atsc_ett_free); - -static gpointer -_parse_ett (GstMpegTsSection * section) -{ - GstMpegTsAtscETT *ett = NULL; - guint i = 0; - guint8 *data, *end; guint8 num_strings; + GPtrArray *res = NULL; + guint8 *end = data + datasize; + gint i; - ett = g_slice_new0 (GstMpegTsAtscETT); - - data = section->data; - end = data + section->section_length; - - /* Skip already parsed data */ - data += 8; - - ett->protocol_version = GST_READ_UINT8 (data); - data += 1; - ett->etm_id = GST_READ_UINT32_BE (data); - data += 4; - - ett->messages = g_ptr_array_new_with_free_func ((GDestroyNotify) - _gst_mpegts_atsc_mult_string_free); - - if (end - data > 4) { + if (datasize > 0) { /* 1 is the minimum entry size, so no need to check here */ num_strings = GST_READ_UINT8 (data); data += 1; + res = + g_ptr_array_new_full (num_strings, + (GDestroyNotify) _gst_mpegts_atsc_mult_string_free); + for (i = 0; i < num_strings; i++) { GstMpegTsAtscMultString *mstring; guint8 num_segments; gint j; mstring = g_slice_new0 (GstMpegTsAtscMultString); - g_ptr_array_add (ett->messages, mstring); + g_ptr_array_add (res, mstring); mstring->segments = g_ptr_array_new_full (num_strings, (GDestroyNotify) _gst_mpegts_atsc_string_segment_free); - /* each entry needs at least 4 bytes (lang code and segments number */ - if (end - data < 4 + 4) { - GST_WARNING ("PID %d invalid ETT entry length %d", - section->pid, (gint) (end - 4 - data)); + /* each entry needs at least 4 bytes (lang code and segments number) */ + if (end - data < 4) { + GST_WARNING ("Data too short for multstring parsing %d", + (gint) (end - data)); goto error; } @@ -575,10 +543,9 @@ _parse_ett (GstMpegTsSection * section) seg = g_slice_new0 (GstMpegTsAtscStringSegment); g_ptr_array_add (mstring->segments, seg); - /* each entry needs at least 4 bytes (lang code and segments number */ - if (end - data < 3 + 4) { - GST_WARNING ("PID %d invalid ETT entry length %d", - section->pid, (gint) (end - 4 - data)); + /* each entry needs at least 3 bytes */ + if (end - data < 3) { + GST_WARNING ("Data too short for multstring parsing %d", datasize); goto error; } @@ -589,9 +556,8 @@ _parse_ett (GstMpegTsSection * section) seg->compressed_data_size = GST_READ_UINT8 (data); data += 1; - if (end - data < seg->compressed_data_size + 4) { - GST_WARNING ("PID %d invalid ETT entry length %d", - section->pid, (gint) (end - 4 - data)); + if (end - data < seg->compressed_data_size) { + GST_WARNING ("Data too short for multstring parsing %d", datasize); goto error; } @@ -602,6 +568,224 @@ _parse_ett (GstMpegTsSection * section) } } + return res; + +error: + if (res) + g_ptr_array_unref (res); + return NULL; +} + +/* EIT */ + +static GstMpegTsAtscEITEvent * +_gst_mpegts_atsc_eit_event_copy (GstMpegTsAtscEITEvent * event) +{ + GstMpegTsAtscEITEvent *copy; + + copy = g_slice_dup (GstMpegTsAtscEITEvent, event); + copy->titles = g_ptr_array_ref (event->titles); + copy->descriptors = g_ptr_array_ref (event->descriptors); + + return copy; +} + +static void +_gst_mpegts_atsc_eit_event_free (GstMpegTsAtscEITEvent * event) +{ + if (event->titles) + g_ptr_array_unref (event->titles); + if (event->descriptors) + g_ptr_array_unref (event->descriptors); + g_slice_free (GstMpegTsAtscEITEvent, event); +} + +G_DEFINE_BOXED_TYPE (GstMpegTsAtscEITEvent, gst_mpegts_atsc_eit_event, + (GBoxedCopyFunc) _gst_mpegts_atsc_eit_event_copy, + (GFreeFunc) _gst_mpegts_atsc_eit_event_free); + +static GstMpegTsAtscEIT * +_gst_mpegts_atsc_eit_copy (GstMpegTsAtscEIT * eit) +{ + GstMpegTsAtscEIT *copy; + + copy = g_slice_dup (GstMpegTsAtscEIT, eit); + copy->events = g_ptr_array_ref (eit->events); + + return copy; +} + +static void +_gst_mpegts_atsc_eit_free (GstMpegTsAtscEIT * eit) +{ + if (eit->events) + g_ptr_array_unref (eit->events); + g_slice_free (GstMpegTsAtscEIT, eit); +} + +G_DEFINE_BOXED_TYPE (GstMpegTsAtscEIT, gst_mpegts_atsc_eit, + (GBoxedCopyFunc) _gst_mpegts_atsc_eit_copy, + (GFreeFunc) _gst_mpegts_atsc_eit_free); + +static gpointer +_parse_atsc_eit (GstMpegTsSection * section) +{ + GstMpegTsAtscEIT *eit = NULL; + guint i = 0; + guint8 *data, *end; + guint8 num_events; + + eit = g_slice_new0 (GstMpegTsAtscEIT); + + data = section->data; + end = data + section->section_length; + + eit->source_id = section->subtable_extension; + + /* Skip already parsed data */ + data += 8; + + eit->protocol_version = GST_READ_UINT8 (data); + data += 1; + num_events = GST_READ_UINT8 (data); + data += 1; + + eit->events = g_ptr_array_new_with_free_func ((GDestroyNotify) + _gst_mpegts_atsc_eit_event_free); + + for (i = 0; i < num_events; i++) { + GstMpegTsAtscEITEvent *event; + guint32 tmp; + guint8 text_length; + guint16 descriptors_loop_length; + + if (end - data < 12) { + GST_WARNING ("PID %d invalid EIT entry length %d with %u events", + section->pid, (gint) (end - 4 - data), num_events); + goto error; + } + + event = g_slice_new0 (GstMpegTsAtscEITEvent); + g_ptr_array_add (eit->events, event); + + event->event_id = GST_READ_UINT16_BE (data) & 0x3FFF; + data += 2; + event->start_time = GST_READ_UINT32_BE (data); + data += 4; + + tmp = GST_READ_UINT32_BE (data); + data += 4; + event->etm_location = (tmp >> 28) & 0x3; + event->length_in_seconds = (tmp >> 8) & 0x0FFFFF; + text_length = tmp & 0xFF; + + if (text_length > end - data - 4 - 2) { + GST_WARNING ("PID %d invalid EIT entry length %d with %u events", + section->pid, (gint) (end - 4 - data), num_events); + goto error; + } + event->titles = _parse_atsc_mult_string (data, text_length); + data += text_length; + + descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + if (end - data - 4 < descriptors_loop_length) { + GST_WARNING ("PID %d invalid EIT entry length %d with %u events", + section->pid, (gint) (end - 4 - data), num_events); + goto error; + } + + event->descriptors = + gst_mpegts_parse_descriptors (data, descriptors_loop_length); + data += descriptors_loop_length; + } + + if (data != end - 4) { + GST_WARNING ("PID %d invalid EIT parsed %d length %d", + section->pid, (gint) (data - section->data), section->section_length); + goto error; + } + + return (gpointer) eit; + +error: + if (eit) + _gst_mpegts_atsc_eit_free (eit); + + return NULL; + +} + +/** + * gst_mpegts_section_get_atsc_eit: + * @section: a #GstMpegTsSection of type %GST_MPEGTS_SECTION_ATSC_EIT + * + * Returns the #GstMpegTsAtscEIT contained in the @section. + * + * Returns: The #GstMpegTsAtscEIT contained in the section, or %NULL if an error + * happened. + */ +const GstMpegTsAtscEIT * +gst_mpegts_section_get_atsc_eit (GstMpegTsSection * section) +{ + g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_ATSC_EIT, + NULL); + g_return_val_if_fail (section->cached_parsed || section->data, NULL); + + if (!section->cached_parsed) + section->cached_parsed = + __common_section_checks (section, 14, _parse_atsc_eit, + (GDestroyNotify) _gst_mpegts_atsc_eit_free); + + return (const GstMpegTsAtscEIT *) section->cached_parsed; +} + + +static GstMpegTsAtscETT * +_gst_mpegts_atsc_ett_copy (GstMpegTsAtscETT * ett) +{ + GstMpegTsAtscETT *copy; + + copy = g_slice_dup (GstMpegTsAtscETT, ett); + copy->messages = g_ptr_array_ref (ett->messages); + + return copy; +} + +static void +_gst_mpegts_atsc_ett_free (GstMpegTsAtscETT * ett) +{ + if (ett->messages) + g_ptr_array_unref (ett->messages); + g_slice_free (GstMpegTsAtscETT, ett); +} + +G_DEFINE_BOXED_TYPE (GstMpegTsAtscETT, gst_mpegts_atsc_ett, + (GBoxedCopyFunc) _gst_mpegts_atsc_ett_copy, + (GFreeFunc) _gst_mpegts_atsc_ett_free); + +static gpointer +_parse_ett (GstMpegTsSection * section) +{ + GstMpegTsAtscETT *ett = NULL; + guint8 *data, *end; + + ett = g_slice_new0 (GstMpegTsAtscETT); + + data = section->data; + end = data + section->section_length; + + /* Skip already parsed data */ + data += 8; + + ett->protocol_version = GST_READ_UINT8 (data); + data += 1; + ett->etm_id = GST_READ_UINT32_BE (data); + data += 4; + + ett->messages = _parse_atsc_mult_string (data, end - data - 4); + data += end - data - 4; if (data != end - 4) { GST_WARNING ("PID %d invalid ETT parsed %d length %d", |