

Public Member Functions | |
| MPEG4VideoStreamParser (MPEG4VideoStreamFramer *usingSource, FramedSource *inputSource) | |
| virtual | ~MPEG4VideoStreamParser () |
| void | registerReadInterest (unsigned char *to, unsigned maxSize) |
| unsigned | numTruncatedBytes () const |
Protected Types | |
| typedef void( | clientContinueFunc )(void *clientData, unsigned char *ptr, unsigned size, struct timeval presentationTime) |
Protected Member Functions | |
| void | setParseState () |
| void | saveByte (u_int8_t byte) |
| void | save4Bytes (u_int32_t word) |
| void | saveToNextCode (u_int32_t &curWord) |
| void | skipToNextCode (u_int32_t &curWord) |
| unsigned | curFrameSize () |
| void | saveParserState () |
| u_int32_t | get4Bytes () |
| u_int32_t | test4Bytes () |
| u_int16_t | get2Bytes () |
| u_int8_t | get1Byte () |
| void | getBytes (u_int8_t *to, unsigned numBytes) |
| void | skipBytes (unsigned numBytes) |
| void | skipBits (unsigned numBits) |
| unsigned | getBits (unsigned numBits) |
| unsigned | curOffset () const |
| unsigned & | totNumValidBytes () |
Protected Attributes | |
| MPEGVideoStreamFramer * | fUsingSource |
| unsigned char * | fStartOfFrame |
| unsigned char * | fTo |
| unsigned char * | fLimit |
| unsigned | fNumTruncatedBytes |
| unsigned char * | fSavedTo |
| unsigned | fSavedNumTruncatedBytes |
Private Member Functions | |
| virtual void | flushInput () |
| virtual unsigned | parse () |
| MPEG4VideoStreamFramer * | usingSource () |
| void | setParseState (MPEGParseState parseState) |
| unsigned | parseVisualObjectSequence (Boolean haveSeenStartCode=False) |
| unsigned | parseVisualObject () |
| unsigned | parseVideoObjectLayer () |
| unsigned | parseGroupOfVideoObjectPlane () |
| unsigned | parseVideoObjectPlane () |
| unsigned | parseVisualObjectSequenceEndCode () |
| Boolean | getNextFrameBit (u_int8_t &result) |
| Boolean | getNextFrameBits (unsigned numBits, u_int32_t &result) |
| void | analyzeVOLHeader () |
Private Attributes | |
| MPEGParseState | fCurrentParseState |
| unsigned | fNumBitsSeenSoFar |
| u_int32_t | vop_time_increment_resolution |
| unsigned | fNumVTIRBits |
| u_int8_t | fixed_vop_rate |
| unsigned | fixed_vop_time_increment |
| unsigned | fSecondsSinceLastTimeCode |
| unsigned | fTotalTicksSinceLastTimeCode |
| unsigned | fPrevNewTotalTicks |
| unsigned | fPrevPictureCountDelta |
| Boolean | fJustSawTimeCode |
Definition at line 43 of file MPEG4VideoStreamFramer.cpp.
typedef void( StreamParser::clientContinueFunc)(void *clientData, unsigned char *ptr, unsigned size, struct timeval presentationTime) [protected, inherited] |
Definition at line 33 of file StreamParser.hh.
| MPEG4VideoStreamParser::MPEG4VideoStreamParser | ( | MPEG4VideoStreamFramer * | usingSource, | |
| FramedSource * | inputSource | |||
| ) |
Definition at line 151 of file MPEG4VideoStreamFramer.cpp.
00153 : MPEGVideoStreamParser(usingSource, inputSource), 00154 fCurrentParseState(PARSING_VISUAL_OBJECT_SEQUENCE), 00155 vop_time_increment_resolution(0), fNumVTIRBits(0), 00156 fixed_vop_rate(0), fixed_vop_time_increment(0), 00157 fSecondsSinceLastTimeCode(0), fTotalTicksSinceLastTimeCode(0), 00158 fPrevNewTotalTicks(0), fPrevPictureCountDelta(1), fJustSawTimeCode(False) { 00159 }
| MPEG4VideoStreamParser::~MPEG4VideoStreamParser | ( | ) | [virtual] |
| void MPEG4VideoStreamParser::flushInput | ( | ) | [private, virtual] |
Reimplemented from StreamParser.
Definition at line 169 of file MPEG4VideoStreamFramer.cpp.
References fCurrentParseState, StreamParser::flushInput(), fPrevNewTotalTicks, fPrevPictureCountDelta, fSecondsSinceLastTimeCode, fTotalTicksSinceLastTimeCode, PARSING_VISUAL_OBJECT_SEQUENCE, and MPEGVideoStreamParser::setParseState().
00169 { 00170 fSecondsSinceLastTimeCode = 0; 00171 fTotalTicksSinceLastTimeCode = 0; 00172 fPrevNewTotalTicks = 0; 00173 fPrevPictureCountDelta = 1; 00174 00175 StreamParser::flushInput(); 00176 if (fCurrentParseState != PARSING_VISUAL_OBJECT_SEQUENCE) { 00177 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE); // later, change to GOV or VOP? ##### 00178 } 00179 }
| unsigned MPEG4VideoStreamParser::parse | ( | ) | [private, virtual] |
Implements MPEGVideoStreamParser.
Definition at line 182 of file MPEG4VideoStreamFramer.cpp.
References fCurrentParseState, parseGroupOfVideoObjectPlane(), parseVideoObjectLayer(), parseVideoObjectPlane(), parseVisualObject(), parseVisualObjectSequence(), parseVisualObjectSequenceEndCode(), PARSING_GROUP_OF_VIDEO_OBJECT_PLANE, PARSING_VIDEO_OBJECT_LAYER, PARSING_VIDEO_OBJECT_PLANE, PARSING_VISUAL_OBJECT, PARSING_VISUAL_OBJECT_SEQUENCE, PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE, PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE, and True.
00182 { 00183 try { 00184 switch (fCurrentParseState) { 00185 case PARSING_VISUAL_OBJECT_SEQUENCE: { 00186 return parseVisualObjectSequence(); 00187 } 00188 case PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE: { 00189 return parseVisualObjectSequence(True); 00190 } 00191 case PARSING_VISUAL_OBJECT: { 00192 return parseVisualObject(); 00193 } 00194 case PARSING_VIDEO_OBJECT_LAYER: { 00195 return parseVideoObjectLayer(); 00196 } 00197 case PARSING_GROUP_OF_VIDEO_OBJECT_PLANE: { 00198 return parseGroupOfVideoObjectPlane(); 00199 } 00200 case PARSING_VIDEO_OBJECT_PLANE: { 00201 return parseVideoObjectPlane(); 00202 } 00203 case PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE: { 00204 return parseVisualObjectSequenceEndCode(); 00205 } 00206 default: { 00207 return 0; // shouldn't happen 00208 } 00209 } 00210 } catch (int /*e*/) { 00211 #ifdef DEBUG 00212 fprintf(stderr, "MPEG4VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n"); 00213 #endif 00214 return 0; // the parsing got interrupted 00215 } 00216 }
| MPEG4VideoStreamFramer* MPEG4VideoStreamParser::usingSource | ( | ) | [inline, private] |
Definition at line 54 of file MPEG4VideoStreamFramer.cpp.
References MPEGVideoStreamParser::fUsingSource.
Referenced by analyzeVOLHeader(), parseGroupOfVideoObjectPlane(), parseVideoObjectLayer(), parseVideoObjectPlane(), parseVisualObject(), parseVisualObjectSequence(), and parseVisualObjectSequenceEndCode().
00054 { 00055 return (MPEG4VideoStreamFramer*)fUsingSource; 00056 }
| void MPEG4VideoStreamParser::setParseState | ( | MPEGParseState | parseState | ) | [private] |
Definition at line 164 of file MPEG4VideoStreamFramer.cpp.
References fCurrentParseState, and MPEGVideoStreamParser::setParseState().
00164 { 00165 fCurrentParseState = parseState; 00166 MPEGVideoStreamParser::setParseState(); 00167 }
| unsigned MPEG4VideoStreamParser::parseVisualObjectSequence | ( | Boolean | haveSeenStartCode = False |
) | [private] |
Definition at line 225 of file MPEG4VideoStreamFramer.cpp.
References MPEG4VideoStreamFramer::appendToNewConfig(), MPEGVideoStreamFramer::computePresentationTime(), MPEGVideoStreamParser::curFrameSize(), MPEG4VideoStreamFramer::fProfileAndLevelIndication, MPEGVideoStreamParser::fStartOfFrame, fTotalTicksSinceLastTimeCode, StreamParser::get1Byte(), StreamParser::get4Bytes(), PARSING_VISUAL_OBJECT, PARSING_VISUAL_OBJECT_SEQUENCE, MPEGVideoStreamParser::save4Bytes(), MPEGVideoStreamParser::saveByte(), MPEGVideoStreamParser::saveToNextCode(), MPEGVideoStreamParser::setParseState(), MPEG4VideoStreamFramer::startNewConfig(), StreamParser::test4Bytes(), usingSource(), VISUAL_OBJECT_SEQUENCE_START_CODE, and VISUAL_OBJECT_START_CODE.
Referenced by parse().
00225 { 00226 #ifdef DEBUG 00227 fprintf(stderr, "parsing VisualObjectSequence\n"); 00228 #endif 00229 usingSource()->startNewConfig(); 00230 u_int32_t first4Bytes; 00231 if (!haveSeenStartCode) { 00232 while ((first4Bytes = test4Bytes()) != VISUAL_OBJECT_SEQUENCE_START_CODE) { 00233 #ifdef DEBUG 00234 fprintf(stderr, "ignoring non VS header: 0x%08x\n", first4Bytes); 00235 #endif 00236 get1Byte(); setParseState(PARSING_VISUAL_OBJECT_SEQUENCE); 00237 // ensures we progress over bad data 00238 } 00239 first4Bytes = get4Bytes(); 00240 } else { 00241 // We've already seen the start code 00242 first4Bytes = VISUAL_OBJECT_SEQUENCE_START_CODE; 00243 } 00244 save4Bytes(first4Bytes); 00245 00246 // The next byte is the "profile_and_level_indication": 00247 u_int8_t pali = get1Byte(); 00248 #ifdef DEBUG 00249 fprintf(stderr, "profile_and_level_indication: %02x\n", pali); 00250 #endif 00251 saveByte(pali); 00252 usingSource()->fProfileAndLevelIndication = pali; 00253 00254 // Now, copy all bytes that we see, up until we reach 00255 // a VISUAL_OBJECT_START_CODE: 00256 u_int32_t next4Bytes = get4Bytes(); 00257 while (next4Bytes != VISUAL_OBJECT_START_CODE) { 00258 saveToNextCode(next4Bytes); 00259 } 00260 00261 setParseState(PARSING_VISUAL_OBJECT); 00262 00263 // Compute this frame's presentation time: 00264 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode); 00265 00266 // This header forms part of the 'configuration' information: 00267 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize()); 00268 00269 return curFrameSize(); 00270 }
| unsigned MPEG4VideoStreamParser::parseVisualObject | ( | ) | [private] |
Definition at line 276 of file MPEG4VideoStreamFramer.cpp.
References MPEG4VideoStreamFramer::appendToNewConfig(), MPEGVideoStreamFramer::computePresentationTime(), MPEGVideoStreamParser::curFrameSize(), Medium::envir(), MPEGVideoStreamParser::fStartOfFrame, fTotalTicksSinceLastTimeCode, StreamParser::get1Byte(), StreamParser::get4Bytes(), isVideoObjectStartCode(), PARSING_VIDEO_OBJECT_LAYER, MPEGVideoStreamParser::save4Bytes(), MPEGVideoStreamParser::saveByte(), MPEGVideoStreamParser::saveToNextCode(), MPEGVideoStreamParser::setParseState(), usingSource(), and VISUAL_OBJECT_START_CODE.
Referenced by parse().
00276 { 00277 #ifdef DEBUG 00278 fprintf(stderr, "parsing VisualObject\n"); 00279 #endif 00280 // Note that we've already read the VISUAL_OBJECT_START_CODE 00281 save4Bytes(VISUAL_OBJECT_START_CODE); 00282 00283 // Next, extract the "visual_object_type" from the next 1 or 2 bytes: 00284 u_int8_t nextByte = get1Byte(); saveByte(nextByte); 00285 Boolean is_visual_object_identifier = (nextByte&0x80) != 0; 00286 u_int8_t visual_object_type; 00287 if (is_visual_object_identifier) { 00288 #ifdef DEBUG 00289 fprintf(stderr, "visual_object_verid: 0x%x; visual_object_priority: 0x%x\n", (nextByte&0x78)>>3, (nextByte&0x07)); 00290 #endif 00291 nextByte = get1Byte(); saveByte(nextByte); 00292 visual_object_type = (nextByte&0xF0)>>4; 00293 } else { 00294 visual_object_type = (nextByte&0x78)>>3; 00295 } 00296 #ifdef DEBUG 00297 fprintf(stderr, "visual_object_type: 0x%x\n", visual_object_type); 00298 #endif 00299 // At present, we support only the "Video ID" "visual_object_type" (1) 00300 if (visual_object_type != 1) { 00301 usingSource()->envir() << "MPEG4VideoStreamParser::parseVisualObject(): Warning: We don't handle visual_object_type " << visual_object_type << "\n"; 00302 } 00303 00304 // Now, copy all bytes that we see, up until we reach 00305 // a video_object_start_code 00306 u_int32_t next4Bytes = get4Bytes(); 00307 while (!isVideoObjectStartCode(next4Bytes)) { 00308 saveToNextCode(next4Bytes); 00309 } 00310 save4Bytes(next4Bytes); 00311 #ifdef DEBUG 00312 fprintf(stderr, "saw a video_object_start_code: 0x%08x\n", next4Bytes); 00313 #endif 00314 00315 setParseState(PARSING_VIDEO_OBJECT_LAYER); 00316 00317 // Compute this frame's presentation time: 00318 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode); 00319 00320 // This header forms part of the 'configuration' information: 00321 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize()); 00322 00323 return curFrameSize(); 00324 }
| unsigned MPEG4VideoStreamParser::parseVideoObjectLayer | ( | ) | [private] |
Definition at line 428 of file MPEG4VideoStreamFramer.cpp.
References analyzeVOLHeader(), MPEG4VideoStreamFramer::appendToNewConfig(), MPEG4VideoStreamFramer::completeNewConfig(), MPEGVideoStreamFramer::computePresentationTime(), MPEGVideoStreamParser::curFrameSize(), Medium::envir(), MPEGVideoStreamParser::fStartOfFrame, fTotalTicksSinceLastTimeCode, StreamParser::get4Bytes(), GROUP_VOP_START_CODE, isVideoObjectLayerStartCode(), PARSING_GROUP_OF_VIDEO_OBJECT_PLANE, PARSING_VIDEO_OBJECT_PLANE, MPEGVideoStreamParser::saveToNextCode(), MPEGVideoStreamParser::setParseState(), usingSource(), and VOP_START_CODE.
Referenced by parse().
00428 { 00429 #ifdef DEBUG 00430 fprintf(stderr, "parsing VideoObjectLayer\n"); 00431 #endif 00432 // The first 4 bytes must be a "video_object_layer_start_code". 00433 // If not, this is a 'short video header', which we currently 00434 // don't support: 00435 u_int32_t next4Bytes = get4Bytes(); 00436 if (!isVideoObjectLayerStartCode(next4Bytes)) { 00437 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectLayer(): This appears to be a 'short video header', which we current don't support\n"; 00438 } 00439 00440 // Now, copy all bytes that we see, up until we reach 00441 // a GROUP_VOP_START_CODE or a VOP_START_CODE: 00442 do { 00443 saveToNextCode(next4Bytes); 00444 } while (next4Bytes != GROUP_VOP_START_CODE 00445 && next4Bytes != VOP_START_CODE); 00446 00447 analyzeVOLHeader(); 00448 00449 setParseState((next4Bytes == GROUP_VOP_START_CODE) 00450 ? PARSING_GROUP_OF_VIDEO_OBJECT_PLANE 00451 : PARSING_VIDEO_OBJECT_PLANE); 00452 00453 // Compute this frame's presentation time: 00454 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode); 00455 00456 // This header ends the 'configuration' information: 00457 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize()); 00458 usingSource()->completeNewConfig(); 00459 00460 return curFrameSize(); 00461 }
| unsigned MPEG4VideoStreamParser::parseGroupOfVideoObjectPlane | ( | ) | [private] |
Definition at line 463 of file MPEG4VideoStreamFramer.cpp.
References MPEGVideoStreamFramer::computePresentationTime(), MPEGVideoStreamParser::curFrameSize(), fixed_vop_rate, fJustSawTimeCode, fSecondsSinceLastTimeCode, fTotalTicksSinceLastTimeCode, StreamParser::get4Bytes(), StreamParser::getBytes(), GROUP_VOP_START_CODE, PARSING_VIDEO_OBJECT_PLANE, MPEGVideoStreamParser::save4Bytes(), MPEGVideoStreamParser::saveByte(), MPEGVideoStreamParser::saveToNextCode(), MPEGVideoStreamParser::setParseState(), MPEGVideoStreamFramer::setTimeCode(), True, usingSource(), and VOP_START_CODE.
Referenced by parse().
00463 { 00464 #ifdef DEBUG 00465 fprintf(stderr, "parsing GroupOfVideoObjectPlane\n"); 00466 #endif 00467 // Note that we've already read the GROUP_VOP_START_CODE 00468 save4Bytes(GROUP_VOP_START_CODE); 00469 00470 // Next, extract the (18-bit) time code from the next 3 bytes: 00471 u_int8_t next3Bytes[3]; 00472 getBytes(next3Bytes, 3); 00473 saveByte(next3Bytes[0]);saveByte(next3Bytes[1]);saveByte(next3Bytes[2]); 00474 unsigned time_code 00475 = (next3Bytes[0]<<10)|(next3Bytes[1]<<2)|(next3Bytes[2]>>6); 00476 unsigned time_code_hours = (time_code&0x0003E000)>>13; 00477 unsigned time_code_minutes = (time_code&0x00001F80)>>7; 00478 #if defined(DEBUG) || defined(DEBUG_TIMESTAMPS) 00479 Boolean marker_bit = (time_code&0x00000040) != 0; 00480 #endif 00481 unsigned time_code_seconds = (time_code&0x0000003F); 00482 #if defined(DEBUG) || defined(DEBUG_TIMESTAMPS) 00483 fprintf(stderr, "time_code: 0x%05x, hours %d, minutes %d, marker_bit %d, seconds %d\n", time_code, time_code_hours, time_code_minutes, marker_bit, time_code_seconds); 00484 #endif 00485 fJustSawTimeCode = True; 00486 00487 // Now, copy all bytes that we see, up until we reach a VOP_START_CODE: 00488 u_int32_t next4Bytes = get4Bytes(); 00489 while (next4Bytes != VOP_START_CODE) { 00490 saveToNextCode(next4Bytes); 00491 } 00492 00493 // Compute this frame's presentation time: 00494 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode); 00495 00496 // Record the time code: 00497 usingSource()->setTimeCode(time_code_hours, time_code_minutes, 00498 time_code_seconds, 0, 0); 00499 // Note: Because the GOV header can appear anywhere (not just at a 1s point), we 00500 // don't pass "fTotalTicksSinceLastTimeCode" as the "picturesSinceLastGOP" parameter. 00501 fSecondsSinceLastTimeCode = 0; 00502 if (fixed_vop_rate) fTotalTicksSinceLastTimeCode = 0; 00503 00504 setParseState(PARSING_VIDEO_OBJECT_PLANE); 00505 00506 return curFrameSize(); 00507 }
| unsigned MPEG4VideoStreamParser::parseVideoObjectPlane | ( | ) | [private] |
Definition at line 509 of file MPEG4VideoStreamFramer.cpp.
References MPEGVideoStreamFramer::computePresentationTime(), MPEGVideoStreamParser::curFrameSize(), Medium::envir(), False, fixed_vop_time_increment, fJustSawTimeCode, fNumVTIRBits, MPEGVideoStreamFramer::fPictureCount, MPEGVideoStreamFramer::fPictureEndMarker, fPrevNewTotalTicks, fPrevPictureCountDelta, fSecondsSinceLastTimeCode, fTotalTicksSinceLastTimeCode, StreamParser::get1Byte(), StreamParser::get4Bytes(), GROUP_VOP_START_CODE, isVideoObjectLayerStartCode(), isVideoObjectStartCode(), PARSING_GROUP_OF_VIDEO_OBJECT_PLANE, PARSING_VIDEO_OBJECT_LAYER, PARSING_VIDEO_OBJECT_PLANE, PARSING_VISUAL_OBJECT, PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE, PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE, MPEGVideoStreamParser::save4Bytes(), MPEGVideoStreamParser::saveByte(), MPEGVideoStreamParser::saveToNextCode(), MPEGVideoStreamParser::setParseState(), True, usingSource(), VISUAL_OBJECT_SEQUENCE_END_CODE, VISUAL_OBJECT_SEQUENCE_START_CODE, VISUAL_OBJECT_START_CODE, VOP_START_CODE, and vop_time_increment_resolution.
Referenced by parse().
00509 { 00510 #ifdef DEBUG 00511 fprintf(stderr, "#parsing VideoObjectPlane\n"); 00512 #endif 00513 // Note that we've already read the VOP_START_CODE 00514 save4Bytes(VOP_START_CODE); 00515 00516 // Get the "vop_coding_type" from the next byte: 00517 u_int8_t nextByte = get1Byte(); saveByte(nextByte); 00518 u_int8_t vop_coding_type = nextByte>>6; 00519 00520 // Next, get the "modulo_time_base" by counting the '1' bits that follow. 00521 // We look at the next 32-bits only. This should be enough in most cases. 00522 u_int32_t next4Bytes = get4Bytes(); 00523 u_int32_t timeInfo = (nextByte<<(32-6))|(next4Bytes>>6); 00524 unsigned modulo_time_base = 0; 00525 u_int32_t mask = 0x80000000; 00526 while ((timeInfo&mask) != 0) { 00527 ++modulo_time_base; 00528 mask >>= 1; 00529 } 00530 mask >>= 1; 00531 00532 // Check the following marker bit: 00533 if ((timeInfo&mask) == 0) { 00534 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): marker bit not set!\n"; 00535 } 00536 mask >>= 1; 00537 00538 // Then, get the "vop_time_increment". 00539 // First, make sure we have enough bits left for this: 00540 if ((mask>>(fNumVTIRBits-1)) == 0) { 00541 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): 32-bits are not enough to get \"vop_time_increment\"!\n"; 00542 } 00543 unsigned vop_time_increment = 0; 00544 for (unsigned i = 0; i < fNumVTIRBits; ++i) { 00545 vop_time_increment |= timeInfo&mask; 00546 mask >>= 1; 00547 } 00548 while (mask != 0) { 00549 vop_time_increment >>= 1; 00550 mask >>= 1; 00551 } 00552 #ifdef DEBUG 00553 fprintf(stderr, "vop_coding_type: %d(%c), modulo_time_base: %d, vop_time_increment: %d\n", vop_coding_type, "IPBS"[vop_coding_type], modulo_time_base, vop_time_increment); 00554 #endif 00555 00556 // Now, copy all bytes that we see, up until we reach a code of some sort: 00557 saveToNextCode(next4Bytes); 00558 00559 // Update our counters based on the frame timing information that we saw: 00560 if (fixed_vop_time_increment > 0) { 00561 // This is a 'fixed_vop_rate' stream. Use 'fixed_vop_time_increment': 00562 usingSource()->fPictureCount += fixed_vop_time_increment; 00563 if (vop_time_increment > 0 || modulo_time_base > 0) { 00564 fTotalTicksSinceLastTimeCode += fixed_vop_time_increment; 00565 // Note: "fSecondsSinceLastTimeCode" and "fPrevNewTotalTicks" are not used. 00566 } 00567 } else { 00568 // Use 'vop_time_increment': 00569 unsigned newTotalTicks 00570 = (fSecondsSinceLastTimeCode + modulo_time_base)*vop_time_increment_resolution 00571 + vop_time_increment; 00572 if (newTotalTicks == fPrevNewTotalTicks && fPrevNewTotalTicks > 0) { 00573 // This is apparently a buggy MPEG-4 video stream, because 00574 // "vop_time_increment" did not change. Overcome this error, 00575 // by pretending that it did change. 00576 #ifdef DEBUG 00577 fprintf(stderr, "Buggy MPEG-4 video stream: \"vop_time_increment\" did not change!\n"); 00578 #endif 00579 // The following assumes that we don't have 'B' frames. If we do, then TARFU! 00580 usingSource()->fPictureCount += vop_time_increment; 00581 fTotalTicksSinceLastTimeCode += vop_time_increment; 00582 fSecondsSinceLastTimeCode += modulo_time_base; 00583 } else { 00584 if (newTotalTicks < fPrevNewTotalTicks && vop_coding_type != 2/*B*/ 00585 && modulo_time_base == 0 && vop_time_increment == 0 && !fJustSawTimeCode) { 00586 // This is another kind of buggy MPEG-4 video stream, in which 00587 // "vop_time_increment" wraps around, but without 00588 // "modulo_time_base" changing (or just having had a new time code). 00589 // Overcome this by pretending that "vop_time_increment" *did* wrap around: 00590 #ifdef DEBUG 00591 fprintf(stderr, "Buggy MPEG-4 video stream: \"vop_time_increment\" wrapped around, but without \"modulo_time_base\" changing!\n"); 00592 #endif 00593 ++fSecondsSinceLastTimeCode; 00594 newTotalTicks += vop_time_increment_resolution; 00595 } 00596 fPrevNewTotalTicks = newTotalTicks; 00597 if (vop_coding_type != 2/*B*/) { 00598 int pictureCountDelta = newTotalTicks - fTotalTicksSinceLastTimeCode; 00599 if (pictureCountDelta <= 0) pictureCountDelta = fPrevPictureCountDelta; 00600 // ensures that the picture count is always increasing 00601 usingSource()->fPictureCount += pictureCountDelta; 00602 fPrevPictureCountDelta = pictureCountDelta; 00603 fTotalTicksSinceLastTimeCode = newTotalTicks; 00604 fSecondsSinceLastTimeCode += modulo_time_base; 00605 } 00606 } 00607 } 00608 fJustSawTimeCode = False; // for next time 00609 00610 // The next thing to parse depends on the code that we just saw, 00611 // but we are assumed to have ended the current picture: 00612 usingSource()->fPictureEndMarker = True; // HACK ##### 00613 switch (next4Bytes) { 00614 case VISUAL_OBJECT_SEQUENCE_END_CODE: { 00615 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE); 00616 break; 00617 } 00618 case VISUAL_OBJECT_SEQUENCE_START_CODE: { 00619 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE); 00620 break; 00621 } 00622 case VISUAL_OBJECT_START_CODE: { 00623 setParseState(PARSING_VISUAL_OBJECT); 00624 break; 00625 } 00626 case GROUP_VOP_START_CODE: { 00627 setParseState(PARSING_GROUP_OF_VIDEO_OBJECT_PLANE); 00628 break; 00629 } 00630 case VOP_START_CODE: { 00631 setParseState(PARSING_VIDEO_OBJECT_PLANE); 00632 break; 00633 } 00634 default: { 00635 if (isVideoObjectStartCode(next4Bytes)) { 00636 setParseState(PARSING_VIDEO_OBJECT_LAYER); 00637 } else if (isVideoObjectLayerStartCode(next4Bytes)){ 00638 // copy all bytes that we see, up until we reach a VOP_START_CODE: 00639 u_int32_t next4Bytes = get4Bytes(); 00640 while (next4Bytes != VOP_START_CODE) { 00641 saveToNextCode(next4Bytes); 00642 } 00643 setParseState(PARSING_VIDEO_OBJECT_PLANE); 00644 } else { 00645 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): Saw unexpected code " 00646 << (void*)next4Bytes << "\n"; 00647 setParseState(PARSING_VIDEO_OBJECT_PLANE); // the safest way to recover... 00648 } 00649 break; 00650 } 00651 } 00652 00653 // Compute this frame's presentation time: 00654 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode); 00655 00656 return curFrameSize(); 00657 }
| unsigned MPEG4VideoStreamParser::parseVisualObjectSequenceEndCode | ( | ) | [private] |
Definition at line 659 of file MPEG4VideoStreamFramer.cpp.
References MPEGVideoStreamParser::curFrameSize(), MPEGVideoStreamFramer::fPictureEndMarker, PARSING_VISUAL_OBJECT_SEQUENCE, MPEGVideoStreamParser::save4Bytes(), MPEGVideoStreamParser::setParseState(), True, usingSource(), and VISUAL_OBJECT_SEQUENCE_END_CODE.
Referenced by parse().
00659 { 00660 #ifdef DEBUG 00661 fprintf(stderr, "parsing VISUAL_OBJECT_SEQUENCE_END_CODE\n"); 00662 #endif 00663 // Note that we've already read the VISUAL_OBJECT_SEQUENCE_END_CODE 00664 save4Bytes(VISUAL_OBJECT_SEQUENCE_END_CODE); 00665 00666 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE); 00667 00668 // Treat this as if we had ended a picture: 00669 usingSource()->fPictureEndMarker = True; // HACK ##### 00670 00671 return curFrameSize(); 00672 }
| Boolean MPEG4VideoStreamParser::getNextFrameBit | ( | u_int8_t & | result | ) | [private] |
Definition at line 330 of file MPEG4VideoStreamFramer.cpp.
References MPEGVideoStreamParser::curFrameSize(), False, fNumBitsSeenSoFar, MPEGVideoStreamParser::fStartOfFrame, and True.
Referenced by analyzeVOLHeader(), and getNextFrameBits().
00330 { 00331 if (fNumBitsSeenSoFar/8 >= curFrameSize()) return False; 00332 00333 u_int8_t nextByte = fStartOfFrame[fNumBitsSeenSoFar/8]; 00334 result = (nextByte>>(7-fNumBitsSeenSoFar%8))&1; 00335 ++fNumBitsSeenSoFar; 00336 return True; 00337 }
| Boolean MPEG4VideoStreamParser::getNextFrameBits | ( | unsigned | numBits, | |
| u_int32_t & | result | |||
| ) | [private] |
Definition at line 339 of file MPEG4VideoStreamFramer.cpp.
References False, getNextFrameBit(), and True.
Referenced by analyzeVOLHeader().
00340 { 00341 result = 0; 00342 for (unsigned i = 0; i < numBits; ++i) { 00343 u_int8_t nextBit; 00344 if (!getNextFrameBit(nextBit)) return False; 00345 result = (result<<1)|nextBit; 00346 } 00347 return True; 00348 }
| void MPEG4VideoStreamParser::analyzeVOLHeader | ( | ) | [private] |
Definition at line 350 of file MPEG4VideoStreamFramer.cpp.
References MPEGVideoStreamParser::curFrameSize(), Medium::envir(), MPEGVideoStreamFramer::fFrameRate, fixed_vop_rate, fixed_vop_time_increment, fNumBitsSeenSoFar, fNumVTIRBits, getNextFrameBit(), getNextFrameBits(), usingSource(), and vop_time_increment_resolution.
Referenced by parseVideoObjectLayer().
00350 { 00351 // Extract timing information (in particular, 00352 // "vop_time_increment_resolution") from the VOL Header: 00353 fNumBitsSeenSoFar = 41; 00354 do { 00355 u_int8_t is_object_layer_identifier; 00356 if (!getNextFrameBit(is_object_layer_identifier)) break; 00357 if (is_object_layer_identifier) fNumBitsSeenSoFar += 7; 00358 00359 u_int32_t aspect_ratio_info; 00360 if (!getNextFrameBits(4, aspect_ratio_info)) break; 00361 if (aspect_ratio_info == 15 /*extended_PAR*/) fNumBitsSeenSoFar += 16; 00362 00363 u_int8_t vol_control_parameters; 00364 if (!getNextFrameBit(vol_control_parameters)) break; 00365 if (vol_control_parameters) { 00366 fNumBitsSeenSoFar += 3; // chroma_format; low_delay 00367 u_int8_t vbw_parameters; 00368 if (!getNextFrameBit(vbw_parameters)) break; 00369 if (vbw_parameters) fNumBitsSeenSoFar += 79; 00370 } 00371 00372 fNumBitsSeenSoFar += 2; // video_object_layer_shape 00373 u_int8_t marker_bit; 00374 if (!getNextFrameBit(marker_bit)) break; 00375 if (marker_bit != 1) { // sanity check 00376 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): marker_bit 1 not set!\n"; 00377 break; 00378 } 00379 00380 if (!getNextFrameBits(16, vop_time_increment_resolution)) break; 00381 #ifdef DEBUG 00382 fprintf(stderr, "vop_time_increment_resolution: %d\n", vop_time_increment_resolution); 00383 #endif 00384 if (vop_time_increment_resolution == 0) { 00385 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): vop_time_increment_resolution is zero!\n"; 00386 break; 00387 } 00388 // Compute how many bits are necessary to represent this: 00389 fNumVTIRBits = 0; 00390 for (unsigned test = vop_time_increment_resolution; test>0; test /= 2) { 00391 ++fNumVTIRBits; 00392 } 00393 00394 if (!getNextFrameBit(marker_bit)) break; 00395 if (marker_bit != 1) { // sanity check 00396 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): marker_bit 2 not set!\n"; 00397 break; 00398 } 00399 00400 if (!getNextFrameBit(fixed_vop_rate)) break; 00401 if (fixed_vop_rate) { 00402 // Get the following "fixed_vop_time_increment": 00403 if (!getNextFrameBits(fNumVTIRBits, fixed_vop_time_increment)) break; 00404 #ifdef DEBUG 00405 fprintf(stderr, "fixed_vop_time_increment: %d\n", fixed_vop_time_increment); 00406 if (fixed_vop_time_increment == 0) { 00407 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): fixed_vop_time_increment is zero!\n"; 00408 } 00409 #endif 00410 } 00411 // Use "vop_time_increment_resolution" as the 'frame rate' 00412 // (really, 'tick rate'): 00413 usingSource()->fFrameRate = (double)vop_time_increment_resolution; 00414 #ifdef DEBUG 00415 fprintf(stderr, "fixed_vop_rate: %d; 'frame' (really tick) rate: %f\n", fixed_vop_rate, usingSource()->fFrameRate); 00416 #endif 00417 00418 return; 00419 } while (0); 00420 00421 if (fNumBitsSeenSoFar/8 >= curFrameSize()) { 00422 char errMsg[200]; 00423 sprintf(errMsg, "Not enough bits in VOL header: %d/8 >= %d\n", fNumBitsSeenSoFar, curFrameSize()); 00424 usingSource()->envir() << errMsg; 00425 } 00426 }
| void MPEGVideoStreamParser::registerReadInterest | ( | unsigned char * | to, | |
| unsigned | maxSize | |||
| ) | [inherited] |
Definition at line 46 of file MPEGVideoStreamParser.cpp.
References MPEGVideoStreamParser::fLimit, MPEGVideoStreamParser::fNumTruncatedBytes, MPEGVideoStreamParser::fSavedNumTruncatedBytes, MPEGVideoStreamParser::fSavedTo, MPEGVideoStreamParser::fStartOfFrame, and MPEGVideoStreamParser::fTo.
Referenced by MPEGVideoStreamFramer::doGetNextFrame().
00047 { 00048 fStartOfFrame = fTo = fSavedTo = to; 00049 fLimit = to + maxSize; 00050 fNumTruncatedBytes = fSavedNumTruncatedBytes = 0; 00051 }
| unsigned MPEGVideoStreamParser::numTruncatedBytes | ( | ) | const [inline, inherited] |
Definition at line 45 of file MPEGVideoStreamParser.hh.
References MPEGVideoStreamParser::fNumTruncatedBytes.
Referenced by MPEGVideoStreamFramer::continueReadProcessing().
00045 { return fNumTruncatedBytes; }
| void MPEGVideoStreamParser::setParseState | ( | ) | [protected, inherited] |
Definition at line 40 of file MPEGVideoStreamParser.cpp.
References MPEGVideoStreamParser::fNumTruncatedBytes, MPEGVideoStreamParser::fSavedNumTruncatedBytes, MPEGVideoStreamParser::fSavedTo, MPEGVideoStreamParser::fTo, and StreamParser::saveParserState().
Referenced by flushInput(), MPEG1or2VideoStreamParser::flushInput(), MPEG1or2VideoStreamParser::parseGOPHeader(), parseGroupOfVideoObjectPlane(), MPEG1or2VideoStreamParser::parsePictureHeader(), MPEG1or2VideoStreamParser::parseSlice(), parseVideoObjectLayer(), parseVideoObjectPlane(), MPEG1or2VideoStreamParser::parseVideoSequenceHeader(), parseVisualObject(), parseVisualObjectSequence(), parseVisualObjectSequenceEndCode(), setParseState(), and MPEG1or2VideoStreamParser::setParseState().
00040 { 00041 fSavedTo = fTo; 00042 fSavedNumTruncatedBytes = fNumTruncatedBytes; 00043 saveParserState(); 00044 }
| void MPEGVideoStreamParser::saveByte | ( | u_int8_t | byte | ) | [inline, protected, inherited] |
Definition at line 51 of file MPEGVideoStreamParser.hh.
References MPEGVideoStreamParser::fLimit, MPEGVideoStreamParser::fNumTruncatedBytes, and MPEGVideoStreamParser::fTo.
Referenced by parseGroupOfVideoObjectPlane(), parseVideoObjectPlane(), parseVisualObject(), parseVisualObjectSequence(), and MPEGVideoStreamParser::saveToNextCode().
00051 { 00052 if (fTo >= fLimit) { // there's no space left 00053 ++fNumTruncatedBytes; 00054 return; 00055 } 00056