MPEG2IFrameIndexFromTransportStream Class Reference

#include <MPEG2IndexFromTransportStream.hh>

Inheritance diagram for MPEG2IFrameIndexFromTransportStream:

Inheritance graph
[legend]
Collaboration diagram for MPEG2IFrameIndexFromTransportStream:

Collaboration graph
[legend]

Public Types

typedef void( afterGettingFunc )(void *clientData, unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds)
typedef void( onCloseFunc )(void *clientData)

Public Member Functions

FramedSourceinputSource () const
void getNextFrame (unsigned char *to, unsigned maxSize, afterGettingFunc *afterGettingFunc, void *afterGettingClientData, onCloseFunc *onCloseFunc, void *onCloseClientData)
void stopGettingFrames ()
virtual unsigned maxFrameSize () const
Boolean isCurrentlyAwaitingData () const
virtual Boolean isRTPSource () const
virtual Boolean isMPEG1or2VideoStreamFramer () const
virtual Boolean isMPEG4VideoStreamFramer () const
virtual Boolean isH264VideoStreamFramer () const
virtual Boolean isJPEGVideoSource () const
virtual Boolean isAMRAudioSource () const
UsageEnvironmentenvir () const
char const * name () const
virtual Boolean isSink () const
virtual Boolean isRTCPInstance () const
virtual Boolean isRTSPClient () const
virtual Boolean isRTSPServer () const
virtual Boolean isMediaSession () const
virtual Boolean isServerMediaSession () const
virtual Boolean isDarwinInjector () const

Static Public Member Functions

static MPEG2IFrameIndexFromTransportStreamcreateNew (UsageEnvironment &env, FramedSource *inputSource)
static Boolean lookupByName (UsageEnvironment &env, char const *sourceName, FramedSource *&resultSource)
static Boolean lookupByName (UsageEnvironment &env, char const *sourceName, MediaSource *&resultSource)
static Boolean lookupByName (UsageEnvironment &env, char const *mediumName, Medium *&resultMedium)
static void handleClosure (void *clientData)
static void close (UsageEnvironment &env, char const *mediumName)
static void close (Medium *medium)

Protected Member Functions

 MPEG2IFrameIndexFromTransportStream (UsageEnvironment &env, FramedSource *inputSource)
virtual ~MPEG2IFrameIndexFromTransportStream ()
virtual char const * MIMEtype () const
virtual void getAttributes () const
virtual void doStopGettingFrames ()
TaskTokennextTask ()

Static Protected Member Functions

static void afterGetting (FramedSource *source)

Protected Attributes

FramedSourcefInputSource
unsigned char * fTo
unsigned fMaxSize
unsigned fFrameSize
unsigned fNumTruncatedBytes
timeval fPresentationTime
unsigned fDurationInMicroseconds

Private Member Functions

virtual void doGetNextFrame ()
void afterGettingFrame1 (unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds)
void handleInputClosure1 ()
void analyzePAT (unsigned char *pkt, unsigned size)
void analyzePMT (unsigned char *pkt, unsigned size)
Boolean deliverIndexRecord ()
Boolean parseFrame ()
Boolean parseToNextCode (unsigned char &nextCode)
void compactParseBuffer ()
void addToTail (IndexRecord *newIndexRecord)

Static Private Member Functions

static void afterGettingFrame (void *clientData, unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds)
static void handleInputClosure (void *clientData)

Private Attributes

unsigned long fInputTransportPacketCounter
unsigned fClosureNumber
u_int8_t fLastContinuityCounter
float fFirstPCR
float fLastPCR
Boolean fHaveSeenFirstPCR
u_int16_t fPMT_PID
u_int16_t fVideo_PID
unsigned char fInputBuffer [TRANSPORT_PACKET_SIZE]
unsigned char * fParseBuffer
unsigned fParseBufferSize
unsigned fParseBufferFrameStart
unsigned fParseBufferParseEnd
unsigned fParseBufferDataEnd
IndexRecordfHeadIndexRecord
IndexRecordfTailIndexRecord

Detailed Description

Definition at line 38 of file MPEG2IndexFromTransportStream.hh.


Member Typedef Documentation

