|
MythTV
0.26-pre
|
00001 /********** 00002 This library is free software; you can redistribute it and/or modify it under 00003 the terms of the GNU Lesser General Public License as published by the 00004 Free Software Foundation; either version 2.1 of the License, or (at your 00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) 00006 00007 This library is distributed in the hope that it will be useful, but WITHOUT 00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00009 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00010 more details. 00011 00012 You should have received a copy of the GNU Lesser General Public License 00013 along with this library; if not, write to the Free Software Foundation, Inc., 00014 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00015 **********/ 00016 // "liveMedia" 00017 // Copyright (c) 1996-2005 Live Networks, Inc. All rights reserved. 00018 // Demultiplexer for a MPEG 1 or 2 Program Stream 00019 // Implementation 00020 00021 #include "MPEG1or2Demux.hh" 00022 #include "MPEG1or2DemuxedElementaryStream.hh" 00023 #include "StreamParser.hh" 00024 #include <stdlib.h> 00025 00027 00028 // An enum representing the current state of the parser: 00029 enum MPEGParseState { 00030 PARSING_PACK_HEADER, 00031 PARSING_SYSTEM_HEADER, 00032 PARSING_PES_PACKET 00033 }; 00034 00035 class MPEGProgramStreamParser: public StreamParser { 00036 public: 00037 MPEGProgramStreamParser(MPEG1or2Demux* usingSource, FramedSource* inputSource); 00038 virtual ~MPEGProgramStreamParser(); 00039 00040 public: 00041 unsigned char parse(); 00042 // returns the stream id of a stream for which a frame was acquired, 00043 // or 0 if no such frame was acquired. 00044 00045 private: 00046 void setParseState(MPEGParseState parseState); 00047 00048 void parsePackHeader(); 00049 void parseSystemHeader(); 00050 unsigned char parsePESPacket(); // returns as does parse() 00051 00052 Boolean isSpecialStreamId(unsigned char stream_id) const; 00053 // for PES packet header parsing 00054 00055 private: 00056 MPEG1or2Demux* fUsingSource; 00057 MPEGParseState fCurrentParseState; 00058 }; 00059 00060 00062 00063 class MPEG1or2Demux::OutputDescriptor::SavedData { 00064 public: 00065 SavedData(unsigned char* buf, unsigned size) 00066 : next(NULL), data(buf), dataSize(size), numBytesUsed(0) { 00067 } 00068 virtual ~SavedData() { 00069 delete[] data; 00070 delete next; 00071 } 00072 00073 SavedData* next; 00074 unsigned char* data; 00075 unsigned dataSize, numBytesUsed; 00076 }; 00077 00078 00080 00081 MPEG1or2Demux 00082 ::MPEG1or2Demux(UsageEnvironment& env, 00083 FramedSource* inputSource, Boolean reclaimWhenLastESDies) 00084 : Medium(env), 00085 fInputSource(inputSource), fMPEGversion(0), 00086 fNextAudioStreamNumber(0), fNextVideoStreamNumber(0), 00087 fReclaimWhenLastESDies(reclaimWhenLastESDies), fNumOutstandingESs(0), 00088 fNumPendingReads(0), fHaveUndeliveredData(False) { 00089 fParser = new MPEGProgramStreamParser(this, inputSource); 00090 for (unsigned i = 0; i < 256; ++i) { 00091 fOutput[i].savedDataHead = fOutput[i].savedDataTail = NULL; 00092 fOutput[i].isPotentiallyReadable = False; 00093 fOutput[i].isCurrentlyActive = False; 00094 fOutput[i].isCurrentlyAwaitingData = False; 00095 } 00096 } 00097 00098 MPEG1or2Demux::~MPEG1or2Demux() { 00099 delete fParser; 00100 for (unsigned i = 0; i < 256; ++i) delete fOutput[i].savedDataHead; 00101 Medium::close(fInputSource); 00102 } 00103 00104 MPEG1or2Demux* MPEG1or2Demux 00105 ::createNew(UsageEnvironment& env, 00106 FramedSource* inputSource, Boolean reclaimWhenLastESDies) { 00107 // Need to add source type checking here??? ##### 00108 00109 return new MPEG1or2Demux(env, inputSource, reclaimWhenLastESDies); 00110 } 00111 00112 MPEG1or2Demux::SCR::SCR() 00113 : highBit(0), remainingBits(0), extension(0), isValid(False) { 00114 } 00115 00116 void MPEG1or2Demux 00117 ::noteElementaryStreamDeletion(MPEG1or2DemuxedElementaryStream* /*es*/) { 00118 if (--fNumOutstandingESs == 0 && fReclaimWhenLastESDies) { 00119 Medium::close(this); 00120 } 00121 } 00122 00123 void MPEG1or2Demux::flushInput() { 00124 fParser->flushInput(); 00125 } 00126 00127 MPEG1or2DemuxedElementaryStream* 00128 MPEG1or2Demux::newElementaryStream(u_int8_t streamIdTag) { 00129 ++fNumOutstandingESs; 00130 fOutput[streamIdTag].isPotentiallyReadable = True; 00131 return new MPEG1or2DemuxedElementaryStream(envir(), streamIdTag, *this); 00132 } 00133 00134 MPEG1or2DemuxedElementaryStream* MPEG1or2Demux::newAudioStream() { 00135 unsigned char newAudioStreamTag = 0xC0 | (fNextAudioStreamNumber++&~0xE0); 00136 // MPEG audio stream tags are 110x xxxx (binary) 00137 return newElementaryStream(newAudioStreamTag); 00138 } 00139 00140 MPEG1or2DemuxedElementaryStream* MPEG1or2Demux::newVideoStream() { 00141 unsigned char newVideoStreamTag = 0xE0 | (fNextVideoStreamNumber++&~0xF0); 00142 // MPEG video stream tags are 1110 xxxx (binary) 00143 return newElementaryStream(newVideoStreamTag); 00144 } 00145 00146 // Appropriate one of the reserved stream id tags to mean: return raw PES packets: 00147 #define RAW_PES 0xFC 00148 00149 MPEG1or2DemuxedElementaryStream* MPEG1or2Demux::newRawPESStream() { 00150 return newElementaryStream(RAW_PES); 00151 } 00152 00153 void MPEG1or2Demux::registerReadInterest(u_int8_t streamIdTag, 00154 unsigned char* to, unsigned maxSize, 00155 FramedSource::afterGettingFunc* afterGettingFunc, 00156 void* afterGettingClientData, 00157 FramedSource::onCloseFunc* onCloseFunc, 00158 void* onCloseClientData) { 00159 struct OutputDescriptor& out = fOutput[streamIdTag]; 00160 00161 // Make sure this stream is not already being read: 00162 if (out.isCurrentlyAwaitingData) { 00163 envir() << "MPEG1or2Demux::registerReadInterest(): attempt to read stream id " 00164 << (void*)streamIdTag << " more than once!\n"; 00165 exit(1); 00166 } 00167 00168 out.to = to; out.maxSize = maxSize; 00169 out.fAfterGettingFunc = afterGettingFunc; 00170 out.afterGettingClientData = afterGettingClientData; 00171 out.fOnCloseFunc = onCloseFunc; 00172 out.onCloseClientData = onCloseClientData; 00173 out.isCurrentlyActive = True; 00174 out.isCurrentlyAwaitingData = True; 00175 // out.frameSize and out.presentationTime will be set when a frame's read 00176 00177 ++fNumPendingReads; 00178 } 00179 00180 Boolean MPEG1or2Demux::useSavedData(u_int8_t streamIdTag, 00181 unsigned char* to, unsigned maxSize, 00182 FramedSource::afterGettingFunc* afterGettingFunc, 00183 void* afterGettingClientData) { 00184 struct OutputDescriptor& out = fOutput[streamIdTag]; 00185 if (out.savedDataHead == NULL) return False; // common case 00186 00187 unsigned totNumBytesCopied = 0; 00188 while (maxSize > 0 && out.savedDataHead != NULL) { 00189 OutputDescriptor::SavedData& savedData = *(out.savedDataHead); 00190 unsigned char* from = &savedData.data[savedData.numBytesUsed]; 00191 unsigned numBytesToCopy = savedData.dataSize - savedData.numBytesUsed; 00192 if (numBytesToCopy > maxSize) numBytesToCopy = maxSize; 00193 memmove(to, from, numBytesToCopy); 00194 to += numBytesToCopy; 00195 maxSize -= numBytesToCopy; 00196 out.savedDataTotalSize -= numBytesToCopy; 00197 totNumBytesCopied += numBytesToCopy; 00198 savedData.numBytesUsed += numBytesToCopy; 00199 if (savedData.numBytesUsed == savedData.dataSize) { 00200 out.savedDataHead = savedData.next; 00201 if (out.savedDataHead == NULL) out.savedDataTail = NULL; 00202 savedData.next = NULL; 00203 delete &savedData; 00204 } 00205 } 00206 00207 out.isCurrentlyActive = True; 00208 if (afterGettingFunc != NULL) { 00209 struct timeval presentationTime; 00210 presentationTime.tv_sec = 0; presentationTime.tv_usec = 0; // should fix ##### 00211 (*afterGettingFunc)(afterGettingClientData, totNumBytesCopied, 00212 0 /* numTruncatedBytes */, presentationTime, 00213 0 /* durationInMicroseconds ?????#####*/); 00214 } 00215 return True; 00216 } 00217 00218 void MPEG1or2Demux 00219 ::continueReadProcessing(void* clientData, 00220 unsigned char* /*ptr*/, unsigned /*size*/, 00221 struct timeval /*presentationTime*/) { 00222 MPEG1or2Demux* demux = (MPEG1or2Demux*)clientData; 00223 demux->continueReadProcessing(); 00224 } 00225 00226 void MPEG1or2Demux::continueReadProcessing() { 00227 while (fNumPendingReads > 0) { 00228 unsigned char acquiredStreamIdTag = fParser->parse(); 00229 00230 if (acquiredStreamIdTag != 0) { 00231 // We were able to acquire a frame from the input. 00232 struct OutputDescriptor& newOut = fOutput[acquiredStreamIdTag]; 00233 newOut.isCurrentlyAwaitingData = False; 00234 // indicates that we can be read again 00235 // (This needs to be set before the 'after getting' call below, 00236 // in case it tries to read another frame) 00237 00238 // Call our own 'after getting' function. Because we're not a 'leaf' 00239 // source, we can call this directly, without risking infinite recursion. 00240 if (newOut.fAfterGettingFunc != NULL) { 00241 (*newOut.fAfterGettingFunc)(newOut.afterGettingClientData, 00242 newOut.frameSize, 0 /* numTruncatedBytes */, 00243 newOut.presentationTime, 00244 0 /* durationInMicroseconds ?????#####*/); 00245 --fNumPendingReads; 00246 } 00247 } else { 00248 // We were unable to parse a complete frame from the input, because: 00249 // - we had to read more data from the source stream, or 00250 // - we found a frame for a stream that was being read, but whose 00251 // reader is not ready to get the frame right now, or 00252 // - the source stream has ended. 00253 break; 00254 } 00255 } 00256 } 00257 00258 void MPEG1or2Demux::getNextFrame(u_int8_t streamIdTag, 00259 unsigned char* to, unsigned maxSize, 00260 FramedSource::afterGettingFunc* afterGettingFunc, 00261 void* afterGettingClientData, 00262 FramedSource::onCloseFunc* onCloseFunc, 00263 void* onCloseClientData) { 00264 // First, check whether we have saved data for this stream id: 00265 if (useSavedData(streamIdTag, to, maxSize, 00266 afterGettingFunc, afterGettingClientData)) { 00267 return; 00268 } 00269 00270 // Then save the parameters of the specified stream id: 00271 registerReadInterest(streamIdTag, to, maxSize, 00272 afterGettingFunc, afterGettingClientData, 00273 onCloseFunc, onCloseClientData); 00274 00275 // Next, if we're the only currently pending read, continue looking for data: 00276 if (fNumPendingReads == 1 || fHaveUndeliveredData) { 00277 fHaveUndeliveredData = 0; 00278 continueReadProcessing(); 00279 } // otherwise the continued read processing has already been taken care of 00280 } 00281 00282 void MPEG1or2Demux::stopGettingFrames(u_int8_t streamIdTag) { 00283 struct OutputDescriptor& out = fOutput[streamIdTag]; 00284 out.isCurrentlyActive = out.isCurrentlyAwaitingData = False; 00285 } 00286 00287 void MPEG1or2Demux::handleClosure(void* clientData) { 00288 MPEG1or2Demux* demux = (MPEG1or2Demux*)clientData; 00289 00290 demux->fNumPendingReads = 0; 00291 00292 // Tell all pending readers that our source has closed. 00293 // Note that we need to make a copy of our readers' close functions 00294 // (etc.) before we start calling any of them, in case one of them 00295 // ends up deleting this. 00296 struct { 00297 FramedSource::onCloseFunc* fOnCloseFunc; 00298 void* onCloseClientData; 00299 } savedPending[256]; 00300 unsigned i, numPending = 0; 00301 for (i = 0; i < 256; ++i) { 00302 struct OutputDescriptor& out = demux->fOutput[i]; 00303 if (out.isCurrentlyAwaitingData) { 00304 if (out.fOnCloseFunc != NULL) { 00305 savedPending[numPending].fOnCloseFunc = out.fOnCloseFunc; 00306 savedPending[numPending].onCloseClientData = out.onCloseClientData; 00307 ++numPending; 00308 } 00309 } 00310 delete out.savedDataHead; out.savedDataHead = out.savedDataTail = NULL; 00311 out.savedDataTotalSize = 0; 00312 out.isPotentiallyReadable = out.isCurrentlyActive = out.isCurrentlyAwaitingData 00313 = False; 00314 } 00315 for (i = 0; i < numPending; ++i) { 00316 (*savedPending[i].fOnCloseFunc)(savedPending[i].onCloseClientData); 00317 } 00318 } 00319 00320 00322 00323 #include <string.h> 00324 00325 MPEGProgramStreamParser::MPEGProgramStreamParser(MPEG1or2Demux* usingSource, 00326 FramedSource* inputSource) 00327 : StreamParser(inputSource, MPEG1or2Demux::handleClosure, usingSource, 00328 &MPEG1or2Demux::continueReadProcessing, usingSource), 00329 fUsingSource(usingSource), fCurrentParseState(PARSING_PACK_HEADER) { 00330 } 00331 00332 MPEGProgramStreamParser::~MPEGProgramStreamParser() { 00333 } 00334 00335 void MPEGProgramStreamParser::setParseState(MPEGParseState parseState) { 00336 fCurrentParseState = parseState; 00337 saveParserState(); 00338 } 00339 00340 unsigned char MPEGProgramStreamParser::parse() { 00341 unsigned char acquiredStreamTagId = 0; 00342 00343 try { 00344 do { 00345 switch (fCurrentParseState) { 00346 case PARSING_PACK_HEADER: { 00347 parsePackHeader(); 00348 break; 00349 } 00350 case PARSING_SYSTEM_HEADER: { 00351 parseSystemHeader(); 00352 break; 00353 } 00354 case PARSING_PES_PACKET: { 00355 acquiredStreamTagId = parsePESPacket(); 00356 break; 00357 } 00358 } 00359 } while(acquiredStreamTagId == 0); 00360 00361 return acquiredStreamTagId; 00362 } catch (int /*e*/) { 00363 #ifdef DEBUG 00364 fprintf(stderr, "MPEGProgramStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n"); 00365 fflush(stderr); 00366 #endif 00367 return 0; // the parsing got interrupted 00368 } 00369 } 00370 00371 #define PACK_START_CODE 0x000001BA 00372 #define SYSTEM_HEADER_START_CODE 0x000001BB 00373 #define PACKET_START_CODE_PREFIX 0x00000100 00374 00375 static inline Boolean isPacketStartCode(unsigned code) { 00376 return (code&0xFFFFFF00) == PACKET_START_CODE_PREFIX 00377 && code > SYSTEM_HEADER_START_CODE; 00378 } 00379 00380 void MPEGProgramStreamParser::parsePackHeader() { 00381 #ifdef DEBUG 00382 fprintf(stderr, "parsing pack header\n"); fflush(stderr); 00383 #endif 00384 unsigned first4Bytes; 00385 while (1) { 00386 first4Bytes = test4Bytes(); 00387 00388 // We're supposed to have a pack header here, but check also for 00389 // a system header or a PES packet, just in case: 00390 if (first4Bytes == PACK_START_CODE) { 00391 skipBytes(4); 00392 break; 00393 } else if (first4Bytes == SYSTEM_HEADER_START_CODE) { 00394 #ifdef DEBUG 00395 fprintf(stderr, "found system header instead of pack header\n"); 00396 #endif 00397 setParseState(PARSING_SYSTEM_HEADER); 00398 return; 00399 } else if (isPacketStartCode(first4Bytes)) { 00400 #ifdef DEBUG 00401 fprintf(stderr, "found packet start code 0x%02x instead of pack header\n", first4Bytes); 00402 #endif 00403 setParseState(PARSING_PES_PACKET); 00404 return; 00405 } 00406 00407 setParseState(PARSING_PACK_HEADER); // ensures we progress over bad data 00408 if ((first4Bytes&0xFF) > 1) { // a system code definitely doesn't start here 00409 skipBytes(4); 00410 } else { 00411 skipBytes(1); 00412 } 00413 } 00414 00415 // The size of the pack header differs depending on whether it's 00416 // MPEG-1 or MPEG-2. The next byte tells us this: 00417 unsigned char nextByte = get1Byte(); 00418 MPEG1or2Demux::SCR& scr = fUsingSource->fLastSeenSCR; // alias 00419 if ((nextByte&0xF0) == 0x20) { // MPEG-1 00420 fUsingSource->fMPEGversion = 1; 00421 scr.highBit = (nextByte&0x08)>>3; 00422 scr.remainingBits = (nextByte&0x06)<<29; 00423 unsigned next4Bytes = get4Bytes(); 00424 scr.remainingBits |= (next4Bytes&0xFFFE0000)>>2; 00425 scr.remainingBits |= (next4Bytes&0x0000FFFE)>>1; 00426 scr.extension = 0; 00427 scr.isValid = True; 00428 skipBits(24); 00429 00430 #if defined(DEBUG_TIMESTAMPS) || defined(DEBUG_SCR_TIMESTAMPS) 00431 fprintf(stderr, "pack hdr system_clock_reference_base: 0x%x", 00432 scr.highBit); 00433 fprintf(stderr, "%08x\n", scr.remainingBits); 00434 #endif 00435 } else if ((nextByte&0xC0) == 0x40) { // MPEG-2 00436 fUsingSource->fMPEGversion = 2; 00437 scr.highBit = (nextByte&0x20)>>5; 00438 scr.remainingBits = (nextByte&0x18)<<27; 00439 scr.remainingBits |= (nextByte&0x03)<<28; 00440 unsigned next4Bytes = get4Bytes(); 00441 scr.remainingBits |= (next4Bytes&0xFFF80000)>>4; 00442 scr.remainingBits |= (next4Bytes&0x0003FFF8)>>3; 00443 scr.extension = (next4Bytes&0x00000003)<<7; 00444 next4Bytes = get4Bytes(); 00445 scr.extension |= (next4Bytes&0xFE000000)>>25; 00446 scr.isValid = True; 00447 skipBits(5); 00448 00449 #if defined(DEBUG_TIMESTAMPS) || defined(DEBUG_SCR_TIMESTAMPS) 00450 fprintf(stderr, "pack hdr system_clock_reference_base: 0x%x", 00451 scr.highBit); 00452 fprintf(stderr, "%08x\n", scr.remainingBits); 00453 fprintf(stderr, "pack hdr system_clock_reference_extension: 0x%03x\n", 00454 scr.extension); 00455 #endif 00456 unsigned char pack_stuffing_length = getBits(3); 00457 skipBytes(pack_stuffing_length); 00458 } else { // unknown 00459 fUsingSource->envir() << "StreamParser::parsePack() saw strange byte " 00460 << (void*)nextByte 00461 << " following pack_start_code\n"; 00462 } 00463 00464 // Check for a System Header next: 00465 setParseState(PARSING_SYSTEM_HEADER); 00466 } 00467 00468 void MPEGProgramStreamParser::parseSystemHeader() { 00469 #ifdef DEBUG 00470 fprintf(stderr, "parsing system header\n"); fflush(stderr); 00471 #endif 00472 unsigned next4Bytes = test4Bytes(); 00473 if (next4Bytes != SYSTEM_HEADER_START_CODE) { 00474 // The system header was optional. Look for a PES Packet instead: 00475 setParseState(PARSING_PES_PACKET); 00476 return; 00477 } 00478 00479 #ifdef DEBUG 00480 fprintf(stderr, "saw system_header_start_code\n"); fflush(stderr); 00481 #endif 00482 skipBytes(4); // we've already seen the system_header_start_code 00483 00484 unsigned short remaining_header_length = get2Bytes(); 00485 00486 // According to the MPEG-1 and MPEG-2 specs, "remaining_header_length" should be 00487 // at least 6 bytes. Check this now: 00488 if (remaining_header_length < 6) { 00489 fUsingSource->envir() << "StreamParser::parseSystemHeader(): saw strange header_length: " 00490 << remaining_header_length << " < 6\n"; 00491 } 00492 skipBytes(remaining_header_length); 00493 00494 // Check for a PES Packet next: 00495 setParseState(PARSING_PES_PACKET); 00496 } 00497 00498 #define private_stream_1 0xBD 00499 #define private_stream_2 0xBF 00500 00501 // A test for stream ids that are exempt from normal PES packet header parsing 00502 Boolean MPEGProgramStreamParser 00503 ::isSpecialStreamId(unsigned char stream_id) const { 00504 if (stream_id == RAW_PES) return True; // hack 00505 00506 if (fUsingSource->fMPEGversion == 1) { 00507 return stream_id == private_stream_2; 00508 } else { // assume MPEG-2 00509 if (stream_id <= private_stream_2) { 00510 return stream_id != private_stream_1; 00511 } else if ((stream_id&0xF0) == 0xF0) { 00512 unsigned char lower4Bits = stream_id&0x0F; 00513 return lower4Bits <= 2 || lower4Bits == 0x8 || lower4Bits == 0xF; 00514 } else { 00515 return False; 00516 } 00517 } 00518 } 00519 00520 #define READER_NOT_READY 2 00521 00522 unsigned char MPEGProgramStreamParser::parsePESPacket() { 00523 #ifdef DEBUG 00524 fprintf(stderr, "parsing PES packet\n"); fflush(stderr); 00525 #endif 00526 unsigned next4Bytes = test4Bytes(); 00527 if (!isPacketStartCode(next4Bytes)) { 00528 // The PES Packet was optional. Look for a Pack Header instead: 00529 setParseState(PARSING_PACK_HEADER); 00530 return 0; 00531 } 00532 00533 #ifdef DEBUG 00534 fprintf(stderr, "saw packet_start_code_prefix\n"); fflush(stderr); 00535 #endif 00536 skipBytes(3); // we've already seen the packet_start_code_prefix 00537 00538 unsigned char stream_id = get1Byte(); 00539 #if defined(DEBUG) || defined(DEBUG_TIMESTAMPS) 00540 unsigned char streamNum = stream_id; 00541 char* streamTypeStr; 00542 if ((stream_id&0xE0) == 0xC0) { 00543 streamTypeStr = "audio"; 00544 streamNum = stream_id&~0xE0; 00545 } else if ((stream_id&0xF0) == 0xE0) { 00546 streamTypeStr = "video"; 00547 streamNum = stream_id&~0xF0; 00548 } else if (stream_id == 0xbc) { 00549 streamTypeStr = "reserved"; 00550 } else if (stream_id == 0xbd) { 00551 streamTypeStr = "private_1"; 00552 } else if (stream_id == 0xbe) { 00553 streamTypeStr = "padding"; 00554 } else if (stream_id == 0xbf) { 00555 streamTypeStr = "private_2"; 00556 } else { 00557 streamTypeStr = "unknown"; 00558 } 00559 #endif 00560 #ifdef DEBUG 00561 static unsigned frameCount = 1; 00562 fprintf(stderr, "%d, saw %s stream: 0x%02x\n", frameCount, streamTypeStr, streamNum); fflush(stderr); 00563 #endif 00564 00565 unsigned short PES_packet_length = get2Bytes(); 00566 #ifdef DEBUG 00567 fprintf(stderr, "PES_packet_length: %d\n", PES_packet_length); fflush(stderr); 00568 #endif 00569 00570 // Parse over the rest of the header, until we get to the packet data itself. 00571 // This varies depending upon the MPEG version: 00572 if (fUsingSource->fOutput[RAW_PES].isPotentiallyReadable) { 00573 // Hack: We've been asked to return raw PES packets, for every stream: 00574 stream_id = RAW_PES; 00575 } 00576 unsigned savedParserOffset = curOffset(); 00577 #ifdef DEBUG_TIMESTAMPS 00578 unsigned char pts_highBit = 0; 00579 unsigned pts_remainingBits = 0; 00580 unsigned char dts_highBit = 0; 00581 unsigned dts_remainingBits = 0; 00582 #endif 00583 if (fUsingSource->fMPEGversion == 1) { 00584 if (!isSpecialStreamId(stream_id)) { 00585 unsigned char nextByte; 00586 while ((nextByte = get1Byte()) == 0xFF) { // stuffing_byte 00587 } 00588 if ((nextByte&0xC0) == 0x40) { // '01' 00589 skipBytes(1); 00590 nextByte = get1Byte(); 00591 } 00592 if ((nextByte&0xF0) == 0x20) { // '0010' 00593 #ifdef DEBUG_TIMESTAMPS 00594 pts_highBit = (nextByte&0x08)>>3; 00595 pts_remainingBits = (nextByte&0x06)<<29; 00596 unsigned next4Bytes = get4Bytes(); 00597 pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2; 00598 pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1; 00599 #else 00600 skipBytes(4); 00601 #endif 00602 } else if ((nextByte&0xF0) == 0x30) { // '0011' 00603 #ifdef DEBUG_TIMESTAMPS 00604 pts_highBit = (nextByte&0x08)>>3; 00605 pts_remainingBits = (nextByte&0x06)<<29; 00606 unsigned next4Bytes = get4Bytes(); 00607 pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2; 00608 pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1; 00609 00610 nextByte = get1Byte(); 00611 dts_highBit = (nextByte&0x08)>>3; 00612 dts_remainingBits = (nextByte&0x06)<<29; 00613 next4Bytes = get4Bytes(); 00614 dts_remainingBits |= (next4Bytes&0xFFFE0000)>>2; 00615 dts_remainingBits |= (next4Bytes&0x0000FFFE)>>1; 00616 #else 00617 skipBytes(9); 00618 #endif 00619 } 00620 } 00621 } else { // assume MPEG-2 00622 if (!isSpecialStreamId(stream_id)) { 00623 // Fields in the next 3 bytes determine the size of the rest: 00624 unsigned next3Bytes = getBits(24); 00625 #ifdef DEBUG_TIMESTAMPS 00626 unsigned char PTS_DTS_flags = (next3Bytes&0x00C000)>>14; 00627 #endif 00628 #ifdef undef 00629 unsigned char ESCR_flag = (next3Bytes&0x002000)>>13; 00630 unsigned char ES_rate_flag = (next3Bytes&0x001000)>>12; 00631 unsigned char DSM_trick_mode_flag = (next3Bytes&0x000800)>>11; 00632 #endif 00633 unsigned char PES_header_data_length = (next3Bytes&0x0000FF); 00634 #ifdef DEBUG 00635 fprintf(stderr, "PES_header_data_length: 0x%02x\n", PES_header_data_length); fflush(stderr); 00636 #endif 00637 #ifdef DEBUG_TIMESTAMPS 00638 if (PTS_DTS_flags == 0x2 && PES_header_data_length >= 5) { 00639 unsigned char nextByte = get1Byte(); 00640 pts_highBit = (nextByte&0x08)>>3; 00641 pts_remainingBits = (nextByte&0x06)<<29; 00642 unsigned next4Bytes = get4Bytes(); 00643 pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2; 00644 pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1; 00645 00646 skipBytes(PES_header_data_length-5); 00647 } else if (PTS_DTS_flags == 0x3 && PES_header_data_length >= 10) { 00648 unsigned char nextByte = get1Byte(); 00649 pts_highBit = (nextByte&0x08)>>3; 00650 pts_remainingBits = (nextByte&0x06)<<29; 00651 unsigned next4Bytes = get4Bytes(); 00652 pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2; 00653 pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1; 00654 00655 nextByte = get1Byte(); 00656 dts_highBit = (nextByte&0x08)>>3; 00657 dts_remainingBits = (nextByte&0x06)<<29; 00658 next4Bytes = get4Bytes(); 00659 dts_remainingBits |= (next4Bytes&0xFFFE0000)>>2; 00660 dts_remainingBits |= (next4Bytes&0x0000FFFE)>>1; 00661 00662 skipBytes(PES_header_data_length-10); 00663 } 00664 #else 00665 skipBytes(PES_header_data_length); 00666 #endif 00667 } 00668 } 00669 #ifdef DEBUG_TIMESTAMPS 00670 fprintf(stderr, "%s stream, ", streamTypeStr); 00671 fprintf(stderr, "packet presentation_time_stamp: 0x%x", pts_highBit); 00672 fprintf(stderr, "%08x\n", pts_remainingBits); 00673 fprintf(stderr, "\t\tpacket decoding_time_stamp: 0x%x", dts_highBit); 00674 fprintf(stderr, "%08x\n", dts_remainingBits); 00675 #endif 00676 00677 // The rest of the packet will be the "PES_packet_data_byte"s 00678 // Make sure that "PES_packet_length" was consistent with where we are now: 00679 unsigned char acquiredStreamIdTag = 0; 00680 unsigned currentParserOffset = curOffset(); 00681 unsigned bytesSkipped = currentParserOffset - savedParserOffset; 00682 if (stream_id == RAW_PES) { 00683 restoreSavedParserState(); // so we deliver from the beginning of the PES packet 00684 PES_packet_length += 6; // to include the whole of the PES packet 00685 bytesSkipped = 0; 00686 } 00687 if (PES_packet_length < bytesSkipped) { 00688 fUsingSource->envir() << "StreamParser::parsePESPacket(): saw inconsistent PES_packet_length " 00689 << PES_packet_length << " < " 00690 << bytesSkipped << "\n"; 00691 } else { 00692 PES_packet_length -= bytesSkipped; 00693 #ifdef DEBUG 00694 unsigned next4Bytes = test4Bytes(); 00695 #endif 00696 00697 // Check whether our using source is interested in this stream type. 00698 // If so, deliver the frame to him: 00699 MPEG1or2Demux::OutputDescriptor_t& out = fUsingSource->fOutput[stream_id]; 00700 if (out.isCurrentlyAwaitingData) { 00701 unsigned numBytesToCopy; 00702 if (PES_packet_length > out.maxSize) { 00703 fUsingSource->envir() << "MPEGProgramStreamParser::parsePESPacket() error: PES_packet_length (" 00704 << PES_packet_length 00705 << ") exceeds max frame size asked for (" 00706 << out.maxSize << ")\n"; 00707 numBytesToCopy = out.maxSize; 00708 } else { 00709 numBytesToCopy = PES_packet_length; 00710 } 00711 00712 getBytes(out.to, numBytesToCopy); 00713 out.frameSize = numBytesToCopy; 00714 #ifdef DEBUG 00715 fprintf(stderr, "%d, %d bytes of PES_packet_data (out.maxSize: %d); first 4 bytes: 0x%08x\n", frameCount, numBytesToCopy, out.maxSize, next4Bytes); fflush(stderr); 00716 #endif 00717 // set out.presentationTime later ##### 00718 acquiredStreamIdTag = stream_id; 00719 PES_packet_length -= numBytesToCopy; 00720 } else if (out.isCurrentlyActive) { 00721 // Someone has been reading this stream, but isn't right now. 00722 // We can't deliver this frame until he asks for it, so punt for now. 00723 // The next time he asks for a frame, he'll get it. 00724 #ifdef DEBUG 00725 fprintf(stderr, "%d, currently undeliverable PES data; first 4 bytes: 0x%08x - currently undeliverable!\n", frameCount, next4Bytes); fflush(stderr); 00726 #endif 00727 restoreSavedParserState(); // so we read from the beginning next time 00728 fUsingSource->fHaveUndeliveredData = True; 00729 throw READER_NOT_READY; 00730 } else if (out.isPotentiallyReadable && 00731 out.savedDataTotalSize + PES_packet_length < 1000000 /*limit*/) { 00732 // Someone is interested in this stream, but hasn't begun reading it yet. 00733 // Save this data, so that the reader will get it when he later asks for it. 00734 unsigned char* buf = new unsigned char[PES_packet_length]; 00735 getBytes(buf, PES_packet_length); 00736 MPEG1or2Demux::OutputDescriptor::SavedData* savedData 00737 = new MPEG1or2Demux::OutputDescriptor::SavedData(buf, PES_packet_length); 00738 if (out.savedDataHead == NULL) { 00739 out.savedDataHead = out.savedDataTail = savedData; 00740 } else { 00741 out.savedDataTail->next = savedData; 00742 out.savedDataTail = savedData; 00743 } 00744 out.savedDataTotalSize += PES_packet_length; 00745 PES_packet_length = 0; 00746 } 00747 skipBytes(PES_packet_length); 00748 } 00749 00750 // Check for another PES Packet next: 00751 setParseState(PARSING_PES_PACKET); 00752 #ifdef DEBUG 00753 ++frameCount; 00754 #endif 00755 return acquiredStreamIdTag; 00756 }
1.7.6.1