mpegts: add linkage descriptor

https://bugzilla.gnome.org/show_bug.cgi?id=727403
This commit is contained in:
Stefan Ringel 2014-04-10 15:58:04 +02:00 committed by Sebastian Dröge
parent 990efe1fc0
commit eb246e2bfd
3 changed files with 283 additions and 0 deletions

View file

@ -292,6 +292,14 @@ gst_mpegts_descriptor_parse_dvb_teletext_nb
<SUBSECTION subtitling> <SUBSECTION subtitling>
gst_mpegts_descriptor_parse_dvb_subtitling gst_mpegts_descriptor_parse_dvb_subtitling
gst_mpegts_descriptor_from_dvb_subtitling gst_mpegts_descriptor_from_dvb_subtitling
<SUBSECTION linkage>
GstMpegTsDVBLinkageType
GstMpegTsDVBLinkageHandOverType
GstMpegTsDVBLinkageMobileHandOver
GstMpegTsDVBLinkageEvent
GstMpegTsDVBLinkageExtendedEvent
GstMpegTsDVBLinkageDescriptor
gst_mpegts_descriptor_parse_dvb_linkage
<SUBSECTION data_broadcast> <SUBSECTION data_broadcast>
GstMpegTsDataBroadcastDescriptor GstMpegTsDataBroadcastDescriptor
gst_mpegts_descriptor_parse_dvb_data_broadcast gst_mpegts_descriptor_parse_dvb_data_broadcast

View file

