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 {
142 if ((
size_t)
buffer.availableForWrite() < len) {
150 size_t toWrite = (size_t)
buffer.availableForWrite() < len
151 ? (size_t)
buffer.availableForWrite()
154 LOGI(
"MTSDecoder::write: Buffer full");
157 LOGI(
"MTSDecoder::write: %d", (
int)toWrite);
158 size_t result =
buffer.writeArray((uint8_t *)data, toWrite);
189 p_dec->setOutput(out_stream);
198 p_dec->setOutput(out_stream);
207 p_dec->setOutput(out_stream);
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);
250 int len =
buffer.available();
252 for (
int j = 0; j < len; j++) {
253 if (
buffer.data()[j] == 0x47) {
263 if (pos < 0)
return false;
265 LOGW(
"Sync byte not found at position 0. Skipping %d bytes", pos);
272 uint8_t *packet =
buffer.data();
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 LOGW(
"-> 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;
472 assert(result == 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 MTS_WRITE_BUFFER_SIZE
Definition CodecMTS.h:6
#define TS_PACKET_SIZE
Definition CodecMTS.h:3
MTSStreamType
PMT Program Element Stream Types.
Definition CodecMTS.h:20
@ VIDEO_H222_0
Definition CodecMTS.h:49
@ SCTE_ISOCH_DATA
Definition CodecMTS.h:53
@ DCII_VIDEO
Definition CodecMTS.h:50
@ AUDIO_EAC3
Definition CodecMTS.h:56
@ H222_0_DSM_CC
Definition CodecMTS.h:29
@ C
Definition CodecMTS.h:33
@ METADATA_DATA_CAROUSEL
Definition CodecMTS.h:44
@ ATSC_USER_PRIV_PROG_ELEMENTS
Definition CodecMTS.h:66
@ VIDEO_H262
Definition CodecMTS.h:23
@ DVB_MPE_FEC
Definition CodecMTS.h:58
@ IPMP
Definition CodecMTS.h:47
@ SCTE_25
Definition CodecMTS.h:55
@ PRV_SECTIONS
Definition CodecMTS.h:26
@ AUDIO_MP3
Definition CodecMTS.h:24
@ VC1
Definition CodecMTS.h:67
@ METADATA_OBJ_CAROUSEL
Definition CodecMTS.h:45
@ SYNC_DOWNLOAD
Definition CodecMTS.h:41
@ H222_1
Definition CodecMTS.h:30
@ PES_METADATA
Definition CodecMTS.h:42
@ VIDEO_AVC
Definition CodecMTS.h:48
@ METDATA_SECTIONS
Definition CodecMTS.h:43
@ DCII_TEXT
Definition CodecMTS.h:63
@ SCTE_IP_DATA
Definition CodecMTS.h:62
@ MHEG
Definition CodecMTS.h:28
@ METADATA_SYNC_DOWNLOAD
Definition CodecMTS.h:46
@ H222_0_AUX
Definition CodecMTS.h:35
@ A
Definition CodecMTS.h:31
@ AUDIO_MP3_LOW_BITRATE
Definition CodecMTS.h:25
@ AUDIO_AAC_LATM
Definition CodecMTS.h:38
@ VISUAL
Definition CodecMTS.h:37
@ PES_PRV
Definition CodecMTS.h:27
@ B
Definition CodecMTS.h:32
@ ATSC_DATA_SERVICE_TABLE
Definition CodecMTS.h:61
@ NONE
Definition CodecMTS.h:21
@ ATSC_PROG_ID
Definition CodecMTS.h:54
@ SCTE_STD_SUBTITLE
Definition CodecMTS.h:52
@ AUDIO_A53
Definition CodecMTS.h:51
@ AUDIO_AAC
Definition CodecMTS.h:36
@ SL_PES
Definition CodecMTS.h:39
@ AUDIO_DTS_HD
Definition CodecMTS.h:57
@ ATSC_SYNC_DATA
Definition CodecMTS.h:64
@ ULE
Definition CodecMTS.h:59
@ VIDEO
Definition CodecMTS.h:22
@ SCTE_AYSNC_DATA
Definition CodecMTS.h:65
@ SL_SECTIONS
Definition CodecMTS.h:40
@ ATSC_USER_PRIV
Definition CodecMTS.h:68
@ VEI
Definition CodecMTS.h:60
@ D
Definition CodecMTS.h:34
MTSDecoder MPEG_TSDecoder
Legacy alias for MPEG Transport Stream decoder.
Definition CodecMTS.h:521