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
@ -86,6 +86,13 @@ typedef enum {
|
|||||||
GST_MTS_DESC_DVB_SERVICE_MOVE = 0x60,
|
GST_MTS_DESC_DVB_SERVICE_MOVE = 0x60,
|
||||||
GST_MTS_DESC_DVB_SHORT_SMOOTHING_BUFFER = 0x61,
|
GST_MTS_DESC_DVB_SHORT_SMOOTHING_BUFFER = 0x61,
|
||||||
GST_MTS_DESC_DVB_FREQUENCY_LIST = 0x62,
|
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_PARTIAL_TRANSPORT_STREAM = 0x63,
|
||||||
GST_MTS_DESC_DVB_DATA_BROADCAST = 0x64,
|
GST_MTS_DESC_DVB_DATA_BROADCAST = 0x64,
|
||||||
GST_MTS_DESC_DVB_SCRAMBLING = 0x65,
|
GST_MTS_DESC_DVB_SCRAMBLING = 0x65,
|
||||||
|
@ -85,6 +85,12 @@
|
|||||||
* * gst_mpegts_section_get_tot()
|
* * gst_mpegts_section_get_tot()
|
||||||
* * %GstMpegtsTOT
|
* * %GstMpegtsTOT
|
||||||
*
|
*
|
||||||
|
* ## Selection Information Table (SIT)
|
||||||
|
* See:
|
||||||
|
* * gst_mpegts_section_get_sit()
|
||||||
|
* * %GstMpegtsSIT
|
||||||
|
* * %GstMpegtsSITService
|
||||||
|
*
|
||||||
* # API
|
* # API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1252,3 +1258,160 @@ gst_mpegts_section_get_tot (GstMpegtsSection * section)
|
|||||||
|
|
||||||
return (const GstMpegtsTOT *) section->cached_parsed;
|
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
|
GST_MPEGTS_API
|
||||||
const GstMpegtsTOT *gst_mpegts_section_get_tot (GstMpegtsSection *section);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* GST_MPEGTS_SECTION_H */
|
#endif /* GST_MPEGTS_SECTION_H */
|
||||||
|
@ -1086,6 +1086,9 @@ _identify_section (guint16 pid, guint8 table_id)
|
|||||||
case GST_MTS_TABLE_ID_SCTE_SPLICE:
|
case GST_MTS_TABLE_ID_SCTE_SPLICE:
|
||||||
return GST_MPEGTS_SECTION_SCTE_SIT;
|
return GST_MPEGTS_SECTION_SCTE_SIT;
|
||||||
break;
|
break;
|
||||||
|
case GST_MTS_TABLE_ID_SELECTION_INFORMATION:
|
||||||
|
if (pid == 0x001f)
|
||||||
|
return GST_MPEGTS_SECTION_SIT;
|
||||||
default:
|
default:
|
||||||
/* Handle ranges */
|
/* Handle ranges */
|
||||||
if (table_id >= GST_MTS_TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_PRESENT &&
|
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_SDT,
|
||||||
GST_MPEGTS_SECTION_TDT,
|
GST_MPEGTS_SECTION_TDT,
|
||||||
GST_MPEGTS_SECTION_TOT,
|
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_TVCT,
|
||||||
GST_MPEGTS_SECTION_ATSC_CVCT,
|
GST_MPEGTS_SECTION_ATSC_CVCT,
|
||||||
GST_MPEGTS_SECTION_ATSC_MGT,
|
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
|
static void
|
||||||
dump_tdt (GstMpegtsSection * section)
|
dump_tdt (GstMpegtsSection * section)
|
||||||
{
|
{
|
||||||
@ -1256,6 +1279,9 @@ dump_section (GstMpegtsSection * section)
|
|||||||
case GST_MPEGTS_SECTION_EIT:
|
case GST_MPEGTS_SECTION_EIT:
|
||||||
dump_eit (section);
|
dump_eit (section);
|
||||||
break;
|
break;
|
||||||
|
case GST_MPEGTS_SECTION_SIT:
|
||||||
|
dump_sit (section);
|
||||||
|
break;
|
||||||
case GST_MPEGTS_SECTION_ATSC_MGT:
|
case GST_MPEGTS_SECTION_ATSC_MGT:
|
||||||
dump_mgt (section);
|
dump_mgt (section);
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user