1 | /********** |
2 | This library is free software; you can redistribute it and/or modify it under |
3 | the terms of the GNU Lesser General Public License as published by the |
4 | Free Software Foundation; either version 3 of the License, or (at your |
5 | option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) |
6 | |
7 | This library is distributed in the hope that it will be useful, but WITHOUT |
8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
9 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
10 | more details. |
11 | |
12 | You should have received a copy of the GNU Lesser General Public License |
13 | along with this library; if not, write to the Free Software Foundation, Inc., |
14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
15 | **********/ |
16 | // "liveMedia" |
17 | // Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved. |
18 | // A parser for a MPEG Transport Stream |
19 | // Implementation |
20 | |
21 | #include "MPEG2TransportStreamParser.hh" |
22 | |
23 | void MPEG2TransportStreamParser |
24 | ::parsePMT(PIDState_PMT* pidState, Boolean pusi, unsigned numDataBytes) { |
25 | #ifdef DEBUG_CONTENTS |
26 | fprintf(stderr, "\tProgram Map Table\n" ); |
27 | #endif |
28 | unsigned startPos = curOffset(); |
29 | |
30 | do { |
31 | if (pusi) { |
32 | u_int8_t pointer_field = get1Byte(); |
33 | skipBytes(pointer_field); // usually 0 |
34 | } |
35 | |
36 | u_int8_t table_id = get1Byte(); |
37 | if (table_id != 0x02) { |
38 | #ifdef DEBUG_ERRORS |
39 | fprintf(stderr, "MPEG2TransportStreamParser::parsePMT(0x%04x, %d, %d): bad table_id: 0x%02x\n" , |
40 | pidState->PID, pusi, numDataBytes, table_id); |
41 | #endif |
42 | break; |
43 | } |
44 | |
45 | u_int16_t flagsPlusSection_length = get2Bytes(); |
46 | u_int16_t section_length = flagsPlusSection_length&0x0FFF; |
47 | #ifdef DEBUG_CONTENTS |
48 | fprintf(stderr, "\t\tsection_length: %d\n" , section_length); |
49 | #endif |
50 | if (section_length < 13/*too small for remaining fields + CRC*/ || |
51 | section_length > 1021/*as per specification*/) { |
52 | #ifdef DEBUG_ERRORS |
53 | fprintf(stderr, "MPEG2TransportStreamParser::parsePMT(0x%04x, %d, %d): Bad section_length: %d\n" , |
54 | pidState->PID, pusi, numDataBytes, section_length); |
55 | #endif |
56 | break; |
57 | } |
58 | unsigned endPos = curOffset() + section_length; |
59 | if (endPos - startPos > numDataBytes) { |
60 | #ifdef DEBUG_ERRORS |
61 | fprintf(stderr, "MPEG2TransportStreamParser::parsePMT(0x%04x, %d, %d): section_length %d gives us a total size %d that's too large!\n" , |
62 | pidState->PID, pusi, numDataBytes, section_length, endPos - startPos); |
63 | #endif |
64 | break; |
65 | } |
66 | |
67 | u_int16_t program_number = get2Bytes(); |
68 | if (program_number != pidState->program_number) { |
69 | #ifdef DEBUG_ERRORS |
70 | fprintf(stderr, "MPEG2TransportStreamParser::parsePMT(0x%04x, %d, %d): program_number %d does not match the value %d that was given to us in the PAT!\n" , |
71 | pidState->PID, pusi, numDataBytes, program_number, pidState->program_number); |
72 | #endif |
73 | break; |
74 | } |
75 | #ifdef DEBUG_CONTENTS |
76 | fprintf(stderr, "\t\tprogram_number: %d\n" , program_number); |
77 | |
78 | u_int8_t version_number_byte = get1Byte(); |
79 | u_int8_t version_number = (version_number_byte&0x1E)>>1; |
80 | u_int8_t section_number = get1Byte(); |
81 | u_int8_t last_section_number = get1Byte(); |
82 | fprintf(stderr, "\t\tversion_number: %d; section_number: %d; last_section_number: %d\n" , |
83 | version_number, section_number, last_section_number); |
84 | u_int16_t PCR_PID = get2Bytes(); PCR_PID &= 0x1FFF; |
85 | fprintf(stderr, "\t\tPCR_PID: 0x%04x\n" , PCR_PID); |
86 | #else |
87 | skipBytes(5); |
88 | #endif |
89 | |
90 | u_int16_t program_info_length = get2Bytes(); program_info_length &= 0x0FFF; |
91 | #ifdef DEBUG_CONTENTS |
92 | fprintf(stderr, "\t\tprogram_info_length: %d\n" , program_info_length); |
93 | #endif |
94 | unsigned endOfDescriptors = curOffset() + program_info_length; |
95 | if (endOfDescriptors + 4/*CRC*/ - startPos > numDataBytes) { |
96 | #ifdef DEBUG_ERRORS |
97 | fprintf(stderr, "MPEG2TransportStreamParser::parsePMT(0x%04x, %d, %d): program_info_length %d gives us a total size %d that's too large!\n" , |
98 | pidState->PID, pusi, numDataBytes, program_info_length, endOfDescriptors + 4 - startPos); |
99 | #endif |
100 | break; |
101 | } |
102 | parseStreamDescriptors(program_info_length); |
103 | |
104 | while (curOffset() <= endPos - 4/*for CRC*/ - 5/*for mapping fields*/) { |
105 | u_int8_t stream_type = get1Byte(); |
106 | u_int16_t elementary_PID = get2Bytes(); elementary_PID &= 0x1FFF; |
107 | u_int16_t ES_info_length = get2Bytes(); ES_info_length &= 0x0FFF; |
108 | #ifdef DEBUG_CONTENTS |
109 | extern StreamType StreamTypes[]; |
110 | char const* const streamTypeDesc = StreamTypes[stream_type].description; |
111 | fprintf(stderr, "\t\tstream_type: 0x%02x (%s); elementary_PID: 0x%04x; ES_info_length: %d\n" , |
112 | stream_type, streamTypeDesc == NULL ? "???" : streamTypeDesc, elementary_PID, ES_info_length); |
113 | #endif |
114 | endOfDescriptors = curOffset() + ES_info_length; |
115 | if (endOfDescriptors + 4/*CRC*/ - startPos > numDataBytes) { |
116 | #ifdef DEBUG_ERRORS |
117 | fprintf(stderr, "MPEG2TransportStreamParser::parsePMT(0x%04x, %d, %d): ES_info_length %d gives us a total size %d that's too large!\n" , |
118 | pidState->PID, pusi, numDataBytes, ES_info_length, endOfDescriptors + 4 - startPos); |
119 | #endif |
120 | break; |
121 | } |
122 | parseStreamDescriptors(ES_info_length); |
123 | |
124 | if (fPIDState[elementary_PID] == NULL) { |
125 | fPIDState[elementary_PID] |
126 | = new PIDState_STREAM(*this, elementary_PID, program_number, stream_type); |
127 | } |
128 | } |
129 | } while (0); |
130 | |
131 | // Skip (ignore) all remaining bytes in this packet (including the CRC): |
132 | int numBytesLeft = numDataBytes - (curOffset() - startPos); |
133 | if (numBytesLeft > 0) { |
134 | #ifdef DEBUG_CONTENTS |
135 | fprintf(stderr, "\t\t+%d CRC and stuffing bytes\n" , numBytesLeft); |
136 | #endif |
137 | skipBytes(numBytesLeft); |
138 | } |
139 | } |
140 | |
141 | #ifdef DEBUG_CONTENTS |
142 | #define pDesc(str) do { fprintf(stderr, "\t\t\tdescriptor_tag: 0x%02x (%s); descriptor_length: %d\n",descriptor_tag, (str), descriptor_length); } while (0) |
143 | #else |
144 | #define pDesc(str) |
145 | #endif |
146 | |
147 | void MPEG2TransportStreamParser::parseStreamDescriptors(unsigned numDescriptorBytes) { |
148 | while (numDescriptorBytes >= 2/* enough for "descriptor_tag" and "descriptor_length" */) { |
149 | u_int8_t descriptor_tag = get1Byte(); |
150 | u_int8_t descriptor_length = get1Byte(); |
151 | numDescriptorBytes -= 2; |
152 | |
153 | if (descriptor_length > numDescriptorBytes) { |
154 | #ifdef DEBUG_ERRORS |
155 | fprintf(stderr, "MPEG2TransportStreamParser::parseStreamDescriptors() error: Saw descriptor_length %d > remaining bytes %d\n" , |
156 | descriptor_length, numDescriptorBytes); |
157 | #endif |
158 | skipBytes(numDescriptorBytes); numDescriptorBytes = 0; |
159 | break; |
160 | } |
161 | |
162 | Boolean parsedDescriptor = False; |
163 | switch (descriptor_tag) { |
164 | // Note: These are the tags that we've seen to date. Add more when we see more. |
165 | case 0x02: { |
166 | pDesc("video" ); |
167 | if (descriptor_length < 1) break; |
168 | u_int8_t flags = get1Byte(); |
169 | Boolean MPEG_1_only_flag = (flags&0x04) != 0; |
170 | #ifdef DEBUG_CONTENTS |
171 | fprintf(stderr, "\t\t\t\tflags: 0x%02x (frame_rate_code 0x%1x; MPEG_1_only_flag %d)\n" , |
172 | flags, (flags&0x78)>>3, MPEG_1_only_flag); |
173 | #endif |
174 | if (MPEG_1_only_flag == 0) { |
175 | if (descriptor_length < 3) break; |
176 | #ifdef DEBUG_CONTENTS |
177 | u_int8_t profile_and_level_indication = get1Byte(); |
178 | flags = get1Byte(); |
179 | fprintf(stderr, "\t\t\t\tprofile_and_level_indication 0x%02x; flags 0x%02x (chroma_format 0x%1x)\n" , |
180 | profile_and_level_indication, flags, (flags&0xC0)>>6); |
181 | #else |
182 | skipBytes(2); |
183 | #endif |
184 | } |
185 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
186 | break; |
187 | } |
188 | case 0x03: { |
189 | pDesc("audio" ); |
190 | if (descriptor_length < 1) break; |
191 | #ifdef DEBUG_CONTENTS |
192 | u_int8_t flags = get1Byte(); |
193 | fprintf(stderr, "\t\t\t\tflags: 0x%02x (layer %d)\n" , flags, (flags&0x30)>>4); |
194 | #else |
195 | skipBytes(1); |
196 | #endif |
197 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
198 | break; |
199 | } |
200 | case 0x05: { |
201 | pDesc("registration" ); |
202 | if (descriptor_length < 4) break; |
203 | #ifdef DEBUG_CONTENTS |
204 | u_int32_t format_identifier = get4Bytes(); |
205 | fprintf(stderr, "\t\t\t\tformat_identifier: 0x%08x (%c%c%c%c)\n" , |
206 | format_identifier, |
207 | format_identifier>>24, format_identifier>>16, format_identifier>>8, format_identifier); |
208 | if (descriptor_length > 4) { |
209 | fprintf(stderr, "\t\t\t\tadditional_identification_info: " ); |
210 | for (unsigned i = 4; i < descriptor_length; ++i) fprintf(stderr, "%02x:" , get1Byte()); |
211 | fprintf(stderr, "\n" ); |
212 | } |
213 | #else |
214 | skipBytes(descriptor_length); |
215 | #endif |
216 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
217 | break; |
218 | } |
219 | case 0x06: { |
220 | pDesc("data stream alignment" ); |
221 | if (descriptor_length < 1) break; |
222 | #ifdef DEBUG_CONTENTS |
223 | u_int8_t alignment_type = get1Byte(); |
224 | fprintf(stderr, "\t\t\t\talignment_type: 0x%02x\n" , alignment_type); |
225 | #else |
226 | skipBytes(1); |
227 | #endif |
228 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
229 | break; |
230 | } |
231 | case 0x0a: { |
232 | pDesc("ISO 639 language descriptor" ); |
233 | for (unsigned i = 0; i < descriptor_length/4; ++i) { |
234 | #ifdef DEBUG_CONTENTS |
235 | fprintf(stderr, "\t\t\t\tISO_639_language_code: %c%c%c; audio_type: 0x%02x\n" , |
236 | get1Byte(), get1Byte(), get1Byte(), get1Byte()); |
237 | #else |
238 | skipBytes(4); |
239 | #endif |
240 | } |
241 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
242 | break; |
243 | } |
244 | case 0x0b: { |
245 | pDesc("system clock" ); |
246 | if (descriptor_length < 2) break; |
247 | #ifdef DEBUG_CONTENTS |
248 | u_int8_t flags = get1Byte(); |
249 | Boolean external_clock_ref = (flags&0x80) != 0; |
250 | u_int8_t clock_accuracy_integer = flags&0x3F; |
251 | |
252 | u_int8_t clock_accuracy_exponent = get1Byte(); clock_accuracy_exponent >>= 5; |
253 | float ppm = clock_accuracy_integer*1.0; |
254 | for (unsigned i = 0; i < clock_accuracy_exponent; ++i) ppm /= 10.0; |
255 | fprintf(stderr, "\t\t\t\texternal_clock: %d; clock_accuracy int: %d, exp: %d -> %f ppm\n" , |
256 | external_clock_ref, clock_accuracy_integer, clock_accuracy_exponent, ppm); |
257 | #else |
258 | skipBytes(2); |
259 | #endif |
260 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
261 | break; |
262 | } |
263 | case 0x0e: { |
264 | pDesc("maximum bitrate" ); |
265 | if (descriptor_length < 3) break; |
266 | #ifdef DEBUG_CONTENTS |
267 | u_int32_t maximum_bitrate = ((get1Byte()&0x3F)<<16)|get2Bytes(); // 22 bits |
268 | fprintf(stderr, "\t\t\t\tmaximum_bitrate: %d => %f Mbps\n" , |
269 | maximum_bitrate, (maximum_bitrate*50*8)/1000000.0); |
270 | #else |
271 | skipBytes(3); |
272 | #endif |
273 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
274 | break; |
275 | } |
276 | case 0x10: { |
277 | pDesc("smoothing buffer" ); |
278 | if (descriptor_length < 6) break; |
279 | #ifdef DEBUG_CONTENTS |
280 | u_int32_t sb_leak_rate = ((get1Byte()&0x3F)<<16)|get2Bytes(); // 22 bits |
281 | u_int32_t sb_size = ((get1Byte()&0x3F)<<16)|get2Bytes(); // 22 bits |
282 | fprintf(stderr, "\t\t\t\tsb_leak_rate: %d => %f Mbps; sb_size: %d bytes\n" , |
283 | sb_leak_rate, (sb_leak_rate*400)/1000000.0, sb_size); |
284 | #else |
285 | skipBytes(6); |
286 | #endif |
287 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
288 | break; |
289 | } |
290 | case 0x1d: { |
291 | pDesc("IOD parameters for ISO/IEC 14496-1" ); |
292 | // Note: We don't know how to parse this. (Where's a document that describes this?) |
293 | skipBytes(descriptor_length); numDescriptorBytes -= descriptor_length; |
294 | parsedDescriptor = True; |
295 | break; |
296 | } |
297 | case 0x28: { |
298 | pDesc("H.264 video parameters" ); |
299 | if (descriptor_length < 4) break; |
300 | #ifdef DEBUG_CONTENTS |
301 | u_int8_t profile_idc = get1Byte(); |
302 | u_int8_t flags1 = get1Byte(); |
303 | u_int8_t level_idc = get1Byte(); |
304 | u_int8_t flags2 = get1Byte(); |
305 | fprintf(stderr, "\t\t\t\tprofile_idc: 0x%02x, flags1: 0x%02x, level_idc: 0x%02x, flags2: 0x%02x\n" , |
306 | profile_idc, flags1, level_idc, flags2); |
307 | #else |
308 | skipBytes(4); |
309 | #endif |
310 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
311 | break; |
312 | } |
313 | case 0x52: { |
314 | pDesc("stream identifier" ); |
315 | if (descriptor_length < 1) break; |
316 | #ifdef DEBUG_CONTENTS |
317 | u_int8_t component_tag = get1Byte(); |
318 | fprintf(stderr, "\t\t\t\tcomponent_tag: %d\n" , component_tag); |
319 | #else |
320 | skipBytes(1); |
321 | #endif |
322 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
323 | break; |
324 | } |
325 | case 0x56: { |
326 | pDesc("teletext" ); |
327 | for (unsigned i = 0; i < descriptor_length/5; ++i) { |
328 | #ifdef DEBUG_CONTENTS |
329 | fprintf(stderr, "\t\t\t\tISO_639_language_code: %c%c%c" , |
330 | get1Byte(), get1Byte(), get1Byte()); |
331 | u_int8_t typePlusMagazine = get1Byte(); |
332 | fprintf(stderr, "; type: 0x%02x; magazine: %d; page: %d\n" , |
333 | typePlusMagazine>>3, typePlusMagazine&0x07, get1Byte()); |
334 | #else |
335 | skipBytes(5); |
336 | #endif |
337 | } |
338 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
339 | break; |
340 | } |
341 | case 0x59: { |
342 | pDesc("subtitling" ); |
343 | for (unsigned i = 0; i < descriptor_length/8; ++i) { |
344 | #ifdef DEBUG_CONTENTS |
345 | fprintf(stderr, "\t\t\t\tISO_639_language_code: %c%c%c" , |
346 | get1Byte(), get1Byte(), get1Byte()); |
347 | fprintf(stderr, "; subtitling_type: 0x%02x; composition_page_id: 0x%04x; ancillary_page_id: 0x%04x\n" , |
348 | get1Byte(), get2Bytes(), get2Bytes()); |
349 | #else |
350 | skipBytes(8); |
351 | #endif |
352 | } |
353 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
354 | break; |
355 | } |
356 | case 0x6f: { |
357 | pDesc("application signalling" ); |
358 | for (unsigned i = 0; i < descriptor_length/3; ++i) { |
359 | #ifdef DEBUG_CONTENTS |
360 | fprintf(stderr, "\t\t\t\tapplication_type: 0x%04x; AIT_version_number: %d\n" , |
361 | get2Bytes()&0x7FFF, get1Byte()&0x1F); |
362 | #else |
363 | skipBytes(3); |
364 | #endif |
365 | } |
366 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
367 | break; |
368 | } |
369 | case 0x7a: { |
370 | pDesc("enhanced AC-3" ); |
371 | if (descriptor_length < 1) break; |
372 | #ifdef DEBUG_CONTENTS |
373 | u_int8_t flags = get1Byte(); |
374 | fprintf(stderr, "\t\t\t\tflags: 0x%02x" , flags); |
375 | if (descriptor_length > 1) { |
376 | fprintf(stderr, "; extra bytes: " ); |
377 | for (unsigned i = 1; i < descriptor_length; ++i) fprintf(stderr, "0x%02x " , get1Byte()); |
378 | } |
379 | fprintf(stderr, "\n" ); |
380 | #else |
381 | skipBytes(descriptor_length); |
382 | #endif |
383 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
384 | break; |
385 | } |
386 | case 0x81: { |
387 | pDesc("AC-3 audio" ); |
388 | if (descriptor_length < 3) break; |
389 | #ifdef DEBUG_CONTENTS |
390 | u_int8_t flags = get1Byte(); |
391 | fprintf(stderr, "\t\t\t\tsample_rate_code: %d; bsid: 0x%02x" , |
392 | flags>>5, flags&0x1F); |
393 | flags = get1Byte(); |
394 | fprintf(stderr, "; bit_rate_code: %d; surround_mode: %d" , |
395 | flags>>2, flags&0x03); |
396 | flags = get1Byte(); |
397 | fprintf(stderr, "; bsmod: %d; num_channels: %d; full_svc: %d" , |
398 | flags>>5, (flags&0x1E)>>1, (flags&0x01)); |
399 | if (descriptor_length > 3) { |
400 | fprintf(stderr, "; extra bytes: " ); |
401 | for (unsigned i = 3; i < descriptor_length; ++i) fprintf(stderr, "0x%02x " , get1Byte()); |
402 | } |
403 | fprintf(stderr, "\n" ); |
404 | #else |
405 | skipBytes(descriptor_length); |
406 | #endif |
407 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
408 | break; |
409 | } |
410 | case 0x86: { |
411 | pDesc("caption service" ); |
412 | if (descriptor_length < 1) break; |
413 | u_int8_t number_of_services = get1Byte()&0x1F; |
414 | #ifdef DEBUG_CONTENTS |
415 | fprintf(stderr, "\t\t\t\tnumber_of_services: %d\n" , number_of_services); |
416 | #endif |
417 | if (descriptor_length < number_of_services*6) break; |
418 | #ifdef DEBUG_CONTENTS |
419 | for (unsigned i = 0; i < number_of_services; ++i) { |
420 | fprintf(stderr, "\t\t\t\t\tlanguage: %c%c%c" , get1Byte(), get1Byte(), get1Byte()); |
421 | |
422 | u_int8_t flags = get1Byte(); |
423 | Boolean digital_cc = (flags&0x80) != 0; |
424 | fprintf(stderr, "; digital_cc %d" , digital_cc); |
425 | if (digital_cc == 0) { |
426 | fprintf(stderr, "; line21_field: %d" , flags&0x01); |
427 | } else { |
428 | fprintf(stderr, "; caption_service_number: %d" , flags&0x3F); |
429 | } |
430 | |
431 | u_int16_t flags2 = get2Bytes(); |
432 | fprintf(stderr, "; easy_reader: %d; wide_aspect_ratio: %d\n" , |
433 | (flags2&0x8000) != 0, (flags2&0x4000) != 0); |
434 | } |
435 | #else |
436 | skipBytes(number_of_services*6); |
437 | #endif |
438 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
439 | break; |
440 | } |
441 | default: { |
442 | pDesc("???" ); |
443 | skipBytes(descriptor_length); |
444 | numDescriptorBytes -= descriptor_length; parsedDescriptor = True; |
445 | break; |
446 | } |
447 | } |
448 | if (!parsedDescriptor) break; // an error occurred |
449 | } |
450 | |
451 | // Skip over any remaining descriptor bytes (as a result of a parsing error): |
452 | if (numDescriptorBytes > 0) { |
453 | #ifdef DEBUG_ERRORS |
454 | fprintf(stderr, "MPEG2TransportStreamParser::parseStreamDescriptors() Parsing error left %d bytes unparsed\n" , |
455 | numDescriptorBytes); |
456 | #endif |
457 | skipBytes(numDescriptorBytes); |
458 | } |
459 | } |
460 | |
461 | |
462 | //########## PIDState_PMT implementation ########## |
463 | |
464 | PIDState_PMT |
465 | ::PIDState_PMT(MPEG2TransportStreamParser& parser, u_int16_t pid, u_int16_t programNumber) |
466 | : PIDState(parser, pid, PMT), |
467 | program_number(programNumber) { |
468 | } |
469 | |
470 | PIDState_PMT::~PIDState_PMT() { |
471 | } |
472 | |