diff --git a/common.h b/common.h index 2766e1a..b183922 100644 --- a/common.h +++ b/common.h @@ -21,6 +21,11 @@ extern "C" { #endif +typedef enum print_type_t { + PRINT_TEXT, + PRINT_XML +} print_type_t; + typedef void (*f_print)(void *, const char *, ...); typedef char * (*f_iconv)(void *, const char *, char *, size_t); diff --git a/dvb/si.h b/dvb/si.h index c3bf3e3..3932d7c 100644 --- a/dvb/si.h +++ b/dvb/si.h @@ -275,7 +275,8 @@ static inline bool desc40_validate(const uint8_t *p_desc) static inline void desc40_print(const uint8_t *p_desc, f_print pf_print, void *print_opaque, - f_iconv pf_iconv, void *iconv_opaque) + f_iconv pf_iconv, void *iconv_opaque, + print_type_t i_print_type) { uint8_t i_network_name_length; const uint8_t *p_network_name = desc40_get_networkname(p_desc, @@ -284,7 +285,15 @@ static inline void desc40_print(const uint8_t *p_desc, i_network_name_length, pf_iconv, iconv_opaque); - pf_print(print_opaque, " - desc 40 networkname=\"%s\"", psz_network_name); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, "", + psz_network_name); + break; + default: + pf_print(print_opaque, " - desc 40 networkname=\"%s\"", + psz_network_name); + } free(psz_network_name); } @@ -344,7 +353,7 @@ static inline bool desc43_validate(const uint8_t *p_desc) } static inline void desc43_print(const uint8_t *p_desc, f_print pf_print, - void *opaque) + void *opaque, print_type_t i_print_type) { unsigned int i_pos = desc43_get_position(p_desc); uint8_t i_polarization = desc43_get_polarization(p_desc); @@ -373,20 +382,39 @@ static inline void desc43_print(const uint8_t *p_desc, f_print pf_print, case 0x3: psz_modulation = "16-qam"; break; } - if (desc43_get_dvbs2(p_desc)) - pf_print(opaque, - " - desc 43 dvb-s2 frequency=%u kHz %s pos=%u.%u%c rolloff=0.%hhu modulation=%s symbolrate=%u fecinner=%s", - desc43_get_frequency(p_desc), psz_polarization, i_pos / 10, i_pos % 10, - desc43_get_east(p_desc) ? 'E' : 'W', i_rolloff, psz_modulation, - desc43_get_symbolrate(p_desc), - dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); - else - pf_print(opaque, - " - desc 43 dvb-s frequency=%u%s pos=%u.%u%c modulation=%s symbolrate=%u fecinner=%s", - desc43_get_frequency(p_desc), psz_polarization, i_pos / 10, i_pos % 10, - desc43_get_east(p_desc) ? 'E' : 'W', psz_modulation, - desc43_get_symbolrate(p_desc), - dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + switch (i_print_type) { + case PRINT_XML: + if (desc43_get_dvbs2(p_desc)) + pf_print(opaque, + "", + desc43_get_frequency(p_desc), psz_polarization, + i_pos / 10, i_pos % 10, desc43_get_east(p_desc) ? 'E' : 'W', + i_rolloff, psz_modulation, desc43_get_symbolrate(p_desc), + dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + else + pf_print(opaque, + "", + desc43_get_frequency(p_desc), psz_polarization, + i_pos / 10, i_pos % 10, desc43_get_east(p_desc) ? 'E' : 'W', + psz_modulation, desc43_get_symbolrate(p_desc), + dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + break; + default: + if (desc43_get_dvbs2(p_desc)) + pf_print(opaque, + " - desc 43 dvb-s2 frequency=%u%s pos=%u.%u%c rolloff=0.%hhu modulation=%s symbolrate=%u fecinner=%s", + desc43_get_frequency(p_desc), psz_polarization, + i_pos / 10, i_pos % 10, desc43_get_east(p_desc) ? 'E' : 'W', + i_rolloff, psz_modulation, desc43_get_symbolrate(p_desc), + dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + else + pf_print(opaque, + " - desc 43 dvb-s frequency=%u%s pos=%u.%u%c modulation=%s symbolrate=%u fecinner=%s", + desc43_get_frequency(p_desc), psz_polarization, + i_pos / 10, i_pos % 10, desc43_get_east(p_desc) ? 'E' : 'W', + psz_modulation, desc43_get_symbolrate(p_desc), + dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + } } /***************************************************************************** @@ -418,7 +446,7 @@ static inline bool desc44_validate(const uint8_t *p_desc) } static inline void desc44_print(const uint8_t *p_desc, f_print pf_print, - void *opaque) + void *opaque, print_type_t i_print_type) { uint8_t i_fecouter = desc44_get_fecouter(p_desc); const char *psz_fecouter = "reserved"; @@ -440,11 +468,21 @@ static inline void desc44_print(const uint8_t *p_desc, f_print pf_print, case 0x5: psz_modulation = "256-qam"; break; } - pf_print(opaque, - " - desc 44 dvb-c frequency=%"PRIu64" Hz fecouter=0x%s modulation=0x%s symbolrate=%u fecinner=%s", - desc44_get_frequency(p_desc), psz_fecouter, psz_modulation, - desc44_get_symbolrate(p_desc), - dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "", + desc44_get_frequency(p_desc), psz_fecouter, psz_modulation, + desc44_get_symbolrate(p_desc), + dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + break; + default: + pf_print(opaque, + " - desc 44 dvb-c frequency=%"PRIu64" Hz fecouter=0x%s modulation=0x%s symbolrate=%u fecinner=%s", + desc44_get_frequency(p_desc), psz_fecouter, psz_modulation, + desc44_get_symbolrate(p_desc), + dvb_delivery_get_fec(desc43_get_fecinner(p_desc))); + } } /***************************************************************************** @@ -509,19 +547,31 @@ static inline bool desc46_validate(const uint8_t *p_desc) } static inline void desc46_print(uint8_t *p_desc, f_print pf_print, - void *opaque) + void *opaque, print_type_t i_print_type) { uint8_t j = 0; uint8_t *p_desc_n; while ((p_desc_n = desc46_get_language(p_desc, j)) != NULL) { j++; - pf_print(opaque, - " - desc %x telx language=%3.3s type=0x%hhx mag=%hhu page=%hhu", - desc_get_tag(p_desc), (const char *)desc46n_get_code(p_desc_n), - desc46n_get_teletexttype(p_desc_n), - desc46n_get_teletextmagazine(p_desc_n), - desc46n_get_teletextpage(p_desc_n)); + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "<%s language=%3.3s type=\"0x%hhx\" mag=\"%hhu\" page=\"%hhu\"/>", + desc_get_tag(p_desc) == 0x46 ? "VBI_TELX_DESC" : "TELX_DESC", + (const char *)desc46n_get_code(p_desc_n), + desc46n_get_teletexttype(p_desc_n), + desc46n_get_teletextmagazine(p_desc_n), + desc46n_get_teletextpage(p_desc_n)); + break; + default: + pf_print(opaque, + " - desc %x telx language=%3.3s type=0x%hhx mag=%hhu page=%hhu", + desc_get_tag(p_desc), (const char *)desc46n_get_code(p_desc_n), + desc46n_get_teletexttype(p_desc_n), + desc46n_get_teletextmagazine(p_desc_n), + desc46n_get_teletextpage(p_desc_n)); + } } } @@ -598,7 +648,8 @@ static inline bool desc48_validate(const uint8_t *p_desc) static inline void desc48_print(const uint8_t *p_desc, f_print pf_print, void *print_opaque, - f_iconv pf_iconv, void *iconv_opaque) + f_iconv pf_iconv, void *iconv_opaque, + print_type_t i_print_type) { uint8_t i_provider_length, i_service_length; const uint8_t *p_provider = desc48_get_provider(p_desc, &i_provider_length); @@ -607,9 +658,17 @@ static inline void desc48_print(const uint8_t *p_desc, pf_iconv, iconv_opaque); char *psz_service = dvb_string_get(p_service, i_service_length, pf_iconv, iconv_opaque); - pf_print(print_opaque, - " - desc 48 type=0x%hhx provider=\"%s\" service=\"%s\"", - desc48_get_type(p_desc), psz_provider, psz_service); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, + "", + desc48_get_type(p_desc), psz_provider, psz_service); + break; + default: + pf_print(print_opaque, + " - desc 48 type=0x%hhx provider=\"%s\" service=\"%s\"", + desc48_get_type(p_desc), psz_provider, psz_service); + } free(psz_provider); free(psz_service); } @@ -699,19 +758,30 @@ static inline bool desc59_validate(const uint8_t *p_desc) } static inline void desc59_print(uint8_t *p_desc, f_print pf_print, - void *opaque) + void *opaque, print_type_t i_print_type) { uint8_t j = 0; uint8_t *p_desc_n; while ((p_desc_n = desc59_get_language(p_desc, j)) != NULL) { j++; - pf_print(opaque, - " - desc 59 dvbs language=%3.3s type=0x%hhx composition=%hu ancillary=%hu", - (const char *)desc59n_get_code(p_desc_n), - desc59n_get_subtitlingtype(p_desc_n), - desc59n_get_compositionpage(p_desc_n), - desc59n_get_ancillarypage(p_desc_n)); + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "", + desc5a_get_frequency(p_desc), i_bandwidth, + desc5a_get_priority(p_desc) ? "HP" : "LP", + desc5a_get_timeslicing(p_desc) ? 1 : 0, + desc5a_get_mpefec(p_desc) ? 1 : 0, psz_constellation, + psz_hierarchy, + dvb_delivery_get_fec(desc5a_get_coderatehp(p_desc)), + b_hierarchy ? dvb_delivery_get_fec(desc5a_get_coderatehp(p_desc)) : "not_applicable", + psz_guard, psz_transmission, + desc5a_get_otherfrequency(p_desc) ? 1 : 0); + break; + default: + pf_print(opaque, + " - desc 5a dvb-t frequency=%"PRIu64" Hz bandwidth=%u MHz priority=%s%s%s constellation=%s hierarchy=%s coderatehp=%s%s%s guard=%s transmission=%s%s", + desc5a_get_frequency(p_desc), i_bandwidth, + desc5a_get_priority(p_desc) ? "HP" : "LP", + desc5a_get_timeslicing(p_desc) ? " timeslicing" : "", + desc5a_get_mpefec(p_desc) ? " mpefec" : "", psz_constellation, + psz_hierarchy, + dvb_delivery_get_fec(desc5a_get_coderatehp(p_desc)), + b_hierarchy ? "coderatelp=" : "", + b_hierarchy ? dvb_delivery_get_fec(desc5a_get_coderatehp(p_desc)) : "", + psz_guard, psz_transmission, + desc5a_get_otherfrequency(p_desc) ? " otherfrequency" : ""); + } } /***************************************************************************** @@ -875,9 +961,15 @@ static inline bool desc6a_validate(const uint8_t *p_desc) } static inline void desc6a_print(const uint8_t *p_desc, f_print pf_print, - void *opaque) -{ - pf_print(opaque, " - desc 6a ac3"); + void *opaque, print_type_t i_print_type) +{ + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, ""); + break; + default: + pf_print(opaque, " - desc 6a ac3"); + } } /***************************************************************************** diff --git a/dvb/si_print.h b/dvb/si_print.h index 7db44ae..66161d4 100644 --- a/dvb/si_print.h +++ b/dvb/si_print.h @@ -34,7 +34,8 @@ extern "C" *****************************************************************************/ static inline void descs_print(uint8_t *p_descs, f_print pf_print, void *print_opaque, - f_iconv pf_iconv, void *iconv_opaque) + f_iconv pf_iconv, void *iconv_opaque, + print_type_t i_print_type) { uint16_t j = 0; uint8_t *p_desc; @@ -43,86 +44,48 @@ static inline void descs_print(uint8_t *p_descs, uint8_t i_tag = desc_get_tag(p_desc); j++; - /* I am not proud of this */ + desc_print_begin(p_desc, pf_print, print_opaque, i_print_type); + switch (i_tag) { - case 0x05: - if (desc05_validate(p_desc)) - desc05_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x09: - if (desc09_validate(p_desc)) - desc09_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x0a: - if (desc0a_validate(p_desc)) - desc0a_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x40: - if (desc40_validate(p_desc)) - desc40_print(p_desc, pf_print, print_opaque, - pf_iconv, iconv_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x43: - if (desc43_validate(p_desc)) - desc43_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x44: - if (desc44_validate(p_desc)) - desc44_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x46: - if (desc46_validate(p_desc)) - desc46_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x48: - if (desc48_validate(p_desc)) - desc48_print(p_desc, pf_print, print_opaque, - pf_iconv, iconv_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x56: - if (desc56_validate(p_desc)) - desc56_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x59: - if (desc59_validate(p_desc)) - desc59_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); - break; - case 0x5a: - if (desc5a_validate(p_desc)) - desc5a_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); +#define CASE_DESC(id) \ + case 0x##id: \ + if (desc##id##_validate(p_desc)) \ + desc##id##_print(p_desc, pf_print, print_opaque, \ + i_print_type); \ + else \ + desc_print_error(p_desc, pf_print, print_opaque, \ + i_print_type); \ break; - case 0x6a: - if (desc6a_validate(p_desc)) - desc6a_print(p_desc, pf_print, print_opaque); - else - pf_print(print_opaque, "desc %hhx invalid", i_tag); + +#define CASE_DESC_ICONV(id) \ + case 0x##id: \ + if (desc##id##_validate(p_desc)) \ + desc##id##_print(p_desc, pf_print, print_opaque, \ + pf_iconv, iconv_opaque, i_print_type); \ + else \ + desc_print_error(p_desc, pf_print, print_opaque, \ + i_print_type); \ break; + + CASE_DESC(05) + CASE_DESC(09) + CASE_DESC(0a) + CASE_DESC_ICONV(40) + CASE_DESC(43) + CASE_DESC(44) + CASE_DESC(46) + CASE_DESC_ICONV(48) + CASE_DESC(56) + CASE_DESC(59) + CASE_DESC(5a) + CASE_DESC(6a) + default: - desc_print(p_desc, pf_print, print_opaque); + desc_print(p_desc, pf_print, print_opaque, i_print_type); break; } + + desc_print_end(p_desc, pf_print, print_opaque, i_print_type); } } @@ -131,19 +94,31 @@ static inline void descs_print(uint8_t *p_descs, *****************************************************************************/ static inline void nit_table_print(uint8_t **pp_sections, f_print pf_print, void *print_opaque, - f_iconv pf_iconv, void *iconv_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; - pf_print(print_opaque, "new NIT %s networkid=%hu version=%hhu%s", - psi_table_get_tableid(pp_sections) == NIT_TABLE_ID_ACTUAL ? - "actual" : "other", - psi_table_get_tableidext(pp_sections), - psi_table_get_version(pp_sections), - !psi_table_get_current(pp_sections) ? " (next)" : ""); + 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 NIT %s networkid=%hu version=%hhu%s", + psi_table_get_tableid(pp_sections) == NIT_TABLE_ID_ACTUAL ? + "actual" : "other", + psi_table_get_tableidext(pp_sections), + psi_table_get_version(pp_sections), + !psi_table_get_current(pp_sections) ? " (next)" : ""); + } + descs_print(nit_get_descs(psi_table_get_section(pp_sections, 0)), - pf_print, print_opaque, pf_iconv, iconv_opaque); + 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); @@ -152,14 +127,36 @@ static inline void nit_table_print(uint8_t **pp_sections, while ((p_ts = nit_get_ts(p_section, j)) != NULL) { j++; - pf_print(print_opaque, " * ts tsid=%hu onid=%hu", - nitn_get_tsid(p_ts), nitn_get_onid(p_ts)); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, "", + nitn_get_tsid(p_ts), nitn_get_onid(p_ts)); + break; + default: + pf_print(print_opaque, " * ts tsid=%hu onid=%hu", + nitn_get_tsid(p_ts), nitn_get_onid(p_ts)); + } + descs_print(nitn_get_descs(p_ts), pf_print, print_opaque, - pf_iconv, iconv_opaque); + pf_iconv, iconv_opaque, i_print_type); + + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + break; + } } } - pf_print(print_opaque, "end NIT"); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + pf_print(print_opaque, "end NIT"); + } } /***************************************************************************** @@ -167,18 +164,30 @@ static inline void nit_table_print(uint8_t **pp_sections, *****************************************************************************/ static inline void sdt_table_print(uint8_t **pp_sections, f_print pf_print, void *print_opaque, - f_iconv pf_iconv, void *iconv_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; - pf_print(print_opaque, "new SDT %s tsid=%hu version=%hhu%s onid=%hu", - psi_table_get_tableid(pp_sections) == SDT_TABLE_ID_ACTUAL ? - "actual" : "other", - psi_table_get_tableidext(pp_sections), - psi_table_get_version(pp_sections), - !psi_table_get_current(pp_sections) ? " (next)" : "", - sdt_get_onid(psi_table_get_section(pp_sections, 0))); + 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, + sdt_get_onid(psi_table_get_section(pp_sections, 0))); + break; + default: + pf_print(print_opaque, "new SDT %s tsid=%hu version=%hhu%s onid=%hu", + psi_table_get_tableid(pp_sections) == SDT_TABLE_ID_ACTUAL ? + "actual" : "other", + psi_table_get_tableidext(pp_sections), + psi_table_get_version(pp_sections), + !psi_table_get_current(pp_sections) ? " (next)" : "", + sdt_get_onid(psi_table_get_section(pp_sections, 0))); + } for (i = 0; i <= i_last_section; i++) { uint8_t *p_section = psi_table_get_section(pp_sections, i); @@ -187,18 +196,44 @@ static inline void sdt_table_print(uint8_t **pp_sections, while ((p_service = sdt_get_service(p_section, j)) != NULL) { j++; - pf_print(print_opaque, " * service sid=%hu eit%s%s running=%hhu%s", - sdtn_get_sid(p_service), - sdtn_get_eitschedule(p_service) ? " schedule" : "", - sdtn_get_eitpresent(p_service) ? " present" : "", - sdtn_get_running(p_service), - sdtn_get_ca(p_service) ? " scrambled" : ""); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, "", + sdtn_get_sid(p_service), + sdtn_get_eitschedule(p_service) ? 1 : 0, + sdtn_get_eitpresent(p_service) ? 1 : 0, + sdtn_get_running(p_service), + sdtn_get_ca(p_service) ? 1 : 0); + break; + default: + pf_print(print_opaque, " * service sid=%hu eit%s%s running=%hhu%s", + sdtn_get_sid(p_service), + sdtn_get_eitschedule(p_service) ? " schedule" : "", + sdtn_get_eitpresent(p_service) ? " present" : "", + sdtn_get_running(p_service), + sdtn_get_ca(p_service) ? " scrambled" : ""); + } + descs_print(sdtn_get_descs(p_service), pf_print, print_opaque, - pf_iconv, iconv_opaque); + pf_iconv, iconv_opaque, i_print_type); + + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + break; + } } } - pf_print(print_opaque, "end SDT"); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + pf_print(print_opaque, "end SDT"); + } } #ifdef __cplusplus diff --git a/examples/dvb_print_si.c b/examples/dvb_print_si.c index 9551d4b..2db0c2c 100644 --- a/examples/dvb_print_si.c +++ b/examples/dvb_print_si.c @@ -62,6 +62,7 @@ static PSI_TABLE_DECLARE(pp_next_sdt_sections); static const char *psz_native_encoding = "UTF-8"; static const char *psz_current_encoding = ""; static iconv_t iconv_handle = (iconv_t)-1; +static print_type_t i_print_type = PRINT_TEXT; /***************************************************************************** * print_wrapper @@ -146,7 +147,13 @@ static void handle_pat(void) } if (!pat_table_validate(pp_next_pat_sections)) { - printf("invalid PAT received\n"); + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + break; + default: + printf("invalid PAT received\n"); + } psi_table_free(pp_next_pat_sections); psi_table_init(pp_next_pat_sections); return; @@ -170,7 +177,7 @@ static void handle_pat(void) if (i_sid == 0) { if (i_pid != NIT_PID) - printf( + fprintf(stderr, "NIT is carried on PID %hu which isn't DVB compliant\n", i_pid); continue; /* NIT */ @@ -237,13 +244,19 @@ static void handle_pat(void) psi_table_free(pp_old_pat_sections); } - pat_table_print( pp_current_pat_sections, print_wrapper, NULL ); + pat_table_print(pp_current_pat_sections, print_wrapper, NULL, i_print_type); } static void handle_pat_section(uint16_t i_pid, uint8_t *p_section) { if (i_pid != PAT_PID || !pat_validate(p_section)) { - printf("invalid PAT section received on PID %hu\n", i_pid); + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + break; + default: + printf("invalid PAT section received on PID %hu\n", i_pid); + } free(p_section); return; } @@ -265,7 +278,14 @@ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt) /* we do this before checking the service ID */ if (!pmt_validate(p_pmt)) { - printf("invalid PMT section received on PID %hu\n", i_pid); + switch (i_print_type) { + case PRINT_XML: + printf("\n", + i_pid); + break; + default: + printf("invalid PMT section received on PID %hu\n", i_pid); + } free(p_pmt); return; } @@ -275,7 +295,15 @@ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt) break; if (i == i_nb_sids) { - printf("ghost PMT for service %hu carried on PID %hu\n", i_sid, i_pid); + switch (i_print_type) { + case PRINT_XML: + printf("\n", + i_sid, i_pid); + break; + default: + printf("ghost PMT for service %hu carried on PID %hu\n", i_sid, + i_pid); + } p_sid = malloc(sizeof(sid_t)); pp_sids = realloc(pp_sids, ++i_nb_sids * sizeof(sid_t *)); pp_sids[i] = p_sid; @@ -284,9 +312,17 @@ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt) p_sid->p_current_pmt = NULL; } else { p_sid = pp_sids[i]; - if (i_pid != p_sid->i_pmt_pid) - printf("ghost PMT for service %hu carried on PID %hu\n", i_sid, - i_pid); + if (i_pid != p_sid->i_pmt_pid) { + switch (i_print_type) { + case PRINT_XML: + printf("\n", + i_sid, i_pid); + break; + default: + printf("ghost PMT for service %hu carried on PID %hu\n", i_sid, + i_pid); + } + } } if (p_sid->p_current_pmt != NULL && @@ -299,7 +335,7 @@ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt) free(p_sid->p_current_pmt); p_sid->p_current_pmt = p_pmt; - pmt_print(p_pmt, print_wrapper, NULL, iconv_wrapper, NULL); + pmt_print(p_pmt, print_wrapper, NULL, iconv_wrapper, NULL, i_print_type); } /***************************************************************************** @@ -317,7 +353,13 @@ static void handle_nit(void) } if (!nit_table_validate(pp_next_nit_sections)) { - printf("invalid NIT received\n"); + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + break; + default: + printf("invalid NIT received\n"); + } psi_table_free( pp_next_nit_sections ); psi_table_init( pp_next_nit_sections ); return; @@ -329,13 +371,20 @@ static void handle_nit(void) psi_table_init(pp_next_nit_sections); nit_table_print(pp_current_nit_sections, print_wrapper, NULL, - iconv_wrapper, NULL); + iconv_wrapper, NULL, i_print_type); } static void handle_nit_section(uint16_t i_pid, uint8_t *p_section) { if (i_pid != NIT_PID || !nit_validate(p_section)) { - printf("invalid NIT section received on PID %hu\n", i_pid); + switch (i_print_type) { + case PRINT_XML: + printf("\n", + i_pid); + break; + default: + printf("invalid NIT section received on PID %hu\n", i_pid); + } free(p_section); return; } @@ -361,7 +410,13 @@ static void handle_sdt(void) } if (!sdt_table_validate(pp_next_sdt_sections)) { - printf("invalid SDT received\n"); + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + break; + default: + printf("invalid SDT received\n"); + } psi_table_free(pp_next_sdt_sections); psi_table_init(pp_next_sdt_sections); return; @@ -373,13 +428,20 @@ static void handle_sdt(void) psi_table_init(pp_next_sdt_sections); sdt_table_print(pp_current_sdt_sections, print_wrapper, NULL, - iconv_wrapper, NULL); + iconv_wrapper, NULL, i_print_type); } static void handle_sdt_section(uint16_t i_pid, uint8_t *p_section) { if (i_pid != SDT_PID || !sdt_validate(p_section)) { - printf("invalid SDT section received on PID %hu\n", i_pid); + switch (i_print_type) { + case PRINT_XML: + printf("\n", + i_pid); + break; + default: + printf("invalid SDT section received on PID %hu\n", i_pid); + } free(p_section); return; } @@ -396,7 +458,14 @@ static void handle_sdt_section(uint16_t i_pid, uint8_t *p_section) static void handle_eit_section(uint16_t i_pid, uint8_t *p_eit) { if (i_pid != EIT_PID || !eit_validate(p_eit)) { - printf("invalid EIT section received on PID %hu\n", i_pid); + switch (i_print_type) { + case PRINT_XML: + printf("\n", + i_pid); + break; + default: + printf("invalid EIT section received on PID %hu\n", i_pid); + } free(p_eit); return; } @@ -412,7 +481,13 @@ static void handle_section(uint16_t i_pid, uint8_t *p_section) uint8_t i_table_id = psi_get_tableid(p_section); if (!psi_validate(p_section)) { - printf("invalid section on PID %hu\n", i_pid); + switch (i_print_type) { + case PRINT_XML: + printf("\n", i_pid); + break; + default: + printf("invalid section on PID %hu\n", i_pid); + } free(p_section); return; } @@ -491,15 +566,30 @@ static void handle_psi_packet(uint8_t *p_ts) /***************************************************************************** * Main loop *****************************************************************************/ +static void usage(const char *psz) +{ + fprintf(stderr, "usage: %s [-x xml] < [> ]\n", psz); + exit(EXIT_FAILURE); +} + int main(int i_argc, char **ppsz_argv) { int i; if (ppsz_argv[1] != NULL && - (!strcmp(ppsz_argv[1], "-h") || !strcmp(ppsz_argv[1], "--help"))) { - fprintf(stderr, "usage: %s < [> ]\n", - ppsz_argv[0]); - return EXIT_FAILURE; + (!strcmp(ppsz_argv[1], "-h") || !strcmp(ppsz_argv[1], "--help"))) + usage(ppsz_argv[0]); + + if (ppsz_argv[1] != NULL && + (!strcmp(ppsz_argv[1], "-x") || !strcmp(ppsz_argv[1], "--print"))) { + if (ppsz_argv[2] == NULL) + usage(ppsz_argv[0]); + if (!strcmp(ppsz_argv[2], "text")) + i_print_type = PRINT_TEXT; + else if (!strcmp(ppsz_argv[2], "xml")) + i_print_type = PRINT_XML; + else + usage(ppsz_argv[0]); } memset(p_pids, 0, sizeof(p_pids)); @@ -515,13 +605,28 @@ int main(int i_argc, char **ppsz_argv) p_pids[SDT_PID].i_psi_refcount++; p_pids[EIT_PID].i_psi_refcount++; + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + printf("\n"); + break; + default: + break; + } + while (!feof(stdin) && !ferror(stdin)) { uint8_t p_ts[TS_SIZE]; size_t i_ret = fread(p_ts, sizeof(p_ts), 1, stdin); if (i_ret != 1) continue; - if (!ts_validate(p_ts)) - printf("invalid TS packet\n"); - else { + if (!ts_validate(p_ts)) { + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + break; + default: + printf("invalid TS packet\n"); + } + } else { uint16_t i_pid = ts_get_pid(p_ts); ts_pid_t *p_pid = &p_pids[i_pid]; if (p_pid->i_psi_refcount) @@ -530,5 +635,13 @@ int main(int i_argc, char **ppsz_argv) } } + switch (i_print_type) { + case PRINT_XML: + printf("\n"); + break; + default: + break; + } + return EXIT_SUCCESS; } diff --git a/mpeg/psi.h b/mpeg/psi.h index 93d2553..a5dafe8 100644 --- a/mpeg/psi.h +++ b/mpeg/psi.h @@ -54,10 +54,63 @@ static inline uint8_t desc_get_length(const uint8_t *p_desc) return p_desc[1]; } -static inline void desc_print(const uint8_t *p_desc, f_print pf_print, - void *opaque) +static inline void desc_print_begin(const uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + + switch (i_print_type) { + case PRINT_XML: + { + uint8_t i, i_length = desc_get_length(p_desc); + char psz_value[2 * i_length + 1]; + + for (i = 0; i < i_length; i++) + sprintf(psz_value + 2 * i, "%2.2hhx", p_desc[2 + i]); + psz_value[2 * i] = '\0'; + + pf_print(opaque, "", + desc_get_tag(p_desc), psz_value); + break; + } + default: + break; + } +} + +static inline void desc_print_end(const uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, ""); + break; + default: + break; + } +} + +static inline void desc_print_error(const uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) { - pf_print(opaque, " - desc %2.2hhx unknown", desc_get_tag(p_desc)); + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, ""); + break; + default: + pf_print(opaque, "desc %2.2hhx invalid", desc_get_tag(p_desc)); + } +} + +static inline void desc_print(const uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, ""); + break; + default: + pf_print(opaque, " - desc %2.2hhx unknown", desc_get_tag(p_desc)); + } } /***************************************************************************** @@ -90,10 +143,17 @@ static inline bool desc05_validate(const uint8_t *p_desc) } static inline void desc05_print(const uint8_t *p_desc, f_print pf_print, - void *opaque) -{ - pf_print(opaque, " - desc 05 identifier=%4.4s", - desc05_get_identifier(p_desc)); + void *opaque, print_type_t i_print_type) +{ + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, "", + desc05_get_identifier(p_desc)); + break; + default: + pf_print(opaque, " - desc 05 identifier=%4.4s", + desc05_get_identifier(p_desc)); + } } /***************************************************************************** @@ -117,10 +177,17 @@ static inline bool desc09_validate(const uint8_t *p_desc) } static inline void desc09_print(const uint8_t *p_desc, f_print pf_print, - void *opaque) -{ - pf_print(opaque, " - desc 09 sysid=0x%hx pid=%hu", - desc09_get_sysid(p_desc), desc09_get_pid(p_desc)); + void *opaque, print_type_t i_print_type) +{ + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, "", + desc09_get_sysid(p_desc), desc09_get_pid(p_desc)); + break; + default: + pf_print(opaque, " - desc 09 sysid=0x%hx pid=%hu", + desc09_get_sysid(p_desc), desc09_get_pid(p_desc)); + } } /***************************************************************************** @@ -171,16 +238,24 @@ static inline bool desc0a_validate(const uint8_t *p_desc) } static inline void desc0a_print(uint8_t *p_desc, f_print pf_print, - void *opaque) + void *opaque, print_type_t i_print_type) { uint8_t j = 0; uint8_t *p_desc_n; while ((p_desc_n = desc0a_get_language(p_desc, j)) != NULL) { j++; - pf_print(opaque, " - desc 0a language=%3.3s audiotype=0x%hhx", - (const char *)desc0an_get_code(p_desc_n), - desc0an_get_audiotype(p_desc_n)); + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, "", + (const char *)desc0an_get_code(p_desc_n), + desc0an_get_audiotype(p_desc_n)); + break; + default: + pf_print(opaque, " - desc 0a language=%3.3s audiotype=0x%hhx", + (const char *)desc0an_get_code(p_desc_n), + desc0an_get_audiotype(p_desc_n)); + } } } @@ -836,15 +911,24 @@ static inline bool pat_table_validate(uint8_t **pp_sections) } static inline void pat_table_print(uint8_t **pp_sections, f_print pf_print, - void *opaque) + void *opaque, print_type_t i_print_type) { uint8_t i_last_section = psi_table_get_lastsection(pp_sections); uint8_t i; - pf_print(opaque, "new PAT tsid=%hu version=%hhu%s", - psi_table_get_tableidext(pp_sections), - psi_table_get_version(pp_sections), - !psi_table_get_current(pp_sections) ? " (next)" : ""); + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, "", + psi_table_get_tableidext(pp_sections), + psi_table_get_version(pp_sections), + !psi_table_get_current(pp_sections) ? 0 : 1); + break; + default: + pf_print(opaque, "new PAT tsid=%hu version=%hhu%s", + psi_table_get_tableidext(pp_sections), + psi_table_get_version(pp_sections), + !psi_table_get_current(pp_sections) ? " (next)" : ""); + } for (i = 0; i <= i_last_section; i++) { uint8_t *p_section = psi_table_get_section(pp_sections, i); @@ -855,15 +939,29 @@ static inline void pat_table_print(uint8_t **pp_sections, f_print pf_print, uint16_t i_program = patn_get_program(p_program); uint16_t i_pid = patn_get_pid(p_program); j++; - if (i_program == 0) - pf_print(opaque, " * NIT pid=%hu", i_pid); - else - pf_print(opaque, " * program number=%hu pid=%hu", + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, "", i_program, i_pid); + break; + default: + if (i_program == 0) + pf_print(opaque, " * NIT pid=%hu", i_pid); + else + pf_print(opaque, " * program number=%hu pid=%hu", + i_program, i_pid); + } } } - pf_print(opaque, "end PAT"); + + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, ""); + break; + default: + pf_print(opaque, "end PAT"); + } } /***************************************************************************** diff --git a/mpeg/psi_print.h b/mpeg/psi_print.h index 48cf255..2f482a2 100644 --- a/mpeg/psi_print.h +++ b/mpeg/psi_print.h @@ -36,27 +36,60 @@ extern "C" *****************************************************************************/ static inline void pmt_print(uint8_t *p_pmt, f_print pf_print, void *print_opaque, - f_iconv pf_iconv, void *iconv_opaque) + f_iconv pf_iconv, void *iconv_opaque, + print_type_t i_print_type) { uint8_t *p_es; uint8_t j = 0; - pf_print(print_opaque, "new PMT program=%hu version=%hhu%s pcrpid=%hu", - pmt_get_program(p_pmt), psi_get_version(p_pmt), - !psi_get_current(p_pmt) ? " (next)" : "", - pmt_get_pcrpid(p_pmt)); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, "", + pmt_get_program(p_pmt), psi_get_version(p_pmt), + !psi_get_current(p_pmt) ? 0 : 1, + pmt_get_pcrpid(p_pmt)); + break; + default: + pf_print(print_opaque, "new PMT program=%hu version=%hhu%s pcrpid=%hu", + pmt_get_program(p_pmt), psi_get_version(p_pmt), + !psi_get_current(p_pmt) ? " (next)" : "", + pmt_get_pcrpid(p_pmt)); + } + descs_print(pmt_get_descs(p_pmt), pf_print, print_opaque, - pf_iconv, iconv_opaque); + pf_iconv, iconv_opaque, i_print_type); while ((p_es = pmt_get_es(p_pmt, j)) != NULL) { j++; - pf_print(print_opaque, " * ES pid=%hu streamtype=0x%hx", pmtn_get_pid(p_es), - pmtn_get_streamtype(p_es)); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, "", pmtn_get_pid(p_es), + pmtn_get_streamtype(p_es)); + break; + default: + pf_print(print_opaque, " * ES pid=%hu streamtype=0x%hx", pmtn_get_pid(p_es), + pmtn_get_streamtype(p_es)); + } + descs_print(pmtn_get_descs(p_es), pf_print, print_opaque, - pf_iconv, iconv_opaque); + pf_iconv, iconv_opaque, i_print_type); + + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + break; + } } - pf_print(print_opaque, "end PMT"); + switch (i_print_type) { + case PRINT_XML: + pf_print(print_opaque, ""); + break; + default: + pf_print(print_opaque, "end PMT"); + } } #ifdef __cplusplus