summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
authorEdward Hervey <edward@centricular.com>2020-11-22 18:48:08 +0100
committerEdward Hervey <bilboed@bilboed.com>2020-12-14 16:37:29 +0100
commit3cb32df838a0a946e3824a55fe092fde20c436b4 (patch)
tree92541c132356737df7e1430d975f750e96ad5e8c /gst-libs
parent5d3a0ca6a9e703a77338ab84df97c2d4a18310ca (diff)
downloadgstreamer-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.h7
-rw-r--r--gst-libs/gst/mpegts/gst-dvb-section.c163
-rw-r--r--gst-libs/gst/mpegts/gst-dvb-section.h62
-rw-r--r--gst-libs/gst/mpegts/gstmpegtssection.c3
-rw-r--r--gst-libs/gst/mpegts/gstmpegtssection.h8
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,