arduino-audio-tools
Loading...
Searching...
No Matches
CodecMTS.h
1#pragma once
2#pragma once
3
4#define TS_PACKET_SIZE 188
5#define TS_HEADER_SIZE 4
6#define PID_ARRAY_LEN 4
7
8#ifndef MTS_UNDERFLOW_LIMIT
9# define MTS_UNDERFLOW_LIMIT 200
10#endif
11
12#ifndef MTS_WRITE_BUFFER_SIZE
13# define MTS_WRITE_BUFFER_SIZE 2000
14#endif
15
16#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
17#include "tsdemux.h"
18#include "stdlib.h"
19
20namespace audio_tools {
21
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,
35 STREAM_TYPE_A = 0x0A,
36 STREAM_TYPE_B = 0x0B,
37 STREAM_TYPE_C = 0x0C,
38 STREAM_TYPE_D = 0x0D,
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,
73};
74
86class MTSDecoder1 : public AudioDecoder {
87 public:
88 MTSDecoder1() = default;
89
90 bool begin() override {
91 TRACED();
92
93 // default supported stream types
94 if (stream_types.empty()){
95 //addStreamType(STREAM_TYPE_PES_METADATA);
96 addStreamType(STREAM_TYPE_AUDIO_AAC);
97 addStreamType(STREAM_TYPE_AUDIO_13818_3);
98 addStreamType(STREAM_TYPE_AUDIO_LATM);
99 }
100
101 // automatically close when called multiple times
102 if (is_active) {
103 end();
104 }
105
106 is_active = true;
107 return true;
108 }
109
110 void end() override {
111 TRACED();
112 is_active = false;
113 }
114
115 virtual operator bool() override { return is_active; }
116
117 const char *mime() { return "video/MP2T"; }
118
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);
123 // demux
124 demux(underflowLimit);
125 return result;
126 }
127
128 void flush(){
129 demux(0);
130 }
131
133 void resizeBuffer(int size){
134 buffer.resize(size);
135 }
136
137 void clearStreamTypes(){
138 TRACED();
139 stream_types.clear();
140 }
141
142 void addStreamType(MTSStreamType type){
143 TRACED();
144 stream_types.push_back(type);
145 }
146
147 bool isStreamTypeActive(MTSStreamType type){
148 for (int j=0;j<stream_types.size();j++){
149 if (stream_types[j]==type) return true;
150 }
151 return false;
152 }
153
154 protected:
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;
160
161
162 struct pid_array{
163 int number;
164 int pids[PID_ARRAY_LEN];
165 };
166
167 uint8_t packetBuff[TS_PACKET_SIZE];
168 bool isSyncByteFound = false;
169 pid_array pidsOfPMT;
170 int16_t relevantPID = -1;
171 int16_t pesDataLength = -1;
172
173
174 void demux(int limit){
175 TRACED();
176 TSDCode res = TSD_OK;
177 int count = 0;
178 while (res == TSD_OK && buffer.available() > limit) {
179 parse();
180 count++;
181 }
182 LOGD("Number of demux calls: %d", count);
183 }
184
185 uint32_t parse() {
186 int len = buffer.available();
187 // If len is too short, return 0
188 if(len < (TS_PACKET_SIZE - TS_HEADER_SIZE)) { return 0; }
189 int read;
190 int aacRead = 0;
191 do {
192 if(!isSyncByteFound) {
193 uint8_t oneByte;
194 do {
195 if(!buffer.readArray(&oneByte, 1)) return 0;
196 } while (oneByte != 0x47);
197 isSyncByteFound = true;
198 packetBuff[0]=0x47;
199 read = buffer.readArray(&packetBuff[1], TS_PACKET_SIZE-1);
200 } else {
201 read = buffer.readArray(packetBuff, TS_PACKET_SIZE);
202 }
203 if(read){
204 int len = parsePacket(packetBuff, &data[aacRead]);
205 if (len<0) {
206 is_active = false;
207 return 0;
208 }
209 aacRead += len;
210 }
211 } while ((len - aacRead) >= (TS_PACKET_SIZE - TS_HEADER_SIZE) && read);
212
213 return aacRead;
214 }
215
216 int parsePacket(uint8_t *packet, uint8_t *data){
217 int read = 0;
218
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);
229 }
230 // if we are at the beginning we start with a pat
231 if (payloadUnitStartIndicator){
232 pid = 0;
233 pidsOfPMT.number = 0;
234 }
235
236 int payloadStart = payloadUnitStartIndicator ? 5 : 4;
237
238 if (pid == 0){
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]);
248 }
249 }
250 }
251
252 return read;
253 }
254
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);
262 return 0;
263 }
264 int indexOfPids = 0;
265 for (int i = startOfProgramNums; i <= sectionLength; i += lengthOfPATValue){
266 //int program_number = ((pat[i] & 0xFF) << 8) | (pat[i + 1] & 0xFF);
267 //LOGD("Program Num: 0x%04X(%d)", program_number, program_number);
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;
271 }
272 pidsOfPMT.number = indexOfPids;
273 return sectionLength;
274 }
275
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);
282
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);
289
290 //if (streamType == 0x04) LOGD("The type of this stream is MP3, which is not yet supported in this program.");
291 //if (streamType == 0x0F || streamType == 0x11) relevantPID = elementaryPID;
292 if (isStreamTypeActive((MTSStreamType)streamType)){
293 relevantPID = elementaryPID;
294 }
295
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;
299 }
300 return sectionLength;
301 }
302
303 int parsePES(uint8_t *pat, const int posOfPacketStart, const bool isNewPayload){
304 int dataSize = 0;
305 if (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);
319 } else {
320 dataSize = TS_PACKET_SIZE - posOfPacketStart;
321 if (p_print) p_print->write(pat, dataSize);
322 pesDataLength -= dataSize;
323 }
324 return dataSize;
325 }
326};
327
328} // namespace audio_tools
329
Docoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:16
virtual int readArray(T data[], int len)
reads multiple values
Definition Buffers.h:41
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:65
MPEG-TS (MTS) decoder. Extracts the AAC audio data from a MPEG-TS (MTS) data stream....
Definition CodecMTS.h:86
void resizeBuffer(int size)
Set a new write buffer size (default is 2000)
Definition CodecMTS.h:133
int available() override
provides the number of entries that are available to read
Definition Buffers.h:219
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioConfig.h:877
MTSStreamType
Definition CodecMTS.h:25
Definition CodecMTS.h:162