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