From cdbad569f28233eb9f4fe0a63277c643469ffb8f Mon Sep 17 00:00:00 2001 From: Georgi Chorbadzhiyski Date: Wed, 2 Nov 2011 12:10:51 +0200 Subject: [PATCH] dvb/si: Add support for descriptor 0x6d (Cell frequency link descriptor). --- README | 1 + TODO | 1 - dvb/si/desc_6d.h | 204 +++++++++++++++++++++++++++++++ dvb/si/descs_list.h | 1 + examples/dvb_gen_si.c | 61 ++++++++- examples/dvb_print_si.output.txt | 7 ++ examples/dvb_print_si.output.xml | 12 ++ mpeg/psi/descs_print.h | 1 + 8 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 dvb/si/desc_6d.h diff --git a/README b/README index 2fdd37e..2ffff76 100644 --- a/README +++ b/README @@ -146,6 +146,7 @@ Supported DVB descriptors * Descriptor 0x6a: AC-3 descriptor * Descriptor 0x6b: Ancillary data descriptor * Descriptor 0x6c: Cell list descriptor + * Descriptor 0x6d: Cell frequency link descriptor * Descriptor 0x7a: Enhanced AC-3 descriptor * Descriptor 0x7b: DTS descriptor * Descriptor 0x7c: AAC descriptor diff --git a/TODO b/TODO index ddd5fe3..274f32f 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,6 @@ so if you like something just do it and send a patch. - Descriptor 0x29 IPMP_descriptor (defined in ISO/IEC 13818-11, MPEG-2 IPMP) - Add support (parser, generator, example) for these DVB descriptors: - - Descriptor 0x6d: cell_frequency_link_descriptor - Descriptor 0x6e: announcement_support_descriptor - Descriptor 0x6f: application_signalling_descriptor - Descriptor 0x70: adaptation_field_data_descriptor diff --git a/dvb/si/desc_6d.h b/dvb/si/desc_6d.h new file mode 100644 index 0000000..c56a623 --- /dev/null +++ b/dvb/si/desc_6d.h @@ -0,0 +1,204 @@ +/***************************************************************************** + * desc_6d.h: ETSI EN 300 468 Descriptor 0x6d: Cell frequency link descriptor + ***************************************************************************** + * Copyright (C) 2011 Unix Solutions Ltd. + * + * Authors: Georgi Chorbadzhiyski + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + +/* + * Normative references: + * - ETSI EN 300 468 V1.11.1 (2010-04) (SI in DVB systems) + */ + +#ifndef __BITSTREAM_DVB_DESC_6D_H__ +#define __BITSTREAM_DVB_DESC_6D_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** + * Descriptor 0x6d: Cell frequency link descriptor + *****************************************************************************/ +#define DESC6D_HEADER_SIZE DESC_HEADER_SIZE +#define DESC6D_DATA_SIZE 7 +#define DESC6D_SUBCELL_SIZE 5 + +static inline void desc6d_init(uint8_t *p_desc) +{ + desc_set_tag(p_desc, 0x6d); +} + +static inline uint16_t desc6dn_get_cell_id(const uint8_t *p_desc_n) +{ + return (p_desc_n[0] << 8) | p_desc_n[1]; +} + +static inline void desc6dn_set_cell_id(uint8_t *p_desc_n, uint16_t i_cell_id) +{ + p_desc_n[0] = (i_cell_id >> 8) & 0xff; + p_desc_n[1] = i_cell_id & 0xff; +} + +static inline uint32_t desc6dn_get_frequency(const uint8_t *p_desc_n) +{ + return (p_desc_n[2] << 24) | (p_desc_n[3] << 16) | (p_desc_n[4] << 8) | p_desc_n[5]; +} + +static inline void desc6dn_set_frequency(uint8_t *p_desc_n, uint16_t i_frequency) +{ + p_desc_n[2] = (i_frequency >> 24) & 0xff; + p_desc_n[3] = (i_frequency >> 16) & 0xff; + p_desc_n[4] = (i_frequency >> 8) & 0xff; + p_desc_n[5] = i_frequency & 0xff; +} + +static inline uint8_t desc6dn_get_subcell_info_loop_length(const uint8_t *p_desc_n) +{ + return p_desc_n[6]; +} + + +static inline void desc6dn_set_subcell_info_loop_length(uint8_t *p_desc_n, uint8_t i_subcell_info_loop_length) +{ + p_desc_n[6] = i_subcell_info_loop_length; +} + + +/* Subcell loop */ + +static inline uint8_t desc6dk_get_cell_id_extension(const uint8_t *p_desc_k) +{ + return p_desc_k[0]; +} + +static inline void desc6dk_set_cell_id_extension(uint8_t *p_desc_k, uint8_t i_cell_id_extension) +{ + p_desc_k[0] = i_cell_id_extension; +} + +static inline uint32_t desc6dk_get_transponder_frequency(const uint8_t *p_desc_k) +{ + return (p_desc_k[1] << 24) | (p_desc_k[2] << 16) | (p_desc_k[3] << 8) | p_desc_k[4]; +} + +static inline void desc6dk_set_transponder_frequency(uint8_t *p_desc_k, uint32_t i_frequency) +{ + p_desc_k[1] = (i_frequency >> 24) & 0xff; + p_desc_k[2] = (i_frequency >> 16) & 0xff; + p_desc_k[3] = (i_frequency >> 8) & 0xff; + p_desc_k[4] = i_frequency & 0xff; +} + +/* ----- */ + +static inline uint8_t *desc6d_get_cell(uint8_t *p_desc, uint8_t n) +{ + uint8_t *p_desc_n = p_desc + DESC6D_HEADER_SIZE; + uint8_t i_desc_size = desc_get_length(p_desc); + + while (n) { + uint8_t i_desc6d_data_size = DESC6D_DATA_SIZE + desc6dn_get_subcell_info_loop_length(p_desc_n); + if (p_desc_n + i_desc6d_data_size - p_desc > i_desc_size) + return NULL; + p_desc_n += i_desc6d_data_size; + n--; + } + if (p_desc_n - p_desc > i_desc_size) + return NULL; + return p_desc_n; +} + +static inline uint8_t *desc6dn_get_subcell(uint8_t *p_desc_n, uint8_t k) +{ + int ofs = k * DESC6D_SUBCELL_SIZE; + if (ofs < desc6dn_get_subcell_info_loop_length(p_desc_n)) + return p_desc_n + DESC6D_DATA_SIZE + ofs; + else + return NULL; +} + +static inline bool desc6d_validate(const uint8_t *p_desc) +{ + const uint8_t *p_desc_n = p_desc + DESC6D_HEADER_SIZE; + int i_desc_size = desc_get_length(p_desc); + while (i_desc_size > (DESC6D_HEADER_SIZE - DESC_HEADER_SIZE)) { + uint8_t i_desc6d_data_size = DESC6D_DATA_SIZE + desc6dn_get_subcell_info_loop_length(p_desc_n); + i_desc_size -= i_desc6d_data_size; + p_desc_n += i_desc6d_data_size; + } + return i_desc_size == (DESC6D_HEADER_SIZE - DESC_HEADER_SIZE); +} + +static inline void desc6d_print(uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + uint8_t n = 0; + uint8_t *p_desc_n; + + while ((p_desc_n = desc6d_get_cell(p_desc, n++)) != NULL) { + uint8_t k = 0; + uint8_t *p_desc_k; + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "", + desc6dn_get_cell_id(p_desc_n), + desc6dn_get_frequency(p_desc_n) + ); + while ((p_desc_k = desc6dn_get_subcell(p_desc_n, k++)) != NULL) { + pf_print(opaque, + "", + desc6dk_get_cell_id_extension(p_desc_k), + desc6dk_get_transponder_frequency(p_desc_k) + ); + } + pf_print(opaque, ""); + break; + default: + pf_print(opaque, + " - desc 6d cell_frequency_link cell_id=%u frequency=%u", + desc6dn_get_cell_id(p_desc_n), + desc6dn_get_frequency(p_desc_n) + ); + while ((p_desc_k = desc6dn_get_subcell(p_desc_n, k++)) != NULL) { + pf_print(opaque, + " - subcell_frequency_link cell_id_extension=%u" + " transponder_frequency=%u", + desc6dk_get_cell_id_extension(p_desc_k), + desc6dk_get_transponder_frequency(p_desc_k) + ); + } + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvb/si/descs_list.h b/dvb/si/descs_list.h index f1db53b..7c520c5 100644 --- a/dvb/si/descs_list.h +++ b/dvb/si/descs_list.h @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include diff --git a/examples/dvb_gen_si.c b/examples/dvb_gen_si.c index 1929705..bd7bc0b 100644 --- a/examples/dvb_gen_si.c +++ b/examples/dvb_gen_si.c @@ -1542,7 +1542,63 @@ static void build_desc6c(uint8_t *desc) { desc_set_length(desc, cell_n - desc - DESC_HEADER_SIZE); } -/* --- Descriptor 0x6d: cell_frequency_link_descriptor */ +/* DVB Descriptor 0x6d: Cell frequency link descriptor */ +static void build_desc6d(uint8_t *desc) { + uint8_t n = 0, k; + uint8_t *cell_n, *subcell_k; + + desc6d_init(desc); + desc_set_length(desc, 255); + + cell_n = desc6d_get_cell(desc, n++); + desc6dn_set_cell_id(cell_n, 1234); + desc6dn_set_frequency(cell_n, 4567); + desc6dn_set_subcell_info_loop_length(cell_n, 0); + + cell_n = desc6d_get_cell(desc, n++); + desc6dn_set_cell_id(cell_n, 4456); + desc6dn_set_frequency(cell_n, 5567); + desc6dn_set_subcell_info_loop_length(cell_n, 0); + { + k = 0; + desc6dn_set_subcell_info_loop_length(cell_n, 255); + + subcell_k = desc6dn_get_subcell(cell_n, k++); + desc6dk_set_cell_id_extension(subcell_k, 0); + desc6dk_set_transponder_frequency(subcell_k, 1122); + + subcell_k = desc6dn_get_subcell(cell_n, k++); + desc6dk_set_cell_id_extension(subcell_k, 1); + desc6dk_set_transponder_frequency(subcell_k, 2233); + + subcell_k = desc6dn_get_subcell(cell_n, k++); + desc6dk_set_cell_id_extension(subcell_k, 2); + desc6dk_set_transponder_frequency(subcell_k, 3344); + + subcell_k = desc6dn_get_subcell(cell_n, k); + desc6dn_set_subcell_info_loop_length(cell_n, subcell_k - cell_n - DESC6D_DATA_SIZE); + } + + cell_n = desc6d_get_cell(desc, n++); + desc6dn_set_cell_id(cell_n, 7890); + desc6dn_set_frequency(cell_n, 56789); + desc6dn_set_subcell_info_loop_length(cell_n, 0); + { + k = 0; + desc6dn_set_subcell_info_loop_length(cell_n, 255); + + subcell_k = desc6dn_get_subcell(cell_n, k++); + desc6dk_set_cell_id_extension(subcell_k, 0); + desc6dk_set_transponder_frequency(subcell_k, 889911); + + subcell_k = desc6dn_get_subcell(cell_n, k); + desc6dn_set_subcell_info_loop_length(cell_n, subcell_k - cell_n - DESC6D_DATA_SIZE); + } + + cell_n = desc6d_get_cell(desc, n); + desc_set_length(desc, cell_n - desc - DESC_HEADER_SIZE); +} + /* --- Descriptor 0x6e: announcement_support_descriptor */ /* --- Descriptor 0x6f: application_signalling_descriptor */ /* --- Descriptor 0x70: adaptation_field_data_descriptor */ @@ -1857,6 +1913,9 @@ static void generate_nit(void) { desc = descs_get_desc(desc_loop, desc_counter++); build_desc6c(desc); + desc = descs_get_desc(desc_loop, desc_counter++); + build_desc6d(desc); + // Finish descriptor generation desc = descs_get_desc(desc_loop, desc_counter); // Get next descriptor pos nit_set_desclength(nit, desc - desc_loop - DESCS_HEADER_SIZE); diff --git a/examples/dvb_print_si.output.txt b/examples/dvb_print_si.output.txt index a1c05a3..23f9dc7 100644 --- a/examples/dvb_print_si.output.txt +++ b/examples/dvb_print_si.output.txt @@ -47,6 +47,13 @@ new NIT actual networkid=40000 version=1 - cell_list_subcell_info cell_id_extension=2 subcell_latitude=8755 subcell_longtitude=17493 subcell_extend_of_latitude=1656 subcell_extend_of_longtitude=2475 - desc 6c cell_list cell_id=65535 cell_latitude=61166 cell_longtitude=56797 cell_extend_of_latitude=1929 cell_extend_of_longtitude=2748 - cell_list_subcell_info cell_id_extension=0 subcell_latitude=4386 subcell_longtitude=13124 subcell_extend_of_latitude=1383 subcell_extend_of_longtitude=2202 + - desc 6d cell_frequency_link cell_id=1234 frequency=4567 + - desc 6d cell_frequency_link cell_id=4456 frequency=5567 + - subcell_frequency_link cell_id_extension=0 transponder_frequency=1122 + - subcell_frequency_link cell_id_extension=1 transponder_frequency=2233 + - subcell_frequency_link cell_id_extension=2 transponder_frequency=3344 + - desc 6d cell_frequency_link cell_id=7890 frequency=56789 + - subcell_frequency_link cell_id_extension=0 transponder_frequency=889911 * ts tsid=10000 onid=40000 - desc 41 service_list sid=20000 type=0x01 - desc 41 service_list sid=20100 type=0x02 diff --git a/examples/dvb_print_si.output.xml b/examples/dvb_print_si.output.xml index af029cd..4dab54b 100644 --- a/examples/dvb_print_si.output.xml +++ b/examples/dvb_print_si.output.xml @@ -78,6 +78,18 @@ + + + + + + + + + + + + diff --git a/mpeg/psi/descs_print.h b/mpeg/psi/descs_print.h index e507104..b4430f2 100644 --- a/mpeg/psi/descs_print.h +++ b/mpeg/psi/descs_print.h @@ -178,6 +178,7 @@ static inline void descl_print(uint8_t *p_descl, uint16_t i_length, CASE_DESC(6a) CASE_DESC(6b) CASE_DESC(6c) + CASE_DESC(6d) CASE_DESC(7a) CASE_DESC(7b) CASE_DESC(7c)