liveMedia/MPEG4VideoStreamFramer.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2013 Live Networks, Inc.  All rights reserved.
00018 // A filter that breaks up an MPEG-4 video elementary stream into
00019 //   frames for:
00020 // - Visual Object Sequence (VS) Header + Visual Object (VO) Header
00021 //   + Video Object Layer (VOL) Header
00022 // - Group of VOP (GOV) Header
00023 // - VOP frame
00024 // Implementation
00025 
00026 #include "MPEG4VideoStreamFramer.hh"
00027 #include "MPEGVideoStreamParser.hh"
00028 #include "MPEG4LATMAudioRTPSource.hh" // for "parseGeneralConfigStr()"
00029 #include <string.h>
00030 
00032 
00033 // An enum representing the current state of the parser:
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: // redefined virtual functions:
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   // These are used for parsing within an already-read frame:
00068   Boolean getNextFrameBit(u_int8_t& result);
00069   Boolean getNextFrameBits(unsigned numBits, u_int32_t& result);
00070 
00071   // Which are used by:
00072   void analyzeVOLHeader();
00073 
00074 private:
00075   MPEGParseState fCurrentParseState;
00076   unsigned fNumBitsSeenSoFar; // used by the getNextFrameBit*() routines
00077   u_int32_t vop_time_increment_resolution;
00078   unsigned fNumVTIRBits;
00079       // # of bits needed to count to "vop_time_increment_resolution"
00080   u_int8_t fixed_vop_rate;
00081   unsigned fixed_vop_time_increment; // used if 'fixed_vop_rate' is set
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   // Need to add source type checking here???  #####
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   // Allocate a new block of memory for the new config bytes:
00135   unsigned char* configNew
00136     = new unsigned char[fNumNewConfigBytes + numNewBytes];
00137 
00138   // Copy the old, then the new, config bytes there:
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); // later, change to GOV or VOP? #####
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; // shouldn't happen
00217     }
00218     }
00219   } catch (int /*e*/) {
00220 #ifdef DEBUG
00221     fprintf(stderr, "MPEG4VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
00222 #endif
00223     return 0;  // the parsing got interrupted
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           // ensures we progress over bad data
00247     }
00248     first4Bytes = get4Bytes();
00249   } else {
00250     // We've already seen the start code
00251     first4Bytes = VISUAL_OBJECT_SEQUENCE_START_CODE;
00252   }
00253   save4Bytes(first4Bytes);
00254 
00255   // The next byte is the "profile_and_level_indication":
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   // Now, copy all bytes that we see, up until we reach
00264   // a VISUAL_OBJECT_START_CODE:
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   // Compute this frame's presentation time:
00273   usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00274 
00275   // This header forms part of the 'configuration' information:
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   // Note that we've already read the VISUAL_OBJECT_START_CODE
00290   save4Bytes(VISUAL_OBJECT_START_CODE);
00291 
00292   // Next, extract the "visual_object_type" from the next 1 or 2 bytes:
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   // At present, we support only the "Video ID" "visual_object_type" (1)
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   // Now, copy all bytes that we see, up until we reach
00314   // a video_object_start_code
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   // Compute this frame's presentation time:
00327   usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00328 
00329   // This header forms part of the 'configuration' information:
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   // Extract timing information (in particular,
00361   // "vop_time_increment_resolution") from the VOL Header:
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 /*extended_PAR*/) 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; // chroma_format; low_delay
00376       u_int8_t vbw_parameters;
00377       if (!getNextFrameBit(vbw_parameters)) break;
00378       if (vbw_parameters) fNumBitsSeenSoFar += 79;
00379     }
00380 
00381     fNumBitsSeenSoFar += 2; // video_object_layer_shape
00382     u_int8_t marker_bit;
00383     if (!getNextFrameBit(marker_bit)) break;
00384     if (marker_bit != 1) { // sanity check
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     // Compute how many bits are necessary to represent this:
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) { // sanity check
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       // Get the following "fixed_vop_time_increment":
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     // Use "vop_time_increment_resolution" as the 'frame rate'
00421     // (really, 'tick rate'):
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   // The first 4 bytes must be a "video_object_layer_start_code".
00442   // If not, this is a 'short video header', which we currently
00443   // don't support:
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   // Now, copy all bytes that we see, up until we reach
00450   // a GROUP_VOP_START_CODE or a VOP_START_CODE:
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   // Compute this frame's presentation time:
00463   usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00464 
00465   // This header ends the 'configuration' information:
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   // Note that we've already read the GROUP_VOP_START_CODE
00477   save4Bytes(GROUP_VOP_START_CODE);
00478 
00479   // Next, extract the (18-bit) time code from the next 3 bytes:
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   // Now, copy all bytes that we see, up until we reach a VOP_START_CODE:
00497   u_int32_t next4Bytes = get4Bytes();
00498   while (next4Bytes != VOP_START_CODE) {
00499     saveToNextCode(next4Bytes);
00500   }
00501 
00502   // Compute this frame's presentation time:
00503   usingSource()->computePresentationTime(fTotalTicksSinceLastTimeCode);
00504 
00505   // Record the time code:
00506   usingSource()->setTimeCode(time_code_hours, time_code_minutes,
00507                              time_code_seconds, 0, 0);
00508     // Note: Because the GOV header can appear anywhere (not just at a 1s point), we
00509     // don't pass "fTotalTicksSinceLastTimeCode" as the "picturesSinceLastGOP" parameter.
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   // Note that we've already read the VOP_START_CODE
00523   save4Bytes(VOP_START_CODE);
00524 
00525   // Get the "vop_coding_type" from the next byte:
00526   u_int8_t nextByte = get1Byte(); saveByte(nextByte);
00527   u_int8_t vop_coding_type = nextByte>>6;
00528 
00529   // Next, get the "modulo_time_base" by counting the '1' bits that follow.
00530   // We look at the next 32-bits only.  This should be enough in most cases.
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   // Check the following marker bit:
00542   if ((timeInfo&mask) == 0) {
00543     usingSource()->envir() << "MPEG4VideoStreamParser::parseVideoObjectPlane(): marker bit not set!\n";
00544   }
00545   mask >>= 1;
00546 
00547   // Then, get the "vop_time_increment".
00548   // First, make sure we have enough bits left for this:
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   // Now, copy all bytes that we see, up until we reach a code of some sort:
00566   saveToNextCode(next4Bytes);
00567 
00568   // Update our counters based on the frame timing information that we saw:
00569   if (fixed_vop_time_increment > 0) {
00570     // This is a 'fixed_vop_rate' stream.  Use 'fixed_vop_time_increment':
00571     usingSource()->fPictureCount += fixed_vop_time_increment;
00572     if (vop_time_increment > 0 || modulo_time_base > 0) {
00573       fTotalTicksSinceLastTimeCode += fixed_vop_time_increment;
00574       // Note: "fSecondsSinceLastTimeCode" and "fPrevNewTotalTicks" are not used.
00575     }
00576   } else {
00577     // Use 'vop_time_increment':
00578     unsigned newTotalTicks
00579       = (fSecondsSinceLastTimeCode + modulo_time_base)*vop_time_increment_resolution
00580       + vop_time_increment;
00581     if (newTotalTicks == fPrevNewTotalTicks && fPrevNewTotalTicks > 0) {
00582       // This is apparently a buggy MPEG-4 video stream, because
00583       // "vop_time_increment" did not change.  Overcome this error,
00584       // by pretending that it did change.
00585 #ifdef DEBUG
00586       fprintf(stderr, "Buggy MPEG-4 video stream: \"vop_time_increment\" did not change!\n");
00587 #endif
00588       // The following assumes that we don't have 'B' frames.  If we do, then TARFU!
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/*B*/
00594           && modulo_time_base == 0 && vop_time_increment == 0 && !fJustSawTimeCode) {
00595         // This is another kind of buggy MPEG-4 video stream, in which
00596         // "vop_time_increment" wraps around, but without
00597         // "modulo_time_base" changing (or just having had a new time code).
00598         // Overcome this by pretending that "vop_time_increment" *did* wrap around:
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/*B*/) {
00607         int pictureCountDelta = newTotalTicks - fTotalTicksSinceLastTimeCode;
00608         if (pictureCountDelta <= 0) pictureCountDelta = fPrevPictureCountDelta;
00609             // ensures that the picture count is always increasing
00610         usingSource()->fPictureCount += pictureCountDelta;
00611         fPrevPictureCountDelta = pictureCountDelta;
00612         fTotalTicksSinceLastTimeCode = newTotalTicks;
00613         fSecondsSinceLastTimeCode += modulo_time_base;
00614       }
00615     }
00616   }
00617   fJustSawTimeCode = False; // for next time
00618 
00619   // The next thing to parse depends on the code that we just saw,
00620   // but we are assumed to have ended the current picture:
00621   usingSource()->fPictureEndMarker = True; // HACK #####
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       // copy all bytes that we see, up until we reach a VOP_START_CODE:
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); // the safest way to recover...
00657     }
00658     break;
00659   }
00660   }
00661 
00662   // Compute this frame's presentation time:
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   // Note that we've already read the VISUAL_OBJECT_SEQUENCE_END_CODE
00673   save4Bytes(VISUAL_OBJECT_SEQUENCE_END_CODE);
00674 
00675   setParseState(PARSING_VISUAL_OBJECT_SEQUENCE);
00676 
00677   // Treat this as if we had ended a picture:
00678   usingSource()->fPictureEndMarker = True; // HACK #####
00679 
00680   return curFrameSize();
00681 }

Generated on Mon Apr 29 13:28:03 2013 for live by  doxygen 1.5.2