diff options
author | Edward Hervey <edward@centricular.com> | 2020-11-22 18:48:08 +0100 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2020-12-14 16:37:29 +0100 |
commit | 3cb32df838a0a946e3824a55fe092fde20c436b4 (patch) | |
tree | 92541c132356737df7e1430d975f750e96ad5e8c /gst-libs | |
parent | 5d3a0ca6a9e703a77338ab84df97c2d4a18310ca (diff) | |
download | gstreamer-plugins-bad-3cb32df838a0a946e3824a55fe092fde20c436b4.tar.gz |
mpegts: Add support for SIT sections
Selection Information Tables (EN 300 468)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1852>
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/mpegts/gst-dvb-descriptor.h | 7 | ||||
-rw-r--r-- | gst-libs/gst/mpegts/gst-dvb-section.c | 163 | ||||
-rw-r--r-- | gst-libs/gst/mpegts/gst-dvb-section.h | 62 | ||||
-rw-r--r-- | gst-libs/gst/mpegts/gstmpegtssection.c | 3 | ||||
-rw-r--r-- | gst-libs/gst/mpegts/gstmpegtssection.h | 8 |
5 files changed, 243 insertions, 0 deletions
diff --git a/gst-libs/gst/mpegts/gst-dvb-descriptor.h b/gst-libs/gst/mpegts/gst-dvb-descriptor.h index e41047e20..d88de8485 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 6b9eb49c2..d41723f51 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 2fa2a9a42..665bb5d0c 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 2f2a96f84..d93253f58 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 95a72085a..18f0e7ffb 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, |