void ts_descriptor_dump(uint8_t *desc_data, int desc_data_len) { char *pad = " * "; uint8_t *data = desc_data; int data_len = desc_data_len; while (data_len >= 2) { int i; uint8_t tag = data[0]; uint8_t this_length = data[1]; // ts_LOGf("%sDescriptor tag: 0x%02x (%d) size: %d\n", padA, tag, tag, this_length); data += 2; data_len -= 2; if (this_length > data_len) { // Not much we can do - try giving up? ts_LOGf("%s!!! Descriptor 0x%02x says length %d, but only %d bytes left\n", pad, tag, this_length, data_len); return; } switch (tag) { case 2: { // Video stream descriptor char *dump = ts_hex_dump(data, this_length, 0); ts_LOGf("%sTag 0x%02x (%02d), sz: %d, Video stream descriptor: %s\n", pad, tag, tag, this_length, dump); free(dump); struct { uint8_t multiple_frame_rate_flag : 1, frame_rate_code : 4, mpeg1_only_flag : 1, constraint_parameter_flag : 1, still_picture_flag : 1; uint8_t profile_and_level_indication; uint8_t chroma_format : 2, frame_rate_extension_flag : 1, reserved : 5; uint8_t escape:1, profile:3, level:4; } vs; if (this_length >= 1) { vs.multiple_frame_rate_flag = bit_on(data[0], bit_8); vs.frame_rate_code = (data[0] &~ 0x80) >> 3; // 1xxxx111 vs.mpeg1_only_flag = bit_on(data[0], bit_3); vs.constraint_parameter_flag = bit_on(data[0], bit_2); vs.still_picture_flag = bit_on(data[0], bit_1); ts_LOGf("%s - multiple_frame_rate_flag : %d\n", pad, vs.multiple_frame_rate_flag); ts_LOGf("%s - frame_rate_code : %d (%s)\n", pad, vs.frame_rate_code, vs.frame_rate_code == 0 ? "forbidden" : vs.frame_rate_code == 1 ? "23.976" : vs.frame_rate_code == 2 ? "24.00" : vs.frame_rate_code == 3 ? "25.00" : vs.frame_rate_code == 4 ? "29.97" : vs.frame_rate_code == 5 ? "30.00" : vs.frame_rate_code == 6 ? "50.00" : vs.frame_rate_code == 7 ? "59.94" : vs.frame_rate_code == 8 ? "60.00" : "reserved" ); ts_LOGf("%s - mpeg1_only_flag : %d\n", pad, vs.mpeg1_only_flag); ts_LOGf("%s - constraint_parameter_flag : %d\n", pad, vs.constraint_parameter_flag); ts_LOGf("%s - still_picture_flag : %d\n", pad, vs.still_picture_flag); } if (this_length >= 2 && vs.mpeg1_only_flag == 0) { vs.profile_and_level_indication = data[1]; vs.chroma_format = data[2] >> 6; // xx111111 vs.frame_rate_extension_flag = bit_on(data[2], bit_6); // 11x11111 vs.reserved = data[2] &~ 0xE0; // 111xxxxx vs.profile = (vs.profile_and_level_indication &~ 0x8f) >> 4; // x111xxxx vs.level = vs.profile_and_level_indication &~ 0xf0; // xxxx1111 ts_LOGf("%s - profile_and_level_indication : 0x%02x, Profile: %d (%s), Level: %d (%s)\n", pad, vs.profile_and_level_indication, vs.profile, vs.profile == 1 ? "High" : vs.profile == 2 ? "Spatially Scalable" : vs.profile == 3 ? "SNR Scalable" : vs.profile == 4 ? "Main" : vs.profile == 5 ? "Simple" : "Reserved", vs.level, vs.level == 4 ? "High" : vs.level == 6 ? "High 1440" : vs.level == 8 ? "Main" : vs.level == 10 ? "Low" : "Reserved" ); ts_LOGf("%s - chroma_format : %d (%s)\n", pad, vs.chroma_format, vs.chroma_format == 0 ? "reserved" : vs.chroma_format == 1 ? "4:2:0" : vs.chroma_format == 2 ? "4:2:2" : vs.chroma_format == 3 ? "4:4:4" : "unknown" ); ts_LOGf("%s - frame_rate_extension_flag : %d\n", pad, vs.frame_rate_extension_flag); ts_LOGf("%s - reserved : 0x%x\n", pad, vs.reserved); } break; } case 3: { // Audio stream descriptor char *dump = ts_hex_dump(data, this_length, 0); ts_LOGf("%sTag 0x%02x (%02d), sz: %d, Audio stream descriptor: %s\n", pad, tag, tag, this_length, dump); free(dump); struct { uint8_t free_format_flag : 1, ID : 1, layer : 2, vbr_flag : 1, reserved : 3; } as; if (this_length >= 1) { as.free_format_flag = bit_on(data[0], bit_8); as.ID = bit_on(data[0], bit_7); as.layer = (data[0] &~ 0xcf) >> 4; // 11xx1111 as.vbr_flag = bit_on(data[0], bit_4); as.reserved = data[0] &~ 0xf0; // 1111xxxx ts_LOGf("%s - free_format_flag : %d\n", pad, as.free_format_flag); ts_LOGf("%s - ID : %d (%s)\n", pad, as.ID, as.ID ? "MPEG Audio" : "Other"); ts_LOGf("%s - layer : %d (%s)\n", pad, as.layer, as.layer == 0 ? "reserved" : as.layer == 1 ? "Layer III" : as.layer == 2 ? "Layer II" : as.layer == 3 ? "Layer I" : "reserved" ); ts_LOGf("%s - vbr_audio_flag : %d\n", pad, as.vbr_flag); ts_LOGf("%s - reserved : 0x%x\n", pad, as.reserved); } break; }
void ts_print_bytes(char *prefix, uint8_t *d, int size) { char *buf = ts_hex_dump(d, size, 0); ts_LOGf("%s -> %s\n", prefix, buf); free(buf); }