From d927ea40b73abf45b2d31a4f88caa5fa2cf09987 Mon Sep 17 00:00:00 2001 From: Georgi Chorbadzhiyski Date: Mon, 31 Oct 2011 19:25:29 +0200 Subject: [PATCH] dvb/si: Add support for descriptor 0x6c (Cell list descriptor). --- README | 1 + TODO | 1 - dvb/si/desc_6c.h | 285 +++++++++++++++++++++++++++++++ dvb/si/descs_list.h | 1 + examples/dvb_gen_si.c | 82 ++++++++- examples/dvb_print_si.output.txt | 7 + examples/dvb_print_si.output.xml | 12 ++ mpeg/psi/descs_print.h | 1 + 8 files changed, 388 insertions(+), 2 deletions(-) create mode 100644 dvb/si/desc_6c.h diff --git a/README b/README index c99aaac..2fdd37e 100644 --- a/README +++ b/README @@ -145,6 +145,7 @@ Supported DVB descriptors * Descriptor 0x69: PDC descriptor * Descriptor 0x6a: AC-3 descriptor * Descriptor 0x6b: Ancillary data descriptor + * Descriptor 0x6c: Cell list descriptor * Descriptor 0x7a: Enhanced AC-3 descriptor * Descriptor 0x7b: DTS descriptor * Descriptor 0x7c: AAC descriptor diff --git a/TODO b/TODO index 9dd0367..ddd5fe3 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 0x6c: cell_list_descriptor - Descriptor 0x6d: cell_frequency_link_descriptor - Descriptor 0x6e: announcement_support_descriptor - Descriptor 0x6f: application_signalling_descriptor diff --git a/dvb/si/desc_6c.h b/dvb/si/desc_6c.h new file mode 100644 index 0000000..eb6d56a --- /dev/null +++ b/dvb/si/desc_6c.h @@ -0,0 +1,285 @@ +/***************************************************************************** + * desc_6c.h: ETSI EN 300 468 Descriptor 0x6c: Cell list 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_6C_H__ +#define __BITSTREAM_DVB_DESC_6C_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** + * Descriptor 0x6c: Cell list descriptors + *****************************************************************************/ +#define DESC6C_HEADER_SIZE DESC_HEADER_SIZE +#define DESC6C_DATA_SIZE 10 +#define DESC6C_SUBCELL_SIZE 8 + +static inline void desc6c_init(uint8_t *p_desc) +{ + desc_set_tag(p_desc, 0x6c); +} + +static inline uint16_t desc6cn_get_cell_id(const uint8_t *p_desc_n) +{ + return (p_desc_n[0] << 8) | p_desc_n[1]; +} + +static inline void desc6cn_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 uint16_t desc6cn_get_cell_latitude(const uint8_t *p_desc_n) +{ + return (p_desc_n[2] << 8) | p_desc_n[3]; +} + +static inline void desc6cn_set_cell_latitude(uint8_t *p_desc_n, uint16_t i_cell_latitude) +{ + p_desc_n[2] = (i_cell_latitude >> 8) & 0xff; + p_desc_n[3] = i_cell_latitude & 0xff; +} + +static inline uint16_t desc6cn_get_cell_longtitude(const uint8_t *p_desc_n) +{ + return (p_desc_n[4] << 8) | p_desc_n[5]; +} + +static inline void desc6cn_set_cell_longtitude(uint8_t *p_desc_n, uint16_t i_cell_longtitude) +{ + p_desc_n[4] = (i_cell_longtitude >> 8) & 0xff; + p_desc_n[5] = i_cell_longtitude & 0xff; +} + +static inline uint16_t desc6cn_get_cell_extend_of_latitude(const uint8_t *p_desc_n) +{ + return (p_desc_n[6] << 4) | ((p_desc_n[7] & 0xf0) >> 4); +} + +static inline void desc6cn_set_cell_extend_of_latitude(uint8_t *p_desc_n, uint16_t i_cell_extend_of_latitude) +{ + p_desc_n[6] = (i_cell_extend_of_latitude >> 4) & 0xff; + p_desc_n[7] = ((i_cell_extend_of_latitude & 0x0f) << 4) | (p_desc_n[7] & 0x0f); +} + +static inline uint16_t desc6cn_get_cell_extend_of_longtitude(const uint8_t *p_desc_n) +{ + return ((p_desc_n[7] & 0x0f) << 8) | p_desc_n[8]; +} + +static inline void desc6cn_set_cell_extend_of_longtitude(uint8_t *p_desc_n, uint16_t i_cell_extend_of_longtitude) +{ + p_desc_n[7] = (p_desc_n[7] & 0xf0) | ((i_cell_extend_of_longtitude >> 8) & 0x0f); + p_desc_n[8] = i_cell_extend_of_longtitude & 0xff; +} + +static inline uint8_t desc6cn_get_subcell_info_loop_length(const uint8_t *p_desc_n) +{ + return p_desc_n[9]; +} + + +static inline void desc6cn_set_subcell_info_loop_length(uint8_t *p_desc_n, uint8_t i_subcell_info_loop_length) +{ + p_desc_n[9] = i_subcell_info_loop_length; +} + + +/* Subcell loop */ + +static inline uint8_t desc6ck_get_cell_id_extension(const uint8_t *p_desc_k) +{ + return p_desc_k[0]; +} + +static inline void desc6ck_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 uint16_t desc6ck_get_subcell_latitude(const uint8_t *p_desc_k) +{ + return (p_desc_k[1] << 8) | p_desc_k[2]; +} + +static inline void desc6ck_set_subcell_latitude(uint8_t *p_desc_k, uint16_t i_cell_latitude) +{ + p_desc_k[1] = (i_cell_latitude >> 8) & 0xff; + p_desc_k[2] = i_cell_latitude & 0xff; +} + +static inline uint16_t desc6ck_get_subcell_longtitude(const uint8_t *p_desc_k) +{ + return (p_desc_k[3] << 8) | p_desc_k[4]; +} + +static inline void desc6ck_set_subcell_longtitude(uint8_t *p_desc_k, uint16_t i_cell_longtitude) +{ + p_desc_k[3] = (i_cell_longtitude >> 8) & 0xff; + p_desc_k[4] = i_cell_longtitude & 0xff; +} + +static inline uint16_t desc6ck_get_subcell_extend_of_latitude(const uint8_t *p_desc_k) +{ + return (p_desc_k[5] << 4) | ((p_desc_k[6] & 0xf0) >> 4); +} + +static inline void desc6ck_set_subcell_extend_of_latitude(uint8_t *p_desc_k, uint16_t i_cell_extend_of_latitude) +{ + p_desc_k[5] = (i_cell_extend_of_latitude >> 4) & 0xff; + p_desc_k[6] = ((i_cell_extend_of_latitude & 0x0f) << 4) | (p_desc_k[6] & 0x0f); +} + +static inline uint16_t desc6ck_get_subcell_extend_of_longtitude(const uint8_t *p_desc_k) +{ + return ((p_desc_k[6] & 0x0f) << 8) | p_desc_k[7]; +} + +static inline void desc6ck_set_subcell_extend_of_longtitude(uint8_t *p_desc_k, uint16_t i_cell_extend_of_longtitude) +{ + p_desc_k[6] = (p_desc_k[6] & 0xf0) | ((i_cell_extend_of_longtitude >> 8) & 0x0f); + p_desc_k[7] = i_cell_extend_of_longtitude & 0xff; +} + +/* ----- */ + +static inline uint8_t *desc6c_get_cell(uint8_t *p_desc, uint8_t n) +{ + uint8_t *p_desc_n = p_desc + DESC6C_HEADER_SIZE; + uint8_t i_desc_size = desc_get_length(p_desc); + + while (n) { + uint8_t i_desc6c_data_size = DESC6C_DATA_SIZE + desc6cn_get_subcell_info_loop_length(p_desc_n); + if (p_desc_n + i_desc6c_data_size - p_desc > i_desc_size) + return NULL; + p_desc_n += i_desc6c_data_size; + n--; + } + if (p_desc_n - p_desc > i_desc_size) + return NULL; + return p_desc_n; +} + +static inline uint8_t *desc6cn_get_subcell(uint8_t *p_desc_n, uint8_t k) +{ + int ofs = k * DESC6C_SUBCELL_SIZE; + if (ofs < desc6cn_get_subcell_info_loop_length(p_desc_n)) + return p_desc_n + DESC6C_DATA_SIZE + ofs; + else + return NULL; +} + +static inline bool desc6c_validate(const uint8_t *p_desc) +{ + const uint8_t *p_desc_n = p_desc + DESC6C_HEADER_SIZE; + int i_desc_size = desc_get_length(p_desc); + while (i_desc_size > (DESC6C_HEADER_SIZE - DESC_HEADER_SIZE)) { + uint8_t i_desc6c_data_size = DESC6C_DATA_SIZE + desc6cn_get_subcell_info_loop_length(p_desc_n); + i_desc_size -= i_desc6c_data_size; + p_desc_n += i_desc6c_data_size; + } + return i_desc_size == (DESC6C_HEADER_SIZE - DESC_HEADER_SIZE); +} + +static inline void desc6c_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 = desc6c_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, + "", + desc6cn_get_cell_id(p_desc_n), + desc6cn_get_cell_latitude(p_desc_n), + desc6cn_get_cell_longtitude(p_desc_n), + desc6cn_get_cell_extend_of_latitude(p_desc_n), + desc6cn_get_cell_extend_of_longtitude(p_desc_n) + ); + while ((p_desc_k = desc6cn_get_subcell(p_desc_n, k++)) != NULL) { + pf_print(opaque, + "", + desc6ck_get_cell_id_extension(p_desc_k), + desc6ck_get_subcell_latitude(p_desc_k), + desc6ck_get_subcell_longtitude(p_desc_k), + desc6ck_get_subcell_extend_of_latitude(p_desc_k), + desc6ck_get_subcell_extend_of_longtitude(p_desc_k) + ); + } + pf_print(opaque, ""); + break; + default: + pf_print(opaque, + " - desc 6c cell_list cell_id=%u cell_latitude=%u" + " cell_longtitude=%u cell_extend_of_latitude=%u" + " cell_extend_of_longtitude=%u", + desc6cn_get_cell_id(p_desc_n), + desc6cn_get_cell_latitude(p_desc_n), + desc6cn_get_cell_longtitude(p_desc_n), + desc6cn_get_cell_extend_of_latitude(p_desc_n), + desc6cn_get_cell_extend_of_longtitude(p_desc_n) + ); + while ((p_desc_k = desc6cn_get_subcell(p_desc_n, k++)) != NULL) { + pf_print(opaque, + " - cell_list_subcell_info cell_id_extension=%u subcell_latitude=%u" + " subcell_longtitude=%u subcell_extend_of_latitude=%u" + " subcell_extend_of_longtitude=%u", + desc6ck_get_cell_id_extension(p_desc_k), + desc6ck_get_subcell_latitude(p_desc_k), + desc6ck_get_subcell_longtitude(p_desc_k), + desc6ck_get_subcell_extend_of_latitude(p_desc_k), + desc6ck_get_subcell_extend_of_longtitude(p_desc_k) + ); + } + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvb/si/descs_list.h b/dvb/si/descs_list.h index 5d109cc..f1db53b 100644 --- a/dvb/si/descs_list.h +++ b/dvb/si/descs_list.h @@ -78,6 +78,7 @@ #include #include #include +#include #include #include #include diff --git a/examples/dvb_gen_si.c b/examples/dvb_gen_si.c index b01ce51..1929705 100644 --- a/examples/dvb_gen_si.c +++ b/examples/dvb_gen_si.c @@ -1464,7 +1464,84 @@ static void build_desc6b(uint8_t *desc) { desc6b_set_rds_via_uecp_flag (desc, true); } -/* --- Descriptor 0x6c: cell_list_descriptor */ +/* DVB Descriptor 0x6c: Cell list descriptor */ +static void build_desc6c(uint8_t *desc) { + uint8_t n = 0, k; + uint8_t *cell_n, *subcell_k; + + desc6c_init(desc); + desc_set_length(desc, 255); + + cell_n = desc6c_get_cell(desc, n++); + desc6cn_set_cell_id(cell_n, 1234); + desc6cn_set_cell_latitude(cell_n, 4567); + desc6cn_set_cell_longtitude(cell_n, 5678); + desc6cn_set_cell_extend_of_latitude(cell_n, 123); + desc6cn_set_cell_extend_of_longtitude(cell_n, 345); + desc6cn_set_subcell_info_loop_length(cell_n, 0); + + cell_n = desc6c_get_cell(desc, n++); + desc6cn_set_cell_id(cell_n, 4456); + desc6cn_set_cell_latitude(cell_n, 5567); + desc6cn_set_cell_longtitude(cell_n, 6678); + desc6cn_set_cell_extend_of_latitude(cell_n, 1234); + desc6cn_set_cell_extend_of_longtitude(cell_n, 1234); + desc6cn_set_subcell_info_loop_length(cell_n, 0); + { + k = 0; + desc6cn_set_subcell_info_loop_length(cell_n, 255); + + subcell_k = desc6cn_get_subcell(cell_n, k++); + desc6ck_set_cell_id_extension(subcell_k, 0); + desc6ck_set_subcell_latitude(subcell_k, 0x1122); + desc6ck_set_subcell_longtitude(subcell_k, 0x3344); + desc6ck_set_subcell_extend_of_latitude(subcell_k, 0xf567); + desc6ck_set_subcell_extend_of_longtitude(subcell_k, 0xf89a); + + subcell_k = desc6cn_get_subcell(cell_n, k++); + desc6ck_set_cell_id_extension(subcell_k, 1); + desc6ck_set_subcell_latitude(subcell_k, 0x2233); + desc6ck_set_subcell_longtitude(subcell_k, 0x4455); + desc6ck_set_subcell_extend_of_latitude(subcell_k, 0xf678); + desc6ck_set_subcell_extend_of_longtitude(subcell_k, 0xf9ab); + + subcell_k = desc6cn_get_subcell(cell_n, k++); + desc6ck_set_cell_id_extension(subcell_k, 2); + desc6ck_set_subcell_latitude(subcell_k, 0x2233); + desc6ck_set_subcell_longtitude(subcell_k, 0x4455); + desc6ck_set_subcell_extend_of_latitude(subcell_k, 0xf678); + desc6ck_set_subcell_extend_of_longtitude(subcell_k, 0xf9ab); + + subcell_k = desc6cn_get_subcell(cell_n, k); + desc6cn_set_subcell_info_loop_length(cell_n, subcell_k - cell_n - DESC6C_DATA_SIZE); + } + + cell_n = desc6c_get_cell(desc, n++); + desc6cn_set_cell_id(cell_n, 0xffff); + desc6cn_set_cell_latitude(cell_n, 0xeeee); + desc6cn_set_cell_longtitude(cell_n, 0xdddd); + desc6cn_set_cell_extend_of_latitude(cell_n, 0xf789); + desc6cn_set_cell_extend_of_longtitude(cell_n, 0xfabc); + desc6cn_set_subcell_info_loop_length(cell_n, 0); + { + k = 0; + desc6cn_set_subcell_info_loop_length(cell_n, 255); + + subcell_k = desc6cn_get_subcell(cell_n, k++); + desc6ck_set_cell_id_extension(subcell_k, 0x00); + desc6ck_set_subcell_latitude(subcell_k, 0x1122); + desc6ck_set_subcell_longtitude(subcell_k, 0x3344); + desc6ck_set_subcell_extend_of_latitude(subcell_k, 0xf567); + desc6ck_set_subcell_extend_of_longtitude(subcell_k, 0xf89a); + + subcell_k = desc6cn_get_subcell(cell_n, k); + desc6cn_set_subcell_info_loop_length(cell_n, subcell_k - cell_n - DESC6C_DATA_SIZE); + } + + cell_n = desc6c_get_cell(desc, n); + desc_set_length(desc, cell_n - desc - DESC_HEADER_SIZE); +} + /* --- Descriptor 0x6d: cell_frequency_link_descriptor */ /* --- Descriptor 0x6e: announcement_support_descriptor */ /* --- Descriptor 0x6f: application_signalling_descriptor */ @@ -1777,6 +1854,9 @@ static void generate_nit(void) { desc = descs_get_desc(desc_loop, desc_counter++); build_desc62(desc); + desc = descs_get_desc(desc_loop, desc_counter++); + build_desc6c(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 2e35130..a1c05a3 100644 --- a/examples/dvb_print_si.output.txt +++ b/examples/dvb_print_si.output.txt @@ -40,6 +40,13 @@ new NIT actual networkid=40000 version=1 - desc 62 frequency_list coding_type=2 coding_type_txt=cable frequency=3240000 - desc 62 frequency_list coding_type=2 coding_type_txt=cable frequency=3300000 - desc 62 frequency_list coding_type=2 coding_type_txt=cable frequency=3360000 + - desc 6c cell_list cell_id=1234 cell_latitude=4567 cell_longtitude=5678 cell_extend_of_latitude=123 cell_extend_of_longtitude=345 + - desc 6c cell_list cell_id=4456 cell_latitude=5567 cell_longtitude=6678 cell_extend_of_latitude=1234 cell_extend_of_longtitude=1234 + - cell_list_subcell_info cell_id_extension=0 subcell_latitude=4386 subcell_longtitude=13124 subcell_extend_of_latitude=1383 subcell_extend_of_longtitude=2202 + - cell_list_subcell_info cell_id_extension=1 subcell_latitude=8755 subcell_longtitude=17493 subcell_extend_of_latitude=1656 subcell_extend_of_longtitude=2475 + - 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 * 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 4e6215a..af029cd 100644 --- a/examples/dvb_print_si.output.xml +++ b/examples/dvb_print_si.output.xml @@ -66,6 +66,18 @@ + + + + + + + + + + + + diff --git a/mpeg/psi/descs_print.h b/mpeg/psi/descs_print.h index 1d06cb6..e507104 100644 --- a/mpeg/psi/descs_print.h +++ b/mpeg/psi/descs_print.h @@ -177,6 +177,7 @@ static inline void descl_print(uint8_t *p_descl, uint16_t i_length, CASE_DESC(69) CASE_DESC(6a) CASE_DESC(6b) + CASE_DESC(6c) CASE_DESC(7a) CASE_DESC(7b) CASE_DESC(7c)