mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
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>
This commit is contained in:
parent
5d3a0ca6a9
commit
3cb32df838
6 changed files with 269 additions and 0 deletions
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue