From: Edward Hervey Date: Sun, 22 Nov 2020 17:48:08 +0000 (+0100) Subject: mpegts: Add support for SIT sections X-Git-Tag: 1.19.3~507^2~966 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3cb32df838a0a946e3824a55fe092fde20c436b4;p=platform%2Fupstream%2Fgstreamer.git mpegts: Add support for SIT sections Selection Information Tables (EN 300 468) Part-of: --- diff --git a/gst-libs/gst/mpegts/gst-dvb-descriptor.h b/gst-libs/gst/mpegts/gst-dvb-descriptor.h index e41047e..d88de84 100644 --- a/gst-libs/gst/mpegts/gst-dvb-descriptor.h +++ b/gst-libs/gst/mpegts/gst-dvb-descriptor.h @@ -86,6 +86,13 @@ typedef enum { GST_MTS_DESC_DVB_SERVICE_MOVE = 0x60, GST_MTS_DESC_DVB_SHORT_SMOOTHING_BUFFER = 0x61, GST_MTS_DESC_DVB_FREQUENCY_LIST = 0x62, + /** + * GST_MTS_DESC_DVB_PARTIAL_TRANSPORT_STREAM: + * + * Partial Transport Stream descriptor. Only present in SIT Sections. + * + * See also: %GST_MPEGTS_SECTION_SIT, %GstMpegtsSIT + */ GST_MTS_DESC_DVB_PARTIAL_TRANSPORT_STREAM = 0x63, GST_MTS_DESC_DVB_DATA_BROADCAST = 0x64, GST_MTS_DESC_DVB_SCRAMBLING = 0x65, diff --git a/gst-libs/gst/mpegts/gst-dvb-section.c b/gst-libs/gst/mpegts/gst-dvb-section.c index 6b9eb49..d41723f 100644 --- a/gst-libs/gst/mpegts/gst-dvb-section.c +++ b/gst-libs/gst/mpegts/gst-dvb-section.c @@ -85,6 +85,12 @@ * * gst_mpegts_section_get_tot() * * %GstMpegtsTOT * + * ## Selection Information Table (SIT) + * See: + * * gst_mpegts_section_get_sit() + * * %GstMpegtsSIT + * * %GstMpegtsSITService + * * # API */ @@ -1252,3 +1258,160 @@ gst_mpegts_section_get_tot (GstMpegtsSection * section) return (const GstMpegtsTOT *) section->cached_parsed; } + + +/* Selection Information Table (SIT) */ + +static GstMpegtsSITService * +_gst_mpegts_sit_service_copy (GstMpegtsSITService * sit) +{ + GstMpegtsSITService *copy = g_slice_dup (GstMpegtsSITService, sit); + + copy->service_id = sit->service_id; + copy->running_status = sit->running_status; + copy->descriptors = g_ptr_array_ref (sit->descriptors); + + return copy; +} + +static void +_gst_mpegts_sit_service_free (GstMpegtsSITService * sit) +{ + if (sit->descriptors) + g_ptr_array_unref (sit->descriptors); + g_slice_free (GstMpegtsSITService, sit); +} + +G_DEFINE_BOXED_TYPE (GstMpegtsSITService, gst_mpegts_sit_service, + (GBoxedCopyFunc) _gst_mpegts_sit_service_copy, + (GFreeFunc) _gst_mpegts_sit_service_free); + +static GstMpegtsSIT * +_gst_mpegts_sit_copy (GstMpegtsSIT * sit) +{ + GstMpegtsSIT *copy = g_slice_dup (GstMpegtsSIT, sit); + + copy->services = g_ptr_array_ref (sit->services); + copy->descriptors = g_ptr_array_ref (sit->descriptors); + + return copy; +} + +static void +_gst_mpegts_sit_free (GstMpegtsSIT * sit) +{ + g_ptr_array_unref (sit->services); + g_ptr_array_unref (sit->descriptors); + g_slice_free (GstMpegtsSIT, sit); +} + +G_DEFINE_BOXED_TYPE (GstMpegtsSIT, gst_mpegts_sit, + (GBoxedCopyFunc) _gst_mpegts_sit_copy, (GFreeFunc) _gst_mpegts_sit_free); + + +static gpointer +_parse_sit (GstMpegtsSection * section) +{ + GstMpegtsSIT *sit = NULL; + guint i = 0, allocated_services = 8; + guint8 *data, *end, *entry_begin; + guint sit_info_length; + guint descriptors_loop_length; + + GST_DEBUG ("SIT"); + + sit = g_slice_new0 (GstMpegtsSIT); + + data = section->data; + end = data + section->section_length; + + /* Skip common fields */ + data += 8; + + descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0fff; + data += 2; + sit->descriptors = + gst_mpegts_parse_descriptors (data, descriptors_loop_length); + if (sit->descriptors == NULL) + goto error; + data += descriptors_loop_length; + + sit_info_length = end - data;; + sit->services = g_ptr_array_new_full (allocated_services, + (GDestroyNotify) _gst_mpegts_sit_service_free); + + /* read up to the CRC */ + while (sit_info_length - 4 > 0) { + GstMpegtsSITService *service = g_slice_new0 (GstMpegtsSITService); + g_ptr_array_add (sit->services, service); + + entry_begin = data; + + if (sit_info_length - 4 < 4) { + /* each entry must be at least 4 bytes (+4 bytes for the CRC) */ + GST_WARNING ("PID %d invalid SIT entry size %d", + section->pid, sit_info_length); + goto error; + } + + service->service_id = GST_READ_UINT16_BE (data); + data += 2; + + service->running_status = (*data >> 5) & 0x07; + descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0fff; + data += 2; + + if (descriptors_loop_length && (data + descriptors_loop_length > end - 4)) { + GST_WARNING ("PID %d invalid SIT entry %d descriptors loop length %d", + section->pid, service->service_id, descriptors_loop_length); + goto error; + } + service->descriptors = + gst_mpegts_parse_descriptors (data, descriptors_loop_length); + if (!service->descriptors) + goto error; + data += descriptors_loop_length; + + sit_info_length -= data - entry_begin; + i += 1; + } + + if (data != end - 4) { + GST_WARNING ("PID %d invalid SIT parsed %d length %d", + section->pid, (gint) (data - section->data), section->section_length); + goto error; + } + + return sit; + +error: + if (sit) + _gst_mpegts_sit_free (sit); + + return NULL; +} + +/** + * gst_mpegts_section_get_sit: + * @section: a #GstMpegtsSection of type %GST_MPEGTS_SECTION_SIT + * + * Returns the #GstMpegtsSIT contained in the @section. + * + * Returns: The #GstMpegtsSIT contained in the section, or %NULL if an error + * happened. + * + * Since: 1.20 + */ +const GstMpegtsSIT * +gst_mpegts_section_get_sit (GstMpegtsSection * section) +{ + g_return_val_if_fail (section->section_type == GST_MPEGTS_SECTION_SIT, NULL); + g_return_val_if_fail (section->cached_parsed || section->data, NULL); + + if (!section->cached_parsed) + section->cached_parsed = + __common_section_checks (section, 18, _parse_sit, + (GDestroyNotify) _gst_mpegts_sit_free); + + return (const GstMpegtsSIT *) section->cached_parsed; +} diff --git a/gst-libs/gst/mpegts/gst-dvb-section.h b/gst-libs/gst/mpegts/gst-dvb-section.h index 2fa2a9a..665bb5d 100644 --- a/gst-libs/gst/mpegts/gst-dvb-section.h +++ b/gst-libs/gst/mpegts/gst-dvb-section.h @@ -433,6 +433,68 @@ GType gst_mpegts_tot_get_type (void); GST_MPEGTS_API const GstMpegtsTOT *gst_mpegts_section_get_tot (GstMpegtsSection *section); +/* SIT */ + +typedef struct _GstMpegtsSITService GstMpegtsSITService; +/** + * GST_TYPE_MPEGTS_SIT_SERVICE: + * + * Since: 1.20 + */ +#define GST_TYPE_MPEGTS_SIT_SERVICE (gst_mpegts_sit_service_get_type()) + +typedef struct _GstMpegtsSIT GstMpegtsSIT; +/** + * GST_TYPE_MPEGTS_SIT: + * + * Since: 1.20 + */ +#define GST_TYPE_MPEGTS_SIT (gst_mpegts_sit_get_type()) + +/** + * GstMpegtsSITService: + * @service_id: The Program number this table belongs to + * @running_status: Status of this service + * @descriptors: (element-type GstMpegtsDescriptor): List of descriptors + * + * SIT Service entry + * + * Since: 1.20 + */ +struct _GstMpegtsSITService +{ + guint16 service_id; + GstMpegtsRunningStatus running_status; + + GPtrArray *descriptors; +}; + +/** + * GstMpegtsSIT: + * @descriptors: (element-type GstMpegtsDescriptor): List of descriptors + * @services: (element-type GstMpegtsSITService): List of services + * + * Selection Information Table (EN 300 468) + * + * Since: 1.20 + */ +struct _GstMpegtsSIT +{ + GPtrArray *descriptors; + GPtrArray *services; +}; + + +GST_MPEGTS_API +GType gst_mpegts_sit_get_type (void); + +GST_MPEGTS_API +GType gst_mpegts_sit_service_get_type (void); + +GST_MPEGTS_API +const GstMpegtsSIT *gst_mpegts_section_get_sit (GstMpegtsSection *section); + + G_END_DECLS #endif /* GST_MPEGTS_SECTION_H */ diff --git a/gst-libs/gst/mpegts/gstmpegtssection.c b/gst-libs/gst/mpegts/gstmpegtssection.c index 2f2a96f..d93253f 100644 --- a/gst-libs/gst/mpegts/gstmpegtssection.c +++ b/gst-libs/gst/mpegts/gstmpegtssection.c @@ -1086,6 +1086,9 @@ _identify_section (guint16 pid, guint8 table_id) case GST_MTS_TABLE_ID_SCTE_SPLICE: return GST_MPEGTS_SECTION_SCTE_SIT; break; + case GST_MTS_TABLE_ID_SELECTION_INFORMATION: + if (pid == 0x001f) + return GST_MPEGTS_SECTION_SIT; default: /* Handle ranges */ if (table_id >= GST_MTS_TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_PRESENT && diff --git a/gst-libs/gst/mpegts/gstmpegtssection.h b/gst-libs/gst/mpegts/gstmpegtssection.h index 95a7208..18f0e7f 100644 --- a/gst-libs/gst/mpegts/gstmpegtssection.h +++ b/gst-libs/gst/mpegts/gstmpegtssection.h @@ -77,6 +77,14 @@ typedef enum { GST_MPEGTS_SECTION_SDT, GST_MPEGTS_SECTION_TDT, GST_MPEGTS_SECTION_TOT, + /** + * GST_MPEGTS_SECTION_SIT: + * + * Selection Information Table (EN 300 468) + * + * Since: 1.20 + */ + GST_MPEGTS_SECTION_SIT, GST_MPEGTS_SECTION_ATSC_TVCT, GST_MPEGTS_SECTION_ATSC_CVCT, GST_MPEGTS_SECTION_ATSC_MGT, diff --git a/tests/examples/mpegts/ts-parser.c b/tests/examples/mpegts/ts-parser.c index ad667f6..32dab35 100644 --- a/tests/examples/mpegts/ts-parser.c +++ b/tests/examples/mpegts/ts-parser.c @@ -1035,6 +1035,29 @@ dump_sdt (GstMpegtsSection * section) } } + +static void +dump_sit (GstMpegtsSection * section) +{ + const GstMpegtsSIT *sit = gst_mpegts_section_get_sit (section); + guint i, len; + + g_assert (sit); + + dump_descriptors (sit->descriptors, 7); + len = sit->services->len; + g_printf (" %d Services:\n", len); + for (i = 0; i < len; i++) { + GstMpegtsSITService *service = g_ptr_array_index (sit->services, i); + g_print + (" service_id:0x%04x, running_status:0x%02x (%s)\n", + service->service_id, service->running_status, + enum_name (GST_TYPE_MPEGTS_RUNNING_STATUS, service->running_status)); + dump_descriptors (service->descriptors, 9); + } +} + + static void dump_tdt (GstMpegtsSection * section) { @@ -1256,6 +1279,9 @@ dump_section (GstMpegtsSection * section) case GST_MPEGTS_SECTION_EIT: dump_eit (section); break; + case GST_MPEGTS_SECTION_SIT: + dump_sit (section); + break; case GST_MPEGTS_SECTION_ATSC_MGT: dump_mgt (section); break;