Commit 0b8f8669 authored by Christophe Massiot's avatar Christophe Massiot

* mpeg/psi.h, dvb/si.h: Add descXX_validate() functions. * mpeg/psi_print.h:...

* mpeg/psi.h, dvb/si.h: Add descXX_validate() functions. * mpeg/psi_print.h: Validate descriptors before accessing them. * mpeg/psi.h: Avoid duplicate copies of the CRC32 table. * ALL: Make sure we return booleans. * dvb/si.h: Add support for DVB character sets. * dvb/si.h: Add content delivery descriptors 0x43, 0x44 and 0x5a. * dvb/si.h: Add VBI teletext descriptor 0x46. * examples/dvb_print_si.c: Add support for charset conversion via iconv.
parent 3df65446
...@@ -22,6 +22,7 @@ extern "C" ...@@ -22,6 +22,7 @@ extern "C"
#endif #endif
typedef void (*f_print)(void *, const char *, ...); typedef void (*f_print)(void *, const char *, ...);
typedef char * (*f_iconv)(void *, const char *, char *, size_t);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -30,6 +30,164 @@ extern "C" ...@@ -30,6 +30,164 @@ extern "C"
{ {
#endif #endif
/*****************************************************************************
* DVB BCD
*****************************************************************************/
static inline unsigned int dvb_bcd_get(const uint8_t *p_bcd, uint8_t i_width)
{
unsigned int i_result = 0;
while (i_width >= 8) {
i_result *= 10;
i_result += (*p_bcd) >> 4;
i_result *= 10;
i_result += (*p_bcd) & 0xf;
i_width -= 8;
p_bcd++;
}
if (i_width == 4) {
i_result *= 10;
i_result += (*p_bcd) >> 4;
}
return i_result;
}
/*****************************************************************************
* DVB string
*****************************************************************************/
static const char *ppsz_dvb_encodings[] = {
/* 0x00 - 0x0f */
"", "ISO_8859-5", "ISO_8859-6", "ISO_8859-7", "ISO_8859-8",
"ISO_8859-9", "ISO_8859-10", "ISO_8859-11", "", "ISO_8859-13",
"ISO_8859-14", "ISO_8859-15", "", "", "", "",
/* 0x10 - 0x1f */
"", "UTF-16", "KSC5601-1987", "GB2312", "BIG-5", "UTF-8",
"", "", "", "", "", "", "", "", "", "", NULL
};
static const char *ppsz_dvb_encodings10[] = {
"", "ISO_8859-1", "ISO_8859-2", "ISO_8859-3", "ISO_8859-4",
"ISO_8859-5", "ISO_8859-6", "ISO_8859-7", "ISO_8859-8", "ISO_8859-9",
"ISO_8859-10", "ISO_8859-11", "", "ISO_8859-13", "ISO_8859-14",
"ISO_8859-15", NULL
};
static inline const char *dvb_string_get_encoding(const uint8_t **pp_string,
size_t *pi_length)
{
uint8_t i_first;
if (!*pi_length) return NULL;
i_first = (*pp_string)[0];
if (!i_first) return NULL;
if (i_first >= 0x20) return "ISO_8859-1";
(*pp_string)++;
(*pi_length)--;
if (i_first == 0x10 && *pi_length >= 2) {
uint8_t i_second = (*pp_string)[0];
uint8_t i_third = (*pp_string)[1];
(*pp_string) += 2;
(*pi_length) -= 2;
if (i_second != 0x0 || i_third == 0 || i_third >= 0x10)
return NULL;
return ppsz_dvb_encodings10[i_third];
}
if (i_first == 0x1f && *pi_length >= 1) {
/* no info on these encodings, skip */
(*pp_string)++;
(*pi_length)--;
return NULL;
}
return ppsz_dvb_encodings[i_first];
}
static inline uint8_t *dvb_string_set(const uint8_t *p_string, size_t i_length,
const char *psz_encoding,
size_t *pi_out_length)
{
int i;
if (!strcmp(psz_encoding, "ISO_8859-9")) {
*pi_out_length = i_length;
return strdup(p_string);
}
for (i = 0; ppsz_dvb_encodings[i] != NULL; i++) {
if (!strcasecmp(psz_encoding, ppsz_dvb_encodings[i])) {
uint8_t *p_encoded = malloc(i_length + 1);
*pi_out_length = i_length + 1;
p_encoded[0] = i;
memcpy(p_encoded + 1, p_string, i_length);
return p_encoded;
}
}
for (i = 0; ppsz_dvb_encodings10[i] != NULL; i++) {
if (!strcasecmp(psz_encoding, ppsz_dvb_encodings10[i])) {
uint8_t *p_encoded = malloc(i_length + 3);
*pi_out_length = i_length + 3;
p_encoded[0] = 0x10;
p_encoded[1] = 0x0;
p_encoded[2] = i;
memcpy(p_encoded + 3, p_string, i_length);
return p_encoded;
}
}
*pi_out_length = 0;
return NULL;
}
/* simpler API because this one doesn't output to multibyte charsets */
static inline char *dvb_string_get(const uint8_t *p_string, size_t i_length,
f_iconv pf_iconv, void *iconv_opaque)
{
if (i_length) {
const char *psz_encoding = dvb_string_get_encoding(&p_string,
&i_length);
if (!*psz_encoding || !i_length) {
/* try one-byte charset */
char *psz_string = malloc(i_length + 1);
memcpy(psz_string, p_string, i_length);
psz_string[i_length] = '\0';
return psz_string;
}
return pf_iconv(iconv_opaque, psz_encoding,
p_string, i_length);
}
return strdup("");
}
/*****************************************************************************
* DVB delivery systems
*****************************************************************************/
static inline const char *dvb_delivery_get_fec(uint8_t i_fec)
{
switch (i_fec) {
case 0x0: return "undefined";
case 0x1: return "1/2";
case 0x2: return "2/3";
case 0x3: return "3/4";
case 0x4: return "5/6";
case 0x5: return "7/8";
case 0x6: return "8/9";
case 0x7: return "3/5";
case 0x8: return "4/5";
case 0x9: return "9/10";
case 0xf: return "none";
default: return "reserved";
}
}
/***************************************************************************** /*****************************************************************************
* Descriptor 0x40: Network name descriptor * Descriptor 0x40: Network name descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -41,139 +199,361 @@ static inline void desc40_init(uint8_t *p_desc) ...@@ -41,139 +199,361 @@ static inline void desc40_init(uint8_t *p_desc)
} }
static inline void desc40_set_networkname(uint8_t *p_desc, static inline void desc40_set_networkname(uint8_t *p_desc,
const char *psz_network_name) const uint8_t *p_network_name,
uint8_t i_length)
{ {
uint8_t i_length = strlen(psz_network_name);
desc_set_length(p_desc, i_length); desc_set_length(p_desc, i_length);
memcpy(p_desc + 2, psz_network_name, i_length); memcpy(p_desc + 2, p_network_name, i_length);
} }
static inline void desc40_get_networkname(const uint8_t *p_desc, static inline const uint8_t *desc40_get_networkname(const uint8_t *p_desc,
char *psz_network_name) uint8_t *pi_length)
{ {
uint8_t i_length = desc_get_length(p_desc); *pi_length = desc_get_length(p_desc);
memcpy(psz_network_name, p_desc + 2, i_length); return p_desc + 2;
psz_network_name[i_length] = '\0'; }
static inline bool desc40_validate(const uint8_t *p_desc)
{
return true;
}
static inline void desc40_print(const uint8_t *p_desc,
f_print pf_print, void *print_opaque,
f_iconv pf_iconv, void *iconv_opaque)
{
uint8_t i_network_name_length;
const uint8_t *p_network_name = desc40_get_networkname(p_desc,
&i_network_name_length);
char *psz_network_name = dvb_string_get(p_network_name,
i_network_name_length,
pf_iconv, iconv_opaque);
pf_print(print_opaque, " - desc 40 networkname=\"%s\"", psz_network_name);
free(psz_network_name);
} }
static inline void desc40_print(const uint8_t *p_desc, f_print pf_print, /*****************************************************************************
* Descriptor 0x43: Satellite delivery system descriptor
*****************************************************************************/
#define DESC43_HEADER_SIZE (DESC_HEADER_SIZE + 11)
static inline uint32_t desc43_get_frequency(const uint8_t *p_desc)
{
return dvb_bcd_get(p_desc + 2, 32) * 10; /* kHz */
}
static inline unsigned int desc43_get_position(const uint8_t *p_desc)
{
return dvb_bcd_get(p_desc + 6, 16); /* 10th degree */
}
static inline bool desc43_get_east(const uint8_t *p_desc)
{
return !!(p_desc[8] & 0x80);
}
static inline uint8_t desc43_get_polarization(const uint8_t *p_desc)
{
return (p_desc[8] & 0x60) >> 5;
}
static inline uint8_t desc43_get_rolloff(const uint8_t *p_desc)
{
return (p_desc[8] & 0x18) >> 3;
}
static inline bool desc43_get_dvbs2(const uint8_t *p_desc)
{
return !!(p_desc[8] & 0x4);
}
static inline bool desc43_get_modulation(const uint8_t *p_desc)
{
return p_desc[8] & 0x3;
}
static inline unsigned int desc43_get_symbolrate(const uint8_t *p_desc)
{
return dvb_bcd_get(p_desc + 9, 28) * 100; /* sy/s */
}
static inline uint8_t desc43_get_fecinner(const uint8_t *p_desc)
{
return p_desc[12] & 0xf;
}
static inline bool desc43_validate(const uint8_t *p_desc)
{
return desc_get_length(p_desc) >= DESC43_HEADER_SIZE - DESC_HEADER_SIZE;
}
static inline void desc43_print(const uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
DESC_DECLARE_STRING1(psz_network_name); unsigned int i_pos = desc43_get_position(p_desc);
desc40_get_networkname(p_desc, psz_network_name); uint8_t i_polarization = desc43_get_polarization(p_desc);
pf_print(opaque, " - desc 40 networkname=%s", psz_network_name); const char *psz_polarization = "";;
uint8_t i_rolloff = desc43_get_rolloff(p_desc);
uint8_t i_modulation = desc43_get_modulation(p_desc);
const char *psz_modulation = "";
switch (i_polarization) {
case 0x0: psz_polarization = "H"; break;
case 0x1: psz_polarization = "V"; break;
case 0x2: psz_polarization = "L"; break;
case 0x3: psz_polarization = "R"; break;
}
switch (i_rolloff) {
case 0x0: i_rolloff = 35; break;
case 0x1: i_rolloff = 25; break;
case 0x2: i_rolloff = 20; break;
}
switch (i_modulation) {
case 0x0: psz_modulation = "auto"; break;
case 0x1: psz_modulation = "qpsk"; break;
case 0x2: psz_modulation = "8psk"; break;
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)));
} }
/***************************************************************************** /*****************************************************************************
* Descriptor 0x48: Service descriptor * Descriptor 0x44: Cable delivery system descriptor
*****************************************************************************/ *****************************************************************************/
#define DESC48_HEADER_SIZE 3 #define DESC44_HEADER_SIZE (DESC_HEADER_SIZE + 11)
static inline uint8_t desc48_get_type(const uint8_t *p_desc) static inline uint64_t desc44_get_frequency(const uint8_t *p_desc)
{ {
return p_desc[2]; return (uint64_t)dvb_bcd_get(p_desc + 2, 32) * 100; /* Hz */
} }
static inline void desc48_get_provider(const uint8_t *p_desc, static inline uint8_t desc44_get_fecouter(const uint8_t *p_desc)
char *psz_provider)
{ {
const uint8_t *p = p_desc + 3; return p_desc[7] & 0xf;
memcpy(psz_provider, p + 1, *p);
psz_provider[*p] = '\0';
} }
static inline void desc48_get_service(const uint8_t *p_desc, static inline uint8_t desc44_get_modulation(const uint8_t *p_desc)
char *psz_service)
{ {
const uint8_t *p = p_desc + 4 + p_desc[3]; return p_desc[8];
memcpy(psz_service, p + 1, *p);
psz_service[*p] = '\0';
} }
static inline void desc48_print(const uint8_t *p_desc, f_print pf_print, #define desc44_get_symbolrate desc43_get_symbolrate
#define desc44_get_fecinner desc43_get_fecinner
static inline bool desc44_validate(const uint8_t *p_desc)
{
return desc_get_length(p_desc) >= DESC44_HEADER_SIZE - DESC_HEADER_SIZE;
}
static inline void desc44_print(const uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
DESC_DECLARE_STRING1(psz_provider); uint8_t i_fecouter = desc44_get_fecouter(p_desc);
DESC_DECLARE_STRING1(psz_service); const char *psz_fecouter = "reserved";
desc48_get_provider(p_desc, psz_provider); uint8_t i_modulation = desc44_get_modulation(p_desc);
desc48_get_service(p_desc, psz_service); const char *psz_modulation = "reserved";
pf_print(opaque, " - desc 48 provider=%s service=%s", psz_provider,
psz_service); switch (i_fecouter) {
case 0x0: psz_fecouter = "undefined"; break;
case 0x1: psz_fecouter = "none"; break;
case 0x2: psz_fecouter = "rs(204/188)"; break;
}
switch (i_modulation) {
case 0x0: psz_modulation = "undefined"; break;
case 0x1: psz_modulation = "16-qam"; break;
case 0x2: psz_modulation = "32-qam"; break;
case 0x3: psz_modulation = "64-qam"; break;
case 0x4: psz_modulation = "128-qam"; break;
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)));
} }
/***************************************************************************** /*****************************************************************************
* Descriptor 0x56: Teletext descriptor * Descriptor 0x46: VBI teletext descriptor
*****************************************************************************/ *****************************************************************************/
#define DESC56_HEADER_SIZE DESC_HEADER_SIZE #define DESC46_HEADER_SIZE DESC_HEADER_SIZE
#define DESC56_LANGUAGE_SIZE 5 #define DESC46_LANGUAGE_SIZE 5
static inline void desc56_init(uint8_t *p_desc) static inline void desc46_init(uint8_t *p_desc)
{ {
desc_set_tag(p_desc, 0x56); desc_set_tag(p_desc, 0x46);
} }
static inline uint8_t *desc56_get_language(uint8_t *p_desc, uint8_t n) static inline uint8_t *desc46_get_language(uint8_t *p_desc, uint8_t n)
{ {
uint8_t *p_desc_n = p_desc + DESC56_HEADER_SIZE + n * DESC56_LANGUAGE_SIZE; uint8_t *p_desc_n = p_desc + DESC46_HEADER_SIZE + n * DESC46_LANGUAGE_SIZE;
if (p_desc_n + DESC56_LANGUAGE_SIZE - p_desc if (p_desc_n + DESC46_LANGUAGE_SIZE - p_desc
> desc_get_length(p_desc) + DESC56_HEADER_SIZE) > desc_get_length(p_desc) + DESC46_HEADER_SIZE)
return NULL; return NULL;
return p_desc_n; return p_desc_n;
} }
#define desc56n_set_code desc0an_set_code #define desc46n_set_code desc0an_set_code
#define desc56n_get_code desc0an_get_code #define desc46n_get_code desc0an_get_code
static inline void desc56n_set_teletexttype(uint8_t *p_desc_n, uint8_t i_type) static inline void desc46n_set_teletexttype(uint8_t *p_desc_n, uint8_t i_type)
{ {
p_desc_n[3] &= ~0xfc; p_desc_n[3] &= ~0xfc;
p_desc_n[3] |= (i_type << 3) & 0xfc; p_desc_n[3] |= (i_type << 3) & 0xfc;
} }
static inline uint8_t desc56n_get_teletexttype(const uint8_t *p_desc_n) static inline uint8_t desc46n_get_teletexttype(const uint8_t *p_desc_n)
{ {
return p_desc_n[3] >> 3; return p_desc_n[3] >> 3;
} }
static inline void desc56n_set_teletextmagazine(uint8_t *p_desc_n, static inline void desc46n_set_teletextmagazine(uint8_t *p_desc_n,
uint8_t i_magazine) uint8_t i_magazine)
{ {
p_desc_n[3] &= ~0x3; p_desc_n[3] &= ~0x3;
p_desc_n[3] |= (i_magazine & 0x3); p_desc_n[3] |= (i_magazine & 0x3);
} }
static inline uint8_t desc56n_get_teletextmagazine(const uint8_t *p_desc_n) static inline uint8_t desc46n_get_teletextmagazine(const uint8_t *p_desc_n)
{ {
return p_desc_n[3] & 0x3; return p_desc_n[3] & 0x3;
} }
static inline void desc56n_set_teletextpage(uint8_t *p_desc_n, uint8_t i_page) static inline void desc46n_set_teletextpage(uint8_t *p_desc_n, uint8_t i_page)
{ {
p_desc_n[4] = i_page; p_desc_n[4] = i_page;
} }
static inline uint8_t desc56n_get_teletextpage(const uint8_t *p_desc_n) static inline uint8_t desc46n_get_teletextpage(const uint8_t *p_desc_n)
{ {
return p_desc_n[4]; return p_desc_n[4];
} }
static inline void desc56_print(uint8_t *p_desc, f_print pf_print, static inline bool desc46_validate(const uint8_t *p_desc)
{
return !(desc_get_length(p_desc) % DESC46_LANGUAGE_SIZE);
}
static inline void desc46_print(uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
uint8_t j = 0; uint8_t j = 0;
uint8_t *p_desc_n; uint8_t *p_desc_n;
while ((p_desc_n = desc56_get_language(p_desc, j)) != NULL) { while ((p_desc_n = desc46_get_language(p_desc, j)) != NULL) {
j++; j++;
pf_print(opaque, pf_print(opaque,
" - desc 56 telx language=%3.3s type=0x%hhx mag=%hhu page=%hhu", " - desc %x telx language=%3.3s type=0x%hhx mag=%hhu page=%hhu",
(const char *)desc56n_get_code(p_desc_n), desc_get_tag(p_desc), (const char *)desc46n_get_code(p_desc_n),
desc56n_get_teletexttype(p_desc_n), desc46n_get_teletexttype(p_desc_n),
desc56n_get_teletextmagazine(p_desc_n), desc46n_get_teletextmagazine(p_desc_n),
desc56n_get_teletextpage(p_desc_n)); desc46n_get_teletextpage(p_desc_n));
} }
} }
/*****************************************************************************
* Descriptor 0x48: Service descriptor
*****************************************************************************/
#define DESC48_HEADER_SIZE (DESC_HEADER_SIZE + 1)
static inline uint8_t desc48_get_type(const uint8_t *p_desc)
{
return p_desc[2];
}
static inline const uint8_t *desc48_get_provider(const uint8_t *p_desc,
uint8_t *pi_length)
{
const uint8_t *p = p_desc + DESC48_HEADER_SIZE;
*pi_length = p[0];
return p + 1;
}
static inline uint8_t *desc48_get_service(const uint8_t *p_desc,
uint8_t *pi_length)
{
const uint8_t *p = p_desc + DESC48_HEADER_SIZE + 1 + p_desc[3];
*pi_length = p[0];
return p + 1;
}
static inline bool desc48_validate(const uint8_t *p_desc)
{
uint8_t i_length = desc_get_length(p_desc);
const uint8_t *p = p_desc + DESC48_HEADER_SIZE;
p += *p + 1;
if (DESC48_HEADER_SIZE + 2 > i_length + DESC_HEADER_SIZE ||
p + 1 - p_desc > i_length + DESC_HEADER_SIZE)
return false;
p += *p + 1;
if (p - p_desc > i_length + DESC_HEADER_SIZE)
return false;
return true;
}
static inline void desc48_print(const uint8_t *p_desc,
f_print pf_print, void *print_opaque,
f_iconv pf_iconv, void *iconv_opaque)
{
uint8_t i_provider_length, i_service_length;
const uint8_t *p_provider = desc48_get_provider(p_desc, &i_provider_length);
const uint8_t *p_service = desc48_get_service(p_desc, &i_service_length);
char *psz_provider = dvb_string_get(p_provider, i_provider_length,
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);
free(psz_provider);
free(psz_service);
}
/*****************************************************************************
* Descriptor 0x56: Teletext descriptor
*****************************************************************************/
#define DESC56_HEADER_SIZE DESC46_HEADER_SIZE
#define DESC56_LANGUAGE_SIZE DESC46_LANGUAGE_SIZE
static inline void desc56_init(uint8_t *p_desc)
{
desc_set_tag(p_desc, 0x56);
}
#define desc56_get_language desc46_get_language
#define desc56n_set_code desc46n_set_code
#define desc56n_get_code desc46n_get_code
#define desc56n_set_teletexttype desc46n_set_teletexttype
#define desc56n_get_teletexttype desc46n_get_teletexttype
#define desc56n_set_teletextmagazine desc46n_set_teletextmagazine
#define desc56n_get_teletextmagazine desc46n_get_teletextmagazine
#define desc56n_set_teletextpage desc46n_set_teletextpage
#define desc56n_get_teletextpage desc46n_get_teletextpage
#define desc56_validate desc46_validate
#define desc56_print desc46_print
/***************************************************************************** /*****************************************************************************
* Descriptor 0x59: Subtitling descriptor * Descriptor 0x59: Subtitling descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -230,6 +610,11 @@ static inline uint16_t desc59n_get_ancillarypage(const uint8_t *p_desc_n) ...@@ -230,6 +610,11 @@ static inline uint16_t desc59n_get_ancillarypage(const uint8_t *p_desc_n)
return (p_desc_n[6] << 8) | p_desc_n[7]; return (p_desc_n[6] << 8) | p_desc_n[7];
} }
static inline bool desc59_validate(const uint8_t *p_desc)
{
return !(desc_get_length(p_desc) % DESC59_LANGUAGE_SIZE);
}
static inline void desc59_print(uint8_t *p_desc, f_print pf_print, static inline void desc59_print(uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
...@@ -247,6 +632,145 @@ static inline void desc59_print(uint8_t *p_desc, f_print pf_print, ...@@ -247,6 +632,145 @@ static inline void desc59_print(uint8_t *p_desc, f_print pf_print,
} }
} }
/*****************************************************************************
* Descriptor 0x5a: Terrestrial delivery system descriptor
*****************************************************************************/
#define DESC5A_HEADER_SIZE (DESC_HEADER_SIZE + 11)
static inline uint64_t desc5a_get_frequency(const uint8_t *p_desc)
{
return (((uint64_t)p_desc[2] << 24) | (p_desc[3] << 16) | (p_desc[4] << 8)
| p_desc[5]) * 10; /* Hz */
}
static inline uint8_t desc5a_get_bandwidth(const uint8_t *p_desc)
{
return p_desc[6] >> 5;
}
static inline bool desc5a_get_priority(const uint8_t *p_desc)
{
return !!((p_desc[6] >> 4) & 0x1);
}
/* ! inverted logic ! */
static inline bool desc5a_get_timeslicing(const uint8_t *p_desc)
{
return !((p_desc[6] >> 3) & 0x1);
}
/* ! inverted logic ! */
static inline bool desc5a_get_mpefec(const uint8_t *p_desc)
{
return !((p_desc[6] >> 2) & 0x1);
}
static inline uint8_t desc5a_get_constellation(const uint8_t *p_desc)
{
return p_desc[7] >> 6;
}
static inline uint8_t desc5a_get_hierarchy(const uint8_t *p_desc)
{
return (p_desc[7] >> 3) & 0x7;
}
static inline uint8_t desc5a_get_coderatehp(const uint8_t *p_desc)
{
return p_desc[7] & 0x7;
}
static inline uint8_t desc5a_get_coderatelp(const uint8_t *p_desc)
{
return p_desc[8] >> 5;
}
static inline uint8_t desc5a_get_guard(const uint8_t *p_desc)
{
return (p_desc[8] >> 3) & 0x3;
}
static inline uint8_t desc5a_get_transmission(const uint8_t *p_desc)
{
return (p_desc[8] >> 1) & 0x3;
}
static inline bool desc5a_get_otherfrequency(const uint8_t *p_desc)
{
return !!(p_desc[8] & 0x1);
}
static inline bool desc5a_validate(const uint8_t *p_desc)
{
return desc_get_length(p_desc) >= DESC5A_HEADER_SIZE - DESC_HEADER_SIZE;
}
static inline void desc5a_print(const uint8_t *p_desc, f_print pf_print,
void *opaque)
{
uint8_t i_bandwidth = desc5a_get_bandwidth(p_desc);
uint8_t i_constellation = desc5a_get_constellation(p_desc);
const char *psz_constellation = "reserved";
uint8_t i_hierarchy = desc5a_get_hierarchy(p_desc);
const char *psz_hierarchy = "";
bool b_hierarchy = !!(i_hierarchy & 0x3);
uint8_t i_guard = desc5a_get_guard(p_desc);
const char *psz_guard = "";
uint8_t i_transmission = desc5a_get_transmission(p_desc);
const char *psz_transmission = "reserved";
switch (i_bandwidth) {
case 0x0: i_bandwidth = 8; break;
case 0x1: i_bandwidth = 7; break;
case 0x2: i_bandwidth = 6; break;
case 0x3: i_bandwidth = 5; break;
default: i_bandwidth = 0; break;
}
switch (i_constellation) {
case 0x0: psz_constellation = "QPSK"; break;
case 0x1: psz_constellation = "16-qam"; break;
case 0x2: psz_constellation = "64-qam"; break;
}
switch (i_hierarchy) {
case 0x0: psz_hierarchy = "none"; break;
case 0x1: psz_hierarchy = "1"; break;
case 0x2: psz_hierarchy = "2"; break;
case 0x3: psz_hierarchy = "4"; break;
case 0x4: psz_hierarchy = "none+in-depth"; break;
case 0x5: psz_hierarchy = "1+in-depth"; break;
case 0x6: psz_hierarchy = "2+in-depth"; break;
case 0x7: psz_hierarchy = "4+in-depth"; break;
}
switch (i_guard) {
case 0x0: psz_guard = "1/32"; break;
case 0x1: psz_guard = "1/16"; break;
case 0x2: psz_guard = "1/8"; break;
case 0x3: psz_guard = "1/4"; break;
}
switch (i_transmission) {
case 0x0: psz_transmission = "2k"; break;
case 0x1: psz_transmission = "8k"; break;
case 0x2: psz_transmission = "4k"; break;
}
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" : "");
}
/***************************************************************************** /*****************************************************************************
* Descriptor 0x6a: AC-3 descriptor * Descriptor 0x6a: AC-3 descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -262,6 +786,11 @@ static inline void desc6a_clear_flags(uint8_t *p_desc) ...@@ -262,6 +786,11 @@ static inline void desc6a_clear_flags(uint8_t *p_desc)
p_desc[2] = 0; p_desc[2] = 0;
} }
static inline bool desc6a_validate(const uint8_t *p_desc)
{
return desc_get_length(p_desc) >= DESC6A_HEADER_SIZE - DESC_HEADER_SIZE;
}
static inline void desc6a_print(const uint8_t *p_desc, f_print pf_print, static inline void desc6a_print(const uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
...@@ -537,7 +1066,7 @@ static inline void sdtn_set_eitschedule(uint8_t *p_sdt_n) ...@@ -537,7 +1066,7 @@ static inline void sdtn_set_eitschedule(uint8_t *p_sdt_n)
static inline bool sdtn_get_eitschedule(const uint8_t *p_sdt_n) static inline bool sdtn_get_eitschedule(const uint8_t *p_sdt_n)
{ {
return p_sdt_n[2] & 0x2; return !!(p_sdt_n[2] & 0x2);
} }
static inline void sdtn_set_eitpresent(uint8_t *p_sdt_n) static inline void sdtn_set_eitpresent(uint8_t *p_sdt_n)
...@@ -547,7 +1076,7 @@ static inline void sdtn_set_eitpresent(uint8_t *p_sdt_n) ...@@ -547,7 +1076,7 @@ static inline void sdtn_set_eitpresent(uint8_t *p_sdt_n)
static inline bool sdtn_get_eitpresent(const uint8_t *p_sdt_n) static inline bool sdtn_get_eitpresent(const uint8_t *p_sdt_n)
{ {
return p_sdt_n[2] & 0x1; return !!(p_sdt_n[2] & 0x1);
} }
static inline void sdtn_set_running(uint8_t *p_sdt_n, uint8_t i_running) static inline void sdtn_set_running(uint8_t *p_sdt_n, uint8_t i_running)
...@@ -568,7 +1097,7 @@ static inline void sdtn_set_ca(uint8_t *p_sdt_n) ...@@ -568,7 +1097,7 @@ static inline void sdtn_set_ca(uint8_t *p_sdt_n)
static inline bool sdtn_get_ca(const uint8_t *p_sdt_n) static inline bool sdtn_get_ca(const uint8_t *p_sdt_n)
{ {
return p_sdt_n[3] & 0x10; return !!(p_sdt_n[3] & 0x10);
} }
static inline void sdtn_set_desclength(uint8_t *p_sdt_n, uint16_t i_length) static inline void sdtn_set_desclength(uint8_t *p_sdt_n, uint16_t i_length)
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <inttypes.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <iconv.h>
#include <bitstream/mpeg/ts.h> #include <bitstream/mpeg/ts.h>
#include <bitstream/mpeg/psi.h> #include <bitstream/mpeg/psi.h>
...@@ -56,10 +58,14 @@ static PSI_TABLE_DECLARE(pp_next_nit_sections); ...@@ -56,10 +58,14 @@ static PSI_TABLE_DECLARE(pp_next_nit_sections);
static PSI_TABLE_DECLARE(pp_current_sdt_sections); static PSI_TABLE_DECLARE(pp_current_sdt_sections);
static PSI_TABLE_DECLARE(pp_next_sdt_sections); 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;
/***************************************************************************** /*****************************************************************************
* print * print_wrapper
*****************************************************************************/ *****************************************************************************/
static void print(void *_unused, const char *psz_format, ...) static void print_wrapper(void *_unused, const char *psz_format, ...)
{ {
char psz_fmt[strlen(psz_format) + 2]; char psz_fmt[strlen(psz_format) + 2];
va_list args; va_list args;
...@@ -69,6 +75,57 @@ static void print(void *_unused, const char *psz_format, ...) ...@@ -69,6 +75,57 @@ static void print(void *_unused, const char *psz_format, ...)
vprintf(psz_fmt, args); vprintf(psz_fmt, args);
} }
/*****************************************************************************
* iconv_wrapper
*****************************************************************************/
static char *iconv_append_null(const char *p_string, size_t i_length)
{
char *psz_string = malloc(i_length + 1);
memcpy(psz_string, p_string, i_length);
psz_string[i_length] = '\0';
return psz_string;
}
static char *iconv_wrapper(void *_unused, const char *psz_encoding,
char *p_string, size_t i_length)
{
char *psz_string, *p;
size_t i_out_length;
if (!strcmp(psz_encoding, psz_native_encoding))
return iconv_append_null(p_string, i_length);
if (iconv_handle != (iconv_t)-1 &&
strcmp(psz_encoding, psz_current_encoding)) {
iconv_close(iconv_handle);
iconv_handle = (iconv_t)-1;
}
if (iconv_handle == (iconv_t)-1)
iconv_handle = iconv_open(psz_native_encoding, psz_encoding);
if (iconv_handle == (iconv_t)-1) {
fprintf(stderr, "couldn't convert from %s to %s (%m)", psz_encoding,
psz_native_encoding);
return iconv_append_null(p_string, i_length);
}
/* converted strings can be up to six times larger */
i_out_length = i_length * 6;
p = psz_string = malloc(i_out_length);
if (iconv(iconv_handle, &p_string, &i_length, &p, &i_out_length) == -1) {
fprintf(stderr, "couldn't convert from %s to %s (%m)", psz_encoding,
psz_native_encoding);
free(psz_string);
return iconv_append_null(p_string, i_length);
}
if (i_length)
fprintf(stderr, "partial conversion from %s to %s", psz_encoding,
psz_native_encoding);
*p = '\0';
return psz_string;
}
/***************************************************************************** /*****************************************************************************
* handle_pat * handle_pat
*****************************************************************************/ *****************************************************************************/
...@@ -179,7 +236,7 @@ static void handle_pat(void) ...@@ -179,7 +236,7 @@ static void handle_pat(void)
psi_table_free(pp_old_pat_sections); psi_table_free(pp_old_pat_sections);
} }
pat_table_print( pp_current_pat_sections, print, NULL ); pat_table_print( pp_current_pat_sections, print_wrapper, NULL );
} }
static void handle_pat_section(uint16_t i_pid, uint8_t *p_section) static void handle_pat_section(uint16_t i_pid, uint8_t *p_section)
...@@ -241,7 +298,7 @@ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt) ...@@ -241,7 +298,7 @@ static void handle_pmt(uint16_t i_pid, uint8_t *p_pmt)
free(p_sid->p_current_pmt); free(p_sid->p_current_pmt);
p_sid->p_current_pmt = p_pmt; p_sid->p_current_pmt = p_pmt;
pmt_print(p_pmt, print, NULL); pmt_print(p_pmt, print_wrapper, NULL, iconv_wrapper, NULL);
} }
/***************************************************************************** /*****************************************************************************
...@@ -270,7 +327,8 @@ static void handle_nit(void) ...@@ -270,7 +327,8 @@ static void handle_nit(void)
psi_table_copy(pp_current_nit_sections, pp_next_nit_sections); psi_table_copy(pp_current_nit_sections, pp_next_nit_sections);
psi_table_init(pp_next_nit_sections); psi_table_init(pp_next_nit_sections);
nit_table_print(pp_current_nit_sections, print, NULL); nit_table_print(pp_current_nit_sections, print_wrapper, NULL,
iconv_wrapper, NULL);
} }
static void handle_nit_section(uint16_t i_pid, uint8_t *p_section) static void handle_nit_section(uint16_t i_pid, uint8_t *p_section)
...@@ -313,7 +371,8 @@ static void handle_sdt(void) ...@@ -313,7 +371,8 @@ static void handle_sdt(void)
psi_table_copy(pp_current_sdt_sections, pp_next_sdt_sections); psi_table_copy(pp_current_sdt_sections, pp_next_sdt_sections);
psi_table_init(pp_next_sdt_sections); psi_table_init(pp_next_sdt_sections);
sdt_table_print(pp_current_sdt_sections, print, NULL); sdt_table_print(pp_current_sdt_sections, print_wrapper, NULL,
iconv_wrapper, NULL);
} }
static void handle_sdt_section(uint16_t i_pid, uint8_t *p_section) static void handle_sdt_section(uint16_t i_pid, uint8_t *p_section)
......
...@@ -34,11 +34,6 @@ extern "C" ...@@ -34,11 +34,6 @@ extern "C"
*****************************************************************************/ *****************************************************************************/
#define DESC_HEADER_SIZE 2 #define DESC_HEADER_SIZE 2
#define DESC_MAX_STRING1 256
#define DESC_DECLARE_STRING1(p_string) \
char p_string[DESC_MAX_STRING1]
static inline void desc_set_tag(uint8_t *p_desc, uint8_t i_tag) static inline void desc_set_tag(uint8_t *p_desc, uint8_t i_tag)
{ {
p_desc[0] = i_tag; p_desc[0] = i_tag;
...@@ -89,6 +84,11 @@ static inline const uint8_t *desc05_get_identifier(const uint8_t *p_desc) ...@@ -89,6 +84,11 @@ static inline const uint8_t *desc05_get_identifier(const uint8_t *p_desc)
return p_desc + 2; return p_desc + 2;
} }
static inline bool desc05_validate(const uint8_t *p_desc)
{
return desc_get_length(p_desc) >= DESC05_HEADER_SIZE - DESC_HEADER_SIZE;
}
static inline void desc05_print(const uint8_t *p_desc, f_print pf_print, static inline void desc05_print(const uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
...@@ -111,6 +111,11 @@ static inline uint16_t desc09_get_pid(const uint8_t *p_desc) ...@@ -111,6 +111,11 @@ static inline uint16_t desc09_get_pid(const uint8_t *p_desc)
return ((p_desc[4] & 0x1f) << 8) | p_desc[5]; return ((p_desc[4] & 0x1f) << 8) | p_desc[5];
} }
static inline bool desc09_validate(const uint8_t *p_desc)
{
return desc_get_length(p_desc) >= DESC09_HEADER_SIZE - DESC_HEADER_SIZE;
}
static inline void desc09_print(const uint8_t *p_desc, f_print pf_print, static inline void desc09_print(const uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
...@@ -160,6 +165,11 @@ static inline uint8_t desc0an_get_audiotype(const uint8_t *p_desc_n) ...@@ -160,6 +165,11 @@ static inline uint8_t desc0an_get_audiotype(const uint8_t *p_desc_n)
return p_desc_n[3]; return p_desc_n[3];
} }
static inline bool desc0a_validate(const uint8_t *p_desc)
{
return !(desc_get_length(p_desc) % DESC0A_LANGUAGE_SIZE);
}
static inline void desc0a_print(uint8_t *p_desc, f_print pf_print, static inline void desc0a_print(uint8_t *p_desc, f_print pf_print,
void *opaque) void *opaque)
{ {
...@@ -218,7 +228,7 @@ static inline bool descs_validate(const uint8_t *p_descs) ...@@ -218,7 +228,7 @@ static inline bool descs_validate(const uint8_t *p_descs)
} }
/***************************************************************************** /*****************************************************************************
* s_crc32_table * p_psi_crc_table
***************************************************************************** *****************************************************************************
* This table is used to compute a PSI CRC byte per byte instead of bit per * This table is used to compute a PSI CRC byte per byte instead of bit per
* bit. It's been generated by 'gen_crc' in the 'misc' directory: * bit. It's been generated by 'gen_crc' in the 'misc' directory:
...@@ -244,73 +254,72 @@ static inline bool descs_validate(const uint8_t *p_descs) ...@@ -244,73 +254,72 @@ static inline bool descs_validate(const uint8_t *p_descs)
* --------------------- * ---------------------
* i_crc = (i_crc << 8) ^ s_crc32_table[(i_crc >> 24) ^ (data_byte)]; * i_crc = (i_crc << 8) ^ s_crc32_table[(i_crc >> 24) ^ (data_byte)];
*****************************************************************************/ *****************************************************************************/
#define PSI_CRC_TABLE \ static const uint32_t p_psi_crc_table[256] = {
{ \ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, \ 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, \ 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, \ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, \ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, \ 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, \ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, \ 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, \ 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, \ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, \ 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, \ 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, \ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, \ 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, \ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, \ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, \ 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, \ 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, \ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, \ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, \ 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, \ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, \ 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, \ 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, \ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, \ 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, \ 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, \ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, \ 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, \ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, \ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, \ 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, \ 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, \ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, \ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, \ 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, \ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, \ 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, \ 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, \ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, \ 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, \ 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, \ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, \ 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, \ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, \ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, \ 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, \ 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, \ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, \ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, \ 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, \ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, \ 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, \ 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, \ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, \ 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, \ 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, \ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, \ 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, \ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, \ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, \ 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, \ 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, \ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 \ };
}
/***************************************************************************** /*****************************************************************************
* PSI section * PSI section
...@@ -353,7 +362,7 @@ static inline void psi_set_syntax(uint8_t *p_section) ...@@ -353,7 +362,7 @@ static inline void psi_set_syntax(uint8_t *p_section)
static inline bool psi_get_syntax(const uint8_t *p_section) static inline bool psi_get_syntax(const uint8_t *p_section)
{ {
return p_section[1] & 0x80; return !!(p_section[1] & 0x80);
} }
static inline void psi_init(uint8_t *p_section, bool b_syntax) static inline void psi_init(uint8_t *p_section, bool b_syntax)
...@@ -407,7 +416,7 @@ static inline void psi_set_current(uint8_t *p_section) ...@@ -407,7 +416,7 @@ static inline void psi_set_current(uint8_t *p_section)
static inline bool psi_get_current(const uint8_t *p_section) static inline bool psi_get_current(const uint8_t *p_section)
{ {
return (p_section[5] & 0x1); return !!(p_section[5] & 0x1);
} }
static inline void psi_set_section(uint8_t *p_section, uint8_t i_section) static inline void psi_set_section(uint8_t *p_section, uint8_t i_section)
...@@ -436,14 +445,13 @@ static inline uint8_t psi_get_lastsection(const uint8_t *p_section) ...@@ -436,14 +445,13 @@ static inline uint8_t psi_get_lastsection(const uint8_t *p_section)
*****************************************************************************/ *****************************************************************************/
static inline void psi_set_crc(uint8_t *p_section) static inline void psi_set_crc(uint8_t *p_section)
{ {
static const uint32_t s_crc32_table[256] = PSI_CRC_TABLE;
uint32_t i_crc = 0xffffffff; uint32_t i_crc = 0xffffffff;
uint16_t i_end = (((p_section[1] & 0xf) << 8) | p_section[2]) uint16_t i_end = (((p_section[1] & 0xf) << 8) | p_section[2])
+ PSI_HEADER_SIZE - PSI_CRC_SIZE; + PSI_HEADER_SIZE - PSI_CRC_SIZE;
uint16_t i; uint16_t i;
for (i = 0; i < i_end; i++) for (i = 0; i < i_end; i++)
i_crc = (i_crc << 8) ^ s_crc32_table[(i_crc >> 24) ^ (p_section[i])]; i_crc = (i_crc << 8) ^ p_psi_crc_table[(i_crc >> 24) ^ (p_section[i])];
p_section[i_end] = i_crc >> 24; p_section[i_end] = i_crc >> 24;
p_section[i_end + 1] = (i_crc >> 16) & 0xff; p_section[i_end + 1] = (i_crc >> 16) & 0xff;
...@@ -453,14 +461,13 @@ static inline void psi_set_crc(uint8_t *p_section) ...@@ -453,14 +461,13 @@ static inline void psi_set_crc(uint8_t *p_section)
static inline bool psi_check_crc(const uint8_t *p_section) static inline bool psi_check_crc(const uint8_t *p_section)
{ {
static const uint32_t s_crc32_table[256] = PSI_CRC_TABLE;
uint32_t i_crc = 0xffffffff; uint32_t i_crc = 0xffffffff;
uint16_t i_end = (((p_section[1] & 0xf) << 8) | p_section[2]) uint16_t i_end = (((p_section[1] & 0xf) << 8) | p_section[2])
+ PSI_HEADER_SIZE - PSI_CRC_SIZE; + PSI_HEADER_SIZE - PSI_CRC_SIZE;
uint16_t i; uint16_t i;
for (i = 0; i < i_end; i++) for (i = 0; i < i_end; i++)
i_crc = (i_crc << 8) ^ s_crc32_table[(i_crc >> 24) ^ (p_section[i])]; i_crc = (i_crc << 8) ^ p_psi_crc_table[(i_crc >> 24) ^ (p_section[i])];
return p_section[i_end] == (i_crc >> 24) return p_section[i_end] == (i_crc >> 24)
&& p_section[i_end + 1] == ((i_crc >> 16) & 0xff) && p_section[i_end + 1] == ((i_crc >> 16) & 0xff)
......
...@@ -32,42 +32,95 @@ extern "C" ...@@ -32,42 +32,95 @@ extern "C"
/***************************************************************************** /*****************************************************************************
* Descriptors list * Descriptors list
*****************************************************************************/ *****************************************************************************/
static inline void descs_print(uint8_t *p_descs, f_print pf_print, void *opaque) static inline void descs_print(uint8_t *p_descs,
f_print pf_print, void *print_opaque,
f_iconv pf_iconv, void *iconv_opaque)
{ {
uint16_t j = 0; uint16_t j = 0;
uint8_t *p_desc; uint8_t *p_desc;
while ((p_desc = descs_get_desc(p_descs, j)) != NULL) { while ((p_desc = descs_get_desc(p_descs, j)) != NULL) {
uint8_t i_tag = desc_get_tag(p_desc);
j++; j++;
/* I am not proud of this */ /* I am not proud of this */
switch (desc_get_tag(p_desc)) { switch (i_tag) {
case 0x05: case 0x05:
desc05_print(p_desc, pf_print, opaque); if (desc05_validate(p_desc))
desc05_print(p_desc, pf_print, print_opaque);
else
pf_print(print_opaque, "desc %hhx invalid", i_tag);
break; break;
case 0x09: case 0x09:
desc09_print(p_desc, pf_print, opaque); if (desc09_validate(p_desc))
desc09_print(p_desc, pf_print, print_opaque);
else
pf_print(print_opaque, "desc %hhx invalid", i_tag);
break; break;
case 0x0a: case 0x0a:
desc0a_print(p_desc, pf_print, opaque); if (desc0a_validate(p_desc))
desc0a_print(p_desc, pf_print, print_opaque);
else
pf_print(print_opaque, "desc %hhx invalid", i_tag);
break; break;
case 0x40: case 0x40:
desc40_print(p_desc, pf_print, opaque); 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; break;
case 0x48: case 0x48:
desc48_print(p_desc, pf_print, opaque); 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; break;
case 0x56: case 0x56:
desc56_print(p_desc, pf_print, opaque); if (desc56_validate(p_desc))
desc56_print(p_desc, pf_print, print_opaque);
else
pf_print(print_opaque, "desc %hhx invalid", i_tag);
break; break;
case 0x59: case 0x59:
desc59_print(p_desc, pf_print, opaque); 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);
break; break;
case 0x6a: case 0x6a:
desc6a_print(p_desc, pf_print, opaque); if (desc6a_validate(p_desc))
desc6a_print(p_desc, pf_print, print_opaque);
else
pf_print(print_opaque, "desc %hhx invalid", i_tag);
break; break;
default: default:
desc_print(p_desc, pf_print, opaque); desc_print(p_desc, pf_print, print_opaque);
break; break;
} }
} }
...@@ -76,44 +129,49 @@ static inline void descs_print(uint8_t *p_descs, f_print pf_print, void *opaque) ...@@ -76,44 +129,49 @@ static inline void descs_print(uint8_t *p_descs, f_print pf_print, void *opaque)
/***************************************************************************** /*****************************************************************************
* Program Map Table * Program Map Table
*****************************************************************************/ *****************************************************************************/
static inline void pmt_print(uint8_t *p_pmt, f_print pf_print, void *opaque) static inline void pmt_print(uint8_t *p_pmt,
f_print pf_print, void *print_opaque,
f_iconv pf_iconv, void *iconv_opaque)
{ {
uint8_t *p_es; uint8_t *p_es;
uint8_t j = 0; uint8_t j = 0;
pf_print(opaque, "new PMT program=%hu version=%hhu%s pcrpid=%hu", pf_print(print_opaque, "new PMT program=%hu version=%hhu%s pcrpid=%hu",
pmt_get_program(p_pmt), psi_get_version(p_pmt), pmt_get_program(p_pmt), psi_get_version(p_pmt),
!psi_get_current(p_pmt) ? " (next)" : "", !psi_get_current(p_pmt) ? " (next)" : "",
pmt_get_pcrpid(p_pmt)); pmt_get_pcrpid(p_pmt));
descs_print(pmt_get_descs(p_pmt), pf_print, opaque); descs_print(pmt_get_descs(p_pmt), pf_print, print_opaque,
pf_iconv, iconv_opaque);
while ((p_es = pmt_get_es(p_pmt, j)) != NULL) { while ((p_es = pmt_get_es(p_pmt, j)) != NULL) {
j++; j++;
pf_print(opaque, " * ES pid=%hu streamtype=0x%hx", pmtn_get_pid(p_es), pf_print(print_opaque, " * ES pid=%hu streamtype=0x%hx", pmtn_get_pid(p_es),
pmtn_get_streamtype(p_es)); pmtn_get_streamtype(p_es));
descs_print(pmtn_get_descs(p_es), pf_print, opaque); descs_print(pmtn_get_descs(p_es), pf_print, print_opaque,
pf_iconv, iconv_opaque);
} }
pf_print(opaque, "end PMT"); pf_print(print_opaque, "end PMT");
} }
/***************************************************************************** /*****************************************************************************
* Network Information Table * Network Information Table
*****************************************************************************/ *****************************************************************************/
static inline void nit_table_print(uint8_t **pp_sections, f_print pf_print, static inline void nit_table_print(uint8_t **pp_sections,
void *opaque) f_print pf_print, void *print_opaque,
f_iconv pf_iconv, void *iconv_opaque)
{ {
uint8_t i_last_section = psi_table_get_lastsection(pp_sections); uint8_t i_last_section = psi_table_get_lastsection(pp_sections);
uint8_t i; uint8_t i;
pf_print(opaque, "new NIT %s networkid=%hu version=%hhu%s", pf_print(print_opaque, "new NIT %s networkid=%hu version=%hhu%s",
psi_table_get_tableid(pp_sections) == NIT_TABLE_ID_ACTUAL ? psi_table_get_tableid(pp_sections) == NIT_TABLE_ID_ACTUAL ?
"actual" : "other", "actual" : "other",
psi_table_get_tableidext(pp_sections), psi_table_get_tableidext(pp_sections),
psi_table_get_version(pp_sections), psi_table_get_version(pp_sections),
!psi_table_get_current(pp_sections) ? " (next)" : ""); !psi_table_get_current(pp_sections) ? " (next)" : "");
descs_print(nit_get_descs(psi_table_get_section(pp_sections, 0)), descs_print(nit_get_descs(psi_table_get_section(pp_sections, 0)),
pf_print, opaque); pf_print, print_opaque, pf_iconv, iconv_opaque);
for (i = 0; i <= i_last_section; i++) { for (i = 0; i <= i_last_section; i++) {
uint8_t *p_section = psi_table_get_section(pp_sections, i); uint8_t *p_section = psi_table_get_section(pp_sections, i);
...@@ -122,25 +180,27 @@ static inline void nit_table_print(uint8_t **pp_sections, f_print pf_print, ...@@ -122,25 +180,27 @@ static inline void nit_table_print(uint8_t **pp_sections, f_print pf_print,
while ((p_ts = nit_get_ts(p_section, j)) != NULL) { while ((p_ts = nit_get_ts(p_section, j)) != NULL) {
j++; j++;
pf_print(opaque, " * ts tsid=%hu onid=%hu", pf_print(print_opaque, " * ts tsid=%hu onid=%hu",
nitn_get_tsid(p_ts), nitn_get_onid(p_ts)); nitn_get_tsid(p_ts), nitn_get_onid(p_ts));
descs_print(nitn_get_descs(p_ts), pf_print, opaque); descs_print(nitn_get_descs(p_ts), pf_print, print_opaque,
pf_iconv, iconv_opaque);
} }
} }
pf_print(opaque, "end NIT"); pf_print(print_opaque, "end NIT");
} }
/***************************************************************************** /*****************************************************************************
* Service Description Table * Service Description Table
*****************************************************************************/ *****************************************************************************/
static inline void sdt_table_print(uint8_t **pp_sections, f_print pf_print, static inline void sdt_table_print(uint8_t **pp_sections,
void *opaque) f_print pf_print, void *print_opaque,
f_iconv pf_iconv, void *iconv_opaque)
{ {
uint8_t i_last_section = psi_table_get_lastsection(pp_sections); uint8_t i_last_section = psi_table_get_lastsection(pp_sections);
uint8_t i; uint8_t i;
pf_print(opaque, "new SDT %s tsid=%hu version=%hhu%s onid=%hu", pf_print(print_opaque, "new SDT %s tsid=%hu version=%hhu%s onid=%hu",
psi_table_get_tableid(pp_sections) == SDT_TABLE_ID_ACTUAL ? psi_table_get_tableid(pp_sections) == SDT_TABLE_ID_ACTUAL ?
"actual" : "other", "actual" : "other",
psi_table_get_tableidext(pp_sections), psi_table_get_tableidext(pp_sections),
...@@ -155,17 +215,18 @@ static inline void sdt_table_print(uint8_t **pp_sections, f_print pf_print, ...@@ -155,17 +215,18 @@ static inline void sdt_table_print(uint8_t **pp_sections, f_print pf_print,
while ((p_service = sdt_get_service(p_section, j)) != NULL) { while ((p_service = sdt_get_service(p_section, j)) != NULL) {
j++; j++;
pf_print(opaque, " * service sid=%hu eit%s%s running=%hhu%s", pf_print(print_opaque, " * service sid=%hu eit%s%s running=%hhu%s",
sdtn_get_sid(p_service), sdtn_get_sid(p_service),
sdtn_get_eitschedule(p_service) ? " schedule" : "", sdtn_get_eitschedule(p_service) ? " schedule" : "",
sdtn_get_eitpresent(p_service) ? " present" : "", sdtn_get_eitpresent(p_service) ? " present" : "",
sdtn_get_running(p_service), sdtn_get_running(p_service),
sdtn_get_ca(p_service) ? " scrambled" : ""); sdtn_get_ca(p_service) ? " scrambled" : "");
descs_print(sdtn_get_descs(p_service), pf_print, opaque); descs_print(sdtn_get_descs(p_service), pf_print, print_opaque,
pf_iconv, iconv_opaque);
} }
} }
pf_print(opaque, "end SDT"); pf_print(print_opaque, "end SDT");
} }
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -52,7 +52,7 @@ static inline void ts_init(uint8_t *p_ts) ...@@ -52,7 +52,7 @@ static inline void ts_init(uint8_t *p_ts)
static inline bool ts_get_transporterror(const uint8_t *p_ts) static inline bool ts_get_transporterror(const uint8_t *p_ts)
{ {
return p_ts[1] & 0x80; return !!(p_ts[1] & 0x80);
} }
static inline void ts_set_unitstart(uint8_t *p_ts) static inline void ts_set_unitstart(uint8_t *p_ts)
...@@ -62,7 +62,7 @@ static inline void ts_set_unitstart(uint8_t *p_ts) ...@@ -62,7 +62,7 @@ static inline void ts_set_unitstart(uint8_t *p_ts)
static inline bool ts_get_unitstart(const uint8_t *p_ts) static inline bool ts_get_unitstart(const uint8_t *p_ts)
{ {
return p_ts[1] & 0x40; return !!(p_ts[1] & 0x40);
} }
static inline void ts_set_transportpriority(uint8_t *p_ts) static inline void ts_set_transportpriority(uint8_t *p_ts)
...@@ -72,7 +72,7 @@ static inline void ts_set_transportpriority(uint8_t *p_ts) ...@@ -72,7 +72,7 @@ static inline void ts_set_transportpriority(uint8_t *p_ts)
static inline bool ts_get_transportpriority(const uint8_t *p_ts) static inline bool ts_get_transportpriority(const uint8_t *p_ts)
{ {
return p_ts[1] & 0x20; return !!(p_ts[1] & 0x20);
} }
static inline void ts_set_pid(uint8_t *p_ts, uint16_t i_pid) static inline void ts_set_pid(uint8_t *p_ts, uint16_t i_pid)
...@@ -105,7 +105,7 @@ static inline void ts_set_payload(uint8_t *p_ts) ...@@ -105,7 +105,7 @@ static inline void ts_set_payload(uint8_t *p_ts)
static inline bool ts_has_payload(const uint8_t *p_ts) static inline bool ts_has_payload(const uint8_t *p_ts)
{ {
return p_ts[3] & 0x10; return !!(p_ts[3] & 0x10);
} }
static inline void ts_set_adaptation(uint8_t *p_ts, uint8_t i_length) static inline void ts_set_adaptation(uint8_t *p_ts, uint8_t i_length)
...@@ -120,7 +120,7 @@ static inline void ts_set_adaptation(uint8_t *p_ts, uint8_t i_length) ...@@ -120,7 +120,7 @@ static inline void ts_set_adaptation(uint8_t *p_ts, uint8_t i_length)
static inline bool ts_has_adaptation(const uint8_t *p_ts) static inline bool ts_has_adaptation(const uint8_t *p_ts)
{ {
return (p_ts[3] & 0x20); return !!(p_ts[3] & 0x20);
} }
static inline uint8_t ts_get_adaptation(const uint8_t *p_ts) static inline uint8_t ts_get_adaptation(const uint8_t *p_ts)
...@@ -193,7 +193,7 @@ static inline void tsaf_set_randomaccess(uint8_t *p_ts) ...@@ -193,7 +193,7 @@ static inline void tsaf_set_randomaccess(uint8_t *p_ts)
static inline bool tsaf_has_randomaccess(const uint8_t *p_ts) static inline bool tsaf_has_randomaccess(const uint8_t *p_ts)
{ {
return p_ts[5] & 0x40; return !!(p_ts[5] & 0x40);
} }
static inline void tsaf_set_streampriority(uint8_t *p_ts) static inline void tsaf_set_streampriority(uint8_t *p_ts)
...@@ -220,7 +220,7 @@ static inline void tsaf_set_pcrext(uint8_t *p_ts, uint16_t i_pcr_ext) ...@@ -220,7 +220,7 @@ static inline void tsaf_set_pcrext(uint8_t *p_ts, uint16_t i_pcr_ext)
static inline bool tsaf_has_pcr(uint8_t *p_ts) static inline bool tsaf_has_pcr(uint8_t *p_ts)
{ {
return p_ts[5] & 0x10; return !!(p_ts[5] & 0x10);
} }
static inline uint64_t tsaf_get_pcr(const uint8_t *p_ts) static inline uint64_t tsaf_get_pcr(const uint8_t *p_ts)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment