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; }