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 <string.h>
00029
00031
00032
00033 enum MPEGParseState {
00034 PARSING_VISUAL_OBJECT_SEQUENCE,
00035 PARSING_VISUAL_OBJECT_SEQUENCE_SEEN_CODE,
00036 PARSING_VISUAL_OBJECT,
00037 PARSING_VIDEO_OBJECT_LAYER,
00038 PARSING_GROUP_OF_VIDEO_OBJECT_PLANE,
00039 PARSING_VIDEO_OBJECT_PLANE,
00040 PARSING_VISUAL_OBJECT_SEQUENCE_END_CODE
00041 };
00042
00043 class MPEG4VideoStreamParser: public MPEGVideoStreamParser {
00044 public:
00045 MPEG4VideoStreamParser(MPEG4VideoStreamFramer* usingSource,
00046 FramedSource* inputSource);
00047 virtual ~MPEG4VideoStreamParser();
00048
00049 private:
00050 virtual void flushInput();
00051 virtual unsigned parse();
00052
00053 private:
00054 MPEG4VideoStreamFramer* usingSource() {
00055 return (MPEG4VideoStreamFramer*)fUsingSource;
00056 }
00057 void setParseState(MPEGParseState parseState);
00058
00059 unsigned parseVisualObjectSequence(Boolean haveSeenStartCode = False);
00060 unsigned parseVisualObject();
00061 unsigned parseVideoObjectLayer();
00062 unsigned parseGroupOfVideoObjectPlane();
00063 unsigned parseVideoObjectPlane();
00064 unsigned parseVisualObjectSequenceEndCode();
00065
00066
00067 Boolean getNextFrameBit(u_int8_t& result);
00068 Boolean getNextFrameBits(unsigned numBits, u_int32_t& result);
00069
00070
00071 void analyzeVOLHeader();
00072
00073 private:
00074 MPEGParseState fCurrentParseState;
00075 unsigned fNumBitsSeenSoFar;
00076 u_int32_t vop_time_increment_resolution;
00077 unsigned fNumVTIRBits;
00078
00079 u_int8_t fixed_vop_rate;
00080 unsigned fixed_vop_time_increment;
00081 unsigned fSecondsSinceLastTimeCode, fTotalTicksSinceLastTimeCode, fPrevNewTotalTicks;
00082 unsigned fPrevPictureCountDelta;
00083 Boolean fJustSawTimeCode;
00084 };
00085
00086
00088
00089 MPEG4VideoStreamFramer*
00090 MPEG4VideoStreamFramer::createNew(UsageEnvironment& env,
00091 FramedSource* inputSource) {
00092
00093 return new MPEG4VideoStreamFramer(env, inputSource);
00094 }
00095
00096 unsigned char* MPEG4VideoStreamFramer
00097 ::getConfigBytes(unsigned& numBytes) const {
00098 numBytes = fNumConfigBytes;
00099 return fConfigBytes;
00100 }
00101
00102 MPEG4VideoStreamFramer::MPEG4VideoStreamFramer(UsageEnvironment& env,
00103 FramedSource* inputSource,
00104 Boolean createParser)
00105 : MPEGVideoStreamFramer(env, inputSource),
00106 fProfileAndLevelIndication(0),
00107 fConfigBytes(NULL), fNumConfigBytes(0),
00108 fNewConfigBytes(NULL), fNumNewConfigBytes(0) {
00109 fParser = createParser
00110 ? new MPEG4VideoStreamParser(this, inputSource)
00111 : NULL;
00112 }
00113
00114 MPEG4VideoStreamFramer::~MPEG4VideoStreamFramer() {
00115 delete[] fConfigBytes; delete[] fNewConfigBytes;
00116 }
00117
00118 void MPEG4VideoStreamFramer::startNewConfig() {
00119 delete[] fNewConfigBytes; fNewConfigBytes = NULL;
00120 fNumNewConfigBytes = 0;
00121 }
00122
00123 void MPEG4VideoStreamFramer
00124 ::appendToNewConfig(unsigned char* newConfigBytes, unsigned numNewBytes) {
00125
00126 unsigned char* configNew
00127 = new unsigned char[fNumNewConfigBytes + numNewBytes];
00128
00129
00130 memmove(configNew, fNewConfigBytes, fNumNewConfigBytes);
00131 memmove(&configNew[fNumNewConfigBytes], newConfigBytes, numNewBytes);
00132
00133 delete[] fNewConfigBytes; fNewConfigBytes = configNew;
00134 fNumNewConfigBytes += numNewBytes;
00135 }
00136
00137 void MPEG4VideoStreamFramer::completeNewConfig() {
00138 delete fConfigBytes; fConfigBytes = fNewConfigBytes;
00139 fNewConfigBytes = NULL;
00140 fNumConfigBytes = fNumNewConfigBytes;
00141 fNumNewConfigBytes = 0;
00142 }
00143
00144 Boolean MPEG4VideoStreamFramer::isMPEG4VideoStreamFramer() const {
00145 return True;
00146 }
00147
00149
00150 MPEG4VideoStreamParser
00151 ::MPEG4VideoStreamParser(MPEG4VideoStreamFramer* usingSource,
00152 FramedSource* inputSource)
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 }
00160
00161 MPEG4VideoStreamParser::~MPEG4VideoStreamParser() {
00162 }
00163
00164 void MPEG4VideoStreamParser::setParseState(MPEGParseState parseState) {
00165 fCurrentParseState = parseState;
00166 MPEGVideoStreamParser::setParseState();
00167 }
00168
00169 void MPEG4VideoStreamParser::flushInput() {
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);
00178 }
00179 }
00180
00181
00182 unsigned MPEG4VideoStreamParser::parse() {
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;
00208 }
00209 }
00210 } catch (int ) {
00211 #ifdef DEBUG
00212 fprintf(stderr, "MPEG4VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
00213 #endif
00214 return 0;
00215 }
00216 }
00217
00218 #define VISUAL_OBJECT_SEQUENCE_START_CODE 0x000001B0
00219 #define VISUAL_OBJECT_SEQUENCE_END_CODE 0x000001B1
00220 #define GROUP_VOP_START_CODE 0x000001B3
00221 #define VISUAL_OBJECT_START_CODE 0x000001B5
00222 #define VOP_START_CODE 0x000001B6
00223
00224 unsigned MPEG4VideoStreamParser
00225 ::parseVisualObjectSequence(Boolean haveSeenStartCode) {
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
00238 }
00239 first4Bytes = get4Bytes();
00240 } else {
00241
00242 first4Bytes = VISUAL_OBJECT_SEQUENCE_START_CODE;
00243 }
00244 save4Bytes(first4Bytes);
00245
00246
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
00255
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
00264 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00265
00266
00267 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize());
00268
00269 return curFrameSize();
00270 }
00271
00272 static inline Boolean isVideoObjectStartCode(u_int32_t code) {
00273 return code >= 0x00000100 && code <= 0x0000011F;
00274 }
00275
00276 unsigned MPEG4VideoStreamParser::parseVisualObject() {
00277 #ifdef DEBUG
00278 fprintf(stderr, "parsing VisualObject\n");
00279 #endif
00280
00281 save4Bytes(VISUAL_OBJECT_START_CODE);
00282
00283
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
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
00305
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
00318 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00319
00320
00321 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize());
00322
00323 return curFrameSize();
00324 }
00325
00326 static inline Boolean isVideoObjectLayerStartCode(u_int32_t code) {
00327 return code >= 0x00000120 && code <= 0x0000012F;
00328 }
00329
00330 Boolean MPEG4VideoStreamParser::getNextFrameBit(u_int8_t& result) {
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 }
00338
00339 Boolean MPEG4VideoStreamParser::getNextFrameBits(unsigned numBits,
00340 u_int32_t& result) {
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 }
00349
00350 void MPEG4VideoStreamParser::analyzeVOLHeader() {
00351
00352
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 ) 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;
00367 u_int8_t vbw_parameters;
00368 if (!getNextFrameBit(vbw_parameters)) break;
00369 if (vbw_parameters) fNumBitsSeenSoFar += 79;
00370 }
00371
00372 fNumBitsSeenSoFar += 2;
00373 u_int8_t marker_bit;
00374 if (!getNextFrameBit(marker_bit)) break;
00375 if (marker_bit != 1) {
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
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) {
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
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
00412
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 }
00427
00428 unsigned MPEG4VideoStreamParser::parseVideoObjectLayer() {
00429 #ifdef DEBUG
00430 fprintf(stderr, "parsing VideoObjectLayer\n");
00431 #endif
00432
00433
00434
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
00441
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
00454 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00455
00456
00457 usingSource()->appendToNewConfig(fStartOfFrame, curFrameSize());
00458 usingSource()->completeNewConfig();
00459
00460 return curFrameSize();
00461 }
00462
00463 unsigned MPEG4VideoStreamParser::parseGroupOfVideoObjectPlane() {
00464 #ifdef DEBUG
00465 fprintf(stderr, "parsing GroupOfVideoObjectPlane\n");
00466 #endif
00467
00468 save4Bytes(GROUP_VOP_START_CODE);
00469
00470
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
00488 u_int32_t next4Bytes = get4Bytes();
00489 while (next4Bytes != VOP_START_CODE) {
00490 saveToNextCode(next4Bytes);
00491 }
00492
00493
00494 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00495
00496
00497 usingSource()->setTimeCode(time_code_hours, time_code_minutes,
00498 time_code_seconds, 0, 0);
00499
00500
00501 fSecondsSinceLastTimeCode = 0;
00502 if (fixed_vop_rate) fTotalTicksSinceLastTimeCode = 0;
00503
00504 setParseState(PARSING_VIDEO_OBJECT_PLANE);
00505
00506 return curFrameSize();
00507 }
00508
00509 unsigned MPEG4VideoStreamParser::parseVideoObjectPlane() {
00510 #ifdef DEBUG
00511 fprintf(stderr, "#parsing VideoObjectPlane\n");
00512 #endif
00513
00514 save4Bytes(VOP_START_CODE);
00515
00516
00517 u_int8_t nextByte = get1Byte(); saveByte(nextByte);
00518 u_int8_t vop_coding_type = nextByte>>6;
00519
00520
00521
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
00533 if ((timeInfo&mask) == 0) {
00534 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): marker bit not set!\n";
00535 }
00536 mask >>= 1;
00537
00538
00539
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
00557 saveToNextCode(next4Bytes);
00558
00559
00560 if (fixed_vop_time_increment > 0) {
00561
00562 usingSource()->fPictureCount += fixed_vop_time_increment;
00563 if (vop_time_increment > 0 || modulo_time_base > 0) {
00564 fTotalTicksSinceLastTimeCode += fixed_vop_time_increment;
00565
00566 }
00567 } else {
00568
00569 unsigned newTotalTicks
00570 = (fSecondsSinceLastTimeCode + modulo_time_base)*vop_time_increment_resolution
00571 + vop_time_increment;
00572 if (newTotalTicks == fPrevNewTotalTicks && fPrevNewTotalTicks > 0) {
00573
00574
00575
00576 #ifdef DEBUG
00577 fprintf(stderr, "Buggy MPEG-4 video stream: \"vop_time_increment\" did not change!\n");
00578 #endif
00579
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
00585 && modulo_time_base == 0 && vop_time_increment == 0 && !fJustSawTimeCode) {
00586
00587
00588
00589
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) {
00598 int pictureCountDelta = newTotalTicks - fTotalTicksSinceLastTimeCode;
00599 if (pictureCountDelta <= 0) pictureCountDelta = fPrevPictureCountDelta;
00600
00601 usingSource()->fPictureCount += pictureCountDelta;
00602 fPrevPictureCountDelta = pictureCountDelta;
00603 fTotalTicksSinceLastTimeCode = newTotalTicks;
00604 fSecondsSinceLastTimeCode += modulo_time_base;
00605 }
00606 }
00607 }
00608 fJustSawTimeCode = False;
00609
00610
00611
00612 usingSource()->fPictureEndMarker = True;
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 {
00638 usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): Saw unexpected code "
00639 << (void*)next4Bytes << "\n";
00640 setParseState(PARSING_VIDEO_OBJECT_PLANE);
00641 }
00642 break;
00643 }
00644 }
00645
00646
00647 usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00648
00649 return curFrameSize();
00650 }
00651
00652 unsigned MPEG4VideoStreamParser::parseVisualObjectSequenceEndCode() {
00653 #ifdef DEBUG
00654 fprintf(stderr, "parsing VISUAL_OBJECT_SEQUENCE_END_CODE\n");
00655 #endif
00656
00657 save4Bytes(VISUAL_OBJECT_SEQUENCE_END_CODE);
00658
00659 setParseState(PARSING_VISUAL_OBJECT_SEQUENCE);
00660
00661
00662 usingSource()->fPictureEndMarker = True;
00663
00664 return curFrameSize();
00665 }