typedef void( FramedSource::afterGettingFunc)(void *clientData, unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds) [inherited]

Definition at line 36 of file FramedSource.hh.

typedef void( FramedSource::onCloseFunc)(void *clientData) [inherited]

Definition at line 40 of file FramedSource.hh.


Constructor & Destructor Documentation

MPEG2IFrameIndexFromTransportStream::MPEG2IFrameIndexFromTransportStream ( UsageEnvironment env,
FramedSource inputSource 
) [protected]

Definition at line 101 of file MPEG2IndexFromTransportStream.cpp.

References fParseBuffer, and fParseBufferSize.

Referenced by createNew().

MPEG2IFrameIndexFromTransportStream::~MPEG2IFrameIndexFromTransportStream (  )  [protected, virtual]

Definition at line 114 of file MPEG2IndexFromTransportStream.cpp.

References fHeadIndexRecord, and fParseBuffer.

00114                                                                           {
00115   delete fHeadIndexRecord;
00116   delete[] fParseBuffer;
00117 }


Member Function Documentation

MPEG2IFrameIndexFromTransportStream * MPEG2IFrameIndexFromTransportStream::createNew ( UsageEnvironment env,
FramedSource inputSource 
) [static]

Definition at line 85 of file MPEG2IndexFromTransportStream.cpp.

References env, FramedFilter::inputSource(), and MPEG2IFrameIndexFromTransportStream().

Referenced by main().

00086                                                                           {
00087   return new MPEG2IFrameIndexFromTransportStream(env, inputSource);
00088 }

void MPEG2IFrameIndexFromTransportStream::doGetNextFrame (  )  [private, virtual]

Implements FramedSource.

Definition at line 119 of file MPEG2IndexFromTransportStream.cpp.

References afterGettingFrame(), compactParseBuffer(), deliverIndexRecord(), Medium::envir(), fInputBuffer, FramedFilter::fInputSource, fParseBufferDataEnd, fParseBufferSize, FramedSource::getNextFrame(), handleInputClosure(), handleInputClosure1(), parseFrame(), and TRANSPORT_PACKET_SIZE.

Referenced by afterGettingFrame1(), and handleInputClosure1().

00119                                                          {
00120   // Begin by trying to deliver an index record (for an already-parsed frame)
00121   // to the client:
00122   if (deliverIndexRecord()) return;
00123 
00124   // No more index records are left to deliver, so try to parse a new frame:
00125   if (parseFrame()) { // success - try again
00126     doGetNextFrame();
00127     return;
00128   }
00129 
00130   // We need to read some more Transport Stream packets.  Check whether we have room:
00131   if (fParseBufferSize - fParseBufferDataEnd < TRANSPORT_PACKET_SIZE) {
00132     // There's no room left.  Compact the buffer, and check again:
00133     compactParseBuffer();
00134     if (fParseBufferSize - fParseBufferDataEnd < TRANSPORT_PACKET_SIZE) {
00135       envir() << "ERROR: parse buffer full; increase MAX_FRAME_SIZE\n";
00136       // Treat this as if the input source ended:
00137       handleInputClosure1();
00138       return;
00139     }
00140   }
00141 
00142   // Arrange to read a new Transport Stream packet:
00143   fInputSource->getNextFrame(fInputBuffer, sizeof fInputBuffer,
00144                              afterGettingFrame, this,
00145                              handleInputClosure, this);
00146 }

void MPEG2IFrameIndexFromTransportStream::afterGettingFrame ( void *  clientData,
unsigned  frameSize,
unsigned  numTruncatedBytes,
struct timeval  presentationTime,
unsigned  durationInMicroseconds 
) [static, private]

Definition at line 149 of file MPEG2IndexFromTransportStream.cpp.

References afterGettingFrame1().

Referenced by doGetNextFrame().

00152                                                      {
00153   MPEG2IFrameIndexFromTransportStream* source
00154     = (MPEG2IFrameIndexFromTransportStream*)clientData;
00155   source->afterGettingFrame1(frameSize, numTruncatedBytes,
00156                              presentationTime, durationInMicroseconds);
00157 }

void MPEG2IFrameIndexFromTransportStream::afterGettingFrame1 ( unsigned  frameSize,
unsigned  numTruncatedBytes,
struct timeval  presentationTime,
unsigned  durationInMicroseconds 
) [private]

