53 bool begin()
override {
60 if (p_dec) p_dec->begin();
65 memset(print_pids, 0,
sizeof(print_pids));
68 if (tsd_context_init(&ctx) != TSD_OK) {
74 if (is_alloc_active) {
75 ctx.malloc = log_malloc;
76 ctx.realloc = log_realloc;
77 ctx.calloc = log_calloc;
82 if (stream_types.empty()) {
83 addStreamType(TSD_PMT_STREAM_TYPE_PES_METADATA);
84 addStreamType(TSD_PMT_STREAM_TYPE_AUDIO_AAC);
91 if (tsd_set_event_callback(&ctx, event_cb) != TSD_OK) {
100 if (p_dec) p_dec->begin();
106 tsd_context_destroy(&ctx);
111 virtual operator bool()
override {
return is_active; }
113 const char *mime() {
return "video/MP2T"; }
115 size_t write(
const uint8_t *data,
size_t len)
override {
116 if (!is_active)
return 0;
117 LOGD(
"MTSDecoderTSDemux::write: %d", (
int)len);
118 size_t result = buffer.
writeArray((uint8_t *)data, len);
120 demux(underflowLimit);
124 void flush() { demux(0); }
126 void clearStreamTypes() {
128 stream_types.clear();
131 void addStreamType(TSDPMTStreamType type) {
133 stream_types.push_back(type);
136 bool isStreamTypeActive(TSDPMTStreamType type) {
137 for (
int j = 0; j < stream_types.size(); j++) {
138 if (stream_types[j] == type)
return true;
178 int underflowLimit = MTS_UNDERFLOW_LIMIT;
179 bool is_active =
false;
180 bool is_write_active =
false;
181 bool is_alloc_active =
false;
183 uint16_t print_pids[MTS_PRINT_PIDS_LEN] = {0};
184 SingleBuffer<uint8_t> buffer{MTS_WRITE_BUFFER_SIZE};
185 Vector<TSDPMTStreamType> stream_types;
186 Vector<AllocSize> alloc_vector;
187 AudioDecoder *p_dec =
nullptr;
189 void set_write_active(
bool flag) {
191 is_write_active = flag;
196 bool payloadUnitStartIndicator = (data[1] & 0x40) >> 6;
197 bool result = data[0] == 0x47 && payloadUnitStartIndicator;
201 void demux(
int limit) {
203 TSDCode res = TSD_OK;
205 while (res == TSD_OK && buffer.
available() >= limit) {
208 LOGD(
"parsing new file");
212 res = tsd_demux(&ctx, (
void *)buffer.
data(), buffer.
available(), &len);
217 if (res != TSD_OK) logResult(res);
219 LOGD(
"Number of demux calls: %d", count);
222 void logResult(TSDCode code) {
227 case TSD_INVALID_SYNC_BYTE:
228 LOGW(
"TSD_INVALID_SYNC_BYTE");
230 case TSD_INVALID_CONTEXT:
231 LOGW(
"TSD_INVALID_CONTEXT");
233 case TSD_INVALID_DATA:
234 LOGW(
"TSD_INVALID_DATA");
236 case TSD_INVALID_DATA_SIZE:
237 LOGW(
"TSD_INVALID_DATA_SIZE");
239 case TSD_INVALID_ARGUMENT:
240 LOGW(
"TSD_INVALID_ARGUMENT");
242 case TSD_INVALID_START_CODE_PREFIX:
243 LOGW(
"TSD_INVALID_START_CODE_PREFIX");
245 case TSD_OUT_OF_MEMORY:
246 LOGW(
"TSD_OUT_OF_MEMORY");
248 case TSD_INCOMPLETE_TABLE:
249 LOGW(
"TSD_INCOMPLETE_TABLE");
251 case TSD_NOT_A_TABLE_PACKET:
252 LOGW(
"TSD_NOT_A_TABLE_PACKET");
254 case TSD_PARSE_ERROR:
255 LOGW(
"TSD_PARSE_ERROR");
257 case TSD_PID_ALREADY_REGISTERED:
258 LOGW(
"TSD_PID_ALREADY_REGISTERED");
260 case TSD_TSD_MAX_PID_REGS_REACHED:
261 LOGW(
"TSD_TSD_MAX_PID_REGS_REACHED");
263 case TSD_PID_NOT_FOUND:
264 LOGW(
"TSD_PID_NOT_FOUND");
266 case TSD_INVALID_POINTER_FIELD:
267 LOGW(
"TSD_INVALID_POINTER_FIELD");
273 static void event_cb(TSDemuxContext *ctx, uint16_t pid, TSDEventId event_id,
276 if (MTSDecoderTSDemux::self !=
nullptr) {
277 MTSDecoderTSDemux::self->event_cb_local(ctx, pid, event_id, data);
281 void event_cb_local(TSDemuxContext *ctx, uint16_t pid, TSDEventId event_id,
283 if (event_id == TSD_EVENT_PAT) {
284 set_write_active(
false);
285 print_pat(ctx, data);
286 }
else if (event_id == TSD_EVENT_PMT) {
287 set_write_active(
false);
288 print_pmt(ctx, data);
289 }
else if (event_id == TSD_EVENT_PES) {
290 TSDPESPacket *pes = (TSDPESPacket *)data;
292 LOGD(
"====================");
293 LOGD(
"PID %x PES Packet, Size: %zu, stream_id=%u, pts=%lu, dts=%lu", pid,
294 pes->data_bytes_length, pes->stream_id, (
unsigned long)pes->pts,
295 (
unsigned long)pes->dts);
298 AudioLogger logger = AudioLogger::instance();
299 for (i = 0; i < MTS_PRINT_PIDS_LEN; ++i) {
300 if (print_pids[i] == pid) {
302 if (logger.isLogging(AudioLogger::Debug)) {
303 logger.print(
" PES data");
304 logger.print(is_write_active ?
"active:" :
"inactive:");
306 while (j < pes->data_bytes_length) {
307 char n = pes->data_bytes[j];
308 logger.printCharHex(n);
311 logger.printChar(
'\n');
314 if (p_print !=
nullptr) {
317 size_t eff = writeData<uint8_t>(
318 p_print, (uint8_t *)pes->data_bytes, pes->data_bytes_length);
319 if (eff != pes->data_bytes_length) {
324 if (p_dec !=
nullptr) {
327 size_t eff = writeDataT<uint8_t,AudioDecoder>(
328 p_dec, (uint8_t *)pes->data_bytes, pes->data_bytes_length);
329 if (eff != pes->data_bytes_length) {
337 }
else if (event_id == TSD_EVENT_ADAP_FIELD_PRV_DATA) {
338 set_write_active(
false);
341 TSDAdaptationField *adap_field = (TSDAdaptationField *)data;
342 TSDDescriptor *descriptors = NULL;
343 size_t descriptors_length = 0;
344 tsd_descriptor_extract(ctx, adap_field->private_data_bytes,
345 adap_field->transport_private_data_length,
346 &descriptors, &descriptors_length);
348 LOGD(
"====================");
349 LOGD(
"Descriptors - Adaptation Fields");
351 for (; i < descriptors_length; ++i) {
352 TSDDescriptor *des = &descriptors[i];
353 LOGD(
" %d) tag: (0x%04X) %s", i, des->tag,
354 descriptor_tag_to_str(des->tag));
355 LOGD(
" length: %d", des->length);
356 print_descriptor_info(des);
361 void print_pat(TSDemuxContext *ctx,
void *data) {
362 LOGD(
"====================");
363 TSDPATData *pat = (TSDPATData *)data;
364 size_t len = pat->length;
366 LOGD(
"PAT, Length %d", (
int)pat->length);
369 LOGD(
"number of progs: %d", (
int)len);
371 for (i = 0; i < len; ++i) {
372 LOGD(
" %d) prog num: 0x%X, pid: 0x%X", (
int)i, pat->program_number[i],
377 void print_pmt(TSDemuxContext *ctx,
void *data) {
378 LOGD(
"====================");
380 TSDPMTData *pmt = (TSDPMTData *)data;
381 LOGD(
"PCR PID: 0x%04X", pmt->pcr_pid);
382 LOGD(
"program info length: %d", (
int)pmt->program_info_length);
383 LOGD(
"descriptors length: %d", (
int)pmt->descriptors_length);
386 for (i = 0; i < pmt->descriptors_length; ++i) {
387 TSDDescriptor *des = &pmt->descriptors[i];
388 LOGD(
" %d) tag: (0x%04X) %s", (
int)i, des->tag,
389 descriptor_tag_to_str(des->tag));
390 LOGD(
" length: %d", des->length);
391 print_descriptor_info(des);
394 LOGD(
"program elements length: %d", (
int)pmt->program_elements_length);
395 for (i = 0; i < pmt->program_elements_length; ++i) {
396 TSDProgramElement *prog = &pmt->program_elements[i];
397 LOGD(
" -----Program #%d", (
int)i);
398 LOGD(
" stream type: (0x%04X) %s", prog->stream_type,
399 stream_type_to_str((TSDPESStreamId)(prog->stream_type)));
400 LOGD(
" elementary pid: 0x%04X", prog->elementary_pid);
401 LOGD(
" es info length: %d", prog->es_info_length);
402 LOGD(
" descriptors length: %d", (
int)prog->descriptors_length);
404 if (isStreamTypeActive((TSDPMTStreamType)prog->stream_type)) {
405 set_write_active(
true);
409 for (
int j = 0; j < stream_types.size(); j++) {
410 add_print_pid(prog, stream_types[j]);
414 int reg_types = TSD_REG_PES;
417 for (j = 0; j < prog->descriptors_length; ++j) {
418 TSDDescriptor *des = &prog->descriptors[j];
419 LOGD(
" %d) tag: (0x%04X) %s", (
int)j, des->tag,
420 descriptor_tag_to_str(des->tag));
421 LOGD(
" length: %d", des->length);
422 print_descriptor_info(des);
426 if (des->tag == 0x97) {
427 reg_types |= TSD_REG_ADAPTATION_FIELD;
432 tsd_register_pid(ctx, prog->elementary_pid, reg_types);
436 void add_print_pid(TSDProgramElement *prog, TSDPMTStreamType type) {
437 if (prog->stream_type == type) {
439 for (k = 0; k < MTS_PRINT_PIDS_LEN; ++k) {
441 if (print_pids[k] == 0) {
442 print_pids[k] = prog->elementary_pid;
449 const char *stream_type_to_str(TSDPESStreamId stream_id) {
450 if (stream_id >= 0x1C && stream_id <= 0x7F && stream_id != 0x24 &&
452 stream_id = (TSDPESStreamId)0x1C;
453 }
else if (stream_id >= 0x8A && stream_id <= 0x8F) {
454 stream_id = (TSDPESStreamId)0x8A;
455 }
else if (stream_id >= 0x93 && stream_id <= 0x94) {
456 stream_id = (TSDPESStreamId)0x93;
457 }
else if (stream_id >= 0x96 && stream_id <= 0x9F) {
458 stream_id = (TSDPESStreamId)0x96;
459 }
else if (stream_id >= 0xA1 && stream_id <= 0xBF) {
460 stream_id = (TSDPESStreamId)0xA1;
461 }
else if (stream_id >= 0xC4 && stream_id <= 0xE9) {
462 stream_id = (TSDPESStreamId)0xC4;
463 }
else if (stream_id >= 0xEB && stream_id <= 0xFF) {
464 stream_id = (TSDPESStreamId)0xEB;
467#pragma GCC diagnostic push
468#pragma GCC diagnostic ignored "-Wswitch"
471 return "ITU-T | ISO/IEC Reserved";
473 return "ISO/IEC 11172 Video";
475 return "ITU-T Rec. H.262 | ISO/IEC 13818-2 Video";
477 return "ISO/IEC 11172 Audio";
479 return "ISO/IEC 13818-3 Audio";
481 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private sections";
483 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing "
486 return "ISO/IEC 13522 MHEG";
488 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 DSM-CC";
490 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1/11172-1 auxiliary";
492 return "ISO/IEC 13818-6 Multi-protocol Encapsulation";
494 return "ISO/IEC 13818-6 DSM-CC U-N Messages";
496 return "ISO/IEC 13818-6 Stream Descriptors";
498 return "ISO/IEC 13818-6 Sections (any type, including private data)";
500 return "ISO/IEC 13818-1 auxiliary";
502 return "ISO/IEC 13818-7 Audio (AAC) with ADTS transport";
504 return "ISO/IEC 14496-2 Visual";
506 return "ISO/IEC 14496-3 Audio with the LATM transport syntax as "
507 "defined in ISO/IEC 14496-3";
509 return "ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried "
512 return "ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried "
513 "in ISO/IEC 14496_sections";
515 return "ISO/IEC 13818-6 DSM-CC Synchronized Download Protocol";
517 return "Metadata carried in PES packets";
519 return "Metadata carried in metadata_sections";
521 return "Metadata carried in ISO/IEC 13818-6 Data Carousel";
523 return "Metadata carried in ISO/IEC 13818-6 Object Carousel";
525 return "Metadata carried in ISO/IEC 13818-6 Synchronized Download "
528 return "IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP)";
530 return "AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC "
533 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved";
535 return "ITU-T Rec. H.265 and ISO/IEC 23008-2 (Ultra HD video) in a "
538 return "Chinese Video Standard in a packetized stream";
540 return "DigiCipher® II video | Identical to ITU-T Rec. H.262 | ISO/IEC "
543 return "ATSC A/53 audio [2] | AC-3 audio";
545 return "SCTE Standard Subtitle";
547 return "SCTE Isochronous Data | Reserved";
549 return "ATSC/SCTE reserved";
551 return "ATSC Program Identifier , SCTE Reserved";
553 return "SCTE 35 splice_information_table | [Cueing]";
557 return "DTS HD Audio";
559 return "ATSC Reserved";
561 return "ATSC Reserved";
563 return "DVB stream_type value for Time Slicing / MPE-FEC";
565 return "IETF Unidirectional Link Encapsulation (ULE)";
567 return "VEI stream_type";
569 return "ATSC Reserved";
571 return "ATSC Data Service Table, Network Resources Table";
573 return "ATSC Reserved";
575 return "SCTE [IP Data] | ATSC Reserved";
577 return "ATSC Reserved";
579 return "DCII (DigiCipher®) Text";
581 return "ATSC Reserved";
583 return "ATSC synchronous data stream | [Isochronous Data]";
585 return "SCTE Asynchronous Data";
587 return "ATSC User Private Program Elements";
589 return "VC-1 Elementary Stream per RP227";
591 return "ATSC User Private Program Elements";
595#pragma GCC diagnostic pop
598 const char *descriptor_tag_to_str(uint8_t tag) {
599 if (tag >= 0x24 && tag <= 0x27) {
601 }
else if (tag >= 0x29 && tag <= 0x35) {
603 }
else if (tag >= 0x3A && tag <= 0x3F) {
605 }
else if (tag >= 0x40 && tag <= 0x51) {
607 }
else if (tag >= 0x98 && tag <= 0x9F) {
611#pragma GCC diagnostic push
612#pragma GCC diagnostic ignored "-Wswitch"
617 return "ISO/IEC 13818 Reserved";
619 return "video_stream_descriptor";
621 return "audio_stream_descriptor";
623 return "hierarchy_descriptor";
625 return "registration_descriptor";
627 return "data_stream_alignment_descriptor";
629 return "target_background_grid_descriptor";
631 return "video_window_descriptor";
633 return "CA_descriptor";
635 return "ISO_639_language_descriptor";
637 return "system_clock_descriptor";
639 return "multiplex_buffer_utilization_descriptor";
641 return "copyright_descriptor";
643 return "Maximum_bitrate_descriptor";
645 return "Private_data_indicator_descriptor";
647 return "smoothing_buffer_descriptor";
649 return "STD_descriptor";
651 return "IBP descriptor";
653 return "DSM-CC carousel_identifier_descriptor";
655 return "DSM-CC association_tag_descriptor";
657 return "DSM-CC deferred_association_tags_descriptor";
659 return "ISO/IEC 13818-6 reserved";
661 return "NPT Reference descriptor";
663 return "NPT Endpoint descriptor";
665 return "Stream Mode descriptor";
667 return "Stream Event descriptor";
669 return "MPEG-4_video_descriptor";
671 return "MPEG-4_audio_descriptor";
673 return "IOD_descriptor";
675 return "SL_descriptor";
677 return "FMC_descriptor";
679 return "External_ES_ID_descriptor";
681 return "MuxCode_descriptor";
683 return "FmxBufferSize_descriptor";
685 return "MultiplexBuffer_descriptor";
687 return "Reserved for ISO/IEC 13818-1 use";
689 return "AVC_video_descriptor()";
691 return "Reserved for ISO/IEC 13818-1 use";
693 return "content_labeling_descriptor";
695 return "Metadata_location_descriptor";
697 return "ISO/IEC 13818 Reserved";
699 return "User Private";
701 return "SCTE 35 Stream Identifier Descriptor";
703 return "ACAP-X Application Descriptor";
705 return "ACAP-X Application Location Descriptor";
707 return "ACAP-X Application Boundary Descriptor";
709 return "Stuffing_descriptor";
711 return "AC3_audio_descriptor";
713 return "SCTE Frame_rate_descriptor";
715 return "SCTE Extended_video_descriptor";
717 return "SCTE Component_name_descriptor";
719 return "ATSC program_identifier";
721 return "Caption_service_descriptor";
723 return "Content_advisory_descriptor";
725 return "ATSC CA_descriptor";
727 return "ATSC Descriptor_tag";
729 return "SCTE 35 cue identifier descriptor";
731 return "ATSC/SCTE Reserved";
733 return "TimeStampDescriptor";
735 return "parameterized_service_descriptor() ";
737 return "Interactive Services Filtering Criteria descriptor";
739 return "Interactive Services NRT Services Summary descriptor";
741 return "SCTE Frequency_spec_descriptor";
743 return "SCTE Modulation_params_descriptor";
745 return "SCTE Transport_stream_id_descriptor";
747 return "SCTE Revision detection descriptor";
749 return "SCTE Two part channel number descriptor";
751 return "SCTE Channel properties descriptor";
753 return "SCTE Daylight Savings Time Descriptor";
755 return "SCTE_adaptation_field_data_descriptor()";
757 return "SCTE Reserved";
759 return "extended_channel_name_descriptor";
761 return "ATSC service_location_descriptor";
763 return "time_shifted_service_descriptor";
765 return "component_name_descriptor";
767 return "ATSC data_service_descriptor";
769 return "ATSC PID Count descriptor";
771 return "ATSC Download descriptor";
773 return "ATSC Multiprotocol Encapsulation descriptor";
775 return "ATSC dcc_departing_request_descriptor";
777 return "ATSC dcc_arriving_request_descriptor";
779 return "ATSC rc_descriptor";
781 return "ATSC Genre descriptor";
783 return "SCTE MAC Address List";
785 return "ATSC private information descriptor";
787 return "ATSC compatibility wrapper descriptor";
789 return "ATSC broadcaster policy descriptor";
791 return "ATSC service name descriptor";
793 return "ATSC URI descriptor";
795 return "ATSC enhanced signaling descriptor";
797 return "ATSC M/H string mapping descriptor";
799 return "ATSC Module Link descriptor";
801 return "ATSC CRC32 descriptor";
803 return "ATSC Content Identifier Descriptor";
805 return "ModuleInfoDescriptor";
807 return "ATSC Group Link descriptor";
809 return "ATSC Time Stamp descriptor";
811 return "ScheduleDescriptor";
813 return "Component list descriptor";
815 return "ATSC M/H component descriptor";
817 return "ATSC M/H rights issuer descriptor";
819 return "ATSC M/H current program descriptor";
821 return "ATSC M/H original service identification descriptor";
823 return "protection_descriptor";
825 return "MH_SG_bootstrap_descriptor";
827 return "Service ID descriptor";
829 return "Protocol Version descriptor";
831 return "NRT Service descriptor";
833 return "Capabilities descriptor";
835 return "Icon descriptor";
837 return "Receiver Targeting descriptor";
839 return "Time Slot descriptor";
841 return "Internet Location Descriptor";
843 return "Associated Service descriptor";
845 return "Eye Identification Descriptor tag";
847 return "E-AC-3 descriptor (A/52 Annex G)";
849 return "2D 3D Corresponding Content Descriptor";
851 return "Multimedia EPG Linkage Descriptor";
853 return "etv_application_information_descriptor()";
855 return "etv_media_time_descriptor()";
857 return "etv_stream_event_descriptor()";
859 return "etv_application_descriptor()";
861 return "RBI_signaling_descriptor()";
863 return "etv_application_metadata_descriptor()";
865 return "etv_bif_platform_descriptor()";
867 return "etv_integrated_signaling_descriptor()";
869 return "3d_MPEG2_descriptor()";
871 return "ebp_descriptor()";
873 return "MPEG_AAC_descriptor";
875 return "IC3D_event_info_descriptor";
877 return "MDTV hybrid stereoscopic service descriptor";
879#pragma GCC diagnostic pop
883 void print_descriptor_info(TSDDescriptor *desc) {
888 TSDDescriptorRegistration res;
889 if (TSD_OK == tsd_parse_descriptor_registration(
890 desc->data, desc->data_length, &res)) {
891 LOGD(
"\n format identififer: 0x%08X", res.format_identifier);
896 TSDDescriptorISO639Language res;
897 if (TSD_OK == tsd_parse_descriptor_iso639_language(
898 desc->data, desc->data_length, &res)) {
901 for (; i < res.language_length; ++i) {
902 LOGD(
" ISO Language Code: 0x%08X, audio type: 0x%02x",
903 res.iso_language_code[i], res.audio_type[i]);
910 TSDDescriptorMaxBitrate res;
911 if (TSD_OK == tsd_parse_descriptor_max_bitrate(
912 desc->data, desc->data_length, &res)) {
913 LOGD(
" Maximum Bitrate: %d x 50 bytes/second", res.max_bitrate);
917 LOGW(
" Unknown Descriptor: 0x%x ", desc->tag);
922 static void *log_malloc(
size_t size) {
923 void *result =
nullptr;
925 result = ps_malloc(size);
926 if (result !=
nullptr)
return result;
928 result = malloc(size);
929 LOGI(
"malloc(%d) -> %p %s", (
int)size, result,
930 result != NULL ?
"OK" :
"ERROR");
934 static void *log_calloc(
size_t num,
size_t size) {
935 void *result =
nullptr;
937 result = ps_calloc(num, size);
938 if (result !=
nullptr)
return result;
940 result = calloc(num, size);
941 LOGI(
"calloc(%d) -> %p %s", (
int)(num * size), result,
942 result != NULL ?
"OK" :
"ERROR");
946 static void *log_realloc(
void *ptr,
size_t size) {
947 void *result =
nullptr;
949 result = ps_realloc(ptr, size);
950 if (result !=
nullptr)
return result;
952 result = realloc(ptr, size);
953 LOGI(
"realloc(%d) -> %p %s", (
int)size, result,
954 result != NULL ?
"OK" :
"ERROR");
958 static void log_free(
void *mem) {
959 LOGD(
"free(%p)", mem);