From b7efacfe15a7ca0bf0258d1fde770be9d47267c6 Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Sun, 30 Mar 2014 21:02:10 +0200 Subject: [PATCH] mpegts: add dvb-t2 delivery system descriptor Signed-off-by: Stefan Ringel https://bugzilla.gnome.org/show_bug.cgi?id=727356 --- gst-libs/gst/mpegts/gst-dvb-descriptor.c | 183 +++++++++++++++++++++++ gst-libs/gst/mpegts/gst-dvb-descriptor.h | 98 ++++++++++++ gst-libs/gst/mpegts/gstmpegts-private.h | 26 ++++ 3 files changed, 307 insertions(+) diff --git a/gst-libs/gst/mpegts/gst-dvb-descriptor.c b/gst-libs/gst/mpegts/gst-dvb-descriptor.c index 57c714377b..fbc75c3acb 100644 --- a/gst-libs/gst/mpegts/gst-dvb-descriptor.c +++ b/gst-libs/gst/mpegts/gst-dvb-descriptor.c @@ -1032,3 +1032,186 @@ gst_mpegts_descriptor_parse_dvb_data_broadcast (const GstMpegTsDescriptor return TRUE; } + +/* GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM (0x7F && 0x04) */ +static void + _gst_mpegts_t2_delivery_system_cell_extension_free + (GstMpegTsT2DeliverySystemCellExtension * ext) +{ + g_slice_free (GstMpegTsT2DeliverySystemCellExtension, ext); +} + +static void +_gst_mpegts_t2_delivery_system_cell_free (GstMpegTsT2DeliverySystemCell * cell) +{ + g_ptr_array_unref (cell->sub_cells); + g_slice_free (GstMpegTsT2DeliverySystemCell, cell); +} + +/** + * gst_mpegts_descriptor_parse_dvb_t2_delivery_system: + * @descriptor: a %GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM #GstMpegTsDescriptor + * @res: (out) (transfer none): #GstMpegTsT2DeliverySystemDescriptor + * + * Parses out the DVB-T2 delivery system from the @descriptor. + * + * Returns: %TRUE if the parsing happened correctly, else %FALSE. + */ +gboolean +gst_mpegts_descriptor_parse_dvb_t2_delivery_system (const GstMpegTsDescriptor + * descriptor, GstMpegTsT2DeliverySystemDescriptor * res) +{ + guint8 *data; + guint8 len, freq_len, sub_cell_len; + guint32 tmp_freq; + + g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE); + __common_desc_ext_checks (descriptor, GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM, + 4, FALSE); + + data = (guint8 *) descriptor->data + 3; + + res->plp_id = *data; + data += 1; + + res->t2_system_id = GST_READ_UINT16_BE (data); + data += 2; + + if (descriptor->length > 4) { + // FIXME: siso / miso + res->siso_miso = (*data >> 6) & 0x03; + switch ((*data >> 2) & 0x0f) { + case 0: + res->bandwidth = 8000000; + break; + case 1: + res->bandwidth = 7000000; + break; + case 2: + res->bandwidth = 6000000; + break; + case 3: + res->bandwidth = 5000000; + break; + case 4: + res->bandwidth = 10000000; + break; + case 5: + res->bandwidth = 1712000; + break; + default: + res->bandwidth = 0; + break; + } + data += 1; + + switch ((*data >> 5) & 0x07) { + case 0: + res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_32; + break; + case 1: + res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_16; + break; + case 2: + res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_8; + break; + case 3: + res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_4; + break; + case 4: + res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_128; + break; + case 5: + res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_19_128; + break; + case 6: + res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_19_256; + break; + default: + break; + } + + switch ((*data >> 2) & 0x07) { + case 0: + res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_2K; + break; + case 1: + res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_8K; + break; + case 2: + res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_4K; + break; + case 3: + res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_1K; + break; + case 4: + res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_16K; + break; + case 5: + res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_32K; + break; + default: + break; + } + res->other_frequency = (*data >> 1) & 0x01; + res->tfs = (*data) & 0x01; + data += 1; + + len = descriptor->length - 6; + + res->cells = g_ptr_array_new_with_free_func ((GDestroyNotify) + _gst_mpegts_t2_delivery_system_cell_free); + + for (guint8 i = 0; i < len;) { + GstMpegTsT2DeliverySystemCell *cell; + + cell = g_slice_new0 (GstMpegTsT2DeliverySystemCell); + g_ptr_array_add (res->cells, cell); + + cell->cell_id = GST_READ_UINT16_BE (data); + data += 2; + i += 2; + + cell->centre_frequencies = g_array_new (FALSE, FALSE, sizeof (guint32)); + + if (res->tfs == TRUE) { + freq_len = *data; + data += 1; + i += 1; + + for (guint8 j = 0; j < freq_len;) { + tmp_freq = GST_READ_UINT32_BE (data) * 10; + g_array_append_val (cell->centre_frequencies, tmp_freq); + data += 4; + j += 4; + i += 4; + } + } else { + tmp_freq = GST_READ_UINT32_BE (data) * 10; + g_array_append_val (cell->centre_frequencies, tmp_freq); + data += 4; + i += 4; + } + sub_cell_len = (*data); + data += 1; + i += 1; + + cell->sub_cells = g_ptr_array_new_with_free_func ((GDestroyNotify) + _gst_mpegts_t2_delivery_system_cell_extension_free); + + for (guint8 k = 0; k < sub_cell_len;) { + GstMpegTsT2DeliverySystemCellExtension *cell_ext; + cell_ext = g_slice_new0 (GstMpegTsT2DeliverySystemCellExtension); + + cell_ext->cell_id_extension = *data; + data += 1; + + cell_ext->transposer_frequency = GST_READ_UINT32_BE (data) * 10; + data += 4; + i += 5; + k += 5; + } + } + } + return TRUE; +} diff --git a/gst-libs/gst/mpegts/gst-dvb-descriptor.h b/gst-libs/gst/mpegts/gst-dvb-descriptor.h index 7ef6701912..1927cb4026 100644 --- a/gst-libs/gst/mpegts/gst-dvb-descriptor.h +++ b/gst-libs/gst/mpegts/gst-dvb-descriptor.h @@ -116,6 +116,42 @@ typedef enum { GST_MTS_DESC_DVB_EXTENSION = 0x7F, } GstMpegTsDVBDescriptorType; +/** + * GstMpegTsDVBExtendedDescriptorType: + * + * The type of #GstMpegTsDescriptor + * + * These values correspond to the registered extended descriptor + * type from the various DVB specifications. + * + * Consult the relevant specifications for more details. + */ +typedef enum { + /* 00 - 0x7F DVB extended tags ETSI EN 300 468 + * (Specification for Service Information (SI) in DVB systems) + */ + GST_MTS_DESC_EXT_DVB_IMAGE_ICON = 0x00, + /* TS/TR 102 825 */ + GST_MTS_DESC_EXT_DVB_CPCM_DELIVERY_SIGNALLING = 0x01, + GST_MTS_DESC_EXT_DVB_CP = 0x02, + GST_MTS_DESC_EXT_DVB_CP_IDENTIFIER = 0x03, + GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM = 0x04, + GST_MTS_DESC_EXT_DVB_SH_DELIVERY_SYSTEM = 0x05, + GST_MTS_DESC_EXT_DVB_SUPPLEMENTARY_AUDIO = 0x06, + GST_MTS_DESC_EXT_DVB_NETWORK_CHANGE_NOTIFY = 0x07, + GST_MTS_DESC_EXT_DVB_MESSAGE = 0x08, + GST_MTS_DESC_EXT_DVB_TARGET_REGION = 0x09, + GST_MTS_DESC_EXT_DVB_TARGET_REGION_NAME = 0x0A, + GST_MTS_DESC_EXT_DVB_SERVICE_RELOCATED = 0x0B, + GST_MTS_DESC_EXT_DVB_XAIT_PID = 0x0C, + GST_MTS_DESC_EXT_DVB_C2_DELIVERY_SYSTEM = 0x0D, + GST_MTS_DESC_EXT_DVB_DTS_HD_AUDIO_STREAM = 0x0E, + GST_MTS_DESC_EXT_DVB_DTS_NEUTRAL = 0x0F, + GST_MTS_DESC_EXT_DVB_VIDEO_DEPTH_RANGE = 0x10, + GST_MTS_DESC_EXT_DVB_T2MI = 0x11, + GST_MTS_DESC_EXT_DVB_URI_LINKAGE = 0x13, +} GstMpegTsDVBExtendedDescriptorType; + /* GST_MTS_DESC_DVB_CAROUSEL_IDENTIFIER (0x13) */ /* FIXME : Implement */ @@ -508,6 +544,68 @@ gboolean gst_mpegts_descriptor_parse_dvb_data_broadcast (const GstMpegTsDescript /* GST_MTS_DESC_DVB_AC3 (0x6a) */ /* FIXME : Implement */ +/* GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM (0x7F && 0x04) */ +typedef struct _GstMpegTsT2DeliverySystemCellExtension GstMpegTsT2DeliverySystemCellExtension; + +/** + * GstMpegTsT2DeliverySystemCellExtension: + * @cell_id_extension: id of the sub cell + * @transposer_frequency: centre frequency of the sub cell in Hz + */ +struct _GstMpegTsT2DeliverySystemCellExtension +{ + guint8 cell_id_extension; + guint32 transposer_frequency; +}; + +typedef struct _GstMpegTsT2DeliverySystemCell GstMpegTsT2DeliverySystemCell; + +/** + * GstMpegTsT2DeliverySystemCell: + * @cell_id: id of the cell + * @centre_frequencies: centre frequencies in Hz + * @sub_cells: (element-type GstMpegTsT2DeliverySystemCellExtension): + */ +struct _GstMpegTsT2DeliverySystemCell +{ + guint16 cell_id; + GArray *centre_frequencies; + GPtrArray *sub_cells; +}; + +typedef struct _GstMpegTsT2DeliverySystemDescriptor GstMpegTsT2DeliverySystemDescriptor; + +/** + * GstMpegTsT2DeliverySystemDescriptor: + * @plp_id: + * @t2_system_id: + * @siso_miso: + * @bandwidth: + * @guard_interval: + * @transmission_mode: + * @other_frequency: + * @tfs: + * @cells: (element-type GstMpegTsT2DeliverySystemCell): + * + * describe DVB-T2 transmissions according to EN 302 755 + */ +struct _GstMpegTsT2DeliverySystemDescriptor +{ + guint8 plp_id; + guint16 t2_system_id; + /* FIXME: */ + guint8 siso_miso; + guint32 bandwidth; + GstMpegTsTerrestrialGuardInterval guard_interval; + GstMpegTsTerrestrialTransmissionMode transmission_mode; + gboolean other_frequency; + gboolean tfs; + GPtrArray *cells; +}; + +gboolean gst_mpegts_descriptor_parse_dvb_t2_delivery_system (const GstMpegTsDescriptor + *descriptor, GstMpegTsT2DeliverySystemDescriptor * res); + G_END_DECLS #endif /* GST_MPEGTS_DESCRIPTOR_H */ diff --git a/gst-libs/gst/mpegts/gstmpegts-private.h b/gst-libs/gst/mpegts/gstmpegts-private.h index 170d16117d..a3e6dc14d7 100644 --- a/gst-libs/gst/mpegts/gstmpegts-private.h +++ b/gst-libs/gst/mpegts/gstmpegts-private.h @@ -74,6 +74,32 @@ G_GNUC_INTERNAL gpointer __common_section_checks (GstMpegTsSection *section, return retval; \ } +#define __common_desc_ext_check_base(desc, tagexttype, retval) \ + if (G_UNLIKELY ((desc)->data == NULL)) { \ + GST_WARNING ("Descriptor is empty (data field == NULL)"); \ + return retval; \ + } \ + if (G_UNLIKELY ((desc)->tag != 0x7f) || \ + ((desc)->tag_extension != (tagexttype))) { \ + GST_WARNING ("Wrong descriptor type (Got 0x%02x, expected 0x%02x)", \ + (desc)->tag_extension, tagexttype); \ + return retval; \ + } +#define __common_desc_ext_checks(desc, tagexttype, minlen, retval) \ + __common_desc_ext_check_base(desc, tagexttype, retval); \ + if (G_UNLIKELY ((desc)->length < (minlen))) { \ + GST_WARNING ("Descriptor too small (Got %d, expected at least %d)", \ + (desc)->length, minlen); \ + return retval; \ + } +#define __common_desc_ext_checks_exact(desc, tagexttype, len, retval) \ + __common_desc_ext_check_base(desc, tagexttype, retval); \ + if (G_UNLIKELY ((desc)->length != (len))) { \ + GST_WARNING ("Wrong descriptor size (Got %d, expected %d)", \ + (desc)->length, len); \ + return retval; \ + } + G_END_DECLS #endif /* _GST_MPEGTS_PRIVATE_H_ */