4 #define TS_PACKET_SIZE 188
5 #define TS_HEADER_SIZE 4
6 #define PID_ARRAY_LEN 4
8 #ifndef MTS_UNDERFLOW_LIMIT
9 # define MTS_UNDERFLOW_LIMIT 200
12 #ifndef MTS_WRITE_BUFFER_SIZE
13 # define MTS_WRITE_BUFFER_SIZE 2000
16 #include "AudioTools/AudioCodecs/AudioCodecsBase.h"
26 STREAM_TYPE_VIDEO = 0x01,
27 STREAM_TYPE_VIDEO_H262 = 0x02,
28 STREAM_TYPE_AUDIO_11172 = 0x03,
29 STREAM_TYPE_AUDIO_13818_3 = 0x04,
30 STREAM_TYPE_PRV_SECTIONS = 0x05,
31 STREAM_TYPE_PES_PRV = 0x06,
32 STREAM_TYPE_MHEG = 0x07,
33 STREAM_TYPE_H222_0_DSM_CC = 0x08,
34 STREAM_TYPE_H222_1 = 0x09,
39 STREAM_TYPE_H222_0_AUX = 0x0E,
40 STREAM_TYPE_AUDIO_AAC = 0x0F,
41 STREAM_TYPE_VISUAL = 0x10,
42 STREAM_TYPE_AUDIO_LATM = 0x11,
43 STREAM_TYPE_SL_PES = 0x12,
44 STREAM_TYPE_SL_SECTIONS = 0x13,
45 STREAM_TYPE_SYNC_DOWNLOAD = 0x14,
46 STREAM_TYPE_PES_METADATA = 0x15,
47 STREAM_TYPE_METDATA_SECTIONS = 0x16,
48 STREAM_TYPE_METADATA_DATA_CAROUSEL = 0x17,
49 STREAM_TYPE_METADATA_OBJ_CAROUSEL = 0x18,
50 STREAM_TYPE_METADATA_SYNC_DOWNLOAD = 0x19,
51 STREAM_TYPE_IPMP = 0x1A,
52 STREAM_TYPE_VIDEO_AVC = 0X1B,
53 STREAM_TYPE_VIDEO_H222_0 = 0x1C,
54 STREAM_TYPE_DCII_VIDEO = 0x80,
55 STREAM_TYPE_AUDIO_A53 = 0x81,
56 STREAM_TYPE_SCTE_STD_SUBTITLE = 0x82,
57 STREAM_TYPE_SCTE_ISOCH_DATA = 0x83,
58 STREAM_TYPE_ATSC_PROG_ID = 0x85,
59 STREAM_TYPE_SCTE_25 = 0x86,
60 STREAM_TYPE_AUDIO_EAC3 = 0x87,
61 STREAM_TYPE_AUDIO_DTS_HD = 0x88,
62 STREAM_TYPE_DVB_MPE_FEC = 0x90,
63 STREAM_TYPE_ULE = 0x91,
64 STREAM_TYPE_VEI = 0x92,
65 STREAM_TYPE_ATSC_DATA_SERVICE_TABLE = 0x95,
66 STREAM_TYPE_SCTE_IP_DATA = 0xA0,
67 STREAM_TYPE_DCII_TEXT = 0xC0,
68 STREAM_TYPE_ATSC_SYNC_DATA = 0xC2,
69 STREAM_TYPE_SCTE_AYSNC_DATA = 0xC3,
70 STREAM_TYPE_ATSC_USER_PRIV_PROG_ELEMENTS = 0xC4,
71 STREAM_TYPE_VC1 = 0xEA,
72 STREAM_TYPE_ATSC_USER_PRIV = 0xEB,
90 bool begin()
override {
94 if (stream_types.empty()){
96 addStreamType(STREAM_TYPE_AUDIO_AAC);
97 addStreamType(STREAM_TYPE_AUDIO_13818_3);
98 addStreamType(STREAM_TYPE_AUDIO_LATM);
110 void end()
override {
115 virtual operator bool()
override {
return is_active; }
117 const char *mime() {
return "video/MP2T"; }
119 size_t write(
const uint8_t *data,
size_t len)
override {
120 if (!is_active)
return 0;
121 LOGD(
"MTSDecoder::write: %d", (
int)len);
122 size_t result = buffer.
writeArray((uint8_t*)data, len);
124 demux(underflowLimit);
137 void clearStreamTypes(){
139 stream_types.clear();
144 stream_types.push_back(type);
148 for (
int j=0;j<stream_types.size();j++){
149 if (stream_types[j]==type)
return true;
155 int underflowLimit = MTS_UNDERFLOW_LIMIT;
156 bool is_active =
false;
157 SingleBuffer<uint8_t> buffer{MTS_WRITE_BUFFER_SIZE};
158 Vector<uint8_t> data{TS_PACKET_SIZE};
159 Vector<MTSStreamType> stream_types;
164 int pids[PID_ARRAY_LEN];
167 uint8_t packetBuff[TS_PACKET_SIZE];
168 bool isSyncByteFound =
false;
170 int16_t relevantPID = -1;
171 int16_t pesDataLength = -1;
174 void demux(
int limit){
176 TSDCode res = TSD_OK;
178 while (res == TSD_OK && buffer.
available() > limit) {
182 LOGD(
"Number of demux calls: %d", count);
188 if(len < (TS_PACKET_SIZE - TS_HEADER_SIZE)) {
return 0; }
192 if(!isSyncByteFound) {
195 if(!buffer.
readArray(&oneByte, 1))
return 0;
196 }
while (oneByte != 0x47);
197 isSyncByteFound =
true;
199 read = buffer.
readArray(&packetBuff[1], TS_PACKET_SIZE-1);
201 read = buffer.
readArray(packetBuff, TS_PACKET_SIZE);
204 int len = parsePacket(packetBuff, &data[aacRead]);
211 }
while ((len - aacRead) >= (TS_PACKET_SIZE - TS_HEADER_SIZE) && read);
216 int parsePacket(uint8_t *packet, uint8_t *data){
219 int pid = ((packet[1] & 0x1F) << 8) | (packet[2] & 0xFF);
220 LOGD(
"PID: 0x%04X(%d)", pid, pid);
221 int payloadUnitStartIndicator = (packet[1] & 0x40) >> 6;
222 LOGD(
"Payload Unit Start Indicator: %d", payloadUnitStartIndicator);
223 int adaptionFieldControl = (packet[3] & 0x30) >> 4;
224 LOGD(
"Adaption Field Control: %d", adaptionFieldControl);
225 int remainingAdaptationFieldLength = -1;
226 if ((adaptionFieldControl & 0b10) == 0b10){
227 remainingAdaptationFieldLength = packet[4] & 0xFF;
228 LOGD(
"Adaptation Field Length: %d", remainingAdaptationFieldLength);
231 if (payloadUnitStartIndicator){
233 pidsOfPMT.number = 0;
236 int payloadStart = payloadUnitStartIndicator ? 5 : 4;
239 parsePAT(&packet[payloadStart]);
240 }
else if (pid == relevantPID){
241 int posOfPacketStart = 4;
242 if (remainingAdaptationFieldLength >= 0) posOfPacketStart = 5 + remainingAdaptationFieldLength;
243 read = parsePES(&packet[posOfPacketStart], posOfPacketStart, payloadUnitStartIndicator ?
true :
false);
244 }
else if (pidsOfPMT.number){
245 for (
int i = 0; i < pidsOfPMT.number; i++){
246 if (pid == pidsOfPMT.pids[i]){
247 parsePMT(&packet[payloadStart]);
255 int parsePAT(uint8_t *pat){
256 int startOfProgramNums = 8;
257 int lengthOfPATValue = 4;
258 int sectionLength = ((pat[1] & 0x0F) << 8) | (pat[2] & 0xFF);
259 LOGD(
"Section Length: %d", sectionLength);
260 if(sectionLength >= PID_ARRAY_LEN*lengthOfPATValue) {
261 LOGE(
"Section Length: %d", sectionLength);
265 for (
int i = startOfProgramNums; i <= sectionLength; i += lengthOfPATValue){
268 int program_map_PID = ((pat[i + 2] & 0x1F) << 8) | (pat[i + 3] & 0xFF);
269 LOGD(
"PMT PID: 0x%04X(%d)", program_map_PID, program_map_PID);
270 pidsOfPMT.pids[indexOfPids++] = program_map_PID;
272 pidsOfPMT.number = indexOfPids;
273 return sectionLength;
276 int parsePMT(uint8_t *pat){
277 int staticLengthOfPMT = 12;
278 int sectionLength = ((pat[1] & 0x0F) << 8) | (pat[2] & 0xFF);
279 LOGD(
"Section Length: %d", sectionLength);
280 int programInfoLength = ((pat[10] & 0x0F) << 8) | (pat[11] & 0xFF);
281 LOGD(
"Program Info Length: %d", programInfoLength);
283 int cursor = staticLengthOfPMT + programInfoLength;
284 while (cursor < sectionLength - 1){
285 int streamType = pat[cursor] & 0xFF;
286 int elementaryPID = ((pat[cursor + 1] & 0x1F) << 8) | (pat[cursor + 2] & 0xFF);
287 LOGD(
"Stream Type: 0x%02X(%d) Elementary PID: 0x%04X(%d)",
288 streamType, streamType, elementaryPID, elementaryPID);
293 relevantPID = elementaryPID;
296 int esInfoLength = ((pat[cursor + 3] & 0x0F) << 8) | (pat[cursor + 4] & 0xFF);
297 LOGD(
"ES Info Length: 0x%04X(%d)", esInfoLength, esInfoLength);
298 cursor += 5 + esInfoLength;
300 return sectionLength;
303 int parsePES(uint8_t *pat,
const int posOfPacketStart,
const bool isNewPayload){
306 uint8_t streamID = pat[3] & 0xFF;
307 LOGD(
"Stream ID:%02X ", streamID);
308 const uint8_t posOfPacketLengthLatterHalf = 5;
309 uint16_t pesRemainingPacketLength = ((pat[4] & 0xFF) << 8) | (pat[5] & 0xFF);
310 LOGD(
"PES Packet length: %d", pesRemainingPacketLength);
311 pesDataLength = pesRemainingPacketLength;
312 const uint8_t posOfHeaderLength = 8;
313 uint8_t pesRemainingHeaderLength = pat[posOfHeaderLength] & 0xFF;
314 LOGD(
"PES Header length: %d", pesRemainingHeaderLength);
315 int startOfData = posOfHeaderLength + pesRemainingHeaderLength + 1;
316 dataSize = (TS_PACKET_SIZE - posOfPacketStart) - startOfData;
317 if (p_print) p_print->write(&pat[startOfData], dataSize);
318 pesDataLength -= (TS_PACKET_SIZE - posOfPacketStart) - (posOfPacketLengthLatterHalf + 1);
320 dataSize = TS_PACKET_SIZE - posOfPacketStart;
321 if (p_print) p_print->write(pat, dataSize);
322 pesDataLength -= dataSize;