1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 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#define NUM_PIDS 0x10000
24
25StreamType StreamTypes[0x100];
26
27MPEG2TransportStreamParser
28::MPEG2TransportStreamParser(FramedSource* inputSource,
29 FramedSource::onCloseFunc* onEndFunc, void* onEndClientData)
30 : StreamParser(inputSource, onEndFunc, onEndClientData, continueParsing, this),
31 fInputSource(inputSource), fAmCurrentlyParsing(False),
32 fOnEndFunc(onEndFunc), fOnEndClientData(onEndClientData),
33 fLastSeenPCR(0.0) {
34 if (StreamTypes[0x01].dataType == StreamType::UNKNOWN) { // initialize array with known values
35 StreamTypes[0x01] = StreamType("MPEG-1 video", StreamType::VIDEO, ".mpv");
36 StreamTypes[0x02] = StreamType("MPEG-2 video", StreamType::VIDEO, ".mpv");
37 StreamTypes[0x03] = StreamType("MPEG-1 audio", StreamType::AUDIO, ".mpa");
38 StreamTypes[0x04] = StreamType("MPEG-2 audio", StreamType::AUDIO, ".mpa");
39 StreamTypes[0x05] = StreamType("privately-defined data", StreamType::DATA);
40 StreamTypes[0x06] = StreamType("privately-defined data", StreamType::DATA);
41 StreamTypes[0x0F] = StreamType("AAC audio", StreamType::AUDIO, ".aac");
42 StreamTypes[0x10] = StreamType("MPEG-4 H.263 based video", StreamType::VIDEO, ".mpv");
43 StreamTypes[0x1B] = StreamType("H.264 video", StreamType::VIDEO, ".h264");
44 StreamTypes[0x1C] = StreamType("MPEG-4 raw audio", StreamType::AUDIO, ".mpa");
45 StreamTypes[0x1D] = StreamType("MPEG-4 text", StreamType::TEXT, ".txt");
46 StreamTypes[0x21] = StreamType("JPEG 2000 video", StreamType::VIDEO, ".mjpg");
47 StreamTypes[0x24] = StreamType("H.265 video", StreamType::VIDEO, ".h265");
48 StreamTypes[0x81] = StreamType("AC-3 audio", StreamType::AUDIO, ".ac3");
49 }
50
51 // Create our 'PID state' array:
52 fPIDState = new PIDState*[NUM_PIDS];
53 for (unsigned i = 0; i < NUM_PIDS; ++i) fPIDState[i] = NULL;
54
55 // Initially, the only PID we know is 0x0000: a Program Association Table:
56 fPIDState[0x0000] = new PIDState_PAT(*this, 0x0000);
57
58 // Begin parsing:
59 continueParsing();
60}
61
62MPEG2TransportStreamParser::~MPEG2TransportStreamParser() {
63 for (unsigned i = 0; i < NUM_PIDS; ++i) delete fPIDState[i];
64 delete[] fPIDState;
65}
66
67UsageEnvironment& MPEG2TransportStreamParser::envir() {
68 return fInputSource->envir();
69}
70
71void MPEG2TransportStreamParser
72::continueParsing(void* clientData, unsigned char* ptr, unsigned size, struct timeval presentationTime) {
73 ((MPEG2TransportStreamParser*)clientData)->continueParsing();
74}
75
76void MPEG2TransportStreamParser::continueParsing() {
77 if (fAmCurrentlyParsing) return; // don't allow recursive calls to parse()
78
79 if (fInputSource != NULL) {
80 fAmCurrentlyParsing = True;
81 Boolean parseSucceeded = parse();
82 fAmCurrentlyParsing = False;
83
84 if (!parseSucceeded) {
85 // We didn't complete the parsing, because we had to read more data from the source,
86 // or because we're waiting for another read from downstream.
87 // Once that happens, we'll get called again.
88 return;
89 }
90 }
91
92 // We successfully parsed the file. Call our 'done' function now:
93 if (fOnEndFunc != NULL) (*fOnEndFunc)(fOnEndClientData);
94}
95
96#define TRANSPORT_SYNC_BYTE 0x47
97#define TRANSPORT_PACKET_SIZE 188
98
99Boolean MPEG2TransportStreamParser::parse() {
100 if (fInputSource->isCurrentlyAwaitingData()) return False;
101 // Our input source is currently being read. Wait until that read completes
102
103 try {
104 while (1) {
105 // Make sure we start with a 'sync byte':
106 do {
107 saveParserState();
108 } while (get1Byte() != TRANSPORT_SYNC_BYTE);
109
110 // Parse and process each (remaining 187 bytes of a) 'Transport Stream Packet' at a time.
111 // (Because these are a lot smaller than the "StreamParser" BANK_SIZE, we don't save
112 // parser state in the middle of processing each such 'Transport Stream Packet'.
113 // Therefore, processing of each 'Transport Stream Packet' needs to be idempotent.)
114
115 u_int16_t flagsPlusPID = get2Bytes();
116 // Check the "transport_error_indicator" flag; reject the packet if it's set:
117 if ((flagsPlusPID&0x8000) != 0) {
118#ifdef DEBUG_ERRORS
119 fprintf(stderr, "MPEG2TransportStreamParser::parse() Rejected packet with \"transport_error_indicator\" flag set!\n");
120#endif
121 continue;
122 }
123 Boolean pusi = (flagsPlusPID&0x4000) != 0; // payload_unit_start_indicator
124 // Ignore "transport_priority"
125 u_int16_t PID = flagsPlusPID&0x1FFF;
126#ifdef DEBUG_CONTENTS
127 fprintf(stderr, "\nTransport Packet: payload_unit_start_indicator: %d; PID: 0x%04x\n",
128 pusi, PID);
129#endif
130
131 u_int8_t controlPlusContinuity_counter = get1Byte();
132 // Reject any packets where the "transport_scrambling_control" field is not zero:
133 if ((controlPlusContinuity_counter&0xC0) != 0) {
134#ifdef DEBUG_ERRORS
135 fprintf(stderr, "MPEG2TransportStreamParser::parse() Rejected packet with \"transport_scrambling_control\" set to non-zero value %d!\n", (controlPlusContinuity_counter&0xC0)>>6);
136#endif
137 continue;
138 }
139 u_int8_t adaptation_field_control = (controlPlusContinuity_counter&0x30)>>4; // 2 bits
140#ifdef DEBUG_CONTENTS
141 u_int8_t continuity_counter = (controlPlusContinuity_counter&0x0F); // 4 bits
142 fprintf(stderr, "adaptation_field_control: %d; continuity_counter: 0x%X\n", adaptation_field_control, continuity_counter);
143#endif
144
145 u_int8_t totalAdaptationFieldSize = adaptation_field_control < 2 ? 0 : parseAdaptationField();
146#ifdef DEBUG_ERRORS
147 if (adaptation_field_control == 2 && totalAdaptationFieldSize != 1+183) {
148 fprintf(stderr, "MPEG2TransportStreamParser::parse() Warning: Got an inconsistent \"totalAdaptationFieldSize\" %d for adaptation_field_control == 2\n", totalAdaptationFieldSize);
149 }
150#endif
151
152 int numDataBytes = TRANSPORT_PACKET_SIZE-4-totalAdaptationFieldSize;
153 if (numDataBytes > 0) {
154#ifdef DEBUG_CONTENTS
155 fprintf(stderr, "+%d data bytes:\n", numDataBytes);
156#endif
157 if (!processDataBytes(PID, pusi, numDataBytes)) {
158 // The parsing got deferred (to be resumed later when a pending read happens)
159 restoreSavedParserState(); // so that we later resume parsing at the start of the packet
160 return False;
161 }
162 }
163 }
164 } catch (int /*e*/) {
165#ifdef DEBUG_CONTENTS
166 fprintf(stderr, "MPEG2TransportStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
167#endif
168 return False; // the parsing got interrupted
169 }
170}
171
172u_int8_t MPEG2TransportStreamParser::parseAdaptationField() {
173 unsigned startPos = curOffset();
174#ifdef DEBUG_CONTENTS
175 fprintf(stderr, "\tAdaptation Field:\n");
176#endif
177 u_int8_t adaptation_field_length = get1Byte();
178#ifdef DEBUG_CONTENTS
179 fprintf(stderr, "\t\tadaptation_field_length: %d\n", adaptation_field_length);
180#endif
181 if (adaptation_field_length > 0) {
182 u_int8_t flags = get1Byte();
183#ifdef DEBUG_CONTENTS
184 fprintf(stderr, "\t\tadaptation field flags: 0x%02x\n", flags);
185#endif
186 if ((flags&0x10) != 0) { // PCR_flag
187 u_int32_t first32PCRBits = get4Bytes();
188 u_int16_t last16PCRBits = get2Bytes();
189 // program_clock_reference_base = "first32PCRBits" and high bit of "last16PCRBits" (33 bits)
190 // program_clock_reference_extension = last 9 bits of "last16PCRBits" (9 bits)
191 double PCR = first32PCRBits/45000.0;
192 if ((last16PCRBits&0x8000) != 0) PCR += 1/90000.0; // add in low-bit (if set)
193 PCR += (last16PCRBits&0x01FF)/27000000.0; // add in extension
194#ifdef DEBUG_CONTENTS
195 fprintf(stderr, "\t\tPCR: %.10f\n", PCR);
196#endif
197 }
198 if ((flags&0x08) != 0) { // OPCR_flag
199 u_int32_t first32OPCRBits = get4Bytes();
200 u_int16_t last16OPCRBits = get2Bytes();
201 // original_program_clock_reference_base = "first32OPCRBits" and high bit of "last16OPCRBits" (33 bits)
202 // original_program_clock_reference_extension = last 9 bits of "last16OPCRBits" (9 bits)
203 double OPCR = first32OPCRBits/45000.0;
204 if ((last16OPCRBits&0x8000) != 0) OPCR += 1/90000.0; // add in low-bit (if set)
205 OPCR += (last16OPCRBits&0x01FF)/27000000.0; // add in extension
206#ifdef DEBUG_CONTENTS
207 fprintf(stderr, "\t\tOPCR: %.10f\n", OPCR);
208#endif
209 }
210 if ((flags&0x04) != 0) { // splicing_point_flag
211 skipBytes(1); // splice_countdown
212 }
213 if ((flags&0x02) != 0) { // transport_private_data_flag
214 u_int8_t transport_private_data_length = get1Byte();
215#ifdef DEBUG_CONTENTS
216 fprintf(stderr, "\t\ttransport_private_data_length: %d\n", transport_private_data_length);
217#endif
218 skipBytes(transport_private_data_length); // "private_data_byte"s
219 }
220 if ((flags&0x01) != 0) { // adaptation_field_extension_flag
221#ifdef DEBUG_CONTENTS
222 u_int8_t adaptation_field_extension_length = get1Byte();
223 fprintf(stderr, "\t\tadaptation_field_extension_length: %d\n", adaptation_field_extension_length);
224#else
225 skipBytes(1); // adaptation_field_extension_length
226#endif
227 u_int8_t flagsPlusReserved = get1Byte();
228#ifdef DEBUG_CONTENTS
229 fprintf(stderr, "\t\t\tflagsPlusReserved: 0x%02x\n", flagsPlusReserved);
230#endif
231 if ((flagsPlusReserved&0x80) != 0) { // ltw_flag
232 skipBytes(2); // "ltw_valid_flag" + "ltw_offset"
233 }
234 if ((flagsPlusReserved&0x40) != 0) { // piecewise_rate_flag
235 skipBytes(3); // reserved + "piecewise_rate"
236 }
237 if ((flagsPlusReserved&0x20) != 0) { // seamless_splice_flag
238 skipBytes(5); // DTS_next_...
239 }
240 // Skip reserved bytes to the end of the adaptation_field:
241 int numBytesLeft = (1 + adaptation_field_length) - (curOffset() - startPos);
242 if (numBytesLeft > 0) {
243#ifdef DEBUG_CONTENTS
244 fprintf(stderr, "\t\t+%d reserved bytes\n", numBytesLeft);
245#endif
246 skipBytes(numBytesLeft);
247 }
248 }
249 // Skip "stuffing_byte"s to the end of the adaptation_field:
250 int numBytesLeft = (1 + adaptation_field_length) - (curOffset() - startPos);
251 if (numBytesLeft > 0) {
252#ifdef DEBUG_CONTENTS
253 fprintf(stderr, "\t\t+%d stuffing bytes\n", numBytesLeft);
254#endif
255#ifdef DEBUG_ERRORS
256 for (int i = 0; i < numBytesLeft; ++i) {
257 if (get1Byte() != 0xFF) {
258 fprintf(stderr, "WARNING: non-stuffing byte in adaptation_field\n");
259 }
260 }
261#else
262 skipBytes(numBytesLeft);
263#endif
264 }
265 }
266
267 // Finally, figure out how many bytes we parsed, and compare it to what we expected:
268 unsigned totalAdaptationFieldSize = curOffset() - startPos;
269#ifdef DEBUG_ERRORS
270 if (totalAdaptationFieldSize != 1 + adaptation_field_length) {
271 fprintf(stderr, "MPEG2TransportStreamParser::parseAdaptationField() Warning: Got an inconsistent \"totalAdaptationFieldSize\" %d; expected %d\n", totalAdaptationFieldSize, 1 + adaptation_field_length);
272 }
273#endif
274 return totalAdaptationFieldSize;
275}
276
277Boolean MPEG2TransportStreamParser
278::processDataBytes(u_int16_t PID, Boolean pusi, unsigned numDataBytes) {
279 PIDState* pidState = fPIDState[PID];
280
281 if (pidState == NULL) { // unknown PID
282#ifdef DEBUG_CONTENTS
283 fprintf(stderr, "\tUnknown PID\n");
284#endif
285 skipBytes(numDataBytes);
286 return True;
287 }
288
289 switch (pidState->type) {
290 case PAT: {
291 parsePAT(pusi, numDataBytes);
292 return True;
293 }
294 case PMT: {
295 parsePMT((PIDState_PMT*)pidState, pusi, numDataBytes);
296 return True;
297 }
298 case STREAM: {
299 return processStreamPacket((PIDState_STREAM*)pidState, pusi, numDataBytes);
300 }
301 default: { // Never reached, but eliminates a possible error with dumb compilers
302 return False;
303 }
304 }
305}
306
307void MPEG2TransportStreamParser::restoreSavedParserState() {
308 StreamParser::restoreSavedParserState();
309 fAmCurrentlyParsing = False;
310}
311
312
313//########## PIDState implementation ##########
314
315PIDState::PIDState(MPEG2TransportStreamParser& parser, u_int16_t pid, PIDType pidType)
316 : ourParser(parser), PID(pid), type(pidType) {
317}
318
319PIDState::~PIDState() {
320}
321
322
323//######### StreamType implementation ########
324
325StreamType
326::StreamType(char const* description, enum dataType dataType, char const* filenameSuffix)
327 : description(description), dataType(dataType), filenameSuffix(filenameSuffix) {
328}
329