66#define MTS_WRITE_BUFFER_SIZE 2000
77#endif
88
9- #include " AudioToolsConfig.h"
10- #include " AudioTools/CoreAudio/AudioTypes.h"
119#include " AudioTools/AudioCodecs/AudioCodecsBase.h"
10+ #include " AudioTools/CoreAudio/AudioTypes.h"
11+ #include " AudioToolsConfig.h"
1212#include " stdlib.h"
1313
1414namespace audio_tools {
@@ -78,7 +78,6 @@ enum class MTSStreamType {
7878 *MPEG-TS (MTS) data stream. You can define the relevant stream types via the
7979 *API: For details see https://tsduck.io/download/docs/mpegts-introduction.pdf
8080 *
81- * Status: experimental!
8281 *
8382 * @ingroup codecs
8483 * @ingroup decoder
@@ -165,7 +164,7 @@ class MTSDecoder : public AudioDecoder {
165164 }
166165 return false ;
167166 }
168-
167+
169168 // / Defines where the decoded result is written to
170169 void setOutput (AudioStream &out_stream) override {
171170 if (p_dec) {
@@ -249,24 +248,49 @@ class MTSDecoder : public AudioDecoder {
249248 buffer.clearArray (pos);
250249 }
251250 // 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+ }
253261
254262 // remove processed data
255263 buffer.clearArray (TS_PACKET_SIZE);
256264 return true ;
257265 }
258266
259267 // / Detailed processing for parsing a single packet
260- void parsePacket () {
268+ void parsePacket (uint8_t *packet, int pid ) {
261269 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);
265270 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) {
266291 uint8_t adaptionField = (packet[3 ] & 0x30 ) >> 4 ;
267292 int adaptationSize = 0 ;
268293 int offset = 4 ; // Start after TS header (4 bytes)
269- bool to_process = true ;
270294
271295 // Check for adaptation field
272296 // 00 (0) → Invalid (should never happen).
@@ -276,38 +300,19 @@ class MTSDecoder : public AudioDecoder {
276300 if (adaptionField == 0b11 ) { // Adaptation field exists
277301 adaptationSize = packet[4 ] + 1 ;
278302 offset += adaptationSize;
279- } else if (adaptionField == 0b10 ) { // Adopation field only
280- to_process = false ;
281303 }
282304
283305 // If PUSI is set, there's a pointer field (skip it)
284306 if (packet[1 ] & 0x40 ) {
285- offset += packet[offset] + 1 ;
307+ if (!isPES) offset += packet[offset] + 1 ;
286308 payloadUnitStartIndicator = true ;
287309 }
288310
289311 LOGI (" Payload Unit Start Indicator (PUSI): %d" , payloadUnitStartIndicator);
290312 LOGI (" Adaption Field Control: 0x%x / size: %d" , adaptionField,
291313 adaptationSize);
292314
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;
311316 }
312317
313318 void parsePAT (uint8_t *pat, int len) {
@@ -366,19 +371,24 @@ class MTSDecoder : public AudioDecoder {
366371 }
367372 }
368373
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 );
371376 ++pes_count;
372- uint8_t *data = nullptr ;
373- int dataSize = 0 ;
374377
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) {
376390 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
382392 if (!isPESStartCodeValid (pes)) {
383393 LOGE (" PES header not aligned correctly" );
384394 return ;
@@ -395,38 +405,38 @@ class MTSDecoder : public AudioDecoder {
395405 pesHeaderSize += pes[8 ]; // PES header stuffing size
396406 }
397407 LOGI (" - PES Header Size: %d" , pesHeaderSize);
398- data = pes + pesHeaderSize;
399- dataSize = len - pesHeaderSize;
408+ pesData = pes + pesHeaderSize;
409+ pesDataSize = len - pesHeaderSize;
400410
401411 assert (pesHeaderSize < len);
402- assert (dataSize > 0 );
412+ assert (pesDataSize > 0 );
403413
404414 // / Check for ADTS
405415 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 ;
407417 }
408418
409419 open_pes_data_size = pesPacketLength;
410420
411421 } else {
412- data = pes;
413- dataSize = len;
422+ pesData = pes;
423+ pesDataSize = len;
414424 }
415- open_pes_data_size -= dataSize ;
425+ open_pes_data_size -= pesDataSize ;
416426
417- if (open_pes_data_size < 0 ){
427+ if (open_pes_data_size < 0 ) {
418428 return ;
419429 }
420430
421- LOGI (" - writing %d bytes (open: %d)" , dataSize , open_pes_data_size);
431+ LOGI (" - writing %d bytes (open: %d)" , pesDataSize , open_pes_data_size);
422432 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 );
425435 }
426436 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+ }
430440 }
431441
432442 // check for PES packet start code prefix
0 commit comments