Definition at line 160 of file MPEG2IndexFromTransportStream.cpp.

References addToTail(), analyzePAT(), analyzePMT(), doGetNextFrame(), Medium::envir(), fFirstPCR, fHaveSeenFirstPCR, fInputBuffer, fInputTransportPacketCounter, fLastContinuityCounter, fLastPCR, fParseBuffer, fParseBufferDataEnd, fPMT_PID, fVideo_PID, handleInputClosure1(), PAT_PID, TRANSPORT_PACKET_SIZE, and True.

Referenced by afterGettingFrame().

00163                                                       {
00164   if (frameSize < TRANSPORT_PACKET_SIZE || fInputBuffer[0] != 0x47/*sync byte*/) {
00165     if (fInputBuffer[0] != 0x47) {
00166       envir() << "Bad TS sync byte: 0x" << fInputBuffer[0] << "\n";
00167     }
00168     // Handle this as if the source ended:
00169     handleInputClosure1();
00170     return;
00171   }
00172 
00173   ++fInputTransportPacketCounter;
00174 
00175   // Figure out how much of this Transport Packet contains PES data:
00176   u_int8_t adaptation_field_control = (fInputBuffer[3]&0x30)>>4;
00177   u_int8_t totalHeaderSize
00178     = adaptation_field_control == 1 ? 4 : 5 + fInputBuffer[4];
00179 
00180   // Check for a PCR:
00181   if (totalHeaderSize > 5 && (fInputBuffer[5]&0x10) != 0) {
00182     // There's a PCR:
00183     u_int32_t pcrBaseHigh
00184       = (fInputBuffer[6]<<24)|(fInputBuffer[7]<<16)
00185       |(fInputBuffer[8]<<8)|fInputBuffer[9];
00186     float pcr = pcrBaseHigh/45000.0f;
00187     if ((fInputBuffer[10]&0x80) != 0) pcr += 1/90000.0f; // add in low-bit (if set)
00188     unsigned short pcrExt = ((fInputBuffer[10]&0x01)<<8) | fInputBuffer[11];
00189     pcr += pcrExt/27000000.0f;
00190 
00191     if (!fHaveSeenFirstPCR) {
00192       fFirstPCR = pcr;
00193       fHaveSeenFirstPCR = True;
00194     }
00195     fLastPCR = pcr;
00196   }
00197 
00198   // Get the PID from the packet, and check for special tables: the PAT and PMT:
00199   u_int16_t PID = ((fInputBuffer[1]&0x1F)<<8) | fInputBuffer[2];
00200   if (PID == PAT_PID) {
00201     analyzePAT(&fInputBuffer[totalHeaderSize], TRANSPORT_PACKET_SIZE-totalHeaderSize);
00202   } else if (PID == fPMT_PID) {
00203     analyzePMT(&fInputBuffer[totalHeaderSize], TRANSPORT_PACKET_SIZE-totalHeaderSize);
00204   }
00205 
00206   // Ignore transport packets for non-video programs,
00207   // or packets with no data, or packets that duplicate the previous packet:
00208   u_int8_t continuity_counter = fInputBuffer[3]&0x0F;
00209   if ((PID != fVideo_PID) ||
00210       !(adaptation_field_control == 1  || adaptation_field_control == 3) ||
00211       continuity_counter == fLastContinuityCounter) {
00212     doGetNextFrame();
00213     return;
00214   }
00215   fLastContinuityCounter = continuity_counter;
00216 
00217   // Also, if this is the start of a PES packet, then skip over the PES header:
00218   Boolean payload_unit_start_indicator = (fInputBuffer[1]&0x40) != 0;
00219   //fprintf(stderr, "PUSI: %d\n", payload_unit_start_indicator);//#####
00220   if (payload_unit_start_indicator) {
00221     // Note: The following works only for MPEG-2 data #####
00222     u_int8_t PES_header_data_length = fInputBuffer[totalHeaderSize+8];
00223     //fprintf(stderr, "PES_header_data_length: %d\n", PES_header_data_length);//#####
00224     totalHeaderSize += 9 + PES_header_data_length;
00225     if (totalHeaderSize >= TRANSPORT_PACKET_SIZE) {
00226       envir() << "Unexpectedly large PES header size: " << PES_header_data_length << "\n";
00227       // Handle this as if the source ended:
00228       handleInputClosure1();
00229       return;
00230     }
00231   }
00232 
00233   // The remaining data is Video Elementary Stream data.  Add it to our parse buffer:
00234   unsigned vesSize = TRANSPORT_PACKET_SIZE - totalHeaderSize;
00235   memmove(&fParseBuffer[fParseBufferDataEnd], &fInputBuffer[totalHeaderSize], vesSize);
00236   fParseBufferDataEnd += vesSize;
00237 
00238   // And add a new index record noting where it came from:
00239   addToTail(new IndexRecord(totalHeaderSize, vesSize, fInputTransportPacketCounter,
00240                             fLastPCR - fFirstPCR));
00241 
00242   // Try again:
00243   doGetNextFrame();
00244 }

