6
6
#define MTS_WRITE_BUFFER_SIZE 2000
7
7
#endif
8
8
9
- #include " AudioToolsConfig.h"
10
- #include " AudioTools/CoreAudio/AudioTypes.h"
11
9
#include " AudioTools/AudioCodecs/AudioCodecsBase.h"
10
+ #include " AudioTools/CoreAudio/AudioTypes.h"
11
+ #include " AudioToolsConfig.h"
12
12
#include " stdlib.h"
13
13
14
14
namespace audio_tools {
@@ -78,7 +78,6 @@ enum class MTSStreamType {
78
78
*MPEG-TS (MTS) data stream. You can define the relevant stream types via the
79
79
*API: For details see https://tsduck.io/download/docs/mpegts-introduction.pdf
80
80
*
81
- * Status: experimental!
82
81
*
83
82
* @ingroup codecs
84
83
* @ingroup decoder
@@ -165,7 +164,7 @@ class MTSDecoder : public AudioDecoder {
165
164
}
166
165
return false ;
167
166
}
168
-
167
+
169
168
// / Defines where the decoded result is written to
170
169
void setOutput (AudioStream &out_stream) override {
171
170
if (p_dec) {
@@ -249,24 +248,49 @@ class MTSDecoder : public AudioDecoder {
249
248
buffer.clearArray (pos);
250
249
}
251
250
// parse data
252
- parsePacket ();
251
+ uint8_t *packet = buffer.data ();
252
+ int pid = ((packet[1 ] & 0x1F ) << 8 ) | (packet[2 ] & 0xFF );
253
+ LOGI (" PID: 0x%04X(%d)" , pid, pid);
254
+
255
+ // PES contains the audio data
256
+ if (!is_adts_missing && pids.contains (pid)) {
257
+ parsePES (packet, pid);
258
+ } else {
259
+ parsePacket (packet, pid);
260
+ }
253
261
254
262
// remove processed data
255
263
buffer.clearArray (TS_PACKET_SIZE);
256
264
return true ;
257
265
}
258
266
259
267
// / Detailed processing for parsing a single packet
260
- void parsePacket () {
268
+ void parsePacket (uint8_t *packet, int pid ) {
261
269
TRACEI ();
262
- uint8_t *packet = buffer.data ();
263
- int pid = ((packet[1 ] & 0x1F ) << 8 ) | (packet[2 ] & 0xFF );
264
- LOGI (" PID: 0x%04X(%d)" , pid, pid);
265
270
bool payloadUnitStartIndicator = false ;
271
+
272
+ int payloadStart = getPayloadStart (packet, false , payloadUnitStartIndicator);
273
+ int len = TS_PACKET_SIZE - payloadStart;
274
+
275
+ // if we are at the beginning we start with a pat
276
+ if (pid == 0 && payloadUnitStartIndicator) {
277
+ pids.clear ();
278
+ }
279
+
280
+ // PID 0 is for PAT
281
+ if (pid == 0 ) {
282
+ parsePAT (&packet[payloadStart], len);
283
+ } else if (pid == pmt_pid && packet[payloadStart] == 0x02 ) {
284
+ parsePMT (&packet[payloadStart], len);
285
+ } else {
286
+ LOGE (" -> Packet ignored for PID 0x%x" , pid);
287
+ }
288
+ }
289
+
290
+ int getPayloadStart (uint8_t *packet, bool isPES, bool &payloadUnitStartIndicator) {
266
291
uint8_t adaptionField = (packet[3 ] & 0x30 ) >> 4 ;
267
292
int adaptationSize = 0 ;
268
293
int offset = 4 ; // Start after TS header (4 bytes)
269
- bool to_process = true ;
270
294
271
295
// Check for adaptation field
272
296
// 00 (0) → Invalid (should never happen).
@@ -276,38 +300,19 @@ class MTSDecoder : public AudioDecoder {
276
300
if (adaptionField == 0b11 ) { // Adaptation field exists
277
301
adaptationSize = packet[4 ] + 1 ;
278
302
offset += adaptationSize;
279
- } else if (adaptionField == 0b10 ) { // Adopation field only
280
- to_process = false ;
281
303
}
282
304
283
305
// If PUSI is set, there's a pointer field (skip it)
284
306
if (packet[1 ] & 0x40 ) {
285
- offset += packet[offset] + 1 ;
307
+ if (!isPES) offset += packet[offset] + 1 ;
286
308
payloadUnitStartIndicator = true ;
287
309
}
288
310
289
311
LOGI (" Payload Unit Start Indicator (PUSI): %d" , payloadUnitStartIndicator);
290
312
LOGI (" Adaption Field Control: 0x%x / size: %d" , adaptionField,
291
313
adaptationSize);
292
314
293
- // if we are at the beginning we start with a pat
294
- if (pid == 0 && payloadUnitStartIndicator) {
295
- // pids.clear();
296
- }
297
-
298
- int payloadStart = offset;
299
- int len = TS_PACKET_SIZE - payloadStart;
300
-
301
- // PID 0 is for PAT
302
- if (pid == 0 ) {
303
- parsePAT (&packet[payloadStart], len);
304
- } else if (pid == pmt_pid && packet[payloadStart] == 0x02 ) {
305
- parsePMT (&packet[payloadStart], len);
306
- } else if (!is_adts_missing && to_process && pids.contains (pid)) {
307
- parsePES (&packet[payloadStart], len, payloadUnitStartIndicator);
308
- } else {
309
- LOGE (" -> Packet ignored for PID 0x%x" , pid);
310
- }
315
+ return offset;
311
316
}
312
317
313
318
void parsePAT (uint8_t *pat, int len) {
@@ -366,19 +371,24 @@ class MTSDecoder : public AudioDecoder {
366
371
}
367
372
}
368
373
369
- void parsePES (uint8_t *pes , int len, const bool isNewPayload ) {
370
- LOGI (" parsePES: %d" , len );
374
+ void parsePES (uint8_t *packet , int pid ) {
375
+ LOGI (" parsePES: %d" , pid );
371
376
++pes_count;
372
- uint8_t *data = nullptr ;
373
- int dataSize = 0 ;
374
377
375
- if (isNewPayload) {
378
+ // calculate payload start
379
+ bool payloadUnitStartIndicator = false ;
380
+ int payloadStart = getPayloadStart (packet, true , payloadUnitStartIndicator);
381
+
382
+ // PES
383
+ uint8_t *pes = packet + payloadStart;
384
+ int len = TS_PACKET_SIZE - payloadStart;
385
+ // PES (AAC) data
386
+ uint8_t *pesData = nullptr ;
387
+ int pesDataSize = 0 ;
388
+
389
+ if (payloadUnitStartIndicator) {
376
390
assert (len >= 6 );
377
- if (!isPESStartCodeValid (pes)) {
378
- LOGI (" PES header not aligned correctly - adjusting" );
379
- pes--;
380
- }
381
- // PES header is not alligned correctly
391
+ // PES header is not alligned correctly
382
392
if (!isPESStartCodeValid (pes)) {
383
393
LOGE (" PES header not aligned correctly" );
384
394
return ;
@@ -395,38 +405,38 @@ class MTSDecoder : public AudioDecoder {
395
405
pesHeaderSize += pes[8 ]; // PES header stuffing size
396
406
}
397
407
LOGI (" - PES Header Size: %d" , pesHeaderSize);
398
- data = pes + pesHeaderSize;
399
- dataSize = len - pesHeaderSize;
408
+ pesData = pes + pesHeaderSize;
409
+ pesDataSize = len - pesHeaderSize;
400
410
401
411
assert (pesHeaderSize < len);
402
- assert (dataSize > 0 );
412
+ assert (pesDataSize > 0 );
403
413
404
414
// / Check for ADTS
405
415
if (pes_count == 1 && selected_stream_type == MTSStreamType::AUDIO_AAC) {
406
- is_adts_missing = findSyncWord (data, dataSize ) == -1 ;
416
+ is_adts_missing = findSyncWord (pesData, pesDataSize ) == -1 ;
407
417
}
408
418
409
419
open_pes_data_size = pesPacketLength;
410
420
411
421
} else {
412
- data = pes;
413
- dataSize = len;
422
+ pesData = pes;
423
+ pesDataSize = len;
414
424
}
415
- open_pes_data_size -= dataSize ;
425
+ open_pes_data_size -= pesDataSize ;
416
426
417
- if (open_pes_data_size < 0 ){
427
+ if (open_pes_data_size < 0 ) {
418
428
return ;
419
429
}
420
430
421
- LOGI (" - writing %d bytes (open: %d)" , dataSize , open_pes_data_size);
431
+ LOGI (" - writing %d bytes (open: %d)" , pesDataSize , open_pes_data_size);
422
432
if (p_print) {
423
- size_t result = writeData<uint8_t >(p_print, data, dataSize );
424
- assert (result==dataSize );
433
+ size_t result = writeData<uint8_t >(p_print, pesData, pesDataSize );
434
+ assert (result == pesDataSize );
425
435
}
426
436
if (p_dec) {
427
- size_t result = writeDataT<uint8_t , AudioDecoder>(p_dec, data, dataSize );
428
- assert (result==dataSize );
429
- }
437
+ size_t result = writeDataT<uint8_t , AudioDecoder>(p_dec, pesData, pesDataSize );
438
+ assert (result == pesDataSize );
439
+ }
430
440
}
431
441
432
442
// check for PES packet start code prefix
0 commit comments