3#define TS_PACKET_SIZE 188
5#ifndef MTS_WRITE_BUFFER_SIZE
6#define MTS_WRITE_BUFFER_SIZE 2000
132 const char *
mime() {
return "video/MP2T"; }
134 size_t write(
const uint8_t *data,
size_t len)
override {
154 LOGI(
"MTSDecoder::write: Buffer full");
157 LOGI(
"MTSDecoder::write: %d", (
int)toWrite);
230 if (pid == 0)
return;
231 for (
int j = 0; j <
pids.
size(); j++) {
232 if (
pids[j] == pid)
return;
234 LOGI(
"-> PMT PID: 0x%04X(%d)", pid, pid);
243 LOGI(
"demux: step #%d with PES #%d", ++count, (
int)
pes_count);
245 LOGI(
"Number of demux calls: %d", count);
252 for (
int j = 0; j < len; j++) {
263 if (pos < 0)
return false;
265 LOGW(
"Sync byte not found at position 0. Skipping %d bytes", pos);
273 int pid = ((packet[1] & 0x1F) << 8) | (packet[2] & 0xFF);
274 LOGI(
"PID: 0x%04X(%d)", pid, pid);
291 bool payloadUnitStartIndicator =
false;
298 if (pid == 0 && payloadUnitStartIndicator) {
304 parsePAT(&packet[payloadStart], len);
305 }
else if (pid ==
pmt_pid && packet[payloadStart] == 0x02) {
306 parsePMT(&packet[payloadStart], len);
308 LOGE(
"-> Packet ignored for PID 0x%x", pid);
313 bool &payloadUnitStartIndicator) {
314 uint8_t adaptionField = (packet[3] & 0x30) >> 4;
315 int adaptationSize = 0;
323 if (adaptionField == 0b11) {
324 adaptationSize = packet[4] + 1;
325 offset += adaptationSize;
329 if (packet[1] & 0x40) {
330 if (!isPES) offset += packet[offset] + 1;
331 payloadUnitStartIndicator =
true;
334 LOGI(
"Payload Unit Start Indicator (PUSI): %d", payloadUnitStartIndicator);
335 LOGI(
"Adaption Field Control: 0x%x / size: %d", adaptionField,
344 int startOfProgramNums = 8;
345 int lengthOfPATValue = 4;
346 int sectionLength = ((pat[1] & 0x0F) << 8) | (pat[2] & 0xFF);
347 LOGI(
"PAT Section Length: %d", sectionLength);
348 if (sectionLength >= len) {
349 LOGE(
"Unexpected PAT Section Length: %d", sectionLength);
353 for (
int i = startOfProgramNums; i <= sectionLength;
354 i += lengthOfPATValue) {
355 int program_number = ((pat[i] & 0xFF) << 8) | (pat[i + 1] & 0xFF);
356 int pid = ((pat[i + 2] & 0x1F) << 8) | (pat[i + 3] & 0xFF);
357 LOGI(
"Program Num: 0x%04X(%d) / PID: 0x%04X(%d) ", program_number,
358 program_number, pid, pid);
360 if (
pmt_pid == 0xFFFF && pid >= 0x0020 && pid <= 0x1FFE) {
370 int staticLengthOfPMT = 12;
371 int sectionLength = ((pmt[1] & 0x0F) << 8) | (pmt[2] & 0xFF);
372 LOGI(
"- PMT Section Length: %d", sectionLength);
373 if (sectionLength >= len) {
374 LOGE(
"Unexpected PMT Section Length: %d", sectionLength);
377 int programInfoLength = ((pmt[10] & 0x0F) << 8) | (pmt[11] & 0xFF);
378 LOGI(
"- PMT Program Info Length: %d", programInfoLength);
380 int cursor = staticLengthOfPMT + programInfoLength;
381 while (cursor < sectionLength - 1) {
382 if (cursor + 4 >= len)
break;
385 ((pmt[cursor + 1] & 0x1F) << 8) | (pmt[cursor + 2] & 0xFF);
386 LOGI(
"-- Stream Type: 0x%02X(%d) [%s] for Elementary PID: 0x%04X(%d)",
387 (
int)streamType, (
int)streamType,
toStr(streamType), elementaryPID,
396 ((pmt[cursor + 3] & 0x0F) << 8) | (pmt[cursor + 4] & 0xFF);
397 LOGI(
"-- ES Info Length: 0x%04X(%d)", esInfoLength, esInfoLength);
398 cursor += 5 + esInfoLength;
403 LOGI(
"parsePES: %d", pid);
407 bool payloadUnitStartIndicator =
false;
408 int payloadStart =
getPayloadStart(packet,
true, payloadUnitStartIndicator);
411 uint8_t *pes = packet + payloadStart;
414 uint8_t *pesData =
nullptr;
417 if (payloadUnitStartIndicator) {
419 LOGE(
"PES packet too short: %d", len);
424 LOGE(
"PES header not aligned correctly");
428 int pesPacketLength =
429 (
static_cast<int>(pes[4]) << 8) |
static_cast<int>(pes[5]);
434 int pesHeaderSize = 6;
435 if (len >= 9 && (pes[6] & 0xC0) != 0) {
436 pesHeaderSize += 3 + ((pes[7] & 0xC0) == 0xC0 ? 5 : 0);
437 pesHeaderSize += pes[8];
439 LOGI(
"- PES Header Size: %d", pesHeaderSize);
443 if (pesHeaderSize >= len) {
444 LOGE(
"Unexpected PES Header Size: %d (len: %d)", pesHeaderSize, len);
447 pesData = pes + pesHeaderSize;
448 pesDataSize = len - pesHeaderSize;
471 size_t result = writeData<uint8_t>(
p_print, pesData, pesDataSize);
472 assert(result == pesDataSize);
476 writeDataT<uint8_t, AudioDecoder>(
p_dec, pesData, pesDataSize);
477 assert(result == pesDataSize);
483 if (pes[0] != 0)
return false;
484 if (pes[1] != 0)
return false;
485 if (pes[2] != 0x1)
return false;
495 return "AUDIO_MP3_LOW_BITRATE";
499 return "AUDIO_AAC_LATM";
506 int findSyncWord(
const uint8_t *buf,
size_t nBytes, uint8_t synch = 0xFF,
507 uint8_t syncl = 0xF0) {
510 if (nBytes < 2)
return -1;
511 for (
size_t i = 0; i < nBytes - 1; i++) {
512 if ((buf[i + 0] & synch) == synch && (buf[i + 1] & syncl) == syncl)
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define TRACEE()
Definition AudioLoggerIDF.h:34
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define MTS_WRITE_BUFFER_SIZE
Definition CodecMTS.h:6
#define TS_PACKET_SIZE
Definition CodecMTS.h:3
#define assert(T)
Definition avr.h:10
MTSStreamType
PMT Program Element Stream Types.
Definition CodecMTS.h:20
@ ATSC_USER_PRIV_PROG_ELEMENTS
@ ATSC_DATA_SERVICE_TABLE