void MPEG2IFrameIndexFromTransportStream::handleInputClosure ( void *  clientData  )  [static, private]

Definition at line 246 of file MPEG2IndexFromTransportStream.cpp.

References handleInputClosure1().

Referenced by doGetNextFrame().

00246                                                                              {
00247   MPEG2IFrameIndexFromTransportStream* source
00248     = (MPEG2IFrameIndexFromTransportStream*)clientData;
00249   source->handleInputClosure1();
00250 }

void MPEG2IFrameIndexFromTransportStream::handleInputClosure1 (  )  [private]

Definition at line 259 of file MPEG2IndexFromTransportStream.cpp.

References doGetNextFrame(), fClosureNumber, fParseBuffer, fParseBufferDataEnd, fParseBufferFrameStart, fParseBufferSize, FramedSource::handleClosure(), and PICTURE_START_CODE.

Referenced by afterGettingFrame1(), doGetNextFrame(), and handleInputClosure().

00259                                                               {
00260   if (++fClosureNumber == 1 && fParseBufferDataEnd > fParseBufferFrameStart
00261       && fParseBufferDataEnd <= fParseBufferSize - 4) {
00262     // This is the first time we saw EOF, and there's still data remaining to be
00263     // parsed.  Hack: Append a Picture Header code to the end of the unparsed
00264     // data, and try again.  This should use up all of the unparsed data.
00265     fParseBuffer[fParseBufferDataEnd++] = 0;
00266     fParseBuffer[fParseBufferDataEnd++] = 0;
00267     fParseBuffer[fParseBufferDataEnd++] = 1;
00268     fParseBuffer[fParseBufferDataEnd++] = PICTURE_START_CODE;
00269 
00270     // Try again:
00271     doGetNextFrame();
00272   } else {
00273     // Handle closure in the regular way:
00274     FramedSource::handleClosure(this);
00275   }
00276 }

void MPEG2IFrameIndexFromTransportStream::analyzePAT ( unsigned char *  pkt,
unsigned  size 
) [private]

Definition at line 279 of file MPEG2IndexFromTransportStream.cpp.

References fPMT_PID.

Referenced by afterGettingFrame1().

00279                                               {
00280   // Get the PMT_PID (we assume that's there just 1 program):
00281   if (size < 16) return; // table too small
00282   u_int16_t program_number = (pkt[9]<<8) | pkt[10];
00283   if (program_number != 0) {
00284     fPMT_PID = ((pkt[11]&0x1F)<<8) | pkt[12];
00285   }
00286 }

void MPEG2IFrameIndexFromTransportStream::analyzePMT ( unsigned char *  pkt,
unsigned  size 
) [private]

Definition at line 289 of file MPEG2IndexFromTransportStream.cpp.

References fVideo_PID.

Referenced by afterGettingFrame1().

