arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
CodecTSDemux.h
1#pragma once
2
3#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
4
5namespace audio_tools {
6
7#include "AudioTools/AudioCodecs/AudioEncoded.h"
8#include "stdlib.h"
9#include "tsdemux.h"
10
11#ifndef MTS_PRINT_PIDS_LEN
12#define MTS_PRINT_PIDS_LEN (16)
13#endif
14
15#ifndef MTS_UNDERFLOW_LIMIT
16#define MTS_UNDERFLOW_LIMIT 188
17#endif
18
19#ifndef MTS_WRITE_BUFFER_SIZE
20#define MTS_WRITE_BUFFER_SIZE 2000
21#endif
22
23#ifndef ALLOC_MEM_INIT
24#define ALLOC_MEM_INIT 0
25#endif
26
27struct AllocSize {
28 void *data = nullptr;
29 size_t size = 0;
30
31 AllocSize() = default;
32 AllocSize(void *data, size_t size) {
33 this->data = data;
34 this->size = size;
35 }
36};
37
49 public:
50 MTSDecoderTSDemux() { self = this; };
51 MTSDecoderTSDemux(AudioDecoder &dec) { p_dec = &dec; };
52
53 bool begin() override {
54 TRACED();
55 // automatically close when called multiple times
56 if (is_active) {
57 end();
58 }
59
60 if (p_dec) p_dec->begin();
61
62 is_active = true;
63
64 // create the pids we plan on printing
65 memset(print_pids, 0, sizeof(print_pids));
66
67 // set default values onto the context.
68 if (tsd_context_init(&ctx) != TSD_OK) {
69 TRACEE();
70 is_active = false;
71 }
72
73 // log memory allocations ?
74 if (is_alloc_active) {
75 ctx.malloc = log_malloc;
76 ctx.realloc = log_realloc;
77 ctx.calloc = log_calloc;
78 ctx.free = log_free;
79 }
80
81 // default supported stream types
82 if (stream_types.empty()) {
83 addStreamType(TSD_PMT_STREAM_TYPE_PES_METADATA);
84 addStreamType(TSD_PMT_STREAM_TYPE_AUDIO_AAC);
85 }
86
87 // add a callback.
88 // the callback is used to determine which PIDs contain the data we want
89 // to demux. We also receive PES data for any PIDs that we register later
90 // on.
91 if (tsd_set_event_callback(&ctx, event_cb) != TSD_OK) {
92 TRACEE();
93 is_active = false;
94 }
95 return true;
96 }
97
98 void end() override {
99 TRACED();
100 if (p_dec) p_dec->begin();
101
102 // finally end the demux process which will flush any remaining PES data.
103 tsd_demux_end(&ctx);
104
105 // destroy context
106 tsd_context_destroy(&ctx);
107
108 is_active = false;
109 }
110
111 virtual operator bool() override { return is_active; }
112
113 const char *mime() { return "video/MP2T"; }
114
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);
119 // demux
120 demux(underflowLimit);
121 return result;
122 }
123
124 void flush() { demux(0); }
125
126 void clearStreamTypes() {
127 TRACED();
128 stream_types.clear();
129 }
130
131 void addStreamType(TSDPMTStreamType type) {
132 TRACED();
133 stream_types.push_back(type);
134 }
135
136 bool isStreamTypeActive(TSDPMTStreamType type) {
137 for (int j = 0; j < stream_types.size(); j++) {
138 if (stream_types[j] == type) return true;
139 }
140 return false;
141 }
142
144 void resizeBuffer(int size) { buffer.resize(size); }
145
147 void setMemoryAllocationLogging(bool flag) { is_alloc_active = flag; }
148
150 void setOutput(AudioStream &out_stream) override {
151 if (p_dec) {
152 p_dec->setOutput(out_stream);
153 } else {
154 AudioDecoder::setOutput(out_stream);
155 }
156 }
157
159 void setOutput(AudioOutput &out_stream) override {
160 if (p_dec) {
161 p_dec->setOutput(out_stream);
162 } else {
163 AudioDecoder::setOutput(out_stream);
164 }
165 }
166
168 void setOutput(Print &out_stream) override {
169 if (p_dec) {
170 p_dec->setOutput(out_stream);
171 } else {
172 AudioDecoder::setOutput(out_stream);
173 }
174 }
175
176 protected:
177 static MTSDecoderTSDemux *self;
178 int underflowLimit = MTS_UNDERFLOW_LIMIT;
179 bool is_active = false;
180 bool is_write_active = false;
181 bool is_alloc_active = false;
182 TSDemuxContext ctx;
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;
188
189 void set_write_active(bool flag) {
190 // LOGD("is_write_active: %s", flag ? "true":"false");
191 is_write_active = flag;
192 }
193
195 bool is_new_file(uint8_t *data) {
196 bool payloadUnitStartIndicator = (data[1] & 0x40) >> 6;
197 bool result = data[0] == 0x47 && payloadUnitStartIndicator;
198 return result;
199 }
200
201 void demux(int limit) {
202 TRACED();
203 TSDCode res = TSD_OK;
204 int count = 0;
205 while (res == TSD_OK && buffer.available() >= limit) {
206 // Unfortunatly we need to reset the demux after each file
207 if (is_new_file(buffer.data())) {
208 LOGD("parsing new file");
209 begin();
210 }
211 size_t len = 0;
212 res = tsd_demux(&ctx, (void *)buffer.data(), buffer.available(), &len);
213 // remove processed bytes
214 buffer.clearArray(len);
215 // get next bytes
216 count++;
217 if (res != TSD_OK) logResult(res);
218 }
219 LOGD("Number of demux calls: %d", count);
220 }
221
222 void logResult(TSDCode code) {
223 switch (code) {
224 case TSD_OK:
225 LOGD("TSD_OK");
226 break;
227 case TSD_INVALID_SYNC_BYTE:
228 LOGW("TSD_INVALID_SYNC_BYTE");
229 break;
230 case TSD_INVALID_CONTEXT:
231 LOGW("TSD_INVALID_CONTEXT");
232 break;
233 case TSD_INVALID_DATA:
234 LOGW("TSD_INVALID_DATA");
235 break;
236 case TSD_INVALID_DATA_SIZE:
237 LOGW("TSD_INVALID_DATA_SIZE");
238 break;
239 case TSD_INVALID_ARGUMENT:
240 LOGW("TSD_INVALID_ARGUMENT");
241 break;
242 case TSD_INVALID_START_CODE_PREFIX:
243 LOGW("TSD_INVALID_START_CODE_PREFIX");
244 break;
245 case TSD_OUT_OF_MEMORY:
246 LOGW("TSD_OUT_OF_MEMORY");
247 break;
248 case TSD_INCOMPLETE_TABLE:
249 LOGW("TSD_INCOMPLETE_TABLE");
250 break;
251 case TSD_NOT_A_TABLE_PACKET:
252 LOGW("TSD_NOT_A_TABLE_PACKET");
253 break;
254 case TSD_PARSE_ERROR:
255 LOGW("TSD_PARSE_ERROR");
256 break;
257 case TSD_PID_ALREADY_REGISTERED:
258 LOGW("TSD_PID_ALREADY_REGISTERED");
259 break;
260 case TSD_TSD_MAX_PID_REGS_REACHED:
261 LOGW("TSD_TSD_MAX_PID_REGS_REACHED");
262 break;
263 case TSD_PID_NOT_FOUND:
264 LOGW("TSD_PID_NOT_FOUND");
265 break;
266 case TSD_INVALID_POINTER_FIELD:
267 LOGW("TSD_INVALID_POINTER_FIELD");
268 break;
269 }
270 }
271
272 // event callback
273 static void event_cb(TSDemuxContext *ctx, uint16_t pid, TSDEventId event_id,
274 void *data) {
275 TRACED();
276 if (MTSDecoderTSDemux::self != nullptr) {
277 MTSDecoderTSDemux::self->event_cb_local(ctx, pid, event_id, data);
278 }
279 }
280
281 void event_cb_local(TSDemuxContext *ctx, uint16_t pid, TSDEventId event_id,
282 void *data) {
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;
291 // This is where we write the PES data into our buffer.
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);
296 // print out the PES Packet data if it's in our print list
297 int i;
298 AudioLogger logger = AudioLogger::instance();
299 for (i = 0; i < MTS_PRINT_PIDS_LEN; ++i) {
300 if (print_pids[i] == pid) {
301 // log data
302 if (logger.isLogging(AudioLogger::Debug)) {
303 logger.print(" PES data");
304 logger.print(is_write_active ? "active:" : "inactive:");
305 int j = 0;
306 while (j < pes->data_bytes_length) {
307 char n = pes->data_bytes[j];
308 logger.printCharHex(n);
309 ++j;
310 }
311 logger.printChar('\n');
312 }
313 // output data
314 if (p_print != nullptr) {
315 // size_t eff = p_print->write(pes->data_bytes,
316 // pes->data_bytes_length);
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) {
320 // we should not get here
321 TRACEE();
322 }
323 }
324 if (p_dec != nullptr) {
325 // size_t eff = p_print->write(pes->data_bytes,
326 // pes->data_bytes_length);
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) {
330 // we should not get here
331 TRACEE();
332 }
333 }
334 }
335 }
336
337 } else if (event_id == TSD_EVENT_ADAP_FIELD_PRV_DATA) {
338 set_write_active(false);
339 // we're only watching for SCTE Adaptions Field Private Data,
340 // so we know that we must parse it as a list of descritors.
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);
347
348 LOGD("====================");
349 LOGD("Descriptors - Adaptation Fields");
350 int i = 0;
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);
357 }
358 }
359 }
360
361 void print_pat(TSDemuxContext *ctx, void *data) {
362 LOGD("====================");
363 TSDPATData *pat = (TSDPATData *)data;
364 size_t len = pat->length;
365 size_t i;
366 LOGD("PAT, Length %d", (int)pat->length);
367
368 if (len > 1) {
369 LOGD("number of progs: %d", (int)len);
370 }
371 for (i = 0; i < len; ++i) {
372 LOGD(" %d) prog num: 0x%X, pid: 0x%X", (int)i, pat->program_number[i],
373 pat->pid[i]);
374 }
375 }
376
377 void print_pmt(TSDemuxContext *ctx, void *data) {
378 LOGD("====================");
379 LOGD("PMT");
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);
384 size_t i;
385
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);
392 }
393
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);
403
404 if (isStreamTypeActive((TSDPMTStreamType)prog->stream_type)) {
405 set_write_active(true);
406 }
407
408 // keep track of metadata pids, we'll print the data for these
409 for (int j = 0; j < stream_types.size(); j++) {
410 add_print_pid(prog, stream_types[j]);
411 }
412
413 // we'll register to listen to the PES data for this program.
414 int reg_types = TSD_REG_PES;
415
416 size_t j;
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);
423
424 // if this tag is the SCTE Adaption field private data descriptor,
425 // we'll also register for the Adaptation Field Privae Data.
426 if (des->tag == 0x97) {
427 reg_types |= TSD_REG_ADAPTATION_FIELD;
428 }
429 }
430
431 // register all the PIDs we come across.
432 tsd_register_pid(ctx, prog->elementary_pid, reg_types);
433 }
434 }
435
436 void add_print_pid(TSDProgramElement *prog, TSDPMTStreamType type) {
437 if (prog->stream_type == type) {
438 int k;
439 for (k = 0; k < MTS_PRINT_PIDS_LEN; ++k) {
440 // find a spare slot in the pids
441 if (print_pids[k] == 0) {
442 print_pids[k] = prog->elementary_pid;
443 break;
444 }
445 }
446 }
447 }
448
449 const char *stream_type_to_str(TSDPESStreamId stream_id) {
450 if (stream_id >= 0x1C && stream_id <= 0x7F && stream_id != 0x24 &&
451 stream_id != 0x42) {
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;
465 }
466
467#pragma GCC diagnostic push
468#pragma GCC diagnostic ignored "-Wswitch"
469 switch (stream_id) {
470 case 0x00:
471 return "ITU-T | ISO/IEC Reserved";
472 case 0x01:
473 return "ISO/IEC 11172 Video";
474 case 0x02:
475 return "ITU-T Rec. H.262 | ISO/IEC 13818-2 Video";
476 case 0x03:
477 return "ISO/IEC 11172 Audio";
478 case 0x04:
479 return "ISO/IEC 13818-3 Audio";
480 case 0x05:
481 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private sections";
482 case 0x06:
483 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing "
484 "private data";
485 case 0x07:
486 return "ISO/IEC 13522 MHEG";
487 case 0x08:
488 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 DSM-CC";
489 case 0x09:
490 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1/11172-1 auxiliary";
491 case 0x0A:
492 return "ISO/IEC 13818-6 Multi-protocol Encapsulation";
493 case 0x0B:
494 return "ISO/IEC 13818-6 DSM-CC U-N Messages";
495 case 0x0C:
496 return "ISO/IEC 13818-6 Stream Descriptors";
497 case 0x0D:
498 return "ISO/IEC 13818-6 Sections (any type, including private data)";
499 case 0x0E:
500 return "ISO/IEC 13818-1 auxiliary";
501 case 0x0F:
502 return "ISO/IEC 13818-7 Audio (AAC) with ADTS transport";
503 case 0x10:
504 return "ISO/IEC 14496-2 Visual";
505 case 0x11:
506 return "ISO/IEC 14496-3 Audio with the LATM transport syntax as "
507 "defined in ISO/IEC 14496-3";
508 case 0x12:
509 return "ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried "
510 "in PES packets";
511 case 0x13:
512 return "ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried "
513 "in ISO/IEC 14496_sections";
514 case 0x14:
515 return "ISO/IEC 13818-6 DSM-CC Synchronized Download Protocol";
516 case 0x15:
517 return "Metadata carried in PES packets";
518 case 0x16:
519 return "Metadata carried in metadata_sections";
520 case 0x17:
521 return "Metadata carried in ISO/IEC 13818-6 Data Carousel";
522 case 0x18:
523 return "Metadata carried in ISO/IEC 13818-6 Object Carousel";
524 case 0x19:
525 return "Metadata carried in ISO/IEC 13818-6 Synchronized Download "
526 "Protocol";
527 case 0x1A:
528 return "IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP)";
529 case 0X1B:
530 return "AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC "
531 "14496-10 Video";
532 case 0x1C:
533 return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved";
534 case 0x24:
535 return "ITU-T Rec. H.265 and ISO/IEC 23008-2 (Ultra HD video) in a "
536 "packetized stream";
537 case 0x42:
538 return "Chinese Video Standard in a packetized stream";
539 case 0x80:
540 return "DigiCipher® II video | Identical to ITU-T Rec. H.262 | ISO/IEC "
541 "13818-2 Video";
542 case 0x81:
543 return "ATSC A/53 audio [2] | AC-3 audio";
544 case 0x82:
545 return "SCTE Standard Subtitle";
546 case 0x83:
547 return "SCTE Isochronous Data | Reserved";
548 case 0x84:
549 return "ATSC/SCTE reserved";
550 case 0x85:
551 return "ATSC Program Identifier , SCTE Reserved";
552 case 0x86:
553 return "SCTE 35 splice_information_table | [Cueing]";
554 case 0x87:
555 return "E-AC-3";
556 case 0x88:
557 return "DTS HD Audio";
558 case 0x89:
559 return "ATSC Reserved";
560 case 0x8A:
561 return "ATSC Reserved";
562 case 0x90:
563 return "DVB stream_type value for Time Slicing / MPE-FEC";
564 case 0x91:
565 return "IETF Unidirectional Link Encapsulation (ULE)";
566 case 0x92:
567 return "VEI stream_type";
568 case 0x93:
569 return "ATSC Reserved";
570 case 0x95:
571 return "ATSC Data Service Table, Network Resources Table";
572 case 0x96:
573 return "ATSC Reserved";
574 case 0xA0:
575 return "SCTE [IP Data] | ATSC Reserved";
576 case 0xA1:
577 return "ATSC Reserved";
578 case 0xC0:
579 return "DCII (DigiCipher®) Text";
580 case 0xC1:
581 return "ATSC Reserved";
582 case 0xC2:
583 return "ATSC synchronous data stream | [Isochronous Data]";
584 case 0xC3:
585 return "SCTE Asynchronous Data";
586 case 0xC4:
587 return "ATSC User Private Program Elements";
588 case 0xEA:
589 return "VC-1 Elementary Stream per RP227";
590 case 0xEB:
591 return "ATSC User Private Program Elements";
592 default:
593 return "Unknown";
594 }
595#pragma GCC diagnostic pop
596 }
597
598 const char *descriptor_tag_to_str(uint8_t tag) {
599 if (tag >= 0x24 && tag <= 0x27) {
600 tag = 0x24;
601 } else if (tag >= 0x29 && tag <= 0x35) {
602 tag = 0x29;
603 } else if (tag >= 0x3A && tag <= 0x3F) {
604 tag = 0x3A;
605 } else if (tag >= 0x40 && tag <= 0x51) {
606 tag = 0x40;
607 } else if (tag >= 0x98 && tag <= 0x9F) {
608 tag = 0x98;
609 }
610
611#pragma GCC diagnostic push
612#pragma GCC diagnostic ignored "-Wswitch"
613
614 switch (tag) {
615 case 0x00:
616 case 0x01:
617 return "ISO/IEC 13818 Reserved";
618 case 0x02:
619 return "video_stream_descriptor";
620 case 0x03:
621 return "audio_stream_descriptor";
622 case 0x04:
623 return "hierarchy_descriptor";
624 case 0x05:
625 return "registration_descriptor";
626 case 0x06:
627 return "data_stream_alignment_descriptor";
628 case 0x07:
629 return "target_background_grid_descriptor";
630 case 0x08:
631 return "video_window_descriptor";
632 case 0x09:
633 return "CA_descriptor";
634 case 0x0A:
635 return "ISO_639_language_descriptor";
636 case 0x0B:
637 return "system_clock_descriptor";
638 case 0x0C:
639 return "multiplex_buffer_utilization_descriptor";
640 case 0x0D:
641 return "copyright_descriptor";
642 case 0x0E:
643 return "Maximum_bitrate_descriptor";
644 case 0x0F:
645 return "Private_data_indicator_descriptor";
646 case 0x10:
647 return "smoothing_buffer_descriptor";
648 case 0x11:
649 return "STD_descriptor";
650 case 0x12:
651 return "IBP descriptor";
652 case 0x13:
653 return "DSM-CC carousel_identifier_descriptor";
654 case 0x14:
655 return "DSM-CC association_tag_descriptor";
656 case 0x15:
657 return "DSM-CC deferred_association_tags_descriptor";
658 case 0x16:
659 return "ISO/IEC 13818-6 reserved";
660 case 0x17:
661 return "NPT Reference descriptor";
662 case 0x18:
663 return "NPT Endpoint descriptor";
664 case 0x19:
665 return "Stream Mode descriptor";
666 case 0x1A:
667 return "Stream Event descriptor";
668 case 0x1B:
669 return "MPEG-4_video_descriptor";
670 case 0x1C:
671 return "MPEG-4_audio_descriptor";
672 case 0x1D:
673 return "IOD_descriptor";
674 case 0x1E:
675 return "SL_descriptor";
676 case 0x1F:
677 return "FMC_descriptor";
678 case 0x20:
679 return "External_ES_ID_descriptor";
680 case 0x21:
681 return "MuxCode_descriptor";
682 case 0x22:
683 return "FmxBufferSize_descriptor";
684 case 0x23:
685 return "MultiplexBuffer_descriptor";
686 case 0x24:
687 return "Reserved for ISO/IEC 13818-1 use";
688 case 0x28:
689 return "AVC_video_descriptor()";
690 case 0x29:
691 return "Reserved for ISO/IEC 13818-1 use";
692 case 0x36:
693 return "content_labeling_descriptor";
694 case 0x37:
695 return "Metadata_location_descriptor";
696 case 0x3A:
697 return "ISO/IEC 13818 Reserved";
698 case 0x40:
699 return "User Private";
700 case 0x52:
701 return "SCTE 35 Stream Identifier Descriptor";
702 case 0x60:
703 return "ACAP-X Application Descriptor";
704 case 0x61:
705 return "ACAP-X Application Location Descriptor";
706 case 0x62:
707 return "ACAP-X Application Boundary Descriptor";
708 case 0x80:
709 return "Stuffing_descriptor";
710 case 0x81:
711 return "AC3_audio_descriptor";
712 case 0x82:
713 return "SCTE Frame_rate_descriptor";
714 case 0x83:
715 return "SCTE Extended_video_descriptor";
716 case 0x84:
717 return "SCTE Component_name_descriptor";
718 case 0x85:
719 return "ATSC program_identifier";
720 case 0x86:
721 return "Caption_service_descriptor";
722 case 0x87:
723 return "Content_advisory_descriptor";
724 case 0x88:
725 return "ATSC CA_descriptor";
726 case 0x89:
727 return "ATSC Descriptor_tag";
728 case 0x8A:
729 return "SCTE 35 cue identifier descriptor";
730 case 0x8B:
731 return "ATSC/SCTE Reserved";
732 case 0x8C:
733 return "TimeStampDescriptor";
734 case 0x8D:
735 return "parameterized_service_descriptor() ";
736 case 0x8E:
737 return "Interactive Services Filtering Criteria descriptor";
738 case 0x8F:
739 return "Interactive Services NRT Services Summary descriptor";
740 case 0x90:
741 return "SCTE Frequency_spec_descriptor";
742 case 0x91:
743 return "SCTE Modulation_params_descriptor";
744 case 0x92:
745 return "SCTE Transport_stream_id_descriptor";
746 case 0x93:
747 return "SCTE Revision detection descriptor";
748 case 0x94:
749 return "SCTE Two part channel number descriptor";
750 case 0x95:
751 return "SCTE Channel properties descriptor";
752 case 0x96:
753 return "SCTE Daylight Savings Time Descriptor";
754 case 0x97:
755 return "SCTE_adaptation_field_data_descriptor()";
756 case 0x98:
757 return "SCTE Reserved";
758 case 0xA0:
759 return "extended_channel_name_descriptor";
760 case 0xA1:
761 return "ATSC service_location_descriptor";
762 case 0xA2:
763 return "time_shifted_service_descriptor";
764 case 0xA3:
765 return "component_name_descriptor";
766 case 0xA4:
767 return "ATSC data_service_descriptor";
768 case 0xA5:
769 return "ATSC PID Count descriptor";
770 case 0xA6:
771 return "ATSC Download descriptor";
772 case 0xA7:
773 return "ATSC Multiprotocol Encapsulation descriptor";
774 case 0xA8:
775 return "ATSC dcc_departing_request_descriptor";
776 case 0xA9:
777 return "ATSC dcc_arriving_request_descriptor";
778 case 0xAA:
779 return "ATSC rc_descriptor";
780 case 0xAB:
781 return "ATSC Genre descriptor";
782 case 0xAC:
783 return "SCTE MAC Address List";
784 case 0xAD:
785 return "ATSC private information descriptor";
786 case 0xAE:
787 return "ATSC compatibility wrapper descriptor";
788 case 0xAF:
789 return "ATSC broadcaster policy descriptor";
790 case 0xB0:
791 return "ATSC service name descriptor";
792 case 0xB1:
793 return "ATSC URI descriptor";
794 case 0xB2:
795 return "ATSC enhanced signaling descriptor";
796 case 0xB3:
797 return "ATSC M/H string mapping descriptor";
798 case 0xB4:
799 return "ATSC Module Link descriptor";
800 case 0xB5:
801 return "ATSC CRC32 descriptor";
802 case 0xB6:
803 return "ATSC Content Identifier Descriptor";
804 case 0xB7:
805 return "ModuleInfoDescriptor";
806 case 0xB8:
807 return "ATSC Group Link descriptor";
808 case 0xB9:
809 return "ATSC Time Stamp descriptor";
810 case 0xBA:
811 return "ScheduleDescriptor";
812 case 0xBB:
813 return "Component list descriptor";
814 case 0xBC:
815 return "ATSC M/H component descriptor";
816 case 0xBD:
817 return "ATSC M/H rights issuer descriptor";
818 case 0xBE:
819 return "ATSC M/H current program descriptor";
820 case 0xBF:
821 return "ATSC M/H original service identification descriptor";
822 case 0xC0:
823 return "protection_descriptor";
824 case 0xC1:
825 return "MH_SG_bootstrap_descriptor";
826 case 0xC2:
827 return "Service ID descriptor";
828 case 0xC3:
829 return "Protocol Version descriptor";
830 case 0xC4:
831 return "NRT Service descriptor";
832 case 0xC5:
833 return "Capabilities descriptor";
834 case 0xC6:
835 return "Icon descriptor";
836 case 0xC7:
837 return "Receiver Targeting descriptor";
838 case 0xC8:
839 return "Time Slot descriptor";
840 case 0xC9:
841 return "Internet Location Descriptor";
842 case 0xCA:
843 return "Associated Service descriptor";
844 case 0xCB:
845 return "Eye Identification Descriptor tag";
846 case 0xCC:
847 return "E-AC-3 descriptor (A/52 Annex G)";
848 case 0xCD:
849 return "2D 3D Corresponding Content Descriptor";
850 case 0xCE:
851 return "Multimedia EPG Linkage Descriptor";
852 case 0xE0:
853 return "etv_application_information_descriptor()";
854 case 0xE1:
855 return "etv_media_time_descriptor()";
856 case 0xE2:
857 return "etv_stream_event_descriptor()";
858 case 0xE3:
859 return "etv_application_descriptor()";
860 case 0xE4:
861 return "RBI_signaling_descriptor()";
862 case 0xE5:
863 return "etv_application_metadata_descriptor()";
864 case 0xE6:
865 return "etv_bif_platform_descriptor()";
866 case 0xE7:
867 return "etv_integrated_signaling_descriptor()";
868 case 0xE8:
869 return "3d_MPEG2_descriptor()";
870 case 0XE9:
871 return "ebp_descriptor()";
872 case 0xEA:
873 return "MPEG_AAC_descriptor";
874 case 0xEB:
875 return "IC3D_event_info_descriptor";
876 case 0xEC:
877 return "MDTV hybrid stereoscopic service descriptor";
878 }
879#pragma GCC diagnostic pop
880 return "Unknown";
881 }
882
883 void print_descriptor_info(TSDDescriptor *desc) {
884 // print out some interesting descriptor data
885 switch (desc->tag) {
886 case 0x05: // Registration descriptor
887 {
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);
892 }
893 } break;
894 case 0x0A: // ISO 639 Language descriptor
895 {
896 TSDDescriptorISO639Language res;
897 if (TSD_OK == tsd_parse_descriptor_iso639_language(
898 desc->data, desc->data_length, &res)) {
899 LOGD("\n");
900 int i = 0;
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]);
904 }
905 LOGD("\n");
906 }
907 } break;
908 case 0x0E: // Maximum bitrate descriptor
909 {
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);
914 }
915 } break;
916 default: {
917 LOGW(" Unknown Descriptor: 0x%x ", desc->tag);
918 } break;
919 }
920 }
921
922 static void *log_malloc(size_t size) {
923 void *result = nullptr;
924#if defined(ESP32)
925 result = ps_malloc(size);
926 if (result != nullptr) return result;
927#endif
928 result = malloc(size);
929 LOGI("malloc(%d) -> %p %s", (int)size, result,
930 result != NULL ? "OK" : "ERROR");
931 return result;
932 }
933
934 static void *log_calloc(size_t num, size_t size) {
935 void *result = nullptr;
936#if defined(ESP32)
937 result = ps_calloc(num, size);
938 if (result != nullptr) return result;
939#endif
940 result = calloc(num, size);
941 LOGI("calloc(%d) -> %p %s", (int)(num * size), result,
942 result != NULL ? "OK" : "ERROR");
943 return result;
944 }
945
946 static void *log_realloc(void *ptr, size_t size) {
947 void *result = nullptr;
948#if defined(ESP32)
949 result = ps_realloc(ptr, size);
950 if (result != nullptr) return result;
951#endif
952 result = realloc(ptr, size);
953 LOGI("realloc(%d) -> %p %s", (int)size, result,
954 result != NULL ? "OK" : "ERROR");
955 return result;
956 }
957
958 static void log_free(void *mem) {
959 LOGD("free(%p)", mem);
960 free(mem);
961 }
962
963 // // store allocated size in first bytes
964 // static void* log_malloc (size_t size) {
965 // void *result = malloc(size);
966 // memset(result, 0, size);
967 // AllocSize entry{result, size};
968 // self->alloc_vector.push_back(entry);
969 // assert(find_size(result)>=0);
970 // LOGI("malloc(%d) -> %p %s\n", (int)size,result,
971 // result!=NULL?"OK":"ERROR"); return result;
972 // }
973
974 // static void* log_calloc(size_t num, size_t size){
975 // return log_malloc(num*size);
976 // }
977
978 // static int find_size(void *ptr){
979 // for (int j=0;j<self->alloc_vector.size();j++){
980 // if (self->alloc_vector[j].data==ptr) return j;
981 // }
982 // return -1;
983 // }
984
985 // static void* log_realloc(void *ptr, size_t size){
986 // int pos = find_size(ptr);
987 // void *result = nullptr;
988 // if (pos>=0){
989 // result = realloc(ptr, size);
990 // // store size in header
991 // size_t old_size = self->alloc_vector[pos].size;
992 // memset(result+old_size, 0, size-old_size);
993 // self->alloc_vector[pos].size = size;
994 // } else {
995 // LOGE("realloc of unallocatd memory %p", ptr);
996 // result = realloc(ptr, size);
997 // AllocSize entry{result, size};
998 // self->alloc_vector.push_back(entry);
999 // assert(find_size(result)>=0);
1000 // }
1001
1002 // LOGI("realloc(%d) -> %p %s\n", (int)size, result,
1003 // result!=NULL?"OK":"ERROR"); return result;
1004 // }
1005
1006 // static void log_free (void *mem){
1007 // LOGD("free(%p)\n", mem);
1008 // free(mem);
1009 // int pos = find_size(mem);
1010 // if (pos>=0){
1011 // self->alloc_vector.erase(pos);
1012 // assert(find_size(mem)==-1);
1013
1014 // } else {
1015 // LOGE("free of unallocatd memory %p", mem);
1016 // }
1017 // }
1018};
1019// init static variable
1020MTSDecoderTSDemux *MTSDecoderTSDemux::self = nullptr;
1021
1022} // namespace audio_tools
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition AudioCodecsBase.h:36
Abstract Audio Ouptut class.
Definition AudioOutput.h:22
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:119
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:59
MPEG-TS (MTS) decoder. Extracts the AAC audio data from a MPEG-TS (MTS) data stream....
Definition CodecTSDemux.h:48
void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition CodecTSDemux.h:168
void resizeBuffer(int size)
Set a new write buffer size (default is 2000)
Definition CodecTSDemux.h:144
bool is_new_file(uint8_t *data)
Determines if we are at the beginning of a new file.
Definition CodecTSDemux.h:195
void setOutput(AudioStream &out_stream) override
Defines where the decoded result is written to.
Definition CodecTSDemux.h:150
void setOutput(AudioOutput &out_stream) override
Defines where the decoded result is written to.
Definition CodecTSDemux.h:159
void setMemoryAllocationLogging(bool flag)
Activate logging for memory allocations.
Definition CodecTSDemux.h:147
Definition NoArduino.h:62
int available() override
provides the number of entries that are available to read
Definition Buffers.h:227
T * data()
Provides address of actual data.
Definition Buffers.h:261
int clearArray(int len) override
consumes len bytes and moves current data to the beginning
Definition Buffers.h:237
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Definition CodecTSDemux.h:27