@ -424,6 +424,185 @@ gst_mpegts_descriptor_from_dvb_service (GstMpegTsDVBServiceType service_type,
return descriptor; return descriptor;
} }
/* GST_MTS_DESC_DVB_LINKAGE (0x4A) */
static void
_gst_mpegts_dvb_linkage_extened_event_free (GstMpegTsDVBLinkageExtendedEvent *
item)
{
g_slice_free (GstMpegTsDVBLinkageExtendedEvent, item);
}
/**
* gst_mpegts_descriptor_parse_dvb_linkage:
* @descriptor: a %GST_MTS_DESC_DVB_LINKAGE #GstMpegTsDescriptor
* @res: (out) (transfer none): the #GstMpegTsDVBLinkageDescriptor to fill
*
* Extracts the DVB linkage information from @descriptor.
*
* Returns: %TRUE if parsing succeeded, else %FALSE.
*/
gboolean
gst_mpegts_descriptor_parse_dvb_linkage (const GstMpegTsDescriptor * descriptor,
GstMpegTsDVBLinkageDescriptor * res)
{
guint8 *data, *end;
g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE);
__common_desc_checks (descriptor, GST_MTS_DESC_DVB_LINKAGE, 7, FALSE);
data = (guint8 *) descriptor->data + 2;
end = data + descriptor->length;
res->transport_stream_id = GST_READ_UINT16_BE (data);
data += 2;
res->original_network_id = GST_READ_UINT16_BE (data);
data += 2;
res->service_id = GST_READ_UINT16_BE (data);
data += 2;
res->linkage_type = *data;
data += 1;
switch (res->linkage_type) {
case GST_MPEGTS_DVB_LINKAGE_MOBILE_HAND_OVER:{
GstMpegTsDVBLinkageMobileHandOver *hand_over;
if (end - data < 1)
return FALSE;
hand_over = g_slice_new0 (GstMpegTsDVBLinkageMobileHandOver);
res->linkage_data = (gpointer) hand_over;
hand_over->origin_type = (*data >> 7) & 0x01;
hand_over->hand_over_type = *data & 0x0f;
data += 1;
if (hand_over->hand_over_type ==
GST_MPEGTS_DVB_LINKAGE_HAND_OVER_IDENTICAL
|| hand_over->hand_over_type ==
GST_MPEGTS_DVB_LINKAGE_HAND_OVER_LOCAL_VARIATION
|| hand_over->hand_over_type ==
GST_MPEGTS_DVB_LINKAGE_HAND_OVER_ASSOCIATED) {
if (end - data < 2) {
g_slice_free (GstMpegTsDVBLinkageMobileHandOver, hand_over);
res->linkage_data = NULL;
return FALSE;
}
hand_over->network_id = GST_READ_UINT16_BE (data);
data += 2;
}
if (hand_over->origin_type == 0) {
if (end - data < 2) {
g_slice_free (GstMpegTsDVBLinkageMobileHandOver, hand_over);
res->linkage_data = NULL;
return FALSE;
}
hand_over->initial_service_id = GST_READ_UINT16_BE (data);
data += 2;
}
break;
}
case GST_MPEGTS_DVB_LINKAGE_EVENT:{
GstMpegTsDVBLinkageEvent *event;
if (end - data < 3)
return FALSE;
event = g_slice_new0 (GstMpegTsDVBLinkageEvent);
res->linkage_data = (gpointer) event;
event->target_event_id = GST_READ_UINT16_BE (data);
data += 2;
event->target_listed = *data & 0x01;
event->event_simulcast = (*data >> 1) & 0x01;
data += 1;
break;
}
case GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT:{
GPtrArray *ext_events;
ext_events = g_ptr_array_new_with_free_func ((GDestroyNotify)
_gst_mpegts_dvb_linkage_extened_event_free);
res->linkage_data = (gpointer) ext_events;
for (guint8 i = 0; i < *data++;) {
GstMpegTsDVBLinkageExtendedEvent *ext_event;
if (end - data < 3)
goto fail;
ext_event = g_slice_new0 (GstMpegTsDVBLinkageExtendedEvent);
g_ptr_array_add (res->linkage_data, ext_event);
ext_event->target_event_id = GST_READ_UINT16_BE (data);
data += 2;
i += 2;
ext_event->target_listed = *data & 0x01;
ext_event->event_simulcast = (*data >> 1) & 0x01;
ext_event->link_type = (*data >> 3) & 0x03;
ext_event->target_id_type = (*data >> 5) & 0x03;
ext_event->original_network_id_flag = (*data >> 6) & 0x01;
ext_event->service_id_flag = (*data >> 7) & 0x01;
data += 1;
i += 1;
if (ext_event->target_id_type == 3) {
if (end - data < 2)
goto fail;
ext_event->user_defined_id = GST_READ_UINT16_BE (data);
data += 2;
i += 2;
} else {
if (ext_event->target_id_type == 1) {
if (end - data < 2)
goto fail;
ext_event->target_transport_stream_id = GST_READ_UINT16_BE (data);
data += 2;
i += 2;
}
if (ext_event->original_network_id_flag) {
if (end - data < 2)
goto fail;
ext_event->target_original_network_id = GST_READ_UINT16_BE (data);
data += 2;
i += 2;
}
if (ext_event->service_id_flag) {
if (end - data < 2)
goto fail;
ext_event->target_service_id = GST_READ_UINT16_BE (data);
data += 2;
i += 2;
}
}
}
break;
}
default:
break;
}
res->private_data_length = end - data;
res->private_data_bytes = g_memdup (data, res->private_data_length);
return TRUE;
fail:
g_ptr_array_unref (res->linkage_data);
res->linkage_data = NULL;
return FALSE;
}
/* GST_MTS_DESC_DVB_SHORT_EVENT (0x4D) */ /* GST_MTS_DESC_DVB_SHORT_EVENT (0x4D) */
/** /**
* gst_mpegts_descriptor_parse_dvb_short_event: * gst_mpegts_descriptor_parse_dvb_short_event:

View file

@ -330,6 +330,102 @@ GstMpegTsDescriptor *gst_mpegts_descriptor_from_dvb_service (GstMpegTsDVBService
const gchar * service_name, const gchar * service_name,
const gchar * service_provider); const gchar * service_provider);
/* GST_MTS_DESC_DVB_LINKAGE (0x4A) */
/**
* GstMpegTsDVBLinkageType:
*
* Linkage Type (EN 300 468 v.1.13.1)
*/
typedef enum {
/* 0x00, 0x0F-0x7F reserved for future use */
GST_MPEGTS_DVB_LINKAGE_RESERVED_00 = 0x00,
GST_MPEGTS_DVB_LINKAGE_INFORMATION = 0x01,
GST_MPEGTS_DVB_LINKAGE_EPG = 0x02,
GST_MPEGTS_DVB_LINKAGE_CA_REPLACEMENT = 0x03,
GST_MPEGTS_DVB_LINKAGE_TS_CONTAINING_COMPLETE_SI = 0x04,
GST_MPEGTS_DVB_LINKAGE_SERVICE_REPLACEMENT = 0x05,
GST_MPEGTS_DVB_LINKAGE_DATA_BROADCAST = 0x06,
GST_MPEGTS_DVB_LINKAGE_RCS_MAP = 0x07,
GST_MPEGTS_DVB_LINKAGE_MOBILE_HAND_OVER = 0x08,
GST_MPEGTS_DVB_LINKAGE_SYSTEM_SOFTWARE_UPDATE = 0x09,
GST_MPEGTS_DVB_LINKAGE_TS_CONTAINING_SSU = 0x0A,
GST_MPEGTS_DVB_LINKAGE_IP_MAC_NOTIFICATION = 0x0B,
GST_MPEGTS_DVB_LINKAGE_TS_CONTAINING_INT = 0x0C,
GST_MPEGTS_DVB_LINKAGE_EVENT = 0x0D,
GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT = 0x0E,
} GstMpegTsDVBLinkageType;
typedef enum {
GST_MPEGTS_DVB_LINKAGE_HAND_OVER_RESERVED = 0x00,
GST_MPEGTS_DVB_LINKAGE_HAND_OVER_IDENTICAL = 0x01,
GST_MPEGTS_DVB_LINKAGE_HAND_OVER_LOCAL_VARIATION = 0x02,
GST_MPEGTS_DVB_LINKAGE_HAND_OVER_ASSOCIATED = 0x03,
} GstMpegTsDVBLinkageHandOverType;
typedef struct _GstMpegTsDVBLinkageMobileHandOver GstMpegTsDVBLinkageMobileHandOver;
typedef struct _GstMpegTsDVBLinkageEvent GstMpegTsDVBLinkageEvent;
typedef struct _GstMpegTsDVBLinkageExtendedEvent GstMpegTsDVBLinkageExtendedEvent;
typedef struct _GstMpegTsDVBLinkageDescriptor GstMpegTsDVBLinkageDescriptor;
struct _GstMpegTsDVBLinkageMobileHandOver
{
GstMpegTsDVBLinkageHandOverType hand_over_type;
/* 0 = NIT, 1 = SDT */
gboolean origin_type;
guint16 network_id;
guint16 initial_service_id;
};
struct _GstMpegTsDVBLinkageEvent
{
guint16 target_event_id;
gboolean target_listed;
gboolean event_simulcast;
};
struct _GstMpegTsDVBLinkageExtendedEvent
{
guint16 target_event_id;
gboolean target_listed;
gboolean event_simulcast;
/* FIXME: */
guint8 link_type;
/* FIXME: */
guint8 target_id_type;
gboolean original_network_id_flag;
gboolean service_id_flag;
/* if (target_id_type == 3) */
guint16 user_defined_id;
/* else */
guint16 target_transport_stream_id;
guint16 target_original_network_id;
guint16 target_service_id;
};
/**
* GstMpegTsDVBLinkageDescriptor:
* @transport_stream_id: the transport id
* @original_network_id: the original network id
* @service_id: the service id
* @linkage_type: the type which %linkage_data has
* @linkage_data: the linkage structure depending from %linkage_type
* @private_data_length: the length for %private_data_bytes
* @private_data_bytes: additional data bytes
*/
struct _GstMpegTsDVBLinkageDescriptor
{
guint16 transport_stream_id;
guint16 original_network_id;
guint16 service_id;
GstMpegTsDVBLinkageType linkage_type;
gpointer linkage_data;
guint8 private_data_length;
guint8 *private_data_bytes;
};
gboolean gst_mpegts_descriptor_parse_dvb_linkage (const GstMpegTsDescriptor * descriptor,
GstMpegTsDVBLinkageDescriptor * res);
/* GST_MTS_DESC_DVB_SHORT_EVENT (0x4D) */ /* GST_MTS_DESC_DVB_SHORT_EVENT (0x4D) */
gboolean gst_mpegts_descriptor_parse_dvb_short_event (const GstMpegTsDescriptor *descriptor, gboolean gst_mpegts_descriptor_parse_dvb_short_event (const GstMpegTsDescriptor *descriptor,
gchar **language_code, gchar **language_code,