00289                                               {
00290   // Scan the "elementary_PID"s in the map, until we see the first video stream.
00291 
00292   // First, get the "section_length", to get the table's size:
00293   u_int16_t section_length = ((pkt[2]&0x0F)<<8) | pkt[3];
00294   if ((unsigned)(4+section_length) < size) size = (4+section_length);
00295 
00296   // Then, skip any descriptors following the "program_info_length":
00297   if (size < 22) return; // not enough data
00298   unsigned program_info_length = ((pkt[11]&0x0F)<<8) | pkt[12];
00299   pkt += 13; size -= 13;
00300   if (size < program_info_length) return; // not enough data
00301   pkt += program_info_length; size -= program_info_length;
00302 
00303   // Look at each ("stream_type","elementary_PID") pair, looking for a video stream
00304   // ("stream_type" == 1 or 2):
00305   while (size >= 9) {
00306     u_int8_t stream_type = pkt[0];
00307     u_int16_t elementary_PID = ((pkt[1]&0x1F)<<8) | pkt[2];
00308     if (stream_type == 1 || stream_type == 2) {
00309       fVideo_PID = elementary_PID;
00310       return;
00311     }
00312 
00313     u_int16_t ES_info_length = ((pkt[3]&0x0F)<<8) | pkt[4];
00314     pkt += 5; size -= 5;
00315     if (size < ES_info_length) return; // not enough data
00316     pkt += ES_info_length; size -= ES_info_length;
00317   }
00318 }

Boolean MPEG2IFrameIndexFromTransportStream::deliverIndexRecord (  )  [private]

Definition at line 320 of file MPEG2IndexFromTransportStream.cpp.

References FramedSource::afterGetting(), Medium::envir(), False, FramedSource::fFrameSize, fHeadIndexRecord, FramedSource::fMaxSize, fTailIndexRecord, FramedSource::fTo, IndexRecord::next(), NULL, IndexRecord::pcr(), RECORD_JUNK, RECORD_UNPARSED, IndexRecord::recordType(), IndexRecord::size(), IndexRecord::startOffset(), IndexRecord::transportPacketNumber(), True, and IndexRecord::unlink().

Referenced by doGetNextFrame().

00320                                                                 {
00321   IndexRecord* head = fHeadIndexRecord;
00322   if (head == NULL) return False;
00323 
00324   // Check whether the head record has been parsed yet:
00325   if (head->recordType() == RECORD_UNPARSED) return False;
00326 
00327   // Remove the head record (the one whose data we'll be delivering):
00328   IndexRecord* next = head->next();
00329   head->unlink();
00330   if (next == head) {
00331     fHeadIndexRecord = fTailIndexRecord = NULL;
00332   } else {
00333     fHeadIndexRecord = next;
00334   }
00335 
00336   if (head->recordType() == RECORD_JUNK) {
00337     // Don't actually deliver the data to the client:
00338     delete head;
00339     return True;
00340   }
00341 
00342   // Deliver data from the head record:
00343 #ifdef DEBUG
00344   envir() << "delivering: " << *head << "\n";
00345 #endif
00346   if (fMaxSize < 11) {
00347     fFrameSize = 0;
00348   } else {
00349     fTo[0] = (u_int8_t)(head->recordType());
00350     fTo[1] = head->startOffset();
00351     fTo[2] = head->size();
00352     // Deliver the PCR, as 24 bits (integer part; little endian) + 8 bits (fractional part)
00353     float pcr = head->pcr();
00354     unsigned pcr_int = (unsigned)pcr;
00355     u_int8_t pcr_frac = (u_int8_t)(256*(pcr-pcr_int));
00356     fTo[3] = (unsigned char)(pcr_int);
00357     fTo[4] = (unsigned char)(pcr_int>>8);
00358     fTo[5] = (unsigned char)(pcr_int>>16);
00359     fTo[6] = (unsigned char)(pcr_frac);
00360     // Deliver the transport packet number (in little-endian order):
00361     unsigned long tpn = head->transportPacketNumber();
00362     fTo[7] = (unsigned char)(tpn);
00363     fTo[8] = (unsigned char)(tpn>>8);
00364     fTo[9] = (unsigned char)(tpn>>16);
00365     fTo[10] = (unsigned char)(tpn>>24);
00366     fFrameSize = 11;
00367   }
00368 
00369   // Free the (former) head record (as we're now done with it):
00370   delete head;
00371 
00372   // Complete delivery to the client:
00373   afterGetting(this);
00374   return True;
00375 }

Boolean MPEG2IFrameIndexFromTransportStream::parseFrame (  )  [private]

Definition at line 377 of file MPEG2IndexFromTransportStream.cpp.

