From f74006e6c135b82e8c6d2b94c0d1a3ef91548cda Mon Sep 17 00:00:00 2001 From: Georgi Chorbadzhiyski Date: Mon, 10 Oct 2011 15:43:48 +0300 Subject: [PATCH] dvb/si: Add support for BAT (Bouquet Association Table). --- dvb/si.h | 1 + dvb/si/bat.h | 126 ++++++++++++++++++++++++++++++++++++++++ dvb/si/bat_print.h | 114 ++++++++++++++++++++++++++++++++++++ dvb/si_print.h | 1 + examples/dvb_print_si.c | 63 ++++++++++++++++++++ 5 files changed, 305 insertions(+) create mode 100644 dvb/si/bat.h create mode 100644 dvb/si/bat_print.h diff --git a/dvb/si.h b/dvb/si.h index 7d07dad..cd2bd17 100644 --- a/dvb/si.h +++ b/dvb/si.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/dvb/si/bat.h b/dvb/si/bat.h new file mode 100644 index 0000000..f88d46b --- /dev/null +++ b/dvb/si/bat.h @@ -0,0 +1,126 @@ +/***************************************************************************** + * bat.h: ETSI EN 300 468 Bouquet Association Table (BAT) + ***************************************************************************** + * Copyright (C) 2009-2010 VideoLAN + * + * Authors: Christophe Massiot + * 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_BAT_H__ +#define __BITSTREAM_DVB_BAT_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** + * Bouquet Association Table + *****************************************************************************/ +#define BAT_PID 0x11 +#define BAT_TABLE_ID 0x4a +#define BAT_HEADER_SIZE (PSI_HEADER_SIZE_SYNTAX1 + 2) +#define BAT_HEADER2_SIZE 2 +#define BAT_TS_SIZE 6 + +#define bat_set_bouquet_id psi_set_tableidext +#define bat_get_bouquet_id psi_get_tableidext + +static inline void bat_init(uint8_t *p_bat) +{ + psi_init(p_bat, true); + psi_set_tableid(p_bat, BAT_TABLE_ID); + p_bat[8] = 0xf0; +} + +#define bat_set_length nit_set_length +#define bat_set_desclength nit_set_desclength +#define bat_get_desclength nit_get_desclength +#define bat_get_descs nit_get_descs +#define bath_init nith_init +#define bath_set_tslength nith_set_tslength +#define bath_get_tslength nith_get_tslength +#define bat_get_header2 nit_get_header2 +#define batn_init nitn_init +#define batn_set_tsid nitn_set_tsid +#define batn_get_tsid nitn_get_tsid +#define batn_set_onid nitn_set_onid +#define batn_get_onid nitn_get_onid +#define batn_set_desclength nitn_set_desclength +#define batn_get_desclength nitn_get_desclength +#define batn_get_descs nitn_get_descs +#define bat_get_ts nit_get_ts +#define bat_validate_ts nit_validate_ts +#define bat_table_find_ts nit_table_find_ts +#define bat_table_validate nit_table_validate + +static inline bool bat_validate(const uint8_t *p_bat) +{ + uint16_t i_section_size = psi_get_length(p_bat) + PSI_HEADER_SIZE + - PSI_CRC_SIZE; + const uint8_t *p_bat_n; + + if (!psi_get_syntax(p_bat) || psi_get_tableid(p_bat) != BAT_TABLE_ID) + return false; + + if (i_section_size < BAT_HEADER_SIZE + || i_section_size < BAT_HEADER_SIZE + bat_get_desclength(p_bat)) + return false; + + if (!descs_validate(p_bat + 8)) + return false; + + p_bat_n = p_bat + BAT_HEADER_SIZE + bat_get_desclength(p_bat); + + if (bath_get_tslength(p_bat_n) != p_bat + i_section_size - p_bat_n + - BAT_HEADER2_SIZE) + return false; + p_bat_n += BAT_HEADER2_SIZE; + + while (p_bat_n + BAT_TS_SIZE - p_bat <= i_section_size + && p_bat_n + BAT_TS_SIZE + batn_get_desclength(p_bat_n) - p_bat + <= i_section_size) { + if (!descs_validate(p_bat_n + 4)) + return false; + + p_bat_n += BAT_TS_SIZE + batn_get_desclength(p_bat_n); + } + + return (p_bat_n - p_bat == i_section_size); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvb/si/bat_print.h b/dvb/si/bat_print.h new file mode 100644 index 0000000..016c08c --- /dev/null +++ b/dvb/si/bat_print.h @@ -0,0 +1,114 @@ +/***************************************************************************** + * bat_print.h: ETSI EN 300 468 Bouquet Association Table (BAT) (printing) + ***************************************************************************** + * Copyright (C) 2010 VideoLAN + * + * Authors: Christophe Massiot + * 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. + *****************************************************************************/ + +#ifndef __BITSTREAM_DVB_BAT_PRINT_H__ +#define __BITSTREAM_DVB_BAT_PRINT_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** + * Bouquet Association Table + *****************************************************************************/ +static inline void bat_table_print(uint8_t **pp_sections, + f_print pf_print, void *print_opaque, + f_iconv pf_iconv, void *iconv_opaque, + print_type_t i_print_type) +{ + uint8_t i_last_section = psi_table_get_lastsection(pp_sections); + uint8_t i; + + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, "", + psi_table_get_tableid(pp_sections), + psi_table_get_tableidext(pp_sections), + psi_table_get_version(pp_sections), + !psi_table_get_current(pp_sections) ? 0 : 1); + break; + default: + pf_print(print_opaque, "new BAT networkid=%hu version=%hhu%s", + psi_table_get_tableidext(pp_sections), + psi_table_get_version(pp_sections), + !psi_table_get_current(pp_sections) ? " (next)" : ""); + } + + descs_print(bat_get_descs(psi_table_get_section(pp_sections, 0)), + pf_print, print_opaque, pf_iconv, iconv_opaque, i_print_type); + + for (i = 0; i <= i_last_section; i++) { + uint8_t *p_section = psi_table_get_section(pp_sections, i); + uint8_t *p_ts; + int j = 0; + + while ((p_ts = bat_get_ts(p_section, j)) != NULL) { + j++; + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, "", + batn_get_tsid(p_ts), batn_get_onid(p_ts)); + break; + default: + pf_print(print_opaque, " * ts tsid=%hu onid=%hu", + batn_get_tsid(p_ts), batn_get_onid(p_ts)); + } + + descs_print(batn_get_descs(p_ts), pf_print, print_opaque, + pf_iconv, iconv_opaque, i_print_type); + + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + break; + } + } + } + + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + pf_print(print_opaque, "end BAT"); + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvb/si_print.h b/dvb/si_print.h index ac3e975..47948b1 100644 --- a/dvb/si_print.h +++ b/dvb/si_print.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include diff --git a/examples/dvb_print_si.c b/examples/dvb_print_si.c index eb29470..610aa82 100644 --- a/examples/dvb_print_si.c +++ b/examples/dvb_print_si.c @@ -71,6 +71,8 @@ static PSI_TABLE_DECLARE(pp_current_cat_sections); static PSI_TABLE_DECLARE(pp_next_cat_sections); static PSI_TABLE_DECLARE(pp_current_nit_sections); static PSI_TABLE_DECLARE(pp_next_nit_sections); +static PSI_TABLE_DECLARE(pp_current_bat_sections); +static PSI_TABLE_DECLARE(pp_next_bat_sections); static PSI_TABLE_DECLARE(pp_current_sdt_sections); static PSI_TABLE_DECLARE(pp_next_sdt_sections); @@ -468,6 +470,62 @@ static void handle_nit_section(uint16_t i_pid, uint8_t *p_section) handle_nit(); } +/***************************************************************************** + * handle_bat + *****************************************************************************/ +static void handle_bat(void) +{ + if (psi_table_validate(pp_current_bat_sections) && + psi_table_compare(pp_current_bat_sections, pp_next_bat_sections)) { + /* Same version BAT. Shortcut. */ + psi_table_free(pp_next_bat_sections); + psi_table_init(pp_next_bat_sections); + return; + } + + if (!bat_table_validate(pp_next_bat_sections)) { + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + break; + default: + printf("invalid BAT received\n"); + } + psi_table_free( pp_next_bat_sections ); + psi_table_init( pp_next_bat_sections ); + return; + } + + /* Switch tables. */ + psi_table_free(pp_current_bat_sections); + psi_table_copy(pp_current_bat_sections, pp_next_bat_sections); + psi_table_init(pp_next_bat_sections); + + bat_table_print(pp_current_bat_sections, print_wrapper, NULL, + iconv_wrapper, NULL, i_print_type); +} + +static void handle_bat_section(uint16_t i_pid, uint8_t *p_section) +{ + if (i_pid != BAT_PID || !bat_validate(p_section)) { + switch (i_print_type) { + case PRINT_XML: + printf("\n", + i_pid); + break; + default: + printf("invalid BAT section received on PID %hu\n", i_pid); + } + free(p_section); + return; + } + + if (!psi_table_section(pp_next_bat_sections, p_section)) + return; + + handle_bat(); +} + /***************************************************************************** * handle_sdt *****************************************************************************/ @@ -629,6 +687,10 @@ static void handle_section(uint16_t i_pid, uint8_t *p_section) handle_nit_section(i_pid, p_section); break; + case BAT_TABLE_ID: + handle_bat_section(i_pid, p_section); + break; + case SDT_TABLE_ID_ACTUAL: handle_sdt_section(i_pid, p_section); break; @@ -737,6 +799,7 @@ int main(int i_argc, char **ppsz_argv) p_pids[PAT_PID].i_psi_refcount++; p_pids[CAT_PID].i_psi_refcount++; p_pids[NIT_PID].i_psi_refcount++; + p_pids[BAT_PID].i_psi_refcount++; p_pids[SDT_PID].i_psi_refcount++; p_pids[EIT_PID].i_psi_refcount++; p_pids[TDT_PID].i_psi_refcount++;