00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "MPEG4VideoStreamFramer.hh"
00027 #include "MPEGVideoStreamParser.hh"
00028 #include "MPEG4LATMAudioRTPSource.hh"
00029 #include <string.h>
00030
00032
00033
00034 enum MPEGParseState {
00035 PARSING_VISUAL_OBJECT_SEQUENCE,
00036 PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE,
00037 PARSING_VISUAL_OBJECT,
00038 PARSING_VIDEO_OBJECT_LAYER,
00039 PARSING_GROUP_OF_VIDEO_OBJECT_PLANE,
00040 PARSING_VIDEO_OBJECT_PLANE,
00041 PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE
00042 };
00043
00044 class MPEG4VideoStreamParser: public MPEGVideoStreamParser {
00045 public:
00046 MPEG4VideoStreamParser(MPEG4VideoStreamFramer* usingSource,
00047 FramedSource* inputSource);
00048 virtual ~MPEG4VideoStreamParser();
00049
00050 private:
00051 virtual void flushInput();
00052 virtual unsigned parse();
00053
00054 private:
00055 MPEG4VideoStreamFramer* usingSource() {
00056 return (MPEG4VideoStreamFramer*)fUsingSource;
00057 }
00058 void setParseState(MPEGParseState parseState);
00059
00060 unsigned parseVisualObjectSequence(Boolean haveSeenStartCode = False);
00061 unsigned parseVisualObject();
00062 unsigned parseVideoObjectLayer();
00063 unsigned parseGroupOfVideoObjectPlane();
00064 unsigned parseVideoObjectPlane();
00065 unsigned parseVisualObjectSequenceEndCode();
00066
00067
00068 Boolean getNextFrameBit(u_int8_t& result);
00069 Boolean getNextFrameBits(unsigned numBits, u_int32_t& result);
00070
00071
00072 void analyzeVOLHeader();
00073
00074 private:
00075 MPEGParseState fCurrentParseState;
00076 unsigned fNumBitsSeenSoFar;
00077 u_int32_t vop_time_increment_resolution;
00078 unsigned fNumVTIRBits;
00079
00080 u_int8_t fixed_vop_rate;
00081 unsigned fixed_vop_time_increment;
00082 unsigned fSecondsSinceLastTimeCode, fTotalTicksSinceLastTimeCode, fPrevNewTotalTicks;
00083 unsigned fPrevPictureCountDelta;
00084 Boolean fJustSawTimeCode;
00085 };
00086
00087
00089
00090 MPEG4VideoStreamFramer*
00091 MPEG4VideoStreamFramer::createNew(UsageEnvironment& env,
00092 FramedSource* inputSource) {
00093
00094 return new MPEG4VideoStreamFramer(env, inputSource);
00095 }
00096
00097 unsigned char* MPEG4VideoStreamFramer
00098 ::getConfigBytes(unsigned& numBytes) const {
00099 numBytes = fNumConfigBytes;
00100 return fConfigBytes;
00101 }
00102
00103 void MPEG4VideoStreamFramer
00104 ::setConfigInfo(u_int8_t profileAndLevelIndication, char const* configStr) {
00105 fProfileAndLevelIndication = profileAndLevelIndication;
00106
00107 delete[] fConfigBytes;
00108 fConfigBytes = parseGeneralConfigStr(configStr, fNumConfigBytes);
00109 }
00110
00111 MPEG4VideoStreamFramer::MPEG4VideoStreamFramer(UsageEnvironment& env,
00112 FramedSource* inputSource,
00113 Boolean createParser)
00114 : MPEGVideoStreamFramer(env, inputSource),
00115 fProfileAndLevelIndication(0),
00116 fConfigBytes(NULL), fNumConfigBytes(0),
00117 fNewConfigBytes(NULL), fNumNewConfigBytes(0) {
00118 fParser = createParser
00119 ? new MPEG4VideoStreamParser(this, inputSource)
00120 : NULL;
00121 }
00122
00123 MPEG4VideoStreamFramer::~MPEG4VideoStreamFramer() {
00124 delete[] fConfigBytes; delete[] fNewConfigBytes;
00125 }
00126
00127 void MPEG4VideoStreamFramer::startNewConfig() {
00128 delete[] fNewConfigBytes; fNewConfigBytes = NULL;
00129 fNumNewConfigBytes = 0;
00130 }
00131
00132 void MPEG4VideoStreamFramer
00133 ::appendToNewConfig(unsigned char* newConfigBytes, unsigned numNewBytes) {
00134
00135 unsigned char* configNew
00136 = new unsigned char[fNumNewConfigBytes + numNewBytes];
00137
00138
00139 memmove(configNew, fNewConfigBytes, fNumNewConfigBytes);
00140 memmove(&configNew[fNumNewConfigBytes], newConfigBytes, numNewBytes);
00141
00142 delete[] fNewConfigBytes; fNewConfigBytes = configNew;
00143 fNumNewConfigBytes += numNewBytes;
00144 }
00145
00146 void MPEG4VideoStreamFramer::completeNewConfig() {
00147 delete[] fConfigBytes; fConfigBytes = fNewConfigBytes;
00148 fNewConfigBytes = NULL;
00149 fNumConfigBytes = fNumNewConfigBytes;
00150 fNumNewConfigBytes = 0;
00151 }
00152
00153 Boolean MPEG4VideoStreamFramer::isMPEG4VideoStreamFramer() const {
00154 return True;
00155 }
00156
00158
00159 MPEG4VideoStreamParser
00160 ::MPEG4VideoStreamParser(MPEG4VideoStreamFramer* usingSource,
00161 FramedSource* inputSource)
00162 : MPEGVideoStreamParser(usingSource, inputSource),
00163 fCurrentParseState(PARSING_VISUAL_OBJECT_SEQUENCE),
00164 vop_time_increment_resolution(0), fNumVTIRBits(0),
00165 fixed_vop_rate(0), fixed_vop_time_increment(0),
00166 fSecondsSinceLastTimeCode(0), fTotalTicksSinceLastTimeCode(0),
00167 fPrevNewTotalTicks(0), fPrevPictureCountDelta(1), fJustSawTimeCode(False) {
00168 }
00169
00170 MPEG4VideoStreamParser::~MPEG4VideoStreamParser() {
00171 }
00172
00173 void MPEG4VideoStreamParser::setParseState(MPEGParseState parseState) {
00174 fCurrentParseState = parseState;
00175 MPEGVideoStreamParser::setParseState();
00176 }
00177
00178 void MPEG4VideoStreamParser::flushInput() {
00179 fSecondsSinceLastTimeCode = 0;
00180 fTotalTicksSinceLastTimeCode = 0;
00181 fPrevNewTotalTicks = 0;
00182 fPrevPictureCountDelta = 1;
00183
00184 StreamParser::flushInput();
00185 if (fCurrentParseState != PARSING_VISUAL_OBJECT_SEQUENCE) {
00186 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE);
00187 }
00188 }
00189
00190
00191 unsigned MPEG4VideoStreamParser::parse() {
00192 try {
00193 switch (fCurrentParseState) {
00194 case PARSING_VISUAL_OBJECT_SEQUENCE: {
00195 return parseVisualObjectSequence();
00196 }
00197 case PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE: {
00198 return parseVisualObjectSequence(True);
00199 }
00200 case PARSING_VISUAL_OBJECT: {
00201 return parseVisualObject();
00202 }
00203 case PARSING_VIDEO_OBJECT_LAYER: {
00204 return parseVideoObjectLayer();
00205 }
00206 case PARSING_GROUP_OF_VIDEO_OBJECT_PLANE: {
00207 return parseGroupOfVideoObjectPlane();
00208 }
00209 case PARSING_VIDEO_OBJECT_PLANE: {
00210 return parseVideoObjectPlane();
00211 }
00212 case PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE: {
00213 return parseVisualObjectSequenceEndCode();
00214 }
00215 default: {
00216 return 0;
00217 }
00218 }
00219 } catch (int ) {
00220 #ifdef DEBUG
00221 fprintf(stderr, "MPEG4VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
00222 #endif
00223 return 0;
00224 }
00225 }
00226
00227 #define VISUAL_OBJECT_SEQUENCE_START_CODE 0x000001B0
00228 #define VISUAL_OBJECT_SEQUENCE_END_CODE 0x000001B1
00229 #define GROUP_VOP_START_CODE 0x000001B3
00230 #define VISUAL_OBJECT_START_CODE 0x000001B5
00231 #define VOP_START_CODE 0x000001B6
00232
00233 unsigned MPEG4VideoStreamParser
00234 ::parseVisualObjectSequence(Boolean haveSeenStartCode) {
00235 #ifdef DEBUG
00236 fprintf(stderr, "parsing VisualObjectSequence\n");
00237 #endif
00238 usingSource()->startNewConfig();
00239 u_int32_t first4Bytes;
00240 if (!haveSeenStartCode) {
00241 while ((first4Bytes = test4Bytes()) != VISUAL_OBJECT_SEQUENCE_START_CODE) {
00242 #ifdef DEBUG
00243 fprintf(stderr, "ignoring non VS header: 0x%08x\n", first4Bytes);
00244 #endif
00245 get1Byte(); setParseState(PARSING_VISUAL_OBJECT_SEQUENCE);
00246
00247 }
00248 first4Bytes = get4Bytes();
00249 } else {
00250
00251 first4Bytes = VISUAL_OBJECT_SEQUENCE_START_CODE;
00252 }
00253 save4Bytes(first4Bytes);
00254
00255
00256 u_int8_t pali = get1Byte();
00257 #ifdef DEBUG
00258 fprintf(stderr, "profile_and_level_indication: %02x\n", pali);
00259 #endif
00260 saveByte(pali);
00261 usingSource()->fProfileAndLevelIndication = pali;
00262
00263
00264
00265 u_int32_t next4Bytes = get4Bytes();
00266 while (next4Bytes != VISUAL_OBJECT_START_CODE) {
00267 saveToNextCode(next4Bytes);
00268 }
00269
00270 setParseState(PARSING_VISUAL_OBJECT);
00271
00272
00273 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00274
00275
00276 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize());
00277
00278 return curFrameSize();
00279 }
00280
00281 static inline Boolean isVideoObjectStartCode(u_int32_t code) {
00282 return code >= 0x00000100 && code <= 0x0000011F;
00283 }
00284
00285 unsigned MPEG4VideoStreamParser::parseVisualObject() {
00286 #ifdef DEBUG
00287 fprintf(stderr, "parsing VisualObject\n");
00288 #endif
00289
00290 save4Bytes(VISUAL_OBJECT_START_CODE);
00291
00292
00293 u_int8_t nextByte = get1Byte(); saveByte(nextByte);
00294 Boolean is_visual_object_identifier = (nextByte&0x80) != 0;
00295 u_int8_t visual_object_type;
00296 if (is_visual_object_identifier) {
00297 #ifdef DEBUG
00298 fprintf(stderr, "visual_object_verid: 0x%x; visual_object_priority: 0x%x\n", (nextByte&0x78)>>3, (nextByte&0x07));
00299 #endif
00300 nextByte = get1Byte(); saveByte(nextByte);
00301 visual_object_type = (nextByte&0xF0)>>4;
00302 } else {
00303 visual_object_type = (nextByte&0x78)>>3;
00304 }
00305 #ifdef DEBUG
00306 fprintf(stderr, "visual_object_type: 0x%x\n", visual_object_type);
00307 #endif
00308
00309 if (visual_object_type != 1) {
00310 usingSource()->envir() << "MPEG4VideoStreamParser::parseVisualObject(): Warning: We don't handle visual_object_type " << visual_object_type << "\n";
00311 }
00312
00313
00314
00315 u_int32_t next4Bytes = get4Bytes();
00316 while (!isVideoObjectStartCode(next4Bytes)) {
00317 saveToNextCode(next4Bytes);
00318 }
00319 save4Bytes(next4Bytes);
00320 #ifdef DEBUG
00321 fprintf(stderr, "saw a video_object_start_code: 0x%08x\n", next4Bytes);
00322 #endif
00323
00324 setParseState(PARSING_VIDEO_OBJECT_LAYER);
00325
00326
00327 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00328
00329
00330 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize());
00331
00332 return curFrameSize();
00333 }
00334
00335 static inline Boolean isVideoObjectLayerStartCode(u_int32_t code) {
00336 return code >= 0x00000120 && code <= 0x0000012F;
00337 }
00338
00339 Boolean MPEG4VideoStreamParser::getNextFrameBit(u_int8_t& result) {
00340 if (fNumBitsSeenSoFar/8 >= curFrameSize()) return False;
00341
00342 u_int8_t nextByte = fStartOfFrame[fNumBitsSeenSoFar/8];
00343 result = (nextByte>>(7-fNumBitsSeenSoFar%8))&1;
00344 ++fNumBitsSeenSoFar;
00345 return True;
00346 }
00347
00348 Boolean MPEG4VideoStreamParser::getNextFrameBits(unsigned numBits,
00349 u_int32_t& result) {
00350 result = 0;
00351 for (unsigned i = 0; i < numBits; ++i) {
00352 u_int8_t nextBit;
00353 if (!getNextFrameBit(nextBit)) return False;
00354 result = (result<<1)|nextBit;
00355 }
00356 return True;
00357 }
00358
00359 void MPEG4VideoStreamParser::analyzeVOLHeader() {
00360
00361
00362 fNumBitsSeenSoFar = 41;
00363 do {
00364 u_int8_t is_object_layer_identifier;
00365 if (!getNextFrameBit(is_object_layer_identifier)) break;
00366 if (is_object_layer_identifier) fNumBitsSeenSoFar += 7;
00367
00368 u_int32_t aspect_ratio_info;
00369 if (!getNextFrameBits(4, aspect_ratio_info)) break;
00370 if (aspect_ratio_info == 15 ) fNumBitsSeenSoFar += 16;
00371
00372 u_int8_t vol_control_parameters;
00373 if (!getNextFrameBit(vol_control_parameters)) break;
00374 if (vol_control_parameters) {
00375 fNumBitsSeenSoFar += 3;
00376 u_int8_t vbw_parameters;
00377 if (!getNextFrameBit(vbw_parameters)) break;
00378 if (vbw_parameters) fNumBitsSeenSoFar += 79;
00379 }
00380
00381 fNumBitsSeenSoFar += 2;
00382 u_int8_t marker_bit;
00383 if (!getNextFrameBit(marker_bit)) break;
00384 if (marker_bit != 1) {
00385 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): marker_bit 1 not set!\n";
00386 break;
00387 }
00388
00389 if (!getNextFrameBits(16, vop_time_increment_resolution)) break;
00390 #ifdef DEBUG
00391 fprintf(stderr, "vop_time_increment_resolution: %d\n", vop_time_increment_resolution);
00392 #endif
00393 if (vop_time_increment_resolution == 0) {
00394 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): vop_time_increment_resolution is zero!\n";
00395 break;
00396 }
00397
00398 fNumVTIRBits = 0;
00399 for (unsigned test = vop_time_increment_resolution; test>0; test /= 2) {
00400 ++fNumVTIRBits;
00401 }
00402
00403 if (!getNextFrameBit(marker_bit)) break;
00404 if (marker_bit != 1) {
00405 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): marker_bit 2 not set!\n";
00406 break;
00407 }
00408
00409 if (!getNextFrameBit(fixed_vop_rate)) break;
00410 if (fixed_vop_rate) {
00411
00412 if (!getNextFrameBits(fNumVTIRBits, fixed_vop_time_increment)) break;
00413 #ifdef DEBUG
00414 fprintf(stderr, "fixed_vop_time_increment: %d\n", fixed_vop_time_increment);
00415 if (fixed_vop_time_increment == 0) {
00416 usingSource()->envir() << "MPEG4VideoStreamParser::analyzeVOLHeader(): fixed_vop_time_increment is zero!\n";
00417 }
00418 #endif
00419 }
00420
00421
00422 usingSource()->fFrameRate = (double)vop_time_increment_resolution;
00423 #ifdef DEBUG
00424 fprintf(stderr, "fixed_vop_rate: %d; 'frame' (really tick) rate: %f\n", fixed_vop_rate, usingSource()->fFrameRate);
00425 #endif
00426
00427 return;
00428 } while (0);
00429
00430 if (fNumBitsSeenSoFar/8 >= curFrameSize()) {
00431 char errMsg[200];
00432 sprintf(errMsg, "Not enough bits in VOL header: %d/8 >= %d\n", fNumBitsSeenSoFar, curFrameSize());
00433 usingSource()->envir() << errMsg;
00434 }
00435 }
00436
00437 unsigned MPEG4VideoStreamParser::parseVideoObjectLayer() {
00438 #ifdef DEBUG
00439 fprintf(stderr, "parsing VideoObjectLayer\n");
00440 #endif
00441
00442
00443
00444 u_int32_t next4Bytes = get4Bytes();
00445 if (!isVideoObjectLayerStartCode(next4Bytes)) {
00446 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectLayer(): This appears to be a 'short video header', which we current don't support\n";
00447 }
00448
00449
00450
00451 do {
00452 saveToNextCode(next4Bytes);
00453 } while (next4Bytes != GROUP_VOP_START_CODE
00454 && next4Bytes != VOP_START_CODE);
00455
00456 analyzeVOLHeader();
00457
00458 setParseState((next4Bytes == GROUP_VOP_START_CODE)
00459 ? PARSING_GROUP_OF_VIDEO_OBJECT_PLANE
00460 : PARSING_VIDEO_OBJECT_PLANE);
00461
00462
00463 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00464
00465
00466 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize());
00467 usingSource()->completeNewConfig();
00468
00469 return curFrameSize();
00470 }
00471
00472 unsigned MPEG4VideoStreamParser::parseGroupOfVideoObjectPlane() {
00473 #ifdef DEBUG
00474 fprintf(stderr, "parsing GroupOfVideoObjectPlane\n");
00475 #endif
00476
00477 save4Bytes(GROUP_VOP_START_CODE);
00478
00479
00480 u_int8_t next3Bytes[3];
00481 getBytes(next3Bytes, 3);
00482 saveByte(next3Bytes[0]);saveByte(next3Bytes[1]);saveByte(next3Bytes[2]);
00483 unsigned time_code
00484 = (next3Bytes[0]<<10)|(next3Bytes[1]<<2)|(next3Bytes[2]>>6);
00485 unsigned time_code_hours = (time_code&0x0003E000)>>13;
00486 unsigned time_code_minutes = (time_code&0x00001F80)>>7;
00487 #if defined(DEBUG) || defined(DEBUG_TIMESTAMPS)
00488 Boolean marker_bit = (time_code&0x00000040) != 0;
00489 #endif
00490 unsigned time_code_seconds = (time_code&0x0000003F);
00491 #if defined(DEBUG) || defined(DEBUG_TIMESTAMPS)
00492 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);
00493 #endif
00494 fJustSawTimeCode = True;
00495
00496
00497 u_int32_t next4Bytes = get4Bytes();
00498 while (next4Bytes != VOP_START_CODE) {
00499 saveToNextCode(next4Bytes);
00500 }
00501
00502
00503 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00504
00505
00506 usingSource()->setTimeCode(time_code_hours, time_code_minutes,
00507 time_code_seconds, 0, 0);
00508
00509
00510 fSecondsSinceLastTimeCode = 0;
00511 if (fixed_vop_rate) fTotalTicksSinceLastTimeCode = 0;
00512
00513 setParseState(PARSING_VIDEO_OBJECT_PLANE);
00514
00515 return curFrameSize();
00516 }
00517
00518 unsigned MPEG4VideoStreamParser::parseVideoObjectPlane() {
00519 #ifdef DEBUG
00520 fprintf(stderr, "#parsing VideoObjectPlane\n");
00521 #endif
00522
00523 save4Bytes(VOP_START_CODE);
00524
00525
00526 u_int8_t nextByte = get1Byte(); saveByte(nextByte);
00527 u_int8_t vop_coding_type = nextByte>>6;
00528
00529
00530
00531 u_int32_t next4Bytes = get4Bytes();
00532 u_int32_t timeInfo = (nextByte<<(32-6))|(next4Bytes>>6);
00533 unsigned modulo_time_base = 0;
00534 u_int32_t mask = 0x80000000;
00535 while ((timeInfo&mask) != 0) {
00536 ++modulo_time_base;
00537 mask >>= 1;
00538 }
00539 mask >>= 1;
00540
00541
00542 if ((timeInfo&mask) == 0) {
00543 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): marker bit not set!\n";
00544 }
00545 mask >>= 1;
00546
00547
00548
00549 if ((mask>>(fNumVTIRBits-1)) == 0) {
00550 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): 32-bits are not enough to get \"vop_time_increment\"!\n";
00551 }
00552 unsigned vop_time_increment = 0;
00553 for (unsigned i = 0; i < fNumVTIRBits; ++i) {
00554 vop_time_increment |= timeInfo&mask;
00555 mask >>= 1;
00556 }
00557 while (mask != 0) {
00558 vop_time_increment >>= 1;
00559 mask >>= 1;
00560 }
00561 #ifdef DEBUG
00562 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);
00563 #endif
00564
00565
00566 saveToNextCode(next4Bytes);
00567
00568
00569 if (fixed_vop_time_increment > 0) {
00570
00571 usingSource()->fPictureCount += fixed_vop_time_increment;
00572 if (vop_time_increment > 0 || modulo_time_base > 0) {
00573 fTotalTicksSinceLastTimeCode += fixed_vop_time_increment;
00574
00575 }
00576 } else {
00577
00578 unsigned newTotalTicks
00579 = (fSecondsSinceLastTimeCode + modulo_time_base)*vop_time_increment_resolution
00580 + vop_time_increment;
00581 if (newTotalTicks == fPrevNewTotalTicks && fPrevNewTotalTicks > 0) {
00582
00583
00584
00585 #ifdef DEBUG
00586 fprintf(stderr, "Buggy MPEG-4 video stream: \"vop_time_increment\" did not change!\n");
00587 #endif
00588
00589 usingSource()->fPictureCount += vop_time_increment;
00590 fTotalTicksSinceLastTimeCode += vop_time_increment;
00591 fSecondsSinceLastTimeCode += modulo_time_base;
00592 } else {
00593 if (newTotalTicks < fPrevNewTotalTicks && vop_coding_type != 2
00594 && modulo_time_base == 0 && vop_time_increment == 0 && !fJustSawTimeCode) {
00595
00596
00597
00598
00599 #ifdef DEBUG
00600 fprintf(stderr, "Buggy MPEG-4 video stream: \"vop_time_increment\" wrapped around, but without \"modulo_time_base\" changing!\n");
00601 #endif
00602 ++fSecondsSinceLastTimeCode;
00603 newTotalTicks += vop_time_increment_resolution;
00604 }
00605 fPrevNewTotalTicks = newTotalTicks;
00606 if (vop_coding_type != 2) {
00607 int pictureCountDelta = newTotalTicks - fTotalTicksSinceLastTimeCode;
00608 if (pictureCountDelta <= 0) pictureCountDelta = fPrevPictureCountDelta;
00609
00610 usingSource()->fPictureCount += pictureCountDelta;
00611 fPrevPictureCountDelta = pictureCountDelta;
00612 fTotalTicksSinceLastTimeCode = newTotalTicks;
00613 fSecondsSinceLastTimeCode += modulo_time_base;
00614 }
00615 }
00616 }
00617 fJustSawTimeCode = False;
00618
00619
00620
00621 usingSource()->fPictureEndMarker = True;
00622 switch (next4Bytes) {
00623 case VISUAL_OBJECT_SEQUENCE_END_CODE: {
00624 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE);
00625 break;
00626 }
00627 case VISUAL_OBJECT_SEQUENCE_START_CODE: {
00628 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE);
00629 break;
00630 }
00631 case VISUAL_OBJECT_START_CODE: {
00632 setParseState(PARSING_VISUAL_OBJECT);
00633 break;
00634 }
00635 case GROUP_VOP_START_CODE: {
00636 setParseState(PARSING_GROUP_OF_VIDEO_OBJECT_PLANE);
00637 break;
00638 }
00639 case VOP_START_CODE: {
00640 setParseState(PARSING_VIDEO_OBJECT_PLANE);
00641 break;
00642 }
00643 default: {
00644 if (isVideoObjectStartCode(next4Bytes)) {
00645 setParseState(PARSING_VIDEO_OBJECT_LAYER);
00646 } else if (isVideoObjectLayerStartCode(next4Bytes)){
00647
00648 u_int32_t next4Bytes = get4Bytes();
00649 while (next4Bytes != VOP_START_CODE) {
00650 saveToNextCode(next4Bytes);
00651 }
00652 setParseState(PARSING_VIDEO_OBJECT_PLANE);
00653 } else {
00654 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): Saw unexpected code "
00655 << (void*)next4Bytes << "\n";
00656 setParseState(PARSING_VIDEO_OBJECT_PLANE);
00657 }
00658 break;
00659 }
00660 }
00661
00662
00663 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00664
00665 return curFrameSize();
00666 }
00667
00668 unsigned MPEG4VideoStreamParser::parseVisualObjectSequenceEndCode() {
00669 #ifdef DEBUG
00670 fprintf(stderr, "parsing VISUAL_OBJECT_SEQUENCE_END_CODE\n");
00671 #endif
00672
00673 save4Bytes(VISUAL_OBJECT_SEQUENCE_END_CODE);
00674
00675 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE);
00676
00677
00678 usingSource()->fPictureEndMarker = True;
00679
00680 return curFrameSize();
00681 }