MPEG4VideoStreamParser Class Reference

Inheritance diagram for MPEG4VideoStreamParser:

Inheritance graph
[legend]
Collaboration diagram for MPEG4VideoStreamParser:

Collaboration graph
[legend]

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

MPEGVideoStreamFramerfUsingSource
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 ()
MPEG4VideoStreamFramerusingSource ()
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

Detailed Description

Definition at line 43 of file MPEG4VideoStreamFramer.cpp.


Member Typedef Documentation

typedef void( StreamParser::clientContinueFunc)(void *clientData, unsigned char *ptr, unsigned size, struct timeval presentationTime) [protected, inherited]

Definition at line 33 of file StreamParser.hh.


Constructor & Destructor Documentation

MPEG4VideoStreamParser::MPEG4VideoStreamParser ( MPEG4VideoStreamFramer usingSource,
FramedSource inputSource 
)

Definition at line 151 of file MPEG4VideoStreamFramer.cpp.

MPEG4VideoStreamParser::~MPEG4VideoStreamParser (  )  [virtual]

Definition at line 161 of file MPEG4VideoStreamFramer.cpp.

00161                                                 {
00162 }


Member Function Documentation

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