Skip to content

Commit fc725fe

Browse files
committed
MTSDecoder: correct PES offsets
1 parent 23233ed commit fc725fe

File tree

1 file changed

+65
-55
lines changed

1 file changed

+65
-55
lines changed

src/AudioTools/AudioCodecs/CodecMTS.h

Lines changed: 65 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
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

1414
namespace 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

Comments
 (0)