liveMedia/MPEG1or2Demux.cpp

Go to the documentation of this file.
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 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2013 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* usingDemux, 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* fUsingDemux;
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     envir().internalError();
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 
00285     if (out.isCurrentlyAwaitingData && fNumPendingReads > 0) --fNumPendingReads;
00286 
00287     out.isCurrentlyActive = out.isCurrentlyAwaitingData = False;
00288 }
00289 
00290 void MPEG1or2Demux::handleClosure(void* clientData) {
00291   MPEG1or2Demux* demux = (MPEG1or2Demux*)clientData;
00292 
00293   demux->fNumPendingReads = 0;
00294 
00295   // Tell all pending readers that our source has closed.
00296   // Note that we need to make a copy of our readers' close functions
00297   // (etc.) before we start calling any of them, in case one of them
00298   // ends up deleting this.
00299   struct {
00300     FramedSource::onCloseFunc* fOnCloseFunc;
00301     void* onCloseClientData;
00302   } savedPending[256];
00303   unsigned i, numPending = 0;
00304   for (i = 0; i < 256; ++i) {
00305     struct OutputDescriptor& out = demux->fOutput[i];
00306     if (out.isCurrentlyAwaitingData) {
00307       if (out.fOnCloseFunc != NULL) {
00308         savedPending[numPending].fOnCloseFunc = out.fOnCloseFunc;
00309         savedPending[numPending].onCloseClientData = out.onCloseClientData;
00310         ++numPending;
00311       }
00312     }
00313     delete out.savedDataHead; out.savedDataHead = out.savedDataTail = NULL;
00314     out.savedDataTotalSize = 0;
00315     out.isPotentiallyReadable = out.isCurrentlyActive = out.isCurrentlyAwaitingData
00316       = False;
00317   }
00318   for (i = 0; i < numPending; ++i) {
00319     (*savedPending[i].fOnCloseFunc)(savedPending[i].onCloseClientData);
00320   }
00321 }
00322 
00323 
00325 
00326 #include <string.h>
00327 
00328 MPEGProgramStreamParser::MPEGProgramStreamParser(MPEG1or2Demux* usingDemux,
00329                                                  FramedSource* inputSource)
00330   : StreamParser(inputSource, MPEG1or2Demux::handleClosure, usingDemux,
00331                  &MPEG1or2Demux::continueReadProcessing, usingDemux),
00332   fUsingDemux(usingDemux), fCurrentParseState(PARSING_PACK_HEADER) {
00333 }
00334 
00335 MPEGProgramStreamParser::~MPEGProgramStreamParser() {
00336 }
00337 
00338 void MPEGProgramStreamParser::setParseState(MPEGParseState parseState) {
00339   fCurrentParseState = parseState;
00340   saveParserState();
00341 }
00342 
00343 unsigned char MPEGProgramStreamParser::parse() {
00344   unsigned char acquiredStreamTagId = 0;
00345 
00346   try {
00347     do {
00348       switch (fCurrentParseState) {
00349       case PARSING_PACK_HEADER: {
00350         parsePackHeader();
00351         break;
00352       }
00353       case PARSING_SYSTEM_HEADER: {
00354         parseSystemHeader();
00355         break;
00356       }
00357       case PARSING_PES_PACKET: {
00358         acquiredStreamTagId = parsePESPacket();
00359         break;
00360       }
00361       }
00362     } while(acquiredStreamTagId == 0);
00363 
00364     return acquiredStreamTagId;
00365   } catch (int /*e*/) {
00366 #ifdef DEBUG
00367     fprintf(stderr, "MPEGProgramStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
00368     fflush(stderr);
00369 #endif
00370     return 0;  // the parsing got interrupted
00371   }
00372 }
00373 
00374 #define PACK_START_CODE          0x000001BA
00375 #define SYSTEM_HEADER_START_CODE 0x000001BB
00376 #define PACKET_START_CODE_PREFIX 0x00000100
00377 
00378 static inline Boolean isPacketStartCode(unsigned code) {
00379   return (code&0xFFFFFF00) == PACKET_START_CODE_PREFIX
00380     && code > SYSTEM_HEADER_START_CODE;
00381 }
00382 
00383 void MPEGProgramStreamParser::parsePackHeader() {
00384 #ifdef DEBUG
00385   fprintf(stderr, "parsing pack header\n"); fflush(stderr);
00386 #endif
00387   unsigned first4Bytes;
00388   while (1) {
00389     first4Bytes = test4Bytes();
00390 
00391     // We're supposed to have a pack header here, but check also for
00392     // a system header or a PES packet, just in case:
00393     if (first4Bytes == PACK_START_CODE) {
00394       skipBytes(4);
00395       break;
00396     } else if (first4Bytes == SYSTEM_HEADER_START_CODE) {
00397 #ifdef DEBUG
00398       fprintf(stderr, "found system header instead of pack header\n");
00399 #endif
00400       setParseState(PARSING_SYSTEM_HEADER);
00401       return;
00402     } else if (isPacketStartCode(first4Bytes)) {
00403 #ifdef DEBUG
00404       fprintf(stderr, "found packet start code 0x%02x instead of pack header\n", first4Bytes);
00405 #endif
00406       setParseState(PARSING_PES_PACKET);
00407       return;
00408     }
00409 
00410     setParseState(PARSING_PACK_HEADER); // ensures we progress over bad data
00411     if ((first4Bytes&0xFF) > 1) { // a system code definitely doesn't start here
00412       skipBytes(4);
00413     } else {
00414       skipBytes(1);
00415     }
00416   }
00417 
00418   // The size of the pack header differs depending on whether it's
00419   // MPEG-1 or MPEG-2.  The next byte tells us this:
00420   unsigned char nextByte = get1Byte();
00421   MPEG1or2Demux::SCR& scr = fUsingDemux->fLastSeenSCR; // alias
00422   if ((nextByte&0xF0) == 0x20) { // MPEG-1
00423     fUsingDemux->fMPEGversion = 1;
00424     scr.highBit =  (nextByte&0x08)>>3;
00425     scr.remainingBits = (nextByte&0x06)<<29;
00426     unsigned next4Bytes = get4Bytes();
00427     scr.remainingBits |= (next4Bytes&0xFFFE0000)>>2;
00428     scr.remainingBits |= (next4Bytes&0x0000FFFE)>>1;
00429     scr.extension = 0;
00430     scr.isValid = True;
00431     skipBits(24);
00432 
00433 #if defined(DEBUG_TIMESTAMPS) || defined(DEBUG_SCR_TIMESTAMPS)
00434     fprintf(stderr, "pack hdr system_clock_reference_base: 0x%x",
00435             scr.highBit);
00436     fprintf(stderr, "%08x\n", scr.remainingBits);
00437 #endif
00438   } else if ((nextByte&0xC0) == 0x40) { // MPEG-2
00439     fUsingDemux->fMPEGversion = 2;
00440     scr.highBit =  (nextByte&0x20)>>5;
00441     scr.remainingBits = (nextByte&0x18)<<27;
00442     scr.remainingBits |= (nextByte&0x03)<<28;
00443     unsigned next4Bytes = get4Bytes();
00444     scr.remainingBits |= (next4Bytes&0xFFF80000)>>4;
00445     scr.remainingBits |= (next4Bytes&0x0003FFF8)>>3;
00446     scr.extension = (next4Bytes&0x00000003)<<7;
00447     next4Bytes = get4Bytes();
00448     scr.extension |= (next4Bytes&0xFE000000)>>25;
00449     scr.isValid = True;
00450     skipBits(5);
00451 
00452 #if defined(DEBUG_TIMESTAMPS) || defined(DEBUG_SCR_TIMESTAMPS)
00453     fprintf(stderr, "pack hdr system_clock_reference_base: 0x%x",
00454             scr.highBit);
00455     fprintf(stderr, "%08x\n", scr.remainingBits);
00456     fprintf(stderr, "pack hdr system_clock_reference_extension: 0x%03x\n",
00457             scr.extension);
00458 #endif
00459     unsigned char pack_stuffing_length = getBits(3);
00460     skipBytes(pack_stuffing_length);
00461   } else { // unknown
00462     fUsingDemux->envir() << "StreamParser::parsePack() saw strange byte "
00463                           << (void*)nextByte
00464                           << " following pack_start_code\n";
00465   }
00466 
00467   // Check for a System Header next:
00468   setParseState(PARSING_SYSTEM_HEADER);
00469 }
00470 
00471 void MPEGProgramStreamParser::parseSystemHeader() {
00472 #ifdef DEBUG
00473   fprintf(stderr, "parsing system header\n"); fflush(stderr);
00474 #endif
00475   unsigned next4Bytes = test4Bytes();
00476   if (next4Bytes != SYSTEM_HEADER_START_CODE) {
00477     // The system header was optional.  Look for a PES Packet instead:
00478     setParseState(PARSING_PES_PACKET);
00479     return;
00480   }
00481 
00482 #ifdef DEBUG
00483   fprintf(stderr, "saw system_header_start_code\n"); fflush(stderr);
00484 #endif
00485   skipBytes(4); // we've already seen the system_header_start_code
00486 
00487   unsigned short remaining_header_length = get2Bytes();
00488 
00489   // According to the MPEG-1 and MPEG-2 specs, "remaining_header_length" should be
00490   // at least 6 bytes.  Check this now:
00491   if (remaining_header_length < 6) {
00492     fUsingDemux->envir() << "StreamParser::parseSystemHeader(): saw strange header_length: "
00493                           << remaining_header_length << " < 6\n";
00494   }
00495   skipBytes(remaining_header_length);
00496 
00497   // Check for a PES Packet next:
00498   setParseState(PARSING_PES_PACKET);
00499 }
00500 
00501 #define private_stream_1 0xBD
00502 #define private_stream_2 0xBF
00503 
00504 // A test for stream ids that are exempt from normal PES packet header parsing
00505 Boolean MPEGProgramStreamParser
00506 ::isSpecialStreamId(unsigned char stream_id) const {
00507   if (stream_id == RAW_PES) return True; // hack
00508 
00509   if (fUsingDemux->fMPEGversion == 1) {
00510     return stream_id == private_stream_2;
00511   } else { // assume MPEG-2
00512     if (stream_id <= private_stream_2) {
00513       return stream_id != private_stream_1;
00514     } else if ((stream_id&0xF0) == 0xF0) {
00515       unsigned char lower4Bits = stream_id&0x0F;
00516       return lower4Bits <= 2 || lower4Bits == 0x8 || lower4Bits == 0xF;
00517     } else {
00518       return False;
00519     }
00520   }
00521 }
00522 
00523 #define READER_NOT_READY 2
00524 
00525 unsigned char MPEGProgramStreamParser::parsePESPacket() {
00526 #ifdef DEBUG
00527   fprintf(stderr, "parsing PES packet\n"); fflush(stderr);
00528 #endif
00529   unsigned next4Bytes = test4Bytes();
00530   if (!isPacketStartCode(next4Bytes)) {
00531     // The PES Packet was optional.  Look for a Pack Header instead:
00532     setParseState(PARSING_PACK_HEADER);
00533     return 0;
00534   }
00535 
00536 #ifdef DEBUG
00537   fprintf(stderr, "saw packet_start_code_prefix\n"); fflush(stderr);
00538 #endif
00539   skipBytes(3); // we've already seen the packet_start_code_prefix
00540 
00541   unsigned char stream_id = get1Byte();
00542 #if defined(DEBUG) || defined(DEBUG_TIMESTAMPS)
00543   unsigned char streamNum = stream_id;
00544   char const* streamTypeStr;
00545   if ((stream_id&0xE0) == 0xC0) {
00546     streamTypeStr = "audio";
00547     streamNum = stream_id&~0xE0;
00548   } else if ((stream_id&0xF0) == 0xE0) {
00549     streamTypeStr = "video";
00550     streamNum = stream_id&~0xF0;
00551   } else if (stream_id == 0xbc) {
00552     streamTypeStr = "reserved";
00553   } else if (stream_id == 0xbd) {
00554     streamTypeStr = "private_1";
00555   } else if (stream_id == 0xbe) {
00556     streamTypeStr = "padding";
00557   } else if (stream_id == 0xbf) {
00558     streamTypeStr = "private_2";
00559   } else {
00560     streamTypeStr = "unknown";
00561   }
00562 #endif
00563 #ifdef DEBUG
00564   static unsigned frameCount = 1;
00565   fprintf(stderr, "%d, saw %s stream: 0x%02x\n", frameCount, streamTypeStr, streamNum); fflush(stderr);
00566 #endif
00567 
00568   unsigned short PES_packet_length = get2Bytes();
00569 #ifdef DEBUG
00570   fprintf(stderr, "PES_packet_length: %d\n", PES_packet_length); fflush(stderr);
00571 #endif
00572 
00573   // Parse over the rest of the header, until we get to the packet data itself.
00574   // This varies depending upon the MPEG version:
00575   if (fUsingDemux->fOutput[RAW_PES].isPotentiallyReadable) {
00576     // Hack: We've been asked to return raw PES packets, for every stream:
00577     stream_id = RAW_PES;
00578   }
00579   unsigned savedParserOffset = curOffset();
00580 #ifdef DEBUG_TIMESTAMPS
00581   unsigned char pts_highBit = 0;
00582   unsigned pts_remainingBits = 0;
00583   unsigned char dts_highBit = 0;
00584   unsigned dts_remainingBits = 0;
00585 #endif
00586   if (fUsingDemux->fMPEGversion == 1) {
00587     if (!isSpecialStreamId(stream_id)) {
00588       unsigned char nextByte;
00589       while ((nextByte = get1Byte()) == 0xFF) { // stuffing_byte
00590       }
00591       if ((nextByte&0xC0) == 0x40) { // '01'
00592         skipBytes(1);
00593         nextByte = get1Byte();
00594       }
00595       if ((nextByte&0xF0) == 0x20) { // '0010'
00596 #ifdef DEBUG_TIMESTAMPS
00597         pts_highBit =  (nextByte&0x08)>>3;
00598         pts_remainingBits = (nextByte&0x06)<<29;
00599         unsigned next4Bytes = get4Bytes();
00600         pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;
00601         pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;
00602 #else
00603         skipBytes(4);
00604 #endif
00605       } else if ((nextByte&0xF0) == 0x30) { // '0011'
00606 #ifdef DEBUG_TIMESTAMPS
00607         pts_highBit =  (nextByte&0x08)>>3;
00608         pts_remainingBits = (nextByte&0x06)<<29;
00609         unsigned next4Bytes = get4Bytes();
00610         pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;
00611         pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;
00612 
00613         nextByte = get1Byte();
00614         dts_highBit =  (nextByte&0x08)>>3;
00615         dts_remainingBits = (nextByte&0x06)<<29;
00616         next4Bytes = get4Bytes();
00617         dts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;
00618         dts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;
00619 #else
00620         skipBytes(9);
00621 #endif
00622       }
00623     }
00624   } else { // assume MPEG-2
00625     if (!isSpecialStreamId(stream_id)) {
00626       // Fields in the next 3 bytes determine the size of the rest:
00627       unsigned next3Bytes = getBits(24);
00628 #ifdef DEBUG_TIMESTAMPS
00629       unsigned char PTS_DTS_flags       = (next3Bytes&0x00C000)>>14;
00630 #endif
00631 #ifdef undef
00632       unsigned char ESCR_flag           = (next3Bytes&0x002000)>>13;
00633       unsigned char ES_rate_flag        = (next3Bytes&0x001000)>>12;
00634       unsigned char DSM_trick_mode_flag = (next3Bytes&0x000800)>>11;
00635 #endif
00636       unsigned char PES_header_data_length = (next3Bytes&0x0000FF);
00637 #ifdef DEBUG
00638       fprintf(stderr, "PES_header_data_length: 0x%02x\n", PES_header_data_length); fflush(stderr);
00639 #endif
00640 #ifdef DEBUG_TIMESTAMPS
00641       if (PTS_DTS_flags == 0x2 && PES_header_data_length >= 5) {
00642         unsigned char nextByte = get1Byte();
00643         pts_highBit =  (nextByte&0x08)>>3;
00644         pts_remainingBits = (nextByte&0x06)<<29;
00645         unsigned next4Bytes = get4Bytes();
00646         pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;
00647         pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;
00648 
00649         skipBytes(PES_header_data_length-5);
00650       } else if (PTS_DTS_flags == 0x3 && PES_header_data_length >= 10) {
00651         unsigned char nextByte = get1Byte();
00652         pts_highBit =  (nextByte&0x08)>>3;
00653         pts_remainingBits = (nextByte&0x06)<<29;
00654         unsigned next4Bytes = get4Bytes();
00655         pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;
00656         pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;
00657 
00658         nextByte = get1Byte();
00659         dts_highBit =  (nextByte&0x08)>>3;
00660         dts_remainingBits = (nextByte&0x06)<<29;
00661         next4Bytes = get4Bytes();
00662         dts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;
00663         dts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;
00664 
00665         skipBytes(PES_header_data_length-10);
00666       }
00667 #else
00668       skipBytes(PES_header_data_length);
00669 #endif
00670     }
00671   }
00672 #ifdef DEBUG_TIMESTAMPS
00673   fprintf(stderr, "%s stream, ", streamTypeStr);
00674   fprintf(stderr, "packet presentation_time_stamp: 0x%x", pts_highBit);
00675   fprintf(stderr, "%08x\n", pts_remainingBits);
00676   fprintf(stderr, "\t\tpacket decoding_time_stamp: 0x%x", dts_highBit);
00677   fprintf(stderr, "%08x\n", dts_remainingBits);
00678 #endif
00679 
00680   // The rest of the packet will be the "PES_packet_data_byte"s
00681   // Make sure that "PES_packet_length" was consistent with where we are now:
00682   unsigned char acquiredStreamIdTag = 0;
00683   unsigned currentParserOffset = curOffset();
00684   unsigned bytesSkipped = currentParserOffset - savedParserOffset;
00685   if (stream_id == RAW_PES) {
00686     restoreSavedParserState(); // so we deliver from the beginning of the PES packet
00687     PES_packet_length += 6; // to include the whole of the PES packet
00688     bytesSkipped = 0;
00689   }
00690   if (PES_packet_length < bytesSkipped) {
00691     fUsingDemux->envir() << "StreamParser::parsePESPacket(): saw inconsistent PES_packet_length "
00692                           << PES_packet_length << " < "
00693                           << bytesSkipped << "\n";
00694   } else {
00695     PES_packet_length -= bytesSkipped;
00696 #ifdef DEBUG
00697     unsigned next4Bytes = test4Bytes();
00698 #endif
00699 
00700     // Check whether our using source is interested in this stream type.
00701     // If so, deliver the frame to him:
00702     MPEG1or2Demux::OutputDescriptor_t& out = fUsingDemux->fOutput[stream_id];
00703     if (out.isCurrentlyAwaitingData) {
00704       unsigned numBytesToCopy;
00705       if (PES_packet_length > out.maxSize) {
00706         fUsingDemux->envir() << "MPEGProgramStreamParser::parsePESPacket() error: PES_packet_length ("
00707                               << PES_packet_length
00708                               << ") exceeds max frame size asked for ("
00709                               << out.maxSize << ")\n";
00710         numBytesToCopy = out.maxSize;
00711       } else {
00712         numBytesToCopy = PES_packet_length;
00713       }
00714 
00715       getBytes(out.to, numBytesToCopy);
00716       out.frameSize = numBytesToCopy;
00717 #ifdef DEBUG
00718       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);
00719 #endif
00720       // set out.presentationTime later #####
00721       acquiredStreamIdTag = stream_id;
00722       PES_packet_length -= numBytesToCopy;
00723     } else if (out.isCurrentlyActive) {
00724       // Someone has been reading this stream, but isn't right now.
00725       // We can't deliver this frame until he asks for it, so punt for now.
00726       // The next time he asks for a frame, he'll get it.
00727 #ifdef DEBUG
00728       fprintf(stderr, "%d, currently undeliverable PES data; first 4 bytes: 0x%08x - currently undeliverable!\n", frameCount, next4Bytes); fflush(stderr);
00729 #endif
00730       restoreSavedParserState(); // so we read from the beginning next time
00731       fUsingDemux->fHaveUndeliveredData = True;
00732       throw READER_NOT_READY;
00733     } else if (out.isPotentiallyReadable &&
00734                out.savedDataTotalSize + PES_packet_length < 1000000 /*limit*/) {
00735       // Someone is interested in this stream, but hasn't begun reading it yet.
00736       // Save this data, so that the reader will get it when he later asks for it.
00737       unsigned char* buf = new unsigned char[PES_packet_length];
00738       getBytes(buf, PES_packet_length);
00739       MPEG1or2Demux::OutputDescriptor::SavedData* savedData
00740         = new MPEG1or2Demux::OutputDescriptor::SavedData(buf, PES_packet_length);
00741       if (out.savedDataHead == NULL) {
00742         out.savedDataHead = out.savedDataTail = savedData;
00743       } else {
00744         out.savedDataTail->next = savedData;
00745         out.savedDataTail = savedData;
00746       }
00747       out.savedDataTotalSize += PES_packet_length;
00748       PES_packet_length = 0;
00749     }
00750     skipBytes(PES_packet_length);
00751   }
00752 
00753   // Check for another PES Packet next:
00754   setParseState(PARSING_PES_PACKET);
00755 #ifdef DEBUG
00756   ++frameCount;
00757 #endif
00758  return acquiredStreamIdTag;
00759 }

Generated on Mon Apr 29 13:28:02 2013 for live by  doxygen 1.5.2