diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt index e37629a30b..a3919dfdb3 100644 --- a/docs/libs/gst-plugins-bad-libs-sections.txt +++ b/docs/libs/gst-plugins-bad-libs-sections.txt @@ -292,6 +292,14 @@ gst_mpegts_descriptor_parse_dvb_teletext_nb gst_mpegts_descriptor_parse_dvb_subtitling gst_mpegts_descriptor_from_dvb_subtitling + +GstMpegTsDVBLinkageType +GstMpegTsDVBLinkageHandOverType +GstMpegTsDVBLinkageMobileHandOver +GstMpegTsDVBLinkageEvent +GstMpegTsDVBLinkageExtendedEvent +GstMpegTsDVBLinkageDescriptor +gst_mpegts_descriptor_parse_dvb_linkage GstMpegTsDataBroadcastDescriptor gst_mpegts_descriptor_parse_dvb_data_broadcast diff --git a/gst-libs/gst/mpegts/gst-dvb-descriptor.c b/gst-libs/gst/mpegts/gst-dvb-descriptor.c index ce2c9863ee..6aac694cba 100644 --- a/gst-libs/gst/mpegts/gst-dvb-descriptor.c +++ b/gst-libs/gst/mpegts/gst-dvb-descriptor.c @@ -424,6 +424,185 @@ gst_mpegts_descriptor_from_dvb_service (GstMpegTsDVBServiceType service_type, 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_mpegts_descriptor_parse_dvb_short_event: diff --git a/gst-libs/gst/mpegts/gst-dvb-descriptor.h b/gst-libs/gst/mpegts/gst-dvb-descriptor.h index 1927cb4026..5f1b92da6c 100644 --- a/gst-libs/gst/mpegts/gst-dvb-descriptor.h +++ b/gst-libs/gst/mpegts/gst-dvb-descriptor.h @@ -330,6 +330,102 @@ GstMpegTsDescriptor *gst_mpegts_descriptor_from_dvb_service (GstMpegTsDVBService const gchar * service_name, 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) */ gboolean gst_mpegts_descriptor_parse_dvb_short_event (const GstMpegTsDescriptor *descriptor, gchar **language_code,