From 6a24504cc5b5c4c4bd11dffc89209f2e2474b814 Mon Sep 17 00:00:00 2001 From: Christophe Massiot Date: Mon, 6 Aug 2012 21:06:44 +0200 Subject: [PATCH] Enforce consistency naming between tables Some fields in BAT, RST and SIT have been renamed to match the same name (for the exact same purpose) in SDT. DVBlast is not impacted but other applications may have to be changed. BAT: table ID extension is a bouquet ID, not a network ID. Correct handling of EIT (service-specific) and BAT (bouquet-specific) in dvb_print_si. Also free all allocated structures so that we now pass valgrind memcheck. --- dvb/si/bat_print.h | 4 +- dvb/si/eit.h | 8 +- dvb/si/eit_print.h | 25 +++--- dvb/si/rst.h | 4 +- dvb/si/rst_print.h | 8 +- dvb/si/sit.h | 4 +- dvb/si/sit_print.h | 8 +- examples/dvb_gen_si.c | 26 +++--- examples/dvb_print_si.c | 180 ++++++++++++++++++++++++++++++++-------- 9 files changed, 187 insertions(+), 80 deletions(-) diff --git a/dvb/si/bat_print.h b/dvb/si/bat_print.h index 016c08c..2c7ebcf 100644 --- a/dvb/si/bat_print.h +++ b/dvb/si/bat_print.h @@ -52,14 +52,14 @@ static inline void bat_table_print(uint8_t **pp_sections, switch (i_print_type) { case PRINT_XML: - pf_print(print_opaque, "", + 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", + pf_print(print_opaque, "new BAT bouquetid=%hu version=%hhu%s", psi_table_get_tableidext(pp_sections), psi_table_get_version(pp_sections), !psi_table_get_current(pp_sections) ? " (next)" : ""); diff --git a/dvb/si/eit.h b/dvb/si/eit.h index b7f4253..0a49cfd 100644 --- a/dvb/si/eit.h +++ b/dvb/si/eit.h @@ -152,22 +152,22 @@ static inline void eitn_set_duration_bcd(uint8_t *p_eit_n, uint32_t i_duration_b p_eit_n[9] = i_duration_bcd & 0xff; } -static inline uint8_t eitn_get_running_status(const uint8_t *p_eit_n) +static inline uint8_t eitn_get_running(const uint8_t *p_eit_n) { return p_eit_n[10] >> 5; } -static inline void eitn_set_running_status(uint8_t *p_eit_n, uint8_t i_running_status) +static inline void eitn_set_running(uint8_t *p_eit_n, uint8_t i_running_status) { p_eit_n[10] = (p_eit_n[10] & 0x1f) | (i_running_status << 5); } -static inline bool eitn_get_free_CA_mode(const uint8_t *p_eit_n) +static inline bool eitn_get_ca(const uint8_t *p_eit_n) { return (p_eit_n[10] & 0x10) == 0x10; } -static inline void eitn_set_free_CA_mode(uint8_t *p_eit_n, bool b_free_CA_mode) +static inline void eitn_set_ca(uint8_t *p_eit_n, bool b_free_CA_mode) { p_eit_n[10] = b_free_CA_mode ? (p_eit_n[10] | 0x10) : (p_eit_n[10] &~ 0x10); } diff --git a/dvb/si/eit_print.h b/dvb/si/eit_print.h index 5e1ed20..a08b591 100644 --- a/dvb/si/eit_print.h +++ b/dvb/si/eit_print.h @@ -65,30 +65,25 @@ static inline void eit_print(uint8_t *p_eit, case PRINT_XML: pf_print(print_opaque, "", + " current_next=\"%u\" tsid=\"%u\" onid=\"%u\">", i_tid, psz_tid, eit_get_sid(p_eit), psi_get_version(p_eit), !psi_get_current(p_eit) ? 0 : 1, eit_get_tsid(p_eit), - eit_get_onid(p_eit), - eit_get_segment_last_sec_number(p_eit), - eit_get_last_table_id(p_eit) + eit_get_onid(p_eit) ); break; default: pf_print(print_opaque, "new EIT tableid=0x%02x type=%s service_id=%u version=%u%s tsid=%u" - " onid=%u seg_last_sec_number=%u last_table_id=0x%02x", + " onid=%u", i_tid, psz_tid, eit_get_sid(p_eit), psi_get_version(p_eit), !psi_get_current(p_eit) ? " (next)" : "", eit_get_tsid(p_eit), - eit_get_onid(p_eit), - eit_get_segment_last_sec_number(p_eit), - eit_get_last_table_id(p_eit) + eit_get_onid(p_eit) ); } @@ -107,21 +102,21 @@ static inline void eit_print(uint8_t *p_eit, case PRINT_XML: pf_print(print_opaque, "", + " running=\"%d\" free_CA=\"%d\">", eitn_get_event_id(p_event), start_ts, start_str, duration, duration_str, - eitn_get_running_status(p_event), - eitn_get_free_CA_mode(p_event) + eitn_get_running(p_event), + eitn_get_ca(p_event) ); break; default: - pf_print(print_opaque, " * EVENT id=%u start_time=%ld start_time_dec=\"%s\" duration=%u duration_dec=%s running_status=%d free_CA_mode=%d", + pf_print(print_opaque, " * EVENT id=%u start_time=%ld start_time_dec=\"%s\" duration=%u duration_dec=%s running=%d free_CA=%d", eitn_get_event_id(p_event), start_ts, start_str, duration, duration_str, - eitn_get_running_status(p_event), - eitn_get_free_CA_mode(p_event) + eitn_get_running(p_event), + eitn_get_ca(p_event) ); } diff --git a/dvb/si/rst.h b/dvb/si/rst.h index 113c54b..0897815 100644 --- a/dvb/si/rst.h +++ b/dvb/si/rst.h @@ -110,12 +110,12 @@ static inline void rstn_set_event_id(uint8_t *p_rst_n, uint16_t i_event_id) p_rst_n[7] = i_event_id & 0xff; } -static inline uint8_t rstn_get_running_status(const uint8_t *p_rst_n) +static inline uint8_t rstn_get_running(const uint8_t *p_rst_n) { return p_rst_n[8] & 0x07; } -static inline void rstn_set_running_status(uint8_t *p_rst_n, uint8_t i_running_status) +static inline void rstn_set_running(uint8_t *p_rst_n, uint8_t i_running_status) { p_rst_n[8] = 0xf8 | (i_running_status & 0x07); } diff --git a/dvb/si/rst_print.h b/dvb/si/rst_print.h index 0d859f4..7eed4dd 100644 --- a/dvb/si/rst_print.h +++ b/dvb/si/rst_print.h @@ -60,23 +60,23 @@ static inline void rst_print(uint8_t *p_rst, case PRINT_XML: pf_print(print_opaque, "", + " event_id=\"%hu\" running=\"%hu\"/>", rstn_get_tsid(p_rst_n), rstn_get_onid(p_rst_n), rstn_get_service_id(p_rst_n), rstn_get_event_id(p_rst_n), - rstn_get_running_status(p_rst_n) + rstn_get_running(p_rst_n) ); break; default: pf_print(print_opaque, " * status tsid=\"%hu\" onid=\"%hu\" service_id=\"%hu\"" - " event_id=\"%hu\" running_status=\"%hu\"", + " event_id=\"%hu\" running=\"%hu\"", rstn_get_tsid(p_rst_n), rstn_get_onid(p_rst_n), rstn_get_service_id(p_rst_n), rstn_get_event_id(p_rst_n), - rstn_get_running_status(p_rst_n) + rstn_get_running(p_rst_n) ); } } diff --git a/dvb/si/sit.h b/dvb/si/sit.h index ae11716..a275569 100644 --- a/dvb/si/sit.h +++ b/dvb/si/sit.h @@ -99,12 +99,12 @@ static inline void sitn_set_sid(uint8_t *p_sit_n, uint16_t i_sid) p_sit_n[1] = i_sid & 0xff; } -static inline uint8_t sitn_get_running_status(const uint8_t *p_sit_n) +static inline uint8_t sitn_get_running(const uint8_t *p_sit_n) { return (p_sit_n[2] & 0x70) >> 4; } -static inline void sitn_set_running_status(uint8_t *p_sit_n, uint8_t i_running_status) +static inline void sitn_set_running(uint8_t *p_sit_n, uint8_t i_running_status) { p_sit_n[2] = (p_sit_n[2] &~ 0x70) | ((i_running_status & 0x07) << 4); } diff --git a/dvb/si/sit_print.h b/dvb/si/sit_print.h index 68a1cb0..107852c 100644 --- a/dvb/si/sit_print.h +++ b/dvb/si/sit_print.h @@ -66,15 +66,15 @@ static inline void sit_print(uint8_t *p_sit, j++; switch (i_print_type) { case PRINT_XML: - pf_print(print_opaque, "", + pf_print(print_opaque, "", sitn_get_sid(p_service), - sitn_get_running_status(p_service) + sitn_get_running(p_service) ); break; default: - pf_print(print_opaque, " * SERVICE sid=%hu running_status=%u", + pf_print(print_opaque, " * SERVICE sid=%hu running=%u", sitn_get_sid(p_service), - sitn_get_running_status(p_service) + sitn_get_running(p_service) ); } diff --git a/examples/dvb_gen_si.c b/examples/dvb_gen_si.c index c4aa3e4..2ea7bef 100644 --- a/examples/dvb_gen_si.c +++ b/examples/dvb_gen_si.c @@ -2384,8 +2384,8 @@ static void generate_eit(void) { eitn_set_event_id(eit_n, event_id); eitn_set_start_time(eit_n, dvb_time_encode_UTC(ts_0)); eitn_set_duration_bcd(eit_n, dvb_time_encode_duration(86399)); - eitn_set_running_status(eit_n, 2); - eitn_set_free_CA_mode(eit_n, false); + eitn_set_running(eit_n, 2); + eitn_set_ca(eit_n, false); eitn_set_desclength(eit_n, 0); { // Add descriptors to transport_stream_n @@ -2405,8 +2405,8 @@ static void generate_eit(void) { eitn_set_event_id(eit_n, event_id + 100); eitn_set_start_time(eit_n, dvb_time_encode_UTC(ts_1)); eitn_set_duration_bcd(eit_n, dvb_time_encode_duration(3600)); - eitn_set_running_status(eit_n, 1); - eitn_set_free_CA_mode(eit_n, false); + eitn_set_running(eit_n, 1); + eitn_set_ca(eit_n, false); eitn_set_desclength(eit_n, 0); { // Add descriptors to transport_stream_n @@ -2435,8 +2435,8 @@ static void generate_eit(void) { eitn_set_event_id(eit_n, event_id + 200); eitn_set_start_time(eit_n, dvb_time_encode_UTC(ts_2)); eitn_set_duration_bcd(eit_n, dvb_time_encode_duration(7200)); - eitn_set_running_status(eit_n, 0); - eitn_set_free_CA_mode(eit_n, false); + eitn_set_running(eit_n, 0); + eitn_set_ca(eit_n, false); eitn_set_desclength(eit_n, 0); { // Add descriptors to transport_stream_n @@ -2471,8 +2471,8 @@ static void generate_eit(void) { eitn_set_event_id(eit_n, event_id + 300); eitn_set_start_time(eit_n, dvb_time_encode_UTC(ts_2)); eitn_set_duration_bcd(eit_n, dvb_time_encode_duration(7200)); - eitn_set_running_status(eit_n, 4); - eitn_set_free_CA_mode(eit_n, true); + eitn_set_running(eit_n, 4); + eitn_set_ca(eit_n, true); eitn_set_desclength(eit_n, 0); { // Add descriptors to transport_stream_n @@ -2602,7 +2602,7 @@ static void generate_rst(void) { rstn_set_onid(rst_n, onid); rstn_set_service_id(rst_n, sid); rstn_set_event_id(rst_n, event_id); - rstn_set_running_status(rst_n, 1); + rstn_set_running(rst_n, 1); rst_n = rst_get_status(rst, j++); rstn_init(rst_n); @@ -2610,7 +2610,7 @@ static void generate_rst(void) { rstn_set_onid(rst_n, onid + 100); rstn_set_service_id(rst_n, sid + 100); rstn_set_event_id(rst_n, event_id + 100); - rstn_set_running_status(rst_n, 2); + rstn_set_running(rst_n, 2); rst_n = rst_get_status(rst, j++); rstn_init(rst_n); @@ -2618,7 +2618,7 @@ static void generate_rst(void) { rstn_set_onid(rst_n, onid + 200); rstn_set_service_id(rst_n, sid + 200); rstn_set_event_id(rst_n, event_id + 200); - rstn_set_running_status(rst_n, 3); + rstn_set_running(rst_n, 3); // Set correct rst length rst_n = rst_get_status(rst, j); // Get offset of the end of last status @@ -3037,7 +3037,7 @@ static void generate_sit(void) { sit_n = sit_get_service(sit, sit_n_counter++); sitn_init(sit_n); sitn_set_sid(sit_n, sid); - sitn_set_running_status(sit_n, 1); + sitn_set_running(sit_n, 1); sitn_set_desclength(sit_n, 0); { // Add descriptors to transport_stream_n @@ -3062,7 +3062,7 @@ static void generate_sit(void) { sit_n = sit_get_service(sit, sit_n_counter++); sitn_init(sit_n); sitn_set_sid(sit_n, sid + 1000); - sitn_set_running_status(sit_n, 3); + sitn_set_running(sit_n, 3); sitn_set_desclength(sit_n, 0); // Set transport_stream_loop length diff --git a/examples/dvb_print_si.c b/examples/dvb_print_si.c index 469428d..896e79e 100644 --- a/examples/dvb_print_si.c +++ b/examples/dvb_print_si.c @@ -57,15 +57,26 @@ typedef struct ts_pid_t { uint16_t i_psi_buffer_used; } ts_pid_t; +static ts_pid_t p_pids[MAX_PIDS]; + typedef struct sid_t { uint16_t i_sid, i_pmt_pid; uint8_t *p_current_pmt; + PSI_TABLE_DECLARE(pp_eit_sections); } sid_t; -ts_pid_t p_pids[MAX_PIDS]; static sid_t **pp_sids = NULL; static int i_nb_sids = 0; +typedef struct bouquet_t { + uint16_t i_bouquet; + PSI_TABLE_DECLARE(pp_current_bat_sections); + PSI_TABLE_DECLARE(pp_next_bat_sections); +} bouquet_t; + +static bouquet_t **pp_bouquets = NULL; +static int i_nb_bouquets = 0; + static PSI_TABLE_DECLARE(pp_current_pat_sections); static PSI_TABLE_DECLARE(pp_next_pat_sections); static PSI_TABLE_DECLARE(pp_current_cat_sections); @@ -74,8 +85,6 @@ static PSI_TABLE_DECLARE(pp_current_tsdt_sections); static PSI_TABLE_DECLARE(pp_next_tsdt_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); @@ -246,6 +255,7 @@ static void handle_pat(void) pp_sids = realloc(pp_sids, ++i_nb_sids * sizeof(sid_t *)); pp_sids[i_pmt] = p_sid; p_sid->p_current_pmt = NULL; + psi_table_init(p_sid->pp_eit_sections); } else p_sid = pp_sids[i_pmt]; @@ -278,6 +288,8 @@ static void handle_pat(void) pp_sids[i_pmt]->i_sid = 0; free(pp_sids[i_pmt]->p_current_pmt); pp_sids[i_pmt]->p_current_pmt = NULL; + psi_table_free(pp_sids[i]->pp_eit_sections); + psi_table_init(pp_sids[i]->pp_eit_sections); break; } } @@ -477,6 +489,7 @@ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt) p_sid->i_sid = i_sid; p_sid->i_pmt_pid = i_pid; p_sid->p_current_pmt = NULL; + psi_table_init(p_sid->pp_eit_sections); } else { p_sid = pp_sids[i]; if (i_pid != p_sid->i_pmt_pid) { @@ -528,8 +541,8 @@ static void handle_nit(void) default: printf("invalid NIT received\n"); } - psi_table_free( pp_next_nit_sections ); - psi_table_init( pp_next_nit_sections ); + psi_table_free(pp_next_nit_sections); + psi_table_init(pp_next_nit_sections); return; } @@ -567,17 +580,18 @@ static void handle_nit_section(uint16_t i_pid, uint8_t *p_section) /***************************************************************************** * handle_bat *****************************************************************************/ -static void handle_bat(void) +static void handle_bat(bouquet_t *p_bouquet) { - if (psi_table_validate(pp_current_bat_sections) && - psi_table_compare(pp_current_bat_sections, pp_next_bat_sections)) { + if (psi_table_validate(p_bouquet->pp_current_bat_sections) && + psi_table_compare(p_bouquet->pp_current_bat_sections, + p_bouquet->pp_next_bat_sections)) { /* Same version BAT. Shortcut. */ - psi_table_free(pp_next_bat_sections); - psi_table_init(pp_next_bat_sections); + psi_table_free(p_bouquet->pp_next_bat_sections); + psi_table_init(p_bouquet->pp_next_bat_sections); return; } - if (!bat_table_validate(pp_next_bat_sections)) { + if (!bat_table_validate(p_bouquet->pp_next_bat_sections)) { switch (i_print_type) { case PRINT_XML: printf("\n"); @@ -585,23 +599,28 @@ static void handle_bat(void) default: printf("invalid BAT received\n"); } - psi_table_free( pp_next_bat_sections ); - psi_table_init( pp_next_bat_sections ); + psi_table_free(p_bouquet->pp_next_bat_sections); + psi_table_init(p_bouquet->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); + psi_table_free(p_bouquet->pp_current_bat_sections); + psi_table_copy(p_bouquet->pp_current_bat_sections, + p_bouquet->pp_next_bat_sections); + psi_table_init(p_bouquet->pp_next_bat_sections); if (pb_print_table[TABLE_BAT]) - bat_table_print(pp_current_bat_sections, print_wrapper, NULL, + bat_table_print(p_bouquet->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) { + uint16_t i_bouquet; + bouquet_t *p_bouquet; + int i; + if (i_pid != BAT_PID || !bat_validate(p_section)) { switch (i_print_type) { case PRINT_XML: @@ -615,10 +634,24 @@ static void handle_bat_section(uint16_t i_pid, uint8_t *p_section) return; } - if (!psi_table_section(pp_next_bat_sections, p_section)) + i_bouquet = psi_get_tableidext(p_section); + for (i = 0; i < i_nb_bouquets; i++) + if (pp_bouquets[i]->i_bouquet && pp_bouquets[i]->i_bouquet == i_bouquet) + break; + if (i == i_nb_bouquets) { + p_bouquet = malloc(sizeof(bouquet_t)); + pp_bouquets = realloc(pp_bouquets, ++i_nb_bouquets * sizeof(bouquet_t *)); + pp_bouquets[i] = p_bouquet; + p_bouquet->i_bouquet = i_bouquet; + psi_table_init(p_bouquet->pp_current_bat_sections); + psi_table_init(p_bouquet->pp_next_bat_sections); + } else + p_bouquet = pp_bouquets[i]; + + if (!psi_table_section(p_bouquet->pp_next_bat_sections, p_section)) return; - handle_bat(); + handle_bat(p_bouquet); } /***************************************************************************** @@ -681,9 +714,14 @@ static void handle_sdt_section(uint16_t i_pid, uint8_t *p_section) /***************************************************************************** * handle_eit *****************************************************************************/ -static void handle_eit_section(uint16_t i_pid, uint8_t *p_eit) +static void handle_eit_section(uint16_t i_pid, uint8_t *p_section) { - if (i_pid != EIT_PID || !eit_validate(p_eit)) { + uint16_t i_sid; + uint8_t i_section; + sid_t *p_sid; + int i; + + if (i_pid != EIT_PID || !eit_validate(p_section)) { switch (i_print_type) { case PRINT_XML: printf("\n", @@ -692,15 +730,49 @@ static void handle_eit_section(uint16_t i_pid, uint8_t *p_eit) default: printf("invalid EIT section received on PID %hu\n", i_pid); } - free(p_eit); + free(p_section); + return; + } + + i_sid = psi_get_tableidext(p_section); + for (i = 0; i < i_nb_sids; i++) + if (pp_sids[i]->i_sid && pp_sids[i]->i_sid == i_sid) + break; + if (i == i_nb_sids) { + switch (i_print_type) { + case PRINT_XML: + printf("\n", i_sid); + break; + default: + printf("ghost EIT for service %hu\n", i_sid); + } + p_sid = malloc(sizeof(sid_t)); + pp_sids = realloc(pp_sids, ++i_nb_sids * sizeof(sid_t *)); + pp_sids[i] = p_sid; + p_sid->i_sid = i_sid; + p_sid->i_pmt_pid = 0; + p_sid->p_current_pmt = NULL; + psi_table_init(p_sid->pp_eit_sections); + } else + p_sid = pp_sids[i]; + + /* We do not use psi_table_* primitives as the spec allows for holes in + * section numbering, and there is no sure way to know whether you have + * gathered all sections. */ + i_section = psi_get_section(p_section); + if (p_sid->pp_eit_sections[i_section] != NULL && + psi_compare(p_sid->pp_eit_sections[i_section], p_section)) { + /* Identical section. Shortcut. */ + free(p_section); return; } + free(p_sid->pp_eit_sections[i_section]); + p_sid->pp_eit_sections[i_section] = p_section; + if (pb_print_table[TABLE_EIT]) - eit_print(p_eit, print_wrapper, NULL, iconv_wrapper, NULL, + eit_print(p_section, print_wrapper, NULL, iconv_wrapper, NULL, i_print_type); - - free(p_eit); } /***************************************************************************** @@ -896,14 +968,11 @@ static void handle_section(uint16_t i_pid, uint8_t *p_section) handle_sit_section(i_pid, p_section); break; - default: - if (i_table_id == EIT_TABLE_ID_PF_ACTUAL || - (i_table_id >= EIT_TABLE_ID_SCHED_ACTUAL_FIRST && - i_table_id <= EIT_TABLE_ID_SCHED_ACTUAL_LAST)) { - handle_eit_section(i_pid, p_section); - break; - } + case EIT_TABLE_ID_PF_ACTUAL: + handle_eit_section(i_pid, p_section); + break; + default: free( p_section ); break; } @@ -1009,8 +1078,8 @@ int main(int i_argc, char **ppsz_argv) for (i = 0; i < 8192; i++) { p_pids[i].i_last_cc = -1; - psi_assemble_init( &p_pids[i].p_psi_buffer, - &p_pids[i].i_psi_buffer_used ); + psi_assemble_init(&p_pids[i].p_psi_buffer, + &p_pids[i].i_psi_buffer_used); } p_pids[PAT_PID].i_psi_refcount++; @@ -1025,6 +1094,17 @@ int main(int i_argc, char **ppsz_argv) p_pids[DIT_PID].i_psi_refcount++; p_pids[SIT_PID].i_psi_refcount++; + psi_table_init(pp_current_pat_sections); + psi_table_init(pp_next_pat_sections); + psi_table_init(pp_current_cat_sections); + psi_table_init(pp_next_cat_sections); + psi_table_init(pp_current_tsdt_sections); + psi_table_init(pp_next_tsdt_sections); + psi_table_init(pp_current_nit_sections); + psi_table_init(pp_next_nit_sections); + psi_table_init(pp_current_sdt_sections); + psi_table_init(pp_next_sdt_sections); + if (psz_tables != NULL) { char *psz_table = psz_tables; for (i = 0; i < TABLE_END; i++) @@ -1084,5 +1164,37 @@ int main(int i_argc, char **ppsz_argv) break; } + if (iconv_handle != (iconv_t)-1) + iconv_close(iconv_handle); + + psi_table_free(pp_current_pat_sections); + psi_table_free(pp_next_pat_sections); + psi_table_free(pp_current_cat_sections); + psi_table_free(pp_next_cat_sections); + psi_table_free(pp_current_tsdt_sections); + psi_table_free(pp_next_tsdt_sections); + psi_table_free(pp_current_nit_sections); + psi_table_free(pp_next_nit_sections); + psi_table_free(pp_current_sdt_sections); + psi_table_free(pp_next_sdt_sections); + + for (i = 0; i < i_nb_bouquets; i++) { + psi_table_free(pp_bouquets[i]->pp_current_bat_sections); + psi_table_free(pp_bouquets[i]->pp_next_bat_sections); + free(pp_bouquets[i]); + } + free(pp_bouquets); + + for (i = 0; i < i_nb_sids; i++) { + psi_table_free(pp_sids[i]->pp_eit_sections); + free(pp_sids[i]->p_current_pmt); + free(pp_sids[i]); + } + free(pp_sids); + + for (i = 0; i < 8192; i++) + psi_assemble_reset(&p_pids[i].p_psi_buffer, + &p_pids[i].i_psi_buffer_used); + return EXIT_SUCCESS; }