From 4b14313e932efd6151b84a3e0bfe1a6b94b6dbe8 Mon Sep 17 00:00:00 2001 From: Georgi Chorbadzhiyski Date: Fri, 7 Oct 2011 04:46:15 +0300 Subject: [PATCH] dvb/si: Add support for descriptor 0x45 (VBI data descriptor). --- README | 1 + TODO | 1 - dvb/si/desc_45.h | 208 +++++++++++++++++++++++++++++++++++++++++ dvb/si/descs_list.h | 1 + examples/dvb_gen_si.c | 61 +++++++++++- mpeg/psi/descs_print.h | 1 + 6 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 dvb/si/desc_45.h diff --git a/README b/README index 7053ed6..1fdd5fa 100644 --- a/README +++ b/README @@ -102,6 +102,7 @@ Supported DVB descriptors * Descriptor 0x41: Service list descriptor * Descriptor 0x43: Satellite delivery system descriptor * Descriptor 0x44: Cable delivery system descriptor + * Descriptor 0x45: VBI data descriptor * Descriptor 0x46: VBI teletext descriptor * Descriptor 0x47: Bouquet name descriptor * Descriptor 0x48: Service descriptor diff --git a/TODO b/TODO index 1286191..7940276 100644 --- a/TODO +++ b/TODO @@ -14,7 +14,6 @@ so if you like something just do it and send a patch. - Descriptor 0x6a: AC-3 descriptor - Add support (parser, generator, example) for these DVB descriptors: - - Descriptor 0x45: VBI data descriptor - Descriptor 0x49: Country availability descriptor - Descriptor 0x4b: NVOD_reference_descriptor - Descriptor 0x4c: time_shifted_service_descriptor diff --git a/dvb/si/desc_45.h b/dvb/si/desc_45.h new file mode 100644 index 0000000..9655d93 --- /dev/null +++ b/dvb/si/desc_45.h @@ -0,0 +1,208 @@ +/***************************************************************************** + * desc_45.h: ETSI EN 300 458 Descriptor 0x45: VBI data 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 458 V1.11.1 (2010-04) (SI in DVB systems) + */ + +#ifndef __BITSTREAM_DVB_DESC_45_H__ +#define __BITSTREAM_DVB_DESC_45_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** + * Descriptor 0x45: VBI data descriptor + *****************************************************************************/ +#define DESC45_HEADER_SIZE DESC_HEADER_SIZE +#define DESC45_DATA_SIZE 2 + +static inline void desc45_init(uint8_t *p_desc) +{ + desc_set_tag(p_desc, 0x45); +} + +static inline void desc45n_set_service_id(uint8_t *p_desc_n, uint8_t i_service_id) +{ + p_desc_n[0] = i_service_id; +} + +static inline uint8_t desc45n_get_service_id(const uint8_t *p_desc_n) +{ + return p_desc_n[0]; +} + +static inline void desc45n_set_data_length(uint8_t *p_desc_n, uint8_t i_length) +{ + p_desc_n[1] = i_length; +} + +static inline uint8_t desc45n_get_data_length(const uint8_t *p_desc_n) +{ + return p_desc_n[1]; +} + +static inline char *desc45_get_service_id_txt(uint8_t i_service_id) +{ + return i_service_id == 0x00 ? "reserved" : + i_service_id == 0x01 ? "EBU teletext" : + i_service_id == 0x02 ? "inverted teletext" : + i_service_id == 0x03 ? "reserved" : + i_service_id == 0x04 ? "VPS" : + i_service_id == 0x05 ? "WSS" : + i_service_id == 0x06 ? "Closed Captioning" : + i_service_id == 0x07 ? "Mono 4:2:2 samples" : "reserved"; +} + +static inline uint8_t desc45n_get_byte(uint8_t *p_desc_n, uint8_t idx) +{ + return p_desc_n[idx + 2]; +} + +static inline void desc45n_set_byte(uint8_t *p_desc_n, uint8_t idx, uint8_t i_byte) +{ + p_desc_n[idx + 2] = i_byte; +} + +static inline bool desc45n_get_field_parity(const uint8_t *p_desc_n, uint8_t idx) +{ + return (p_desc_n[idx + 2] & 0x20) == 0x20; +} + +static inline void desc45n_set_field_parity(uint8_t *p_desc_n, uint8_t idx, bool b_parity) +{ + p_desc_n[idx + 2] = 0xc0 | (b_parity ? (p_desc_n[idx + 2] | 0x20) : (p_desc_n[idx + 2] &~ 0x20)); +} + +static inline uint8_t desc45n_get_line_offset(const uint8_t *p_desc_n, uint8_t idx) +{ + return p_desc_n[idx + 2] & 0x1f; +} + +static inline void desc45n_set_line_offset(uint8_t *p_desc_n, uint8_t idx, uint8_t i_line_offset) +{ + p_desc_n[idx + 2] = 0xc0 | (p_desc_n[idx + 2] & 0x20) | (i_line_offset & 0x1f); +} + +static inline uint8_t *desc45_get_data(uint8_t *p_desc, uint8_t n) +{ + uint8_t *p_desc_n = p_desc + DESC45_HEADER_SIZE; + uint8_t i_desc_size = desc_get_length(p_desc); + + while (n) { + if (p_desc_n + DESC45_DATA_SIZE - p_desc > i_desc_size) + return NULL; + p_desc_n += DESC45_DATA_SIZE + desc45n_get_data_length(p_desc_n); + n--; + } + if (p_desc_n - p_desc > i_desc_size) + return NULL; + return p_desc_n; +} + +static inline bool desc45_validate(const uint8_t *p_desc) +{ + const uint8_t *p_desc_n = p_desc + DESC45_HEADER_SIZE; + int i_desc_size = desc_get_length(p_desc); + while (i_desc_size > 0) + { + uint8_t i_data_sz = DESC45_DATA_SIZE + desc45n_get_data_length(p_desc_n); + i_desc_size -= i_data_sz; + p_desc_n += i_data_sz; + } + return i_desc_size == 0; +} + +static inline void desc45_print(uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + uint8_t j = 0; + uint8_t *p_desc_n; + + if (i_print_type == PRINT_XML) + pf_print(opaque, ""); + + while ((p_desc_n = desc45_get_data(p_desc, j++)) != NULL) { + uint8_t k; + uint8_t i_service_id = desc45n_get_service_id(p_desc_n); + uint8_t i_service_len = desc45n_get_data_length(p_desc_n); + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "", + i_service_id, i_service_len, desc45_get_service_id_txt(i_service_id) + ); + for (k = 0; k < i_service_len; k++) { + if (i_service_id >= 1 && i_service_id <= 7 && i_service_id != 3) + { + pf_print(opaque, + "", + desc45n_get_field_parity(p_desc_n, k), + desc45n_get_line_offset(p_desc_n, k)); + } else { + pf_print(opaque, + "", + desc45n_get_byte(p_desc_n, k)); + } + } + pf_print(opaque, ""); + break; + default: + pf_print(opaque, + " - desc 45 vbi_data service_id=0x%02x length=%u service_txt=\"%s\"", + i_service_id, i_service_len, desc45_get_service_id_txt(i_service_id)); + for (k = 0; k < i_service_len; k++) { + if (i_service_id >= 1 && i_service_id <= 7 && i_service_id != 3) + { + pf_print(opaque, + " - vbi_data field_parity=%u line_offset=%u", + desc45n_get_field_parity(p_desc_n, k), + desc45n_get_line_offset(p_desc_n, k)); + } else { + pf_print(opaque, + " - vbi_data reserved_byte=0x%02x", + desc45n_get_byte(p_desc_n, k)); + } + } + } + } + + if (i_print_type == PRINT_XML) + pf_print(opaque, ""); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvb/si/descs_list.h b/dvb/si/descs_list.h index 8f3c936..3540ecf 100644 --- a/dvb/si/descs_list.h +++ b/dvb/si/descs_list.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/examples/dvb_gen_si.c b/examples/dvb_gen_si.c index 8e25539..5525be9 100644 --- a/examples/dvb_gen_si.c +++ b/examples/dvb_gen_si.c @@ -407,7 +407,63 @@ static void build_desc44(uint8_t *desc) { desc44_set_fecinner (desc, 6); // 8/9 } -/* --- Descriptor 0x45: VBI data descriptor */ +/* DVB Descriptor 0x45: VBI data descriptor */ +static void build_desc45(uint8_t *desc) { + uint8_t k = 0; + uint8_t *data_n; + + desc45_init(desc); + desc_set_length(desc, 255); + + data_n = desc45_get_data(desc, k++); + desc45n_set_service_id (data_n, 0x01); // EBU teletext + desc45n_set_data_length(data_n, 8); // How much bytes are after this + { + uint8_t j, max_j = desc45n_get_data_length(data_n); + for (j = 0; j < max_j; j++) { + desc45n_set_field_parity(data_n, j, (j % 2) == 0); + desc45n_set_line_offset (data_n, j, j); + } + } + + data_n = desc45_get_data(desc, k++); + desc45n_set_service_id (data_n, 0x03); // Reserved + desc45n_set_data_length(data_n, 4); // How much bytes are after this + desc45n_set_byte(data_n, 0, 0x12); + desc45n_set_byte(data_n, 1, 0x34); + desc45n_set_byte(data_n, 2, 0x56); + desc45n_set_byte(data_n, 3, 0x78); + + data_n = desc45_get_data(desc, k++); + desc45n_set_service_id (data_n, 0x04); // VPS + desc45n_set_data_length(data_n, 1); // How much bytes are after this + { + uint8_t j, max_j = desc45n_get_data_length(data_n); + for (j = 0; j < max_j; j++) { + desc45n_set_field_parity(data_n, j, (j % 2) == 2); + desc45n_set_line_offset (data_n, j, j + 10); + } + } + + data_n = desc45_get_data(desc, k++); + desc45n_set_service_id (data_n, 0x05); // WSS + desc45n_set_data_length(data_n, 4); // How much bytes are after this + { + uint8_t j, max_j = desc45n_get_data_length(data_n); + for (j = 0; j < max_j; j++) { + desc45n_set_field_parity(data_n, j, (j % 2) == 1); + desc45n_set_line_offset (data_n, j, j + 20); + } + } + + data_n = desc45_get_data(desc, k++); + desc45n_set_service_id (data_n, 0x06); // Closed Captioning + desc45n_set_data_length(data_n, 0); // How much bytes are after this + + data_n = desc45_get_data(desc, k); + desc_set_length(desc, data_n - desc - DESC45_HEADER_SIZE); +} + /* DVB Descriptor 0x46: VBI teletext descriptor */ static void build_desc46(uint8_t *desc) { uint8_t k = 0; @@ -1681,6 +1737,9 @@ static void generate_pmt(void) { desc = descs_get_desc(desc_loop, desc_counter++); build_desc46(desc); + desc = descs_get_desc(desc_loop, desc_counter++); + build_desc45(desc); + // Finish descriptor generation desc = descs_get_desc(desc_loop, desc_counter); // Get next descriptor pos descs_set_length(desc_loop, desc - desc_loop - DESCS_HEADER_SIZE); diff --git a/mpeg/psi/descs_print.h b/mpeg/psi/descs_print.h index d313d5f..f9f1bbe 100644 --- a/mpeg/psi/descs_print.h +++ b/mpeg/psi/descs_print.h @@ -134,6 +134,7 @@ static inline void descl_print(uint8_t *p_descl, uint16_t i_length, CASE_DESC(42) CASE_DESC(43) CASE_DESC(44) + CASE_DESC(45) CASE_DESC(46) CASE_DESC_ICONV(47) CASE_DESC_ICONV(48)