#include <MPEG2IndexFromTransportStream.hh>
Inheritance diagram for MPEG2IFrameIndexFromTransportStream:


Public Types | |
| typedef void( | afterGettingFunc )(void *clientData, unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds) |
| typedef void( | onCloseFunc )(void *clientData) |
Public Member Functions | |
| FramedSource * | inputSource () 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 |
| UsageEnvironment & | envir () 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 MPEG2IFrameIndexFromTransportStream * | createNew (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 () |
| TaskToken & | nextTask () |
Static Protected Member Functions | |
| static void | afterGetting (FramedSource *source) |
Protected Attributes | |
| FramedSource * | fInputSource |
| 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 |
| IndexRecord * | fHeadIndexRecord |
| IndexRecord * | fTailIndexRecord |
Definition at line 38 of file MPEG2IndexFromTransportStream.hh.
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.
| MPEG2IFrameIndexFromTransportStream::MPEG2IFrameIndexFromTransportStream | ( | UsageEnvironment & | env, | |
| FramedSource * | inputSource | |||
| ) | [protected] |
Definition at line 101 of file MPEG2IndexFromTransportStream.cpp.
References fParseBuffer, and fParseBufferSize.
Referenced by createNew().
00103 : FramedFilter(env, inputSource), 00104 fInputTransportPacketCounter((unsigned)-1), fClosureNumber(0), 00105 fLastContinuityCounter(~0), 00106 fFirstPCR(0.0), fLastPCR(0.0), fHaveSeenFirstPCR(False), 00107 fPMT_PID(0x10), fVideo_PID(0xE0), // default values 00108 fParseBufferSize(PARSE_BUFFER_SIZE), 00109 fParseBufferFrameStart(0), fParseBufferParseEnd(4), fParseBufferDataEnd(0), 00110 fHeadIndexRecord(NULL), fTailIndexRecord(NULL) { 00111 fParseBuffer = new unsigned char[fParseBufferSize]; 00112 }
| MPEG2IFrameIndexFromTransportStream::~MPEG2IFrameIndexFromTransportStream | ( | ) | [protected, virtual] |
Definition at line 114 of file MPEG2IndexFromTransportStream.cpp.
References fHeadIndexRecord, and fParseBuffer.
00114 { 00115 delete fHeadIndexRecord; 00116 delete[] fParseBuffer; 00117 }
| 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; }