References IndexRecord::addAfter(), Medium::envir(), False, fHeadIndexRecord, fParseBuffer, fParseBufferDataEnd, fParseBufferFrameStart, fParseBufferParseEnd, frameSize, fTailIndexRecord, GROUP_START_CODE, GROUP_VOP_START_CODE, IndexRecord::next(), parseToNextCode(), IndexRecord::pcr(), PICTURE_START_CODE, RECORD_GOP, RECORD_JUNK, RECORD_PIC_IFRAME, RECORD_PIC_NON_IFRAME, RECORD_VSH, IndexRecord::recordType(), IndexRecord::setFirstFlag(), IndexRecord::size(), IndexRecord::startOffset(), IndexRecord::transportPacketNumber(), True, VIDEO_SEQUENCE_START_CODE, VISUAL_OBJECT_SEQUENCE_START_CODE, and VOP_START_CODE.

Referenced by doGetNextFrame().

00377                                                         {
00378   // At this point, we have a queue of >=0 (unparsed) index records, representing
00379   // the data in the parse buffer from "fParseBufferFrameStart"
00380   // to "fParseBufferDataEnd".  We now parse through this data, looking for
00381   // a complete 'frame' (where a 'frame', in this case, means
00382   // a Video Sequence Header, GOP Header, Picture Header, or Slice).
00383 
00384   // Inspect the frame's initial 4-byte code, to make sure it starts with a system code:
00385   if (fParseBufferDataEnd-fParseBufferFrameStart < 4) return False; // not enough data
00386   unsigned numInitialBadBytes = 0;
00387   unsigned char const* p = &fParseBuffer[fParseBufferFrameStart];
00388   if (!(p[0] == 0 && p[1] == 0 && p[2] == 1)) {
00389     // There's no system code at the beginning.  Parse until we find one:
00390     if (fParseBufferParseEnd == fParseBufferFrameStart + 4) {
00391       // Start parsing from the beginning of the frame data:
00392       fParseBufferParseEnd = fParseBufferFrameStart;
00393     }
00394     unsigned char nextCode;
00395     if (!parseToNextCode(nextCode)) return False;
00396 
00397     numInitialBadBytes = fParseBufferParseEnd - fParseBufferFrameStart;
00398     //fprintf(stderr, "#####numInitialBadBytes: 0x%x\n", numInitialBadBytes);
00399     fParseBufferFrameStart = fParseBufferParseEnd;
00400     fParseBufferParseEnd += 4; // skip over the code that we just saw
00401     p = &fParseBuffer[fParseBufferFrameStart];
00402   }
00403 
00404   unsigned char curCode = p[3];
00405   RecordType curRecordType;
00406   unsigned char nextCode;
00407   switch (curCode) {
00408   case VIDEO_SEQUENCE_START_CODE:
00409   case VISUAL_OBJECT_SEQUENCE_START_CODE: {
00410     curRecordType = RECORD_VSH;
00411     while (1) {
00412       if (!parseToNextCode(nextCode)) return False;
00413       if (nextCode == GROUP_START_CODE || /*nextCode == GROUP_VOP_START_CODE ||*/
00414           nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;
00415       fParseBufferParseEnd += 4; // skip over the code that we just saw
00416     }
00417     break;
00418   }
00419   case GROUP_START_CODE:
00420     /*case GROUP_VOP_START_CODE:*/ {
00421     curRecordType = RECORD_GOP;
00422     while (1) {
00423       if (!parseToNextCode(nextCode)) return False;
00424       if (nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;
00425       fParseBufferParseEnd += 4; // skip over the code that we just saw
00426     }
00427     break;
00428   }
00429   default: { // picture (including slices)
00430     curRecordType = RECORD_PIC_NON_IFRAME; // may get changed to IFRAME later
00431     while (1) {
00432       if (!parseToNextCode(nextCode)) return False;
00433       if (nextCode == VIDEO_SEQUENCE_START_CODE || nextCode == VISUAL_OBJECT_SEQUENCE_START_CODE ||
00434           nextCode == GROUP_START_CODE || nextCode == GROUP_VOP_START_CODE ||
00435           nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;
00436       fParseBufferParseEnd += 4; // skip over the code that we just saw
00437     }
00438     break;
00439   }
00440   }
00441 
00442   if (curRecordType == RECORD_PIC_NON_IFRAME) {
00443     if (curCode == VOP_START_CODE) { // MPEG-4
00444       //fprintf(stderr, "#####parseFrame()1(4): 0x%x, 0x%x\n", curCode, fParseBuffer[fParseBufferFrameStart+4]&0xC0);
00445       if ((fParseBuffer[fParseBufferFrameStart+4]&0xC0) == 0) {
00446         // This is actually an I-frame.  Note it as such:
00447         curRecordType = RECORD_PIC_IFRAME;
00448       }
00449     } else { // MPEG-1 or 2
00450       //fprintf(stderr, "#####parseFrame()1(!4): 0x%x, 0x%x\n", curCode, fParseBuffer[fParseBufferFrameStart+5]&0x38);
00451       if ((fParseBuffer[fParseBufferFrameStart+5]&0x38) == 0x08) {
00452         // This is actually an I-frame.  Note it as such:
00453         curRecordType = RECORD_PIC_IFRAME;
00454       }
00455     }
00456   }
00457 
00458   // There is now a parsed 'frame', from "fParseBufferFrameStart"
00459   // to "fParseBufferParseEnd". Tag the corresponding index records to note this:
00460   unsigned frameSize = fParseBufferParseEnd - fParseBufferFrameStart + numInitialBadBytes;
00461 #ifdef DEBUG
00462   envir() << "parsed " << recordTypeStr[curRecordType] << "; length "
00463           << frameSize << "\n";
00464 #endif
00465   for (IndexRecord* r = fHeadIndexRecord; ; r = r->next()) {
00466     if (numInitialBadBytes >= r->size()) {
00467       r->recordType() = RECORD_JUNK;
00468       numInitialBadBytes -= r->size();
00469     } else {
00470       r->recordType() = curRecordType;
00471     }
00472     if (r == fHeadIndexRecord) r->setFirstFlag();
00473     // indicates that this is the first record for this frame
00474 
00475     if (r->size() > frameSize) {
00476       // This record contains extra data that's not part of the frame.
00477       // Shorten this record, and move the extra data to a new record
00478       // that comes afterwards:
00479       u_int8_t newOffset = r->startOffset() + frameSize;
00480       u_int8_t newSize = r->size() - frameSize;
00481       r->size() = frameSize;
00482 #ifdef DEBUG
00483       envir() << "tagged record (modified): " << *r << "\n";
00484 #endif
00485 
00486       IndexRecord* newRecord
00487         = new IndexRecord(newOffset, newSize, r->transportPacketNumber(), r->pcr());
00488       newRecord->addAfter(r);
00489       if (fTailIndexRecord == r) fTailIndexRecord = newRecord;
00490 #ifdef DEBUG
00491       envir() << "added extra record: " << *newRecord << "\n";
00492 #endif
00493     } else {
00494 #ifdef DEBUG
00495       envir() << "tagged record: " << *r << "\n";
00496 #endif
00497     }
00498     frameSize -= r->size();
00499     if (frameSize == 0) break;
00500     if (r == fTailIndexRecord) { // this shouldn't happen
00501       envir() << "!!!!!Internal consistency error!!!!!\n";
00502       return False;
00503     }
00504   }
00505 
00506   // Finally, update our parse state (to skip over the now-parsed data):
00507   fParseBufferFrameStart = fParseBufferParseEnd;
00508   fParseBufferParseEnd += 4; // to skip over the next code (that we found)
00509 
00510   return True;
00511 }

Boolean MPEG2IFrameIndexFromTransportStream::parseToNextCode ( unsigned char &  nextCode  )  [private]

Definition at line 514 of file MPEG2IndexFromTransportStream.cpp.

References False, fParseBuffer, fParseBufferDataEnd, fParseBufferParseEnd, and True.

Referenced by parseFrame().

00514                                          {
00515   unsigned char const* p = &fParseBuffer[fParseBufferParseEnd];
00516   unsigned char const* end = &fParseBuffer[fParseBufferDataEnd];
00517   while (p <= end-4) {
00518     if (p[2] > 1) p += 3; // common case (optimized)
00519     else if (p[2] == 0) ++p;
00520     else if (p[0] == 0 && p[1] == 0) { // && p[2] == 1
00521       // We found a code here:
00522       nextCode = p[3];
00523       fParseBufferParseEnd = p - &fParseBuffer[0]; // where we've gotten to
00524       return True;
00525     } else p += 3;
00526   }
00527 
00528   fParseBufferParseEnd = p - &fParseBuffer[0]; // where we've gotten to
00529   return False; // no luck this time
00530 }

void MPEG2IFrameIndexFromTransportStream::compactParseBuffer (  )  [private]

Definition at line 532 of file MPEG2IndexFromTransportStream.cpp.

References Medium::envir(), fParseBuffer, fParseBufferDataEnd, fParseBufferFrameStart, and fParseBufferParseEnd.

Referenced by doGetNextFrame().

00532                                                              {
00533 #ifdef DEBUG
00534   envir() << "Compacting parse buffer: [" << fParseBufferFrameStart
00535           << "," << fParseBufferParseEnd << "," << fParseBufferDataEnd << "]";
00536 #endif
00537   memmove(&fParseBuffer[0], &fParseBuffer[fParseBufferFrameStart],
00538           fParseBufferDataEnd - fParseBufferFrameStart);
00539   fParseBufferDataEnd -= fParseBufferFrameStart;
00540   fParseBufferParseEnd -= fParseBufferFrameStart;
00541   fParseBufferFrameStart = 0;
00542 #ifdef DEBUG
00543   envir() << "-> [" << fParseBufferFrameStart
00544           << "," << fParseBufferParseEnd << "," << fParseBufferDataEnd << "]\n";
00545 #endif
00546 }

void MPEG2IFrameIndexFromTransportStream::addToTail ( IndexRecord newIndexRecord  )  [private]

Definition at line 548 of file MPEG2IndexFromTransportStream.cpp.

References IndexRecord::addAfter(), Medium::envir(), fHeadIndexRecord, fTailIndexRecord, and NULL.

Referenced by afterGettingFrame1().

00548                                                                                {
00549 #ifdef DEBUG
00550   envir() << "adding new: " << *newIndexRecord << "\n";
00551 #endif
00552   if (fTailIndexRecord == NULL) {
00553     fHeadIndexRecord = fTailIndexRecord = newIndexRecord;
00554   } else {
00555     newIndexRecord->addAfter(fTailIndexRecord);
00556     fTailIndexRecord = newIndexRecord;
00557   }
00558 }

FramedSource* FramedFilter::inputSource (  )  const [inline, inherited]

Definition at line 30 of file FramedFilter.hh.

References FramedFilter::fInputSource.

Referenced by AC3AudioStreamFramer::AC3AudioStreamFramer(), EndianSwap16::createNew(), HostFromNetworkOrder16::createNew(), NetworkFromHostOrder16::createNew(), PCMFromuLawAudioSource::createNew(), QCELPDeinterleaver::createNew(), MPEG4VideoStreamFramer::createNew(), MPEG4VideoStreamDiscreteFramer::createNew(), createNew(), MPEG1or2VideoStreamFramer::createNew(), MPEG1or2VideoStreamDiscreteFramer::createNew(), MPEG1or2AudioStreamFramer::createNew(), MP3Transcoder::createNew(), MP3ADUTranscoder::createNew(), MP3ADUdeinterleaver::createNew(), MP3ADUinterleaver::createNew(), MP3FromADUSource::createNew(), ADUFromMP3Source::createNew(), H263plusVideoStreamFramer::createNew(), AC3AudioStreamFramer::createNew(), H264VideoRTPSink::doSpecialFrameHandling(), MP3ADUinterleaverBase::getInputSource(), H263plusVideoStreamFramer::H263plusVideoStreamFramer(), MPEG1or2VideoStreamFramer::MPEG1or2VideoStreamFramer(), MPEG4VideoStreamFramer::MPEG4VideoStreamFramer(), MP3AudioFileServerMediaSubsession::seekStreamSource(), ClientTrickPlayState::setSource(), and MP3AudioFileServerMediaSubsession::setStreamSourceScale().

00030 { return fInputSource; }