MatroskaFileParser Class Reference

#include <MatroskaFileParser.hh>

Inheritance diagram for MatroskaFileParser:

Inheritance graph
[legend]
Collaboration diagram for MatroskaFileParser:

Collaboration graph
[legend]

Public Member Functions

 MatroskaFileParser (MatroskaFile &ourFile, FramedSource *inputSource, FramedSource::onCloseFunc *onEndFunc, void *onEndClientData, MatroskaDemux *ourDemux=NULL)
virtual ~MatroskaFileParser ()
void seekToTime (double &seekNPT)
void continueParsing ()
virtual void flushInput ()

Static Public Member Functions

static void continueParsing (void *clientData, unsigned char *ptr, unsigned size, struct timeval presentationTime)

Protected Types

typedef void( clientContinueFunc )(void *clientData, unsigned char *ptr, unsigned size, struct timeval presentationTime)

Protected Member Functions

void saveParserState ()
u_int32_t get4Bytes ()
u_int32_t test4Bytes ()
u_int16_t get2Bytes ()
u_int8_t get1Byte ()
u_int8_t test1Byte ()
void getBytes (u_int8_t *to, unsigned numBytes)
void testBytes (u_int8_t *to, unsigned numBytes)
void skipBytes (unsigned numBytes)
void skipBits (unsigned numBits)
unsigned getBits (unsigned numBits)
unsigned curOffset () const
unsigned & totNumValidBytes ()
Boolean haveSeenEOF () const
unsigned bankSize () const

Private Member Functions

Boolean parse ()
Boolean parseStartOfFile ()
void lookForNextTrack ()
Boolean parseTrack ()
Boolean parseCues ()
void lookForNextBlock ()
void parseBlock ()
Boolean deliverFrameWithinBlock ()
void deliverFrameBytes ()
void getCommonFrameBytes (MatroskaTrack *track, u_int8_t *to, unsigned numBytesToGet, unsigned numBytesToSkip)
Boolean parseEBMLNumber (EBMLNumber &num)
Boolean parseEBMLIdAndSize (EBMLId &id, EBMLDataSize &size)
Boolean parseEBMLVal_unsigned64 (EBMLDataSize &size, u_int64_t &result)
Boolean parseEBMLVal_unsigned (EBMLDataSize &size, unsigned &result)
Boolean parseEBMLVal_float (EBMLDataSize &size, float &result)
Boolean parseEBMLVal_string (EBMLDataSize &size, char *&result)
Boolean parseEBMLVal_binary (EBMLDataSize &size, u_int8_t *&result)
void skipHeader (EBMLDataSize const &size)
void skipRemainingHeaderBytes (Boolean isContinuation)
void setParseState ()
void seekToFilePosition (u_int64_t offsetInFile)
void seekToEndOfFile ()
void resetStateAfterSeeking ()
virtual void restoreSavedParserState ()

Private Attributes

MatroskaFilefOurFile
FramedSourcefInputSource
FramedSource::onCloseFuncfOnEndFunc
void * fOnEndClientData
MatroskaDemuxfOurDemux
MatroskaParseState fCurrentParseState
u_int64_t fCurOffsetInFile
u_int64_t fSavedCurOffsetInFile
u_int64_t fLimitOffsetInFile
u_int64_t fNumHeaderBytesToSkip
EBMLId fLastSeekId
unsigned fClusterTimecode
unsigned fBlockSize
unsigned fBlockTrackNumber
short fBlockTimecode
unsigned fNumFramesInBlock
unsigned * fFrameSizesWithinBlock
double fPresentationTimeOffset
unsigned fNextFrameNumberToDeliver
unsigned fCurOffsetWithinFrame
unsigned fSavedCurOffsetWithinFrame
u_int8_t * fCurFrameTo
unsigned fCurFrameNumBytesToGet
unsigned fCurFrameNumBytesToSkip

Detailed Description

Definition at line 46 of file MatroskaFileParser.hh.


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

MatroskaFileParser::MatroskaFileParser ( MatroskaFile ourFile,
FramedSource inputSource,
FramedSource::onCloseFunc onEndFunc,
void *  onEndClientData,
MatroskaDemux ourDemux = NULL 
)

Definition at line 26 of file MatroskaFileParser.cpp.

References continueParsing(), fCurrentParseState, LOOKING_FOR_CLUSTER, NULL, and PARSING_START_OF_FILE.

00029   : StreamParser(inputSource, onEndFunc, onEndClientData, continueParsing, this),
00030     fOurFile(ourFile), fInputSource(inputSource),
00031     fOnEndFunc(onEndFunc), fOnEndClientData(onEndClientData),
00032     fOurDemux(ourDemux),
00033     fCurOffsetInFile(0), fSavedCurOffsetInFile(0), fLimitOffsetInFile(0),
00034     fNumHeaderBytesToSkip(0), fClusterTimecode(0), fBlockTimecode(0),
00035     fFrameSizesWithinBlock(NULL),
00036     fPresentationTimeOffset(0.0) {
00037   if (ourDemux == NULL) {
00038     // Initialization
00039     fCurrentParseState = PARSING_START_OF_FILE;
00040     continueParsing();
00041   } else {
00042     fCurrentParseState = LOOKING_FOR_CLUSTER;
00043     // In this case, parsing (of track data) doesn't start until a client starts reading from a track.
00044   }
00045 }

MatroskaFileParser::~MatroskaFileParser (  )  [virtual]

Definition at line 47 of file MatroskaFileParser.cpp.

References Medium::close(), fFrameSizesWithinBlock, and fInputSource.

00047                                         {
00048   delete[] fFrameSizesWithinBlock;
00049   Medium::close(fInputSource);
00050 }


Member Function Documentation

void MatroskaFileParser::seekToTime ( double &  seekNPT  ) 

Definition at line 52 of file MatroskaFileParser.cpp.

References fCurrentParseState, MatroskaFile::fileDuration(), fOurFile, LOOKING_FOR_BLOCK, MatroskaFile::lookupCuePoint(), seekToEndOfFile(), and seekToFilePosition().

Referenced by MatroskaDemux::seekToTime().

00052                                                    {
00053 #ifdef DEBUG
00054   fprintf(stderr, "seekToTime(%f)\n", seekNPT);
00055 #endif
00056   if (seekNPT <= 0.0) {
00057 #ifdef DEBUG
00058     fprintf(stderr, "\t=> start of file\n");
00059 #endif
00060     seekNPT = 0.0;
00061     seekToFilePosition(0);
00062   } else if (seekNPT >= fOurFile.fileDuration()) {
00063 #ifdef DEBUG
00064     fprintf(stderr, "\t=> end of file\n");
00065 #endif
00066     seekNPT = fOurFile.fileDuration();
00067     seekToEndOfFile();
00068   } else {
00069     u_int64_t clusterOffsetInFile;
00070     unsigned blockNumWithinCluster;
00071     if (!fOurFile.lookupCuePoint(seekNPT, clusterOffsetInFile, blockNumWithinCluster)) {
00072 #ifdef DEBUG
00073       fprintf(stderr, "\t=> not supported\n");
00074 #endif
00075       return; // seeking not supported
00076     }
00077 
00078 #ifdef DEBUG
00079     fprintf(stderr, "\t=> seek time %f, file position %llu, block number within cluster %d\n", seekNPT, clusterOffsetInFile, blockNumWithinCluster);
00080 #endif
00081     seekToFilePosition(clusterOffsetInFile);
00082     fCurrentParseState = LOOKING_FOR_BLOCK;
00083     // LATER handle "blockNumWithinCluster"; for now, we assume that it's 0 #####
00084   }
00085 }

void MatroskaFileParser::continueParsing ( void *  clientData,
unsigned char *  ptr,
unsigned  size,
struct timeval  presentationTime 
) [static]

Definition at line 88 of file MatroskaFileParser.cpp.

Referenced by MatroskaDemux::continueReading().

00088                                                                                                                   {
00089   ((MatroskaFileParser*)clientData)->continueParsing();
00090 }

void MatroskaFileParser::continueParsing (  ) 

Definition at line 92 of file MatroskaFileParser.cpp.

References fInputSource, fOnEndClientData, fOnEndFunc, FramedSource::isCurrentlyAwaitingData(), NULL, and parse().

Referenced by MatroskaFileParser().

00092                                          {
00093   if (fInputSource != NULL) {
00094     if (fInputSource->isCurrentlyAwaitingData()) return; // Our input source is currently being read. Wait until that read completes
00095 
00096     if (!parse()) {
00097       // We didn't complete the parsing, because we had to read more data from the source, or because we're waiting for
00098       // another read from downstream.  Once that happens, we'll get called again.
00099       return;
00100     }
00101   }
00102 
00103   // We successfully parsed the file.  Call our 'done' function now:
00104   if (fOnEndFunc != NULL) (*fOnEndFunc)(fOnEndClientData);
00105 }

Boolean MatroskaFileParser::parse (  )  [private]

Definition at line 107 of file MatroskaFileParser.cpp.

References deliverFrameBytes(), deliverFrameWithinBlock(), DELIVERING_FRAME_BYTES, DELIVERING_FRAME_WITHIN_BLOCK, False, MatroskaFile::fClusterOffset, MatroskaFile::fCuesOffset, fCurrentParseState, fOurFile, lookForNextBlock(), lookForNextTrack(), LOOKING_FOR_BLOCK, LOOKING_FOR_CLUSTER, LOOKING_FOR_TRACKS, parseBlock(), parseCues(), parseStartOfFile(), parseTrack(), PARSING_BLOCK, PARSING_CUES, PARSING_START_OF_FILE, PARSING_TRACK, seekToFilePosition(), skipRemainingHeaderBytes(), and True.

Referenced by continueParsing().

00107                                   {
00108   Boolean areDone = False;
00109 
00110   try {
00111     skipRemainingHeaderBytes(True); // if any
00112     do {
00113       switch (fCurrentParseState) {
00114         case PARSING_START_OF_FILE: {
00115           areDone = parseStartOfFile();
00116           break;
00117         }
00118         case LOOKING_FOR_TRACKS: {
00119           lookForNextTrack();
00120           break;
00121         }
00122         case PARSING_TRACK: {
00123           areDone = parseTrack();
00124           if (areDone && fOurFile.fCuesOffset > 0) {
00125             // We've finished parsing the 'Track' information.  There are also 'Cues' in the file, so parse those before finishing:
00126             // Seek to the specified position in the file.  We were already told that the 'Cues' begins there:
00127 #ifdef DEBUG
00128             fprintf(stderr, "Seeking to file position %llu (the previously-reported location of 'Cues')\n", fOurFile.fCuesOffset);
00129 #endif
00130             seekToFilePosition(fOurFile.fCuesOffset);
00131             fCurrentParseState = PARSING_CUES;
00132             areDone = False;
00133           }
00134           break;
00135         }
00136         case PARSING_CUES: {
00137           areDone = parseCues();
00138           break;
00139         }
00140         case LOOKING_FOR_CLUSTER: {
00141           if (fOurFile.fClusterOffset > 0) {
00142             // Optimization: Seek to the specified position in the file.  We were already told that the 'Cluster' begins there:
00143 #ifdef DEBUG
00144             fprintf(stderr, "Optimization: Seeking to file position %llu (the previously-reported location of a 'Cluster')\n", fOurFile.fClusterOffset);
00145 #endif
00146             seekToFilePosition(fOurFile.fClusterOffset);
00147           }
00148           fCurrentParseState = LOOKING_FOR_BLOCK;
00149           break;
00150         }
00151         case LOOKING_FOR_BLOCK: {
00152           lookForNextBlock();
00153           break;
00154         }
00155         case PARSING_BLOCK: {
00156           parseBlock();
00157           break;
00158         }
00159         case DELIVERING_FRAME_WITHIN_BLOCK: {
00160           if (!deliverFrameWithinBlock()) return False;
00161           break;
00162         }
00163         case DELIVERING_FRAME_BYTES: {
00164           deliverFrameBytes();
00165           return False; // Halt parsing for now.  A new 'read' from downstream will cause parsing to resume.
00166           break;
00167         }
00168       }
00169     } while (!areDone);
00170 
00171     return True;
00172   } catch (int /*e*/) {
00173 #ifdef DEBUG
00174     fprintf(stderr, "MatroskaFileParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
00175 #endif
00176     return False;  // the parsing got interrupted
00177   }
00178 }

Boolean MatroskaFileParser::parseStartOfFile (  )  [private]

Definition at line 180 of file MatroskaFileParser.cpp.

References Medium::envir(), False, fCurrentParseState, fOurFile, LOOKING_FOR_TRACKS, MATROSKA_ID_EBML, parseEBMLIdAndSize(), size, skipHeader(), and True.

Referenced by parse().

00180                                              {
00181 #ifdef DEBUG
00182   fprintf(stderr, "parsing start of file\n");
00183 #endif
00184   EBMLId id;
00185   EBMLDataSize size;
00186 
00187   // The file must begin with the standard EBML header (which we skip):
00188   if (!parseEBMLIdAndSize(id, size) || id != MATROSKA_ID_EBML) {
00189     fOurFile.envir() << "ERROR: File does not begin with an EBML header\n";
00190     return True; // We're done with the file, because it's not valid
00191   }
00192 #ifdef DEBUG
00193     fprintf(stderr, "MatroskaFileParser::parseStartOfFile(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val());
00194 #endif
00195 
00196   fCurrentParseState = LOOKING_FOR_TRACKS;
00197   skipHeader(size);
00198 
00199   return False; // because we have more parsing to do - inside the 'Track' header
00200 }

void MatroskaFileParser::lookForNextTrack (  )  [private]

Definition at line 202 of file MatroskaFileParser.cpp.

References MatroskaFile::fClusterOffset, MatroskaFile::fCuesOffset, fCurOffsetInFile, fCurrentParseState, fLastSeekId, fLimitOffsetInFile, fOurFile, MatroskaFile::fSegmentDataOffset, MatroskaFile::fSegmentDuration, MatroskaFile::fTimecodeScale, EBMLNumber::hexString(), LOOKING_FOR_TRACKS, MATROSKA_ID_CLUSTER, MATROSKA_ID_CUES, MATROSKA_ID_DURATION, MATROSKA_ID_INFO, MATROSKA_ID_SEEK, MATROSKA_ID_SEEK_HEAD, MATROSKA_ID_SEEK_ID, MATROSKA_ID_SEEK_POSITION, MATROSKA_ID_SEGMENT, MATROSKA_ID_TIMECODE_SCALE, MATROSKA_ID_TITLE, MATROSKA_ID_TRACKS, parseEBMLIdAndSize(), parseEBMLNumber(), parseEBMLVal_float(), parseEBMLVal_string(), parseEBMLVal_unsigned(), parseEBMLVal_unsigned64(), PARSING_TRACK, MatroskaFile::segmentDuration(), setParseState(), size, skipHeader(), EBMLId::stringName(), and MatroskaFile::timecodeScale().

Referenced by parse().

00202                                           {
00203 #ifdef DEBUG
00204   fprintf(stderr, "looking for Track\n");
00205 #endif
00206   EBMLId id;
00207   EBMLDataSize size;
00208 
00209   // Read and skip over (or enter) each Matroska header, until we get to a 'Track'.
00210   while (fCurrentParseState == LOOKING_FOR_TRACKS) {
00211     while (!parseEBMLIdAndSize(id, size)) {}
00212 #ifdef DEBUG
00213     fprintf(stderr, "MatroskaFileParser::lookForNextTrack(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val());
00214 #endif
00215     switch (id.val()) {
00216       case MATROSKA_ID_SEGMENT: { // 'Segment' header: enter this
00217         // Remember the position, within the file, of the start of Segment data, because Seek Positions are relative to this:
00218         fOurFile.fSegmentDataOffset = fCurOffsetInFile;
00219         break;
00220       }
00221       case MATROSKA_ID_SEEK_HEAD: { // 'Seek Head' header: enter this
00222         break;
00223       }
00224       case MATROSKA_ID_SEEK: { // 'Seek' header: enter this
00225         break;
00226       }
00227       case MATROSKA_ID_SEEK_ID: { // 'Seek ID' header: get this value
00228         if (parseEBMLNumber(fLastSeekId)) {
00229 #ifdef DEBUG
00230           fprintf(stderr, "\tSeek ID 0x%s:\t%s\n", fLastSeekId.hexString(), fLastSeekId.stringName());
00231 #endif
00232         }
00233         break;
00234       }
00235       case MATROSKA_ID_SEEK_POSITION: { // 'Seek Position' header: get this value
00236         u_int64_t seekPosition;
00237         if (parseEBMLVal_unsigned64(size, seekPosition)) {
00238           u_int64_t offsetInFile = fOurFile.fSegmentDataOffset + seekPosition;
00239 #ifdef DEBUG
00240           fprintf(stderr, "\tSeek Position %llu (=> offset within the file: %llu (0x%llx))\n", seekPosition, offsetInFile, offsetInFile);
00241 #endif
00242           // The only 'Seek Position's that we care about are for 'Cluster' and 'Cues':
00243           if (fLastSeekId == MATROSKA_ID_CLUSTER) {
00244             fOurFile.fClusterOffset = offsetInFile;
00245           } else if (fLastSeekId == MATROSKA_ID_CUES) {
00246             fOurFile.fCuesOffset = offsetInFile;
00247           }
00248         }
00249         break;
00250       }
00251       case MATROSKA_ID_INFO: { // 'Segment Info' header: enter this
00252         break;
00253       }
00254       case MATROSKA_ID_TIMECODE_SCALE: { // 'Timecode Scale' header: get this value
00255         unsigned timecodeScale;
00256         if (parseEBMLVal_unsigned(size, timecodeScale) && timecodeScale > 0) {
00257           fOurFile.fTimecodeScale = timecodeScale;
00258 #ifdef DEBUG
00259           fprintf(stderr, "\tTimecode Scale %u ns (=> Segment Duration == %f seconds)\n",
00260                   fOurFile.timecodeScale(), fOurFile.segmentDuration()*(fOurFile.fTimecodeScale/1000000000.0f));
00261 #endif
00262         }
00263         break;
00264       }
00265       case MATROSKA_ID_DURATION: { // 'Segment Duration' header: get this value
00266         if (parseEBMLVal_float(size, fOurFile.fSegmentDuration)) {
00267 #ifdef DEBUG
00268           fprintf(stderr, "\tSegment Duration %f (== %f seconds)\n",
00269                   fOurFile.segmentDuration(), fOurFile.segmentDuration()*(fOurFile.fTimecodeScale/1000000000.0f));
00270 #endif
00271         }
00272         break;
00273       }
00274 #ifdef DEBUG
00275       case MATROSKA_ID_TITLE: { // 'Segment Title': display this value
00276         char* title;
00277         if (parseEBMLVal_string(size, title)) {
00278 #ifdef DEBUG
00279           fprintf(stderr, "\tTitle: %s\n", title);
00280 #endif
00281           delete[] title;
00282         }
00283         break;
00284       }
00285 #endif
00286       case MATROSKA_ID_TRACKS: { // enter this, and move on to parsing 'Tracks'
00287         fLimitOffsetInFile = fCurOffsetInFile + size.val(); // Make sure we don't read past the end of this header
00288         fCurrentParseState = PARSING_TRACK;
00289         break;
00290       }
00291       default: { // skip over this header
00292         skipHeader(size);
00293         break;
00294       }
00295     }
00296     setParseState();
00297   }
00298 }

Boolean MatroskaFileParser::parseTrack (  )  [private]

Definition at line 300 of file MatroskaFileParser.cpp.

References MatroskaFile::addTrack(), MatroskaTrack::codecID, MatroskaTrack::codecIsOpus, MatroskaTrack::codecPrivate, MatroskaTrack::codecPrivateSize, MatroskaTrack::codecPrivateUsesH264FormatForH265, MatroskaTrack::defaultDuration, False, fCurOffsetInFile, fLimitOffsetInFile, fOurFile, MatroskaTrack::headerStrippedBytes, MatroskaTrack::headerStrippedBytesSize, MatroskaTrack::isDefault, MatroskaTrack::isEnabled, MatroskaTrack::isForced, MatroskaTrack::language, MATROSKA_ID_AUDIO, MATROSKA_ID_BIT_DEPTH, MATROSKA_ID_CHANNELS, MATROSKA_ID_CODEC, MATROSKA_ID_CODEC_PRIVATE, MATROSKA_ID_CONTENT_COMP_ALGO, MATROSKA_ID_CONTENT_COMP_SETTINGS, MATROSKA_ID_CONTENT_COMPRESSION, MATROSKA_ID_CONTENT_ENCODING, MATROSKA_ID_CONTENT_ENCODINGS, MATROSKA_ID_CONTENT_ENCRYPTION, MATROSKA_ID_DEFAULT_DURATION, MATROSKA_ID_DISPLAY_HEIGHT, MATROSKA_ID_DISPLAY_UNIT, MATROSKA_ID_DISPLAY_WIDTH, MATROSKA_ID_FLAG_DEFAULT, MATROSKA_ID_FLAG_ENABLED, MATROSKA_ID_FLAG_FORCED, MATROSKA_ID_LANGUAGE, MATROSKA_ID_MAX_BLOCK_ADDITION_ID, MATROSKA_ID_NAME, MATROSKA_ID_OUTPUT_SAMPLING_FREQUENCY, MATROSKA_ID_PIXEL_HEIGHT, MATROSKA_ID_PIXEL_WIDTH, MATROSKA_ID_SAMPLING_FREQUENCY, MATROSKA_ID_TRACK_ENTRY, MATROSKA_ID_TRACK_NUMBER, MATROSKA_ID_TRACK_TYPE, MATROSKA_ID_VIDEO, MATROSKA_TRACK_TYPE_AUDIO, MATROSKA_TRACK_TYPE_OTHER, MATROSKA_TRACK_TYPE_SUBTITLE, MATROSKA_TRACK_TYPE_VIDEO, MatroskaTrack::mimeType, MatroskaTrack::name, NULL, MatroskaTrack::numChannels, parseEBMLIdAndSize(), parseEBMLVal_binary(), parseEBMLVal_float(), parseEBMLVal_string(), parseEBMLVal_unsigned(), MatroskaTrack::samplingFrequency, setParseState(), size, skipHeader(), MatroskaTrack::subframeSizeSize, trackNumber, MatroskaTrack::trackNumber, MatroskaTrack::trackType, and True.

Referenced by parse().

00300                                        {
00301 #ifdef DEBUG
00302   fprintf(stderr, "parsing Track\n");
00303 #endif
00304   // Read and process each Matroska header, until we get to the end of the Track:
00305   MatroskaTrack* track = NULL;
00306   EBMLId id;
00307   EBMLDataSize size;
00308   while (fCurOffsetInFile < fLimitOffsetInFile) {
00309     while (!parseEBMLIdAndSize(id, size)) {}
00310 #ifdef DEBUG
00311     if (id == MATROSKA_ID_TRACK_ENTRY) fprintf(stderr, "\n"); // makes debugging output easier to read
00312     fprintf(stderr, "MatroskaFileParser::parseTrack(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val());
00313 #endif
00314     switch (id.val()) {
00315       case MATROSKA_ID_TRACK_ENTRY: { // 'Track Entry' header: enter this
00316         // Create a new "MatroskaTrack" object for this entry:
00317         if (track != NULL && track->trackNumber == 0) delete track; // We had a previous "MatroskaTrack" object that was never used
00318         track = new MatroskaTrack;
00319         break;
00320       }
00321       case MATROSKA_ID_TRACK_NUMBER: {
00322         unsigned trackNumber;
00323         if (parseEBMLVal_unsigned(size, trackNumber)) {
00324 #ifdef DEBUG
00325           fprintf(stderr, "\tTrack Number %d\n", trackNumber);
00326 #endif
00327           if (track != NULL && trackNumber != 0) {
00328             track->trackNumber = trackNumber;
00329             fOurFile.addTrack(track, trackNumber);
00330           }
00331         }
00332         break;
00333       }
00334       case MATROSKA_ID_TRACK_TYPE: {
00335         unsigned trackType;
00336         if (parseEBMLVal_unsigned(size, trackType) && track != NULL) {
00337           // We convert the Matroska 'track type' code into our own code (which we can use as a bitmap):
00338           track->trackType
00339             = trackType == 1 ? MATROSKA_TRACK_TYPE_VIDEO : trackType == 2 ? MATROSKA_TRACK_TYPE_AUDIO
00340             : trackType == 0x11 ? MATROSKA_TRACK_TYPE_SUBTITLE : MATROSKA_TRACK_TYPE_OTHER;
00341 #ifdef DEBUG
00342           fprintf(stderr, "\tTrack Type 0x%02x (%s)\n", trackType,
00343                   track->trackType == MATROSKA_TRACK_TYPE_VIDEO ? "video" :
00344                   track->trackType == MATROSKA_TRACK_TYPE_AUDIO ? "audio" :
00345                   track->trackType == MATROSKA_TRACK_TYPE_SUBTITLE ? "subtitle" :
00346                   "<other>");
00347 #endif
00348         }
00349         break;
00350       }
00351       case MATROSKA_ID_FLAG_ENABLED: {
00352         unsigned flagEnabled;
00353         if (parseEBMLVal_unsigned(size, flagEnabled)) {
00354 #ifdef DEBUG
00355           fprintf(stderr, "\tTrack is Enabled: %d\n", flagEnabled);
00356 #endif
00357           if (track != NULL) track->isEnabled = flagEnabled != 0;
00358         }
00359         break;
00360       }
00361       case MATROSKA_ID_FLAG_DEFAULT: {
00362         unsigned flagDefault;
00363         if (parseEBMLVal_unsigned(size, flagDefault)) {
00364 #ifdef DEBUG
00365           fprintf(stderr, "\tTrack is Default: %d\n", flagDefault);
00366 #endif
00367           if (track != NULL) track->isDefault = flagDefault != 0;
00368         }
00369         break;
00370       }
00371       case MATROSKA_ID_FLAG_FORCED: {
00372         unsigned flagForced;
00373         if (parseEBMLVal_unsigned(size, flagForced)) {
00374 #ifdef DEBUG
00375           fprintf(stderr, "\tTrack is Forced: %d\n", flagForced);
00376 #endif
00377           if (track != NULL) track->isForced = flagForced != 0;
00378         }
00379         break;
00380       }
00381       case MATROSKA_ID_DEFAULT_DURATION: {
00382         unsigned defaultDuration;
00383         if (parseEBMLVal_unsigned(size, defaultDuration)) {
00384 #ifdef DEBUG
00385           fprintf(stderr, "\tDefault duration %f ms\n", defaultDuration/1000000.0);
00386 #endif
00387           if (track != NULL) track->defaultDuration = defaultDuration;
00388         }
00389         break;
00390       }
00391       case MATROSKA_ID_MAX_BLOCK_ADDITION_ID: {
00392         unsigned maxBlockAdditionID;
00393         if (parseEBMLVal_unsigned(size, maxBlockAdditionID)) {
00394 #ifdef DEBUG
00395           fprintf(stderr, "\tMax Block Addition ID: %u\n", maxBlockAdditionID);
00396 #endif
00397         }
00398         break;
00399       }
00400       case MATROSKA_ID_NAME: {
00401         char* name;
00402         if (parseEBMLVal_string(size, name)) {
00403 #ifdef DEBUG
00404           fprintf(stderr, "\tName: %s\n", name);
00405 #endif
00406           if (track != NULL) {
00407             delete[] track->name; track->name = name;
00408           } else {
00409             delete[] name;
00410           }
00411         }
00412         break;
00413       }
00414       case MATROSKA_ID_LANGUAGE: {
00415         char* language;
00416         if (parseEBMLVal_string(size, language)) {
00417 #ifdef DEBUG
00418           fprintf(stderr, "\tLanguage: %s\n", language);
00419 #endif
00420           if (track != NULL) {
00421             delete[] track->language; track->language = language;
00422           } else {
00423             delete[] language;
00424           }
00425         }
00426         break;
00427       }
00428       case MATROSKA_ID_CODEC: {
00429         char* codecID;
00430         if (parseEBMLVal_string(size, codecID)) {
00431 #ifdef DEBUG
00432           fprintf(stderr, "\tCodec ID: %s\n", codecID);
00433 #endif
00434           if (track != NULL) {
00435             delete[] track->codecID; track->codecID = codecID;
00436 
00437             // Also set the track's "mimeType" field, if we can deduce it from the "codecID":
00438             if (strncmp(codecID, "A_MPEG", 6) == 0) {
00439               track->mimeType = "audio/MPEG";
00440             } else if (strncmp(codecID, "A_AAC", 5) == 0) {
00441               track->mimeType = "audio/AAC";
00442             } else if (strncmp(codecID, "A_AC3", 5) == 0) {
00443               track->mimeType = "audio/AC3";
00444             } else if (strncmp(codecID, "A_VORBIS", 8) == 0) {
00445               track->mimeType = "audio/VORBIS";
00446             } else if (strcmp(codecID, "A_OPUS") == 0) {
00447               track->mimeType = "audio/OPUS";
00448               track->codecIsOpus = True;
00449             } else if (strcmp(codecID, "V_MPEG4/ISO/AVC") == 0) {
00450               track->mimeType = "video/H264";
00451             } else if (strcmp(codecID, "V_MPEGH/ISO/HEVC") == 0) {
00452               track->mimeType = "video/H265";
00453             } else if (strncmp(codecID, "V_VP8", 5) == 0) {
00454               track->mimeType = "video/VP8";
00455             } else if (strncmp(codecID, "V_THEORA", 8) == 0) {
00456               track->mimeType = "video/THEORA";
00457             } else if (strncmp(codecID, "S_TEXT", 6) == 0) {
00458               track->mimeType = "text/T140";
00459             }
00460           } else {
00461             delete[] codecID;
00462           }
00463         }
00464         break;
00465       }
00466       case MATROSKA_ID_CODEC_PRIVATE: {
00467         u_int8_t* codecPrivate;
00468         unsigned codecPrivateSize;
00469         if (parseEBMLVal_binary(size, codecPrivate)) {
00470           codecPrivateSize = (unsigned)size.val();
00471 #ifdef DEBUG
00472           fprintf(stderr, "\tCodec Private: ");
00473           for (unsigned i = 0; i < codecPrivateSize; ++i) fprintf(stderr, "%02x:", codecPrivate[i]);
00474           fprintf(stderr, "\n");
00475 #endif
00476           if (track != NULL) {
00477             delete[] track->codecPrivate; track->codecPrivate = codecPrivate;
00478             track->codecPrivateSize = codecPrivateSize;
00479 
00480             // Hack for H.264 and H.265: The 'codec private' data contains
00481             // the size of NAL unit lengths:
00482             if (track->codecID != NULL) {
00483               if (strcmp(track->codecID, "V_MPEG4/ISO/AVC") == 0) { // H.264
00484                 // Byte 4 of the 'codec private' data contains 'lengthSizeMinusOne':
00485                 if (codecPrivateSize >= 5) track->subframeSizeSize = (codecPrivate[4])&0x3 + 1;
00486               } else if (strcmp(track->codecID, "V_MPEGH/ISO/HEVC") == 0) { // H.265
00487                 // H.265 'codec private' data is *supposed* to use the format that's described in
00488                 // http://lists.matroska.org/pipermail/matroska-devel/2013-September/004567.html
00489                 // However, some Matroska files use the same format that was used for H.264.
00490                 // We check for this here, by checking various fields that are supposed to be
00491                 // 'all-1' in the 'correct' format:
00492                 if (codecPrivateSize < 23 || (codecPrivate[13]&0xF0) != 0xF0 ||
00493                     (codecPrivate[15]&0xFC) != 0xFC || (codecPrivate[16]&0xFC) != 0xFC ||
00494                     (codecPrivate[17]&0xF8) != 0xF8 || (codecPrivate[18]&0xF8) != 0xF8) {
00495                   // The 'correct' format isn't being used, so assume the H.264 format instead:
00496                   track->codecPrivateUsesH264FormatForH265 = True;
00497                   
00498                   // Byte 4 of the 'codec private' data contains 'lengthSizeMinusOne':
00499                   if (codecPrivateSize >= 5) track->subframeSizeSize = (codecPrivate[4])&0x3 + 1;
00500                 } else {
00501                   // This looks like the 'correct' format:
00502                   track->codecPrivateUsesH264FormatForH265 = False;
00503 
00504                   // Byte 21 of the 'codec private' data contains 'lengthSizeMinusOne':
00505                   track->subframeSizeSize = (codecPrivate[21])&0x3 + 1;
00506                 }
00507               }
00508             }
00509           } else {
00510             delete[] codecPrivate;
00511           }
00512         }
00513         break;
00514       }
00515       case MATROSKA_ID_VIDEO: { // 'Video settings' header: enter this
00516         break;
00517       }
00518       case MATROSKA_ID_PIXEL_WIDTH: {
00519         unsigned pixelWidth;
00520         if (parseEBMLVal_unsigned(size, pixelWidth)) {
00521 #ifdef DEBUG
00522           fprintf(stderr, "\tPixel Width %d\n", pixelWidth);
00523 #endif
00524         }
00525         break;
00526       }
00527       case MATROSKA_ID_PIXEL_HEIGHT: {
00528         unsigned pixelHeight;
00529         if (parseEBMLVal_unsigned(size, pixelHeight)) {
00530 #ifdef DEBUG
00531           fprintf(stderr, "\tPixel Height %d\n", pixelHeight);
00532 #endif
00533         }
00534         break;
00535       }
00536       case MATROSKA_ID_DISPLAY_WIDTH: {
00537         unsigned displayWidth;
00538         if (parseEBMLVal_unsigned(size, displayWidth)) {
00539 #ifdef DEBUG
00540           fprintf(stderr, "\tDisplay Width %d\n", displayWidth);
00541 #endif
00542         }
00543         break;
00544       }
00545       case MATROSKA_ID_DISPLAY_HEIGHT: {
00546         unsigned displayHeight;
00547         if (parseEBMLVal_unsigned(size, displayHeight)) {
00548 #ifdef DEBUG
00549           fprintf(stderr, "\tDisplay Height %d\n", displayHeight);
00550 #endif
00551         }
00552         break;
00553       }
00554       case MATROSKA_ID_DISPLAY_UNIT: {
00555         unsigned displayUnit;
00556         if (parseEBMLVal_unsigned(size, displayUnit)) {
00557 #ifdef DEBUG
00558           fprintf(stderr, "\tDisplay Unit %d\n", displayUnit);
00559 #endif
00560         }
00561         break;
00562       }
00563       case MATROSKA_ID_AUDIO: { // 'Audio settings' header: enter this
00564         break;
00565       }
00566       case MATROSKA_ID_SAMPLING_FREQUENCY: {
00567         float samplingFrequency;
00568         if (parseEBMLVal_float(size, samplingFrequency)) {
00569           if (track != NULL) {
00570             track->samplingFrequency = (unsigned)samplingFrequency;
00571 #ifdef DEBUG
00572             fprintf(stderr, "\tSampling frequency %f (->%d)\n", samplingFrequency, track->samplingFrequency);
00573 #endif
00574           }
00575         }
00576         break;
00577       }
00578       case MATROSKA_ID_OUTPUT_SAMPLING_FREQUENCY: {
00579         float outputSamplingFrequency;
00580         if (parseEBMLVal_float(size, outputSamplingFrequency)) {
00581 #ifdef DEBUG
00582           fprintf(stderr, "\tOutput sampling frequency %f\n", outputSamplingFrequency);
00583 #endif
00584         }
00585         break;
00586       }
00587       case MATROSKA_ID_CHANNELS: {
00588         unsigned numChannels;
00589         if (parseEBMLVal_unsigned(size, numChannels)) {
00590 #ifdef DEBUG
00591           fprintf(stderr, "\tChannels %d\n", numChannels);
00592 #endif
00593           if (track != NULL) track->numChannels = numChannels;
00594         }
00595         break;
00596       }
00597       case MATROSKA_ID_BIT_DEPTH: {
00598         unsigned bitDepth;
00599         if (parseEBMLVal_unsigned(size, bitDepth)) {
00600 #ifdef DEBUG
00601           fprintf(stderr, "\tBit Depth %d\n", bitDepth);
00602 #endif
00603         }
00604         break;
00605       }
00606       case MATROSKA_ID_CONTENT_ENCODINGS:
00607       case MATROSKA_ID_CONTENT_ENCODING: { // 'Content Encodings' or 'Content Encoding' header: enter this
00608         break;
00609       }
00610       case MATROSKA_ID_CONTENT_COMPRESSION: { // 'Content Compression' header: enter this
00611         // Note: We currently support only 'Header Stripping' compression, not 'zlib' compression (the default algorithm).
00612         // Therefore, we disable this track, unless/until we later see that 'Header Stripping' is supported:
00613         if (track != NULL) track->isEnabled = False;
00614         break;
00615       }
00616       case MATROSKA_ID_CONTENT_COMP_ALGO: {
00617         unsigned contentCompAlgo;
00618         if (parseEBMLVal_unsigned(size, contentCompAlgo)) {
00619 #ifdef DEBUG
00620           fprintf(stderr, "\tContent Compression Algorithm %d (%s)\n", contentCompAlgo,
00621                   contentCompAlgo == 0 ? "zlib" : contentCompAlgo == 3 ? "Header Stripping" : "<unknown>");
00622 #endif
00623           // The only compression algorithm that we support is #3: Header Stripping; disable the track otherwise
00624           if (track != NULL) track->isEnabled = contentCompAlgo == 3;
00625         }
00626         break;
00627       }
00628       case MATROSKA_ID_CONTENT_COMP_SETTINGS: {
00629         u_int8_t* headerStrippedBytes;
00630         unsigned headerStrippedBytesSize;
00631         if (parseEBMLVal_binary(size, headerStrippedBytes)) {
00632           headerStrippedBytesSize = (unsigned)size.val();
00633 #ifdef DEBUG
00634           fprintf(stderr, "\tHeader Stripped Bytes: ");
00635           for (unsigned i = 0; i < headerStrippedBytesSize; ++i) fprintf(stderr, "%02x:", headerStrippedBytes[i]);
00636           fprintf(stderr, "\n");
00637 #endif
00638           if (track != NULL) {
00639             delete[] track->headerStrippedBytes; track->headerStrippedBytes = headerStrippedBytes;
00640             track->headerStrippedBytesSize = headerStrippedBytesSize;
00641           } else {
00642             delete[] headerStrippedBytes;
00643           }
00644         }
00645         break;
00646       }
00647       case MATROSKA_ID_CONTENT_ENCRYPTION: { // 'Content Encrpytion' header: skip this
00648         // Note: We don't currently support encryption at all.  Therefore, we disable this track:
00649         if (track != NULL) track->isEnabled = False;
00650         // Fall through to...
00651       }
00652       default: { // We don't process this header, so just skip over it:
00653         skipHeader(size);
00654         break;
00655       }
00656     }
00657     setParseState();
00658   }
00659 
00660   fLimitOffsetInFile = 0; // reset
00661   if (track != NULL && track->trackNumber == 0) delete track; // We had a previous "MatroskaTrack" object that was never used
00662   return True; // we're done parsing track entries
00663 }

Boolean MatroskaFileParser::parseCues (  )  [private]

Definition at line 769 of file MatroskaFileParser.cpp.

References MatroskaFile::addCuePoint(), fCurOffsetInFile, fLimitOffsetInFile, fOurFile, MatroskaFile::fSegmentDataOffset, MatroskaFile::fTimecodeScale, MATROSKA_ID_CUE_BLOCK_NUMBER, MATROSKA_ID_CUE_CLUSTER_POSITION, MATROSKA_ID_CUE_POINT, MATROSKA_ID_CUE_TIME, MATROSKA_ID_CUE_TRACK, MATROSKA_ID_CUE_TRACK_POSITIONS, MATROSKA_ID_CUES, parseEBMLIdAndSize(), parseEBMLVal_unsigned(), parseEBMLVal_unsigned64(), MatroskaFile::printCuePoints(), setParseState(), size, skipHeader(), and True.

Referenced by parse().

00769                                       {
00770 #if defined(DEBUG) || defined(DEBUG_CUES)
00771   fprintf(stderr, "parsing Cues\n");
00772 #endif
00773   EBMLId id;
00774   EBMLDataSize size;
00775 
00776   // Read the next header, which should be MATROSKA_ID_CUES:
00777   if (!parseEBMLIdAndSize(id, size) || id != MATROSKA_ID_CUES) return True; // The header wasn't what we expected, so we're done
00778   fLimitOffsetInFile = fCurOffsetInFile + size.val(); // Make sure we don't read past the end of this header
00779 
00780   double currentCueTime = 0.0;
00781   u_int64_t currentClusterOffsetInFile = 0;
00782 
00783   while (fCurOffsetInFile < fLimitOffsetInFile) {
00784     while (!parseEBMLIdAndSize(id, size)) {}
00785 #ifdef DEBUG_CUES
00786     if (id == MATROSKA_ID_CUE_POINT) fprintf(stderr, "\n"); // makes debugging output easier to read
00787     fprintf(stderr, "MatroskaFileParser::parseCues(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val());
00788 #endif
00789     switch (id.val()) {
00790       case MATROSKA_ID_CUE_POINT: { // 'Cue Point' header: enter this
00791         break;
00792       }
00793       case MATROSKA_ID_CUE_TIME: { // 'Cue Time' header: get this value
00794         unsigned cueTime;
00795         if (parseEBMLVal_unsigned(size, cueTime)) {
00796           currentCueTime = cueTime*(fOurFile.fTimecodeScale/1000000000.0);
00797 #ifdef DEBUG_CUES
00798           fprintf(stderr, "\tCue Time %d (== %f seconds)\n", cueTime, currentCueTime);
00799 #endif
00800         }
00801         break;
00802       }
00803       case MATROSKA_ID_CUE_TRACK_POSITIONS: { // 'Cue Track Positions' header: enter this
00804         break;
00805       }
00806       case MATROSKA_ID_CUE_TRACK: { // 'Cue Track' header: get this value (but only for debugging; we don't do anything with it)
00807         unsigned cueTrack;
00808         if (parseEBMLVal_unsigned(size, cueTrack)) {
00809 #ifdef DEBUG_CUES
00810           fprintf(stderr, "\tCue Track %d\n", cueTrack);
00811 #endif
00812         }
00813         break;
00814       }
00815       case MATROSKA_ID_CUE_CLUSTER_POSITION: { // 'Cue Cluster Position' header: get this value
00816         u_int64_t cueClusterPosition;
00817         if (parseEBMLVal_unsigned64(size, cueClusterPosition)) {
00818           currentClusterOffsetInFile = fOurFile.fSegmentDataOffset + cueClusterPosition;
00819 #ifdef DEBUG_CUES
00820           fprintf(stderr, "\tCue Cluster Position %llu (=> offset within the file: %llu (0x%llx))\n", cueClusterPosition, currentClusterOffsetInFile, currentClusterOffsetInFile);
00821 #endif
00822           // Record this cue point:
00823           fOurFile.addCuePoint(currentCueTime, currentClusterOffsetInFile, 1/*default block number within cluster*/);
00824         }
00825         break;
00826       }
00827       case MATROSKA_ID_CUE_BLOCK_NUMBER: { // 'Cue Block Number' header: get this value
00828         unsigned cueBlockNumber;
00829         if (parseEBMLVal_unsigned(size, cueBlockNumber) && cueBlockNumber != 0) {
00830 #ifdef DEBUG_CUES
00831           fprintf(stderr, "\tCue Block Number %d\n", cueBlockNumber);
00832 #endif
00833           // Record this cue point (overwriting any existing entry for this cue time):
00834           fOurFile.addCuePoint(currentCueTime, currentClusterOffsetInFile, cueBlockNumber);
00835         }
00836         break;
00837       }
00838       default: { // We don't process this header, so just skip over it:
00839         skipHeader(size);
00840         break;
00841       }
00842     }
00843     setParseState();
00844   }
00845 
00846   fLimitOffsetInFile = 0; // reset
00847 #if defined(DEBUG) || defined(DEBUG_CUES)
00848   fprintf(stderr, "done parsing Cues\n");
00849 #endif
00850 #ifdef DEBUG_CUES
00851   fprintf(stderr, "Cue Point tree: ");
00852   fOurFile.printCuePoints(stderr);
00853   fprintf(stderr, "\n");
00854 #endif
00855   return True; // we're done parsing Cues
00856 }

void MatroskaFileParser::lookForNextBlock (  )  [private]

Definition at line 665 of file MatroskaFileParser.cpp.

References fBlockSize, fClusterTimecode, fCurrentParseState, fOurFile, MatroskaFile::fTimecodeScale, LOOKING_FOR_BLOCK, MATROSKA_ID_ATTACHED_FILE, MATROSKA_ID_ATTACHMENTS, MATROSKA_ID_BLOCK, MATROSKA_ID_BLOCK_DURATION, MATROSKA_ID_BLOCK_GROUP, MATROSKA_ID_CLUSTER, MATROSKA_ID_FILE_DESCRIPTION, MATROSKA_ID_FILE_MIME_TYPE, MATROSKA_ID_FILE_NAME, MATROSKA_ID_FILE_UID, MATROSKA_ID_SEGMENT, MATROSKA_ID_SIMPLEBLOCK, MATROSKA_ID_TIMECODE, parseEBMLIdAndSize(), parseEBMLVal_string(), parseEBMLVal_unsigned(), PARSING_BLOCK, setParseState(), size, and skipHeader().

Referenced by parse().

00665                                           {
00666 #ifdef DEBUG
00667   fprintf(stderr, "looking for Block\n");
00668 #endif
00669   // Read and skip over each Matroska header, until we get to a 'Cluster':
00670   EBMLId id;
00671   EBMLDataSize size;
00672   while (fCurrentParseState == LOOKING_FOR_BLOCK) {
00673     while (!parseEBMLIdAndSize(id, size)) {}
00674 #ifdef DEBUG
00675     fprintf(stderr, "MatroskaFileParser::lookForNextBlock(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val());
00676 #endif
00677     switch (id.val()) {
00678       case MATROSKA_ID_SEGMENT: { // 'Segment' header: enter this
00679         break;
00680       }
00681       case MATROSKA_ID_CLUSTER: { // 'Cluster' header: enter this
00682         break;
00683       }
00684       case MATROSKA_ID_TIMECODE: { // 'Timecode' header: get this value
00685         unsigned timecode;
00686         if (parseEBMLVal_unsigned(size, timecode)) {
00687           fClusterTimecode = timecode;
00688 #ifdef DEBUG
00689           fprintf(stderr, "\tCluster timecode: %d (== %f seconds)\n", fClusterTimecode, fClusterTimecode*(fOurFile.fTimecodeScale/1000000000.0));
00690 #endif
00691         }
00692         break;
00693       }
00694       case MATROSKA_ID_BLOCK_GROUP: { // 'Block Group' header: enter this
00695         break;
00696       }
00697       case MATROSKA_ID_SIMPLEBLOCK:
00698       case MATROSKA_ID_BLOCK: { // 'SimpleBlock' or 'Block' header: enter this (and we're done)
00699         fBlockSize = (unsigned)size.val();
00700         fCurrentParseState = PARSING_BLOCK;
00701         break;
00702       }
00703       case MATROSKA_ID_BLOCK_DURATION: { // 'Block Duration' header: get this value (but we currently don't do anything with it)
00704         unsigned blockDuration;
00705         if (parseEBMLVal_unsigned(size, blockDuration)) {
00706 #ifdef DEBUG
00707           fprintf(stderr, "\tblock duration: %d (== %f ms)\n", blockDuration, (float)(blockDuration*fOurFile.fTimecodeScale/1000000.0));
00708 #endif
00709         }
00710         break;
00711       }
00712       // Attachments are parsed only if we're in DEBUG mode (otherwise we just skip over them):
00713 #ifdef DEBUG
00714       case MATROSKA_ID_ATTACHMENTS: { // 'Attachments': enter this
00715         break;
00716       }
00717       case MATROSKA_ID_ATTACHED_FILE: { // 'Attached File': enter this
00718         break;
00719       }
00720       case MATROSKA_ID_FILE_DESCRIPTION: { // 'File Description': get this value
00721         char* fileDescription;
00722         if (parseEBMLVal_string(size, fileDescription)) {
00723 #ifdef DEBUG
00724           fprintf(stderr, "\tFile Description: %s\n", fileDescription);
00725 #endif
00726           delete[] fileDescription;
00727         }
00728         break;
00729       }
00730       case MATROSKA_ID_FILE_NAME: { // 'File Name': get this value
00731         char* fileName;
00732         if (parseEBMLVal_string(size, fileName)) {
00733 #ifdef DEBUG
00734           fprintf(stderr, "\tFile Name: %s\n", fileName);
00735 #endif
00736           delete[] fileName;
00737         }
00738         break;
00739       }
00740       case MATROSKA_ID_FILE_MIME_TYPE: { // 'File MIME Type': get this value
00741         char* fileMIMEType;
00742         if (parseEBMLVal_string(size, fileMIMEType)) {
00743 #ifdef DEBUG
00744           fprintf(stderr, "\tFile MIME Type: %s\n", fileMIMEType);
00745 #endif
00746           delete[] fileMIMEType;
00747         }
00748         break;
00749       }
00750       case MATROSKA_ID_FILE_UID: { // 'File UID': get this value
00751         unsigned fileUID;
00752         if (parseEBMLVal_unsigned(size, fileUID)) {
00753 #ifdef DEBUG
00754           fprintf(stderr, "\tFile UID: 0x%x\n", fileUID);
00755 #endif
00756         }
00757         break;
00758       }
00759 #endif
00760       default: { // skip over this header
00761         skipHeader(size);
00762         break;
00763       }
00764     }
00765     setParseState();
00766   }
00767 }

void MatroskaFileParser::parseBlock (  )  [private]

Definition at line 860 of file MatroskaFileParser.cpp.

References StreamParser::curOffset(), DELIVERING_FRAME_WITHIN_BLOCK, EBMLLacing, fBlockSize, fBlockTimecode, fBlockTrackNumber, fClusterTimecode, fCurOffsetWithinFrame, fCurrentParseState, fFrameSizesWithinBlock, FixedSizeLacing, fNextFrameNumberToDeliver, fNumFramesInBlock, fOurDemux, fOurFile, frameSize, MatroskaFile::fTimecodeScale, StreamParser::get1Byte(), MatroskaTrack::headerStrippedBytesSize, LOOKING_FOR_BLOCK, MatroskaFile::lookup(), MatroskaDemux::lookupDemuxedTrack(), NoLacing, NULL, parseEBMLNumber(), setParseState(), StreamParser::skipBytes(), trackNumber, and XiphLacing.

Referenced by parse().

00860                                     {
00861 #ifdef DEBUG
00862   fprintf(stderr, "parsing SimpleBlock or Block\n");
00863 #endif
00864   do {
00865     unsigned blockStartPos = curOffset();
00866 
00867     // The block begins with the track number:
00868     EBMLNumber trackNumber;
00869     if (!parseEBMLNumber(trackNumber)) break;
00870     fBlockTrackNumber = (unsigned)trackNumber.val();
00871 
00872     // If this track is not being read, then skip the rest of this block, and look for another one:
00873     if (fOurDemux->lookupDemuxedTrack(fBlockTrackNumber) == NULL) {
00874       unsigned headerBytesSeen = curOffset() - blockStartPos;
00875       if (headerBytesSeen < fBlockSize) {
00876         skipBytes(fBlockSize - headerBytesSeen);
00877       }
00878 #ifdef DEBUG
00879       fprintf(stderr, "\tSkipped block for unused track number %d\n", fBlockTrackNumber);
00880 #endif
00881       fCurrentParseState = LOOKING_FOR_BLOCK;
00882       setParseState();
00883       return;
00884     }
00885 
00886     MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber);
00887     if (track == NULL) break; // shouldn't happen
00888 
00889     // The next two bytes are the block's timecode (relative to the cluster timecode)
00890     fBlockTimecode = (get1Byte()<<8)|get1Byte();
00891 
00892     // The next byte indicates the type of 'lacing' used:
00893     u_int8_t c = get1Byte();
00894     c &= 0x6; // we're interested in bits 5-6 only
00895     MatroskaLacingType lacingType = (c==0x0)?NoLacing : (c==0x02)?XiphLacing : (c==0x04)?FixedSizeLacing : EBMLLacing;
00896 #ifdef DEBUG
00897     fprintf(stderr, "\ttrack number %d, timecode %d (=> %f seconds), %s lacing\n", fBlockTrackNumber, fBlockTimecode, (fClusterTimecode+fBlockTimecode)*(fOurFile.fTimecodeScale/1000000000.0), (lacingType==NoLacing)?"no" : (lacingType==XiphLacing)?"Xiph" : (lacingType==FixedSizeLacing)?"fixed-size" : "EBML");
00898 #endif
00899 
00900     if (lacingType == NoLacing) {
00901       fNumFramesInBlock = 1;
00902     } else {
00903       // The next byte tells us how many frames are present in this block
00904       fNumFramesInBlock = get1Byte() + 1;
00905     }
00906     delete[] fFrameSizesWithinBlock; fFrameSizesWithinBlock = new unsigned[fNumFramesInBlock];
00907     if (fFrameSizesWithinBlock == NULL) break;
00908   
00909     if (lacingType == NoLacing) {
00910       unsigned headerBytesSeen = curOffset() - blockStartPos;
00911       if (headerBytesSeen > fBlockSize) break;
00912 
00913       fFrameSizesWithinBlock[0] = fBlockSize - headerBytesSeen;
00914     } else if (lacingType == FixedSizeLacing) {
00915       unsigned headerBytesSeen = curOffset() - blockStartPos;
00916       if (headerBytesSeen > fBlockSize) break;
00917 
00918       unsigned frameBytesAvailable = fBlockSize - headerBytesSeen;
00919       unsigned constantFrameSize = frameBytesAvailable/fNumFramesInBlock;
00920 
00921       for (unsigned i = 0; i < fNumFramesInBlock; ++i) {
00922         fFrameSizesWithinBlock[i] = constantFrameSize;
00923       }
00924       // If there are any bytes left over, assign them to the last frame:
00925       fFrameSizesWithinBlock[fNumFramesInBlock-1] += frameBytesAvailable%fNumFramesInBlock;
00926     } else { // EBML or Xiph lacing
00927       unsigned curFrameSize = 0;
00928       unsigned frameSizesTotal = 0;
00929       unsigned i;
00930 
00931       for (i = 0; i < fNumFramesInBlock-1; ++i) {
00932         if (lacingType == EBMLLacing) {
00933           EBMLNumber frameSize;
00934           if (!parseEBMLNumber(frameSize)) break;
00935           unsigned fsv = (unsigned)frameSize.val();
00936 
00937           if (i == 0) {
00938             curFrameSize = fsv;
00939           } else {
00940             // The value we read is a signed value, that's added to the previous frame size, to get the current frame size:
00941             unsigned toSubtract = (fsv>0xFFFFFF)?0x07FFFFFF : (fsv>0xFFFF)?0x0FFFFF : (fsv>0xFF)?0x1FFF : 0x3F;
00942             int fsv_signed = fsv - toSubtract;
00943             curFrameSize += fsv_signed;
00944             if ((int)curFrameSize < 0) break;
00945           }
00946         } else { // Xiph lacing
00947           curFrameSize = 0;
00948           u_int8_t c;
00949           do {
00950             c = get1Byte();
00951             curFrameSize += c;
00952           } while (c == 0xFF);
00953         }
00954         fFrameSizesWithinBlock[i] = curFrameSize;
00955         frameSizesTotal += curFrameSize;
00956       }
00957       if (i != fNumFramesInBlock-1) break; // an error occurred within the "for" loop
00958 
00959       // Compute the size of the final frame within the block (from the block's size, and the frame sizes already computed):)
00960       unsigned headerBytesSeen = curOffset() - blockStartPos;
00961       if (headerBytesSeen + frameSizesTotal > fBlockSize) break;
00962       fFrameSizesWithinBlock[i] = fBlockSize - (headerBytesSeen + frameSizesTotal);
00963     }
00964 
00965     // We're done parsing headers within the block, and (as a result) we now know the sizes of all frames within the block.
00966     // If we have 'stripped bytes' that are common to (the front of) all frames, then count them now:
00967     if (track->headerStrippedBytesSize != 0) {
00968       for (unsigned i = 0; i < fNumFramesInBlock; ++i) fFrameSizesWithinBlock[i] += track->headerStrippedBytesSize;
00969     }
00970 #ifdef DEBUG
00971     fprintf(stderr, "\tThis block contains %d frame(s); size(s):", fNumFramesInBlock);
00972     unsigned frameSizesTotal = 0;
00973     for (unsigned i = 0; i < fNumFramesInBlock; ++i) {
00974       fprintf(stderr, " %d", fFrameSizesWithinBlock[i]);
00975       frameSizesTotal += fFrameSizesWithinBlock[i];
00976     }
00977     if (fNumFramesInBlock > 1) fprintf(stderr, " (total: %u)", frameSizesTotal);
00978     fprintf(stderr, " bytes\n");
00979 #endif
00980     // Next, start delivering these frames:
00981     fCurrentParseState = DELIVERING_FRAME_WITHIN_BLOCK;
00982     fCurOffsetWithinFrame = fNextFrameNumberToDeliver = 0;
00983     setParseState();
00984     return;
00985   } while (0);
00986 
00987   // An error occurred.  Try to recover:
00988 #ifdef DEBUG
00989   fprintf(stderr, "parseBlock(): Error parsing data; trying to recover...\n");
00990 #endif
00991   fCurrentParseState = LOOKING_FOR_BLOCK;
00992 }

Boolean MatroskaFileParser::deliverFrameWithinBlock (  )  [private]

Definition at line 994 of file MatroskaFileParser.cpp.

References FramedSource::afterGetting(), MatroskaTrack::codecIsOpus, MatroskaTrack::codecPrivate, MatroskaTrack::codecPrivateSize, MatroskaTrack::defaultDuration, DELIVERING_FRAME_BYTES, MatroskaDemuxedTrack::durationImbalance(), MatroskaDemuxedTrack::durationInMicroseconds(), False, fBlockTimecode, fBlockTrackNumber, fClusterTimecode, fCurFrameNumBytesToGet, fCurOffsetWithinFrame, fCurrentParseState, fFrameSizesWithinBlock, fNextFrameNumberToDeliver, MatroskaDemuxedTrack::fOpusTrackNumber, fOurDemux, fOurFile, fPresentationTimeOffset, MatroskaDemuxedTrack::frameSize(), frameSize, MatroskaFile::fTimecodeScale, StreamParser::get1Byte(), getCommonFrameBytes(), MatroskaTrack::haveSubframes(), FramedSource::isCurrentlyAwaitingData(), LOOKING_FOR_BLOCK, MatroskaFile::lookup(), MatroskaDemux::lookupDemuxedTrack(), MatroskaDemuxedTrack::maxSize(), NULL, MatroskaDemuxedTrack::numTruncatedBytes(), MatroskaDemuxedTrack::presentationTime(), MatroskaDemuxedTrack::prevPresentationTime(), restoreSavedParserState(), setParseState(), MatroskaTrack::subframeSizeSize, MatroskaDemuxedTrack::to(), and True.

Referenced by parse().

00994                                                     {
00995 #ifdef DEBUG
00996   fprintf(stderr, "delivering frame within SimpleBlock or Block\n");
00997 #endif
00998   do {
00999     MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber);
01000     if (track == NULL) break; // shouldn't happen
01001 
01002     MatroskaDemuxedTrack* demuxedTrack = fOurDemux->lookupDemuxedTrack(fBlockTrackNumber);
01003     if (demuxedTrack == NULL) break; // shouldn't happen
01004     if (!demuxedTrack->isCurrentlyAwaitingData()) {
01005       // Someone has been reading this stream, but isn't right now.
01006       // We can't deliver this frame until he asks for it, so punt for now.
01007       // The next time he asks for a frame, he'll get it.
01008 #ifdef DEBUG
01009       fprintf(stderr, "\tdeferring delivery of frame #%d (%d bytes)", fNextFrameNumberToDeliver, fFrameSizesWithinBlock[fNextFrameNumberToDeliver]);
01010       if (track->haveSubframes()) fprintf(stderr, "[offset %d]", fCurOffsetWithinFrame);
01011       fprintf(stderr, "\n");
01012 #endif
01013       restoreSavedParserState(); // so we read from the beginning next time
01014       return False;
01015     }
01016 
01017     unsigned frameSize;
01018     u_int8_t const* specialFrameSource = NULL;
01019     u_int8_t const opusCommentHeader[16]
01020       = {'O','p','u','s','T','a','g','s', 0, 0, 0, 0, 0, 0, 0, 0};
01021     if (track->codecIsOpus && demuxedTrack->fOpusTrackNumber < 2) {
01022       // Special case for Opus audio.  The first frame (the 'configuration' header) comes from
01023       // the 'private data'.  The second frame (the 'comment' header) comes is synthesized by
01024       // us here:
01025       if (demuxedTrack->fOpusTrackNumber == 0) {
01026         specialFrameSource = track->codecPrivate;
01027         frameSize = track->codecPrivateSize;
01028       } else if (demuxedTrack->fOpusTrackNumber == 1) {
01029         specialFrameSource = opusCommentHeader;
01030         frameSize = sizeof opusCommentHeader;
01031       }
01032       ++demuxedTrack->fOpusTrackNumber;
01033     } else {
01034       frameSize = fFrameSizesWithinBlock[fNextFrameNumberToDeliver];
01035       if (track->haveSubframes()) {
01036         // The next "track->subframeSizeSize" bytes contain the length of a 'subframe':
01037         if (fCurOffsetWithinFrame + track->subframeSizeSize > frameSize) break; // sanity check
01038         unsigned subframeSize = 0;
01039         for (unsigned i = 0; i < track->subframeSizeSize; ++i) {
01040           u_int8_t c;
01041           getCommonFrameBytes(track, &c, 1, 0);
01042           if (fCurFrameNumBytesToGet > 0) { // it'll be 1
01043             c = get1Byte();
01044             ++fCurOffsetWithinFrame;
01045           }
01046           subframeSize = subframeSize*256 + c;
01047         }
01048         if (subframeSize == 0 || fCurOffsetWithinFrame + subframeSize > frameSize) break; // sanity check
01049         frameSize = subframeSize;
01050       }
01051     }
01052 
01053     // Compute the presentation time of this frame (from the cluster timecode, the block timecode, and the default duration):
01054     double pt = (fClusterTimecode+fBlockTimecode)*(fOurFile.fTimecodeScale/1000000000.0)
01055       + fNextFrameNumberToDeliver*(track->defaultDuration/1000000000.0);
01056     if (fPresentationTimeOffset == 0.0) {
01057       // This is the first time we've computed a presentation time.  Compute an offset to make the presentation times aligned
01058       // with 'wall clock' time:
01059       struct timeval timeNow;
01060       gettimeofday(&timeNow, NULL);
01061       double ptNow = timeNow.tv_sec + timeNow.tv_usec/1000000.0;
01062       fPresentationTimeOffset = ptNow - pt;
01063     }
01064     pt += fPresentationTimeOffset;
01065     struct timeval presentationTime;
01066     presentationTime.tv_sec = (unsigned)pt;
01067     presentationTime.tv_usec = (unsigned)((pt - presentationTime.tv_sec)*1000000);
01068     unsigned durationInMicroseconds;
01069     if (specialFrameSource != NULL) {
01070       durationInMicroseconds = 0;
01071     } else { // normal case
01072       durationInMicroseconds = track->defaultDuration/1000;
01073       if (track->haveSubframes()) {
01074         // If this is a 'subframe', use a duration of 0 instead (unless it's the last 'subframe'):
01075         if (fCurOffsetWithinFrame + frameSize + track->subframeSizeSize < fFrameSizesWithinBlock[fNextFrameNumberToDeliver]) {
01076           // There's room for at least one more subframe after this, so give this subframe a duration of 0
01077           durationInMicroseconds = 0;
01078         }
01079       }
01080     }
01081 
01082     if (track->defaultDuration == 0) {
01083       // Adjust the frame duration to keep the sum of frame durations aligned with presentation times.
01084       if (demuxedTrack->prevPresentationTime().tv_sec != 0) { // not the first time for this track
01085         demuxedTrack->durationImbalance()
01086           += (presentationTime.tv_sec - demuxedTrack->prevPresentationTime().tv_sec)*1000000
01087           + (presentationTime.tv_usec - demuxedTrack->prevPresentationTime().tv_usec);
01088       }
01089       int adjustment = 0;
01090       if (demuxedTrack->durationImbalance() > 0) {
01091         // The duration needs to be increased.
01092         int const adjustmentThreshold = 100000; // don't increase the duration by more than this amount (in case there's a mistake)
01093         adjustment = demuxedTrack->durationImbalance() > adjustmentThreshold
01094           ? adjustmentThreshold : demuxedTrack->durationImbalance();
01095       } else if (demuxedTrack->durationImbalance() < 0) {
01096         // The duration needs to be decreased.
01097         adjustment = (unsigned)(-demuxedTrack->durationImbalance()) < durationInMicroseconds
01098           ? demuxedTrack->durationImbalance() : -(int)durationInMicroseconds;
01099       }
01100       durationInMicroseconds += adjustment;
01101       demuxedTrack->durationImbalance() -= durationInMicroseconds; // for next time
01102       demuxedTrack->prevPresentationTime() = presentationTime; // for next time
01103     }
01104 
01105     demuxedTrack->presentationTime() = presentationTime;
01106     demuxedTrack->durationInMicroseconds() = durationInMicroseconds;
01107 
01108     // Deliver the next block now:
01109     if (frameSize > demuxedTrack->maxSize()) {
01110       demuxedTrack->numTruncatedBytes() = frameSize - demuxedTrack->maxSize();
01111       demuxedTrack->frameSize() = demuxedTrack->maxSize();
01112     } else { // normal case
01113       demuxedTrack->numTruncatedBytes() = 0;
01114       demuxedTrack->frameSize() = frameSize;
01115     }
01116     getCommonFrameBytes(track, demuxedTrack->to(), demuxedTrack->frameSize(), demuxedTrack->numTruncatedBytes());
01117 
01118     // Next, deliver (and/or skip) bytes from the input file:
01119     if (specialFrameSource != NULL) {
01120       memmove(demuxedTrack->to(), specialFrameSource, demuxedTrack->frameSize());
01121 #ifdef DEBUG
01122       fprintf(stderr, "\tdelivered special frame: %d bytes", demuxedTrack->frameSize());
01123       if (demuxedTrack->numTruncatedBytes() > 0) fprintf(stderr, " (%d bytes truncated)", demuxedTrack->numTruncatedBytes());
01124       fprintf(stderr, " @%u.%06u (%.06f from start); duration %u us\n", demuxedTrack->presentationTime().tv_sec, demuxedTrack->presentationTime().tv_usec, demuxedTrack->presentationTime().tv_sec+demuxedTrack->presentationTime().tv_usec/1000000.0-fPresentationTimeOffset, demuxedTrack->durationInMicroseconds());
01125 #endif
01126       setParseState();
01127       FramedSource::afterGetting(demuxedTrack); // completes delivery
01128     } else { // normal case
01129       fCurrentParseState = DELIVERING_FRAME_BYTES;
01130       setParseState();
01131     }
01132     return True;
01133   } while (0);
01134 
01135   // An error occurred.  Try to recover:
01136 #ifdef DEBUG
01137   fprintf(stderr, "deliverFrameWithinBlock(): Error parsing data; trying to recover...\n");
01138 #endif
01139   fCurrentParseState = LOOKING_FOR_BLOCK;
01140   return True;
01141 }

void MatroskaFileParser::deliverFrameBytes (  )  [private]

Definition at line 1143 of file MatroskaFileParser.cpp.

References FramedSource::afterGetting(), BANK_SIZE, StreamParser::bankSize(), DELIVERING_FRAME_WITHIN_BLOCK, MatroskaDemuxedTrack::durationInMicroseconds(), fBlockTrackNumber, fCurFrameNumBytesToGet, fCurFrameNumBytesToSkip, fCurFrameTo, fCurOffsetWithinFrame, fCurrentParseState, fFrameSizesWithinBlock, fNextFrameNumberToDeliver, fNumFramesInBlock, fOurDemux, fOurFile, fPresentationTimeOffset, MatroskaDemuxedTrack::frameSize(), StreamParser::getBytes(), MatroskaTrack::haveSubframes(), LOOKING_FOR_BLOCK, MatroskaFile::lookup(), MatroskaDemux::lookupDemuxedTrack(), NULL, MatroskaDemuxedTrack::numTruncatedBytes(), MatroskaDemuxedTrack::presentationTime(), setParseState(), StreamParser::skipBytes(), and MatroskaTrack::subframeSizeSize.

Referenced by parse().

01143                                            {
01144   do {
01145     MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber);
01146     if (track == NULL) break; // shouldn't happen
01147 
01148     MatroskaDemuxedTrack* demuxedTrack = fOurDemux->lookupDemuxedTrack(fBlockTrackNumber);
01149     if (demuxedTrack == NULL) break; // shouldn't happen
01150 
01151     unsigned const BANK_SIZE = bankSize();
01152     while (fCurFrameNumBytesToGet > 0) {
01153       // Hack: We can get no more than BANK_SIZE bytes at a time:
01154       unsigned numBytesToGet = fCurFrameNumBytesToGet > BANK_SIZE ? BANK_SIZE : fCurFrameNumBytesToGet;
01155       getBytes(fCurFrameTo, numBytesToGet);
01156       fCurFrameTo += numBytesToGet;
01157       fCurFrameNumBytesToGet -= numBytesToGet;
01158       fCurOffsetWithinFrame += numBytesToGet;
01159       setParseState();
01160     }
01161     while (fCurFrameNumBytesToSkip > 0) {
01162       // Hack: We can skip no more than BANK_SIZE bytes at a time:
01163       unsigned numBytesToSkip = fCurFrameNumBytesToSkip > BANK_SIZE ? BANK_SIZE : fCurFrameNumBytesToSkip;
01164       skipBytes(numBytesToSkip);
01165       fCurFrameNumBytesToSkip -= numBytesToSkip;
01166       fCurOffsetWithinFrame += numBytesToSkip;
01167       setParseState();
01168     }
01169 #ifdef DEBUG
01170     fprintf(stderr, "\tdelivered frame #%d: %d bytes", fNextFrameNumberToDeliver, demuxedTrack->frameSize());
01171     if (track->haveSubframes()) fprintf(stderr, "[offset %d]", fCurOffsetWithinFrame - track->subframeSizeSize - demuxedTrack->frameSize() - demuxedTrack->numTruncatedBytes());
01172     if (demuxedTrack->numTruncatedBytes() > 0) fprintf(stderr, " (%d bytes truncated)", demuxedTrack->numTruncatedBytes());
01173     fprintf(stderr, " @%u.%06u (%.06f from start); duration %u us\n", demuxedTrack->presentationTime().tv_sec, demuxedTrack->presentationTime().tv_usec, demuxedTrack->presentationTime().tv_sec+demuxedTrack->presentationTime().tv_usec/1000000.0-fPresentationTimeOffset, demuxedTrack->durationInMicroseconds());
01174 #endif
01175 
01176     if (!track->haveSubframes()
01177         || fCurOffsetWithinFrame + track->subframeSizeSize >= fFrameSizesWithinBlock[fNextFrameNumberToDeliver]) {
01178       // Either we don't have subframes, or there's no more room for another subframe => We're completely done with this frame now:
01179       ++fNextFrameNumberToDeliver;
01180       fCurOffsetWithinFrame = 0;
01181     }
01182     if (fNextFrameNumberToDeliver == fNumFramesInBlock) {
01183       // We've delivered all of the frames from this block.  Look for another block next:
01184       fCurrentParseState = LOOKING_FOR_BLOCK;
01185     } else {
01186       fCurrentParseState = DELIVERING_FRAME_WITHIN_BLOCK;
01187     }
01188 
01189     setParseState();
01190     FramedSource::afterGetting(demuxedTrack); // completes delivery
01191     return;
01192   } while (0);
01193 
01194   // An error occurred.  Try to recover:
01195 #ifdef DEBUG
01196   fprintf(stderr, "deliverFrameBytes(): Error parsing data; trying to recover...\n");
01197 #endif
01198   fCurrentParseState = LOOKING_FOR_BLOCK;
01199 }

void MatroskaFileParser::getCommonFrameBytes ( MatroskaTrack track,
u_int8_t *  to,
unsigned  numBytesToGet,
unsigned  numBytesToSkip 
) [private]

Definition at line 1202 of file MatroskaFileParser.cpp.

References fCurFrameNumBytesToGet, fCurFrameNumBytesToSkip, fCurFrameTo, fCurOffsetWithinFrame, MatroskaTrack::headerStrippedBytes, and MatroskaTrack::headerStrippedBytesSize.

Referenced by deliverFrameWithinBlock().

01202                                                                                                          {
01203   if (track->headerStrippedBytesSize > fCurOffsetWithinFrame) {
01204     // We have some common 'header stripped' bytes that remain to be prepended to the frame.  Use these first:
01205     unsigned numRemainingHeaderStrippedBytes = track->headerStrippedBytesSize - fCurOffsetWithinFrame;
01206     unsigned numHeaderStrippedBytesToGet;
01207     if (numBytesToGet <= numRemainingHeaderStrippedBytes) {
01208       numHeaderStrippedBytesToGet = numBytesToGet;
01209       numBytesToGet = 0;
01210       if (numBytesToGet + numBytesToSkip <= numRemainingHeaderStrippedBytes) {
01211         numBytesToSkip = 0;
01212       } else {
01213         numBytesToSkip = numBytesToGet + numBytesToSkip - numRemainingHeaderStrippedBytes;
01214       }
01215     } else {
01216       numHeaderStrippedBytesToGet = numRemainingHeaderStrippedBytes;
01217       numBytesToGet = numBytesToGet - numRemainingHeaderStrippedBytes;
01218     }
01219 
01220     if (numHeaderStrippedBytesToGet > 0) {
01221       memmove(to, &track->headerStrippedBytes[fCurOffsetWithinFrame], numHeaderStrippedBytesToGet);
01222       to += numHeaderStrippedBytesToGet;
01223       fCurOffsetWithinFrame += numHeaderStrippedBytesToGet;
01224     }
01225   }
01226 
01227   fCurFrameTo = to;
01228   fCurFrameNumBytesToGet = numBytesToGet;
01229   fCurFrameNumBytesToSkip = numBytesToSkip;
01230 }

Boolean MatroskaFileParser::parseEBMLNumber ( EBMLNumber num  )  [private]

Definition at line 1232 of file MatroskaFileParser.cpp.

References EBMLNumber::data, EBML_NUMBER_MAX_LEN, False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), EBMLNumber::len, setParseState(), EBMLNumber::stripLeading1, and True.

Referenced by lookForNextTrack(), parseBlock(), and parseEBMLIdAndSize().

01232                                                            {
01233   unsigned i;
01234   u_int8_t bitmask = 0x80;
01235   for (i = 0; i < EBML_NUMBER_MAX_LEN; ++i) {
01236     while (1) {
01237       if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) return False; // We've hit our pre-set limit
01238       num.data[i] = get1Byte();
01239       ++fCurOffsetInFile;
01240 
01241       // If we're looking for an id, skip any leading bytes that don't contain a '1' in the first 4 bits:
01242       if (i == 0/*we're a leading byte*/ && !num.stripLeading1/*we're looking for an id*/ && (num.data[i]&0xF0) == 0) {
01243         setParseState(); // ensures that we make forward progress if the parsing gets interrupted
01244         continue;
01245       }
01246       break;
01247     }
01248     if ((num.data[0]&bitmask) != 0) {
01249       // num[i] is the last byte of the id
01250       if (num.stripLeading1) num.data[0] &=~ bitmask;
01251       break;
01252     }
01253     bitmask >>= 1;
01254   }
01255   if (i == EBML_NUMBER_MAX_LEN) return False;
01256 
01257   num.len = i+1;
01258   return True;
01259 }

Boolean MatroskaFileParser::parseEBMLIdAndSize ( EBMLId id,
EBMLDataSize size 
) [private]

Definition at line 1261 of file MatroskaFileParser.cpp.

References parseEBMLNumber(), and size.

Referenced by lookForNextBlock(), lookForNextTrack(), parseCues(), parseStartOfFile(), and parseTrack().

01261                                                                              {
01262   return parseEBMLNumber(id) && parseEBMLNumber(size);
01263 }

Boolean MatroskaFileParser::parseEBMLVal_unsigned64 ( EBMLDataSize size,
u_int64_t &  result 
) [private]

Definition at line 1265 of file MatroskaFileParser.cpp.

References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), size, and True.

Referenced by lookForNextTrack(), parseCues(), parseEBMLVal_float(), and parseEBMLVal_unsigned().

01265                                                                                          {
01266   u_int64_t sv = size.val();
01267   if (sv > 8) return False; // size too large
01268 
01269   result = 0; // initially
01270   for (unsigned i = (unsigned)sv; i > 0; --i) {
01271     if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) return False; // We've hit our pre-set limit
01272 
01273     u_int8_t c = get1Byte();
01274     ++fCurOffsetInFile;
01275 
01276     result = result*256 + c;
01277   }
01278 
01279   return True;
01280 }

Boolean MatroskaFileParser::parseEBMLVal_unsigned ( EBMLDataSize size,
unsigned &  result 
) [private]

Definition at line 1282 of file MatroskaFileParser.cpp.

References False, parseEBMLVal_unsigned64(), size, and True.

Referenced by lookForNextBlock(), lookForNextTrack(), parseCues(), parseEBMLVal_float(), and parseTrack().

01282                                                                                       {
01283   if (size.val() > 4) return False; // size too large
01284 
01285   u_int64_t result64;
01286   if (!parseEBMLVal_unsigned64(size, result64)) return False;
01287 
01288   result = (unsigned)result64;
01289 
01290   return True;
01291 }

Boolean MatroskaFileParser::parseEBMLVal_float ( EBMLDataSize size,
float &  result 
) [private]

Definition at line 1293 of file MatroskaFileParser.cpp.

References False, parseEBMLVal_unsigned(), parseEBMLVal_unsigned64(), size, and True.

Referenced by lookForNextTrack(), and parseTrack().

01293                                                                                 {
01294   if (size.val() == 4) {
01295     // Normal case.  Read the value as if it were a 4-byte integer, then copy it to the 'float' result:
01296     unsigned resultAsUnsigned;
01297     if (!parseEBMLVal_unsigned(size, resultAsUnsigned)) return False;
01298 
01299     if (sizeof result != sizeof resultAsUnsigned) return False;
01300     memcpy(&result, &resultAsUnsigned, sizeof result);
01301     return True;
01302   } else if (size.val() == 8) {
01303     // Read the value as if it were an 8-byte integer, then copy it to a 'double', the convert that to the 'float' result:
01304     u_int64_t resultAsUnsigned64;
01305     if (!parseEBMLVal_unsigned64(size, resultAsUnsigned64)) return False;
01306 
01307     double resultDouble;
01308     if (sizeof resultDouble != sizeof resultAsUnsigned64) return False;
01309     memcpy(&resultDouble, &resultAsUnsigned64, sizeof resultDouble);
01310 
01311     result = (float)resultDouble;
01312     return True;
01313   } else {
01314     // Unworkable size
01315     return False;
01316   }
01317 }

Boolean MatroskaFileParser::parseEBMLVal_string ( EBMLDataSize size,
char *&  result 
) [private]

Definition at line 1319 of file MatroskaFileParser.cpp.

References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), NULL, size, and True.

Referenced by lookForNextBlock(), lookForNextTrack(), and parseTrack().

01319                                                                                  {
01320   unsigned resultLength = (unsigned)size.val();
01321   result = new char[resultLength + 1]; // allow for the trailing '\0'
01322   if (result == NULL) return False;
01323 
01324   char* p = result;
01325   unsigned i;
01326   for (i = 0; i < resultLength; ++i) {
01327     if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) break; // We've hit our pre-set limit
01328 
01329     u_int8_t c = get1Byte();
01330     ++fCurOffsetInFile;
01331 
01332     *p++ = c;
01333   }
01334   if (i < resultLength) { // an error occurred
01335     delete[] result;
01336     result = NULL;
01337     return False;
01338   }
01339   *p = '\0';
01340 
01341   return True;
01342 }

Boolean MatroskaFileParser::parseEBMLVal_binary ( EBMLDataSize size,
u_int8_t *&  result 
) [private]

Definition at line 1344 of file MatroskaFileParser.cpp.

References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), NULL, size, and True.

Referenced by parseTrack().

01344                                                                                      {
01345   unsigned resultLength = (unsigned)size.val();
01346   result = new u_int8_t[resultLength];
01347   if (result == NULL) return False;
01348 
01349   u_int8_t* p = result;
01350   unsigned i;
01351   for (i = 0; i < resultLength; ++i) {
01352     if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) break; // We've hit our pre-set limit
01353 
01354     u_int8_t c = get1Byte();
01355     ++fCurOffsetInFile;
01356 
01357     *p++ = c;
01358   }
01359   if (i < resultLength) { // an error occurred
01360     delete[] result;
01361     result = NULL;
01362     return False;
01363   }
01364 
01365   return True;
01366 }

void MatroskaFileParser::skipHeader ( EBMLDataSize const &  size  )  [private]

Definition at line 1368 of file MatroskaFileParser.cpp.

References False, fNumHeaderBytesToSkip, size, and skipRemainingHeaderBytes().

Referenced by lookForNextBlock(), lookForNextTrack(), parseCues(), parseStartOfFile(), and parseTrack().

01368                                                             {
01369   u_int64_t sv = (unsigned)size.val();
01370 #ifdef DEBUG
01371   fprintf(stderr, "\tskipping %llu bytes\n", sv);
01372 #endif
01373 
01374   fNumHeaderBytesToSkip = sv;
01375   skipRemainingHeaderBytes(False);
01376 }

void MatroskaFileParser::skipRemainingHeaderBytes ( Boolean  isContinuation  )  [private]

Definition at line 1378 of file MatroskaFileParser.cpp.

References StreamParser::bankSize(), fCurOffsetInFile, fNumHeaderBytesToSkip, setParseState(), and StreamParser::skipBytes().

Referenced by parse(), and skipHeader().

01378                                                                         {
01379   if (fNumHeaderBytesToSkip == 0) return; // common case
01380 
01381   // Hack: To avoid tripping into a parser 'internal error' if we try to skip an excessively large
01382   // distance, break up the skipping into manageable chunks, to ensure forward progress:
01383   unsigned const maxBytesToSkip = bankSize();
01384   while (fNumHeaderBytesToSkip > 0) {
01385     unsigned numBytesToSkipNow
01386       = fNumHeaderBytesToSkip < maxBytesToSkip ? (unsigned)fNumHeaderBytesToSkip : maxBytesToSkip;
01387     setParseState();
01388     skipBytes(numBytesToSkipNow);
01389 #ifdef DEBUG
01390     if (isContinuation || numBytesToSkipNow < fNumHeaderBytesToSkip) {
01391       fprintf(stderr, "\t\t(skipped %u bytes; %llu bytes remaining)\n",
01392               numBytesToSkipNow, fNumHeaderBytesToSkip - numBytesToSkipNow);
01393     }
01394 #endif
01395     fCurOffsetInFile += numBytesToSkipNow;
01396     fNumHeaderBytesToSkip -= numBytesToSkipNow;
01397   }
01398 }

void MatroskaFileParser::setParseState (  )  [private]

Definition at line 1400 of file MatroskaFileParser.cpp.

References fCurOffsetInFile, fCurOffsetWithinFrame, fSavedCurOffsetInFile, fSavedCurOffsetWithinFrame, and StreamParser::saveParserState().

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), lookForNextBlock(), lookForNextTrack(), parseBlock(), parseCues(), parseEBMLNumber(), parseTrack(), and skipRemainingHeaderBytes().

void MatroskaFileParser::seekToFilePosition ( u_int64_t  offsetInFile  )  [private]

Definition at line 1412 of file MatroskaFileParser.cpp.

References fInputSource, NULL, resetStateAfterSeeking(), and ByteStreamFileSource::seekToByteAbsolute().

Referenced by parse(), and seekToTime().

01412                                                                   {
01413   ByteStreamFileSource* fileSource = (ByteStreamFileSource*)fInputSource; // we know it's a "ByteStreamFileSource"
01414   if (fileSource != NULL) {
01415     fileSource->seekToByteAbsolute(offsetInFile);
01416     resetStateAfterSeeking();
01417   }
01418 }

void MatroskaFileParser::seekToEndOfFile (  )  [private]

Definition at line 1420 of file MatroskaFileParser.cpp.

References fInputSource, NULL, resetStateAfterSeeking(), and ByteStreamFileSource::seekToEnd().

Referenced by seekToTime().

01420                                          {
01421   ByteStreamFileSource* fileSource = (ByteStreamFileSource*)fInputSource; // we know it's a "ByteStreamFileSource"
01422   if (fileSource != NULL) {
01423     fileSource->seekToEnd();
01424     resetStateAfterSeeking();
01425   }
01426 }

void MatroskaFileParser::resetStateAfterSeeking (  )  [private]

Definition at line 1428 of file MatroskaFileParser.cpp.

References fCurOffsetInFile, fCurOffsetWithinFrame, StreamParser::flushInput(), fSavedCurOffsetInFile, and fSavedCurOffsetWithinFrame.

Referenced by seekToEndOfFile(), and seekToFilePosition().

01428                                                 {
01429   // Because we're resuming parsing after seeking to a new position in the file, reset the parser state:
01430   fCurOffsetInFile = fSavedCurOffsetInFile = 0;
01431   fCurOffsetWithinFrame = fSavedCurOffsetWithinFrame = 0;
01432   flushInput();
01433 }

void MatroskaFileParser::restoreSavedParserState (  )  [private, virtual]

Reimplemented from StreamParser.

Definition at line 1406 of file MatroskaFileParser.cpp.

References fCurOffsetInFile, fCurOffsetWithinFrame, fSavedCurOffsetInFile, fSavedCurOffsetWithinFrame, and StreamParser::restoreSavedParserState().

Referenced by deliverFrameWithinBlock().

void StreamParser::flushInput (  )  [virtual, inherited]

Reimplemented in H264or5VideoStreamParser, MPEG1or2VideoStreamParser, and MPEG4VideoStreamParser.

Definition at line 28 of file StreamParser.cpp.

References StreamParser::fCurParserIndex, StreamParser::fRemainingUnparsedBits, StreamParser::fSavedParserIndex, StreamParser::fSavedRemainingUnparsedBits, and StreamParser::fTotNumValidBytes.

Referenced by MPEGVideoStreamFramer::flushInput(), MPEG4VideoStreamParser::flushInput(), MPEG1or2VideoStreamParser::flushInput(), MPEG1or2Demux::flushInput(), MPEG1or2AudioStreamFramer::flushInput(), H264or5VideoStreamParser::flushInput(), AC3AudioStreamFramer::flushInput(), and resetStateAfterSeeking().

void StreamParser::saveParserState (  )  [protected, inherited]

Definition at line 58 of file StreamParser.cpp.

References StreamParser::fCurParserIndex, StreamParser::fRemainingUnparsedBits, StreamParser::fSavedParserIndex, and StreamParser::fSavedRemainingUnparsedBits.

Referenced by OggFileParser::deliverPacketWithinPage(), MPEG1or2AudioStreamParser::parse(), OggFileParser::parseAndDeliverPage(), AC3AudioStreamParser::parseFrame(), OggFileParser::parseStartOfPage(), MPEGVideoStreamParser::setParseState(), MPEGProgramStreamParser::setParseState(), setParseState(), and H263plusVideoStreamParser::setParseState().

u_int32_t StreamParser::get4Bytes (  )  [inline, protected, inherited]

Definition at line 46 of file StreamParser.hh.

References StreamParser::fCurParserIndex, StreamParser::fRemainingUnparsedBits, and StreamParser::test4Bytes().

Referenced by AC3AudioStreamParser::parseFrame(), MPEG1or2VideoStreamParser::parseGOPHeader(), MPEG4VideoStreamParser::parseGroupOfVideoObjectPlane(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), MPEG1or2VideoStreamParser::parsePictureHeader(), OggFileParser::parseStartOfPage(), MPEG4VideoStreamParser::parseVideoObjectLayer(), MPEG4VideoStreamParser::parseVideoObjectPlane(), MPEG1or2VideoStreamParser::parseVideoSequenceHeader(), MPEG4VideoStreamParser::parseVisualObject(), MPEG4VideoStreamParser::parseVisualObjectSequence(), MPEGVideoStreamParser::saveToNextCode(), and MPEGVideoStreamParser::skipToNextCode().

00046                         { // byte-aligned; returned in big-endian order
00047     u_int32_t result = test4Bytes();
00048     fCurParserIndex += 4;
00049     fRemainingUnparsedBits = 0;
00050 
00051     return result;
00052   }

u_int32_t StreamParser::test4Bytes (  )  [inline, protected, inherited]

Definition at line 53 of file StreamParser.hh.

References StreamParser::ensureValidBytes(), and StreamParser::nextToParse().

Referenced by StreamParser::get4Bytes(), StreamParser::getBits(), MPEG1or2AudioStreamParser::parse(), H264or5VideoStreamParser::parse(), AC3AudioStreamParser::parseFrame(), MPEG1or2VideoStreamParser::parseGOPHeader(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), OggFileParser::parseStartOfPage(), MPEGProgramStreamParser::parseSystemHeader(), MPEG1or2VideoStreamParser::parseVideoSequenceHeader(), and MPEG4VideoStreamParser::parseVisualObjectSequence().

00053                          { // as above, but doesn't advance ptr
00054     ensureValidBytes(4);
00055 
00056     unsigned char const* ptr = nextToParse();
00057     return (ptr[0]<<24)|(ptr[1]<<16)|(ptr[2]<<8)|ptr[3];
00058   }

u_int16_t StreamParser::get2Bytes (  )  [inline, protected, inherited]

Definition at line 60 of file StreamParser.hh.

References StreamParser::ensureValidBytes(), StreamParser::fCurParserIndex, StreamParser::fRemainingUnparsedBits, and StreamParser::nextToParse().

Referenced by MPEGProgramStreamParser::parsePESPacket(), and MPEGProgramStreamParser::parseSystemHeader().

00060                         {
00061     ensureValidBytes(2);
00062 
00063     unsigned char const* ptr = nextToParse();
00064     u_int16_t result = (ptr[0]<<8)|ptr[1];
00065 
00066     fCurParserIndex += 2;
00067     fRemainingUnparsedBits = 0;
00068 
00069     return result;
00070   }

u_int8_t StreamParser::get1Byte (  )  [inline, protected, inherited]

Definition at line 72 of file StreamParser.hh.

References StreamParser::curBank(), StreamParser::ensureValidBytes(), StreamParser::fCurParserIndex, and StreamParser::fRemainingUnparsedBits.

Referenced by deliverFrameWithinBlock(), H264or5VideoStreamParser::parse(), parseBlock(), parseEBMLNumber(), parseEBMLVal_binary(), parseEBMLVal_string(), parseEBMLVal_unsigned64(), MPEG1or2VideoStreamParser::parseGOPHeader(), H263plusVideoStreamParser::parseH263Frame(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), OggFileParser::parseStartOfPage(), MPEG4VideoStreamParser::parseVideoObjectPlane(), MPEG1or2VideoStreamParser::parseVideoSequenceHeader(), MPEG4VideoStreamParser::parseVisualObject(), MPEG4VideoStreamParser::parseVisualObjectSequence(), MPEGVideoStreamParser::saveToNextCode(), and MPEGVideoStreamParser::skipToNextCode().

00072                       { // byte-aligned
00073     ensureValidBytes(1);
00074     fRemainingUnparsedBits = 0;
00075     return curBank()[fCurParserIndex++];
00076   }

u_int8_t StreamParser::test1Byte (  )  [inline, protected, inherited]

Definition at line 77 of file StreamParser.hh.

References StreamParser::ensureValidBytes(), and StreamParser::nextToParse().

00077                        { // as above, but doesn't advance ptr
00078     ensureValidBytes(1);
00079     return nextToParse()[0];
00080   }

void StreamParser::getBytes ( u_int8_t *  to,
unsigned  numBytes 
) [inline, protected, inherited]

Definition at line 82 of file StreamParser.hh.

References StreamParser::fCurParserIndex, StreamParser::fRemainingUnparsedBits, and StreamParser::testBytes().

Referenced by deliverFrameBytes(), OggFileParser::deliverPacketWithinPage(), MPEG1or2AudioStreamParser::parse(), AC3AudioStreamParser::parseFrame(), MPEG4VideoStreamParser::parseGroupOfVideoObjectPlane(), H263plusVideoStreamParser::parseH263Frame(), OggFileParser::parseInitialPage(), and MPEGProgramStreamParser::parsePESPacket().

00082                                                  {
00083     testBytes(to, numBytes);
00084     fCurParserIndex += numBytes;
00085     fRemainingUnparsedBits = 0;
00086   }

void StreamParser::testBytes ( u_int8_t *  to,
unsigned  numBytes 
) [inline, protected, inherited]

Definition at line 87 of file StreamParser.hh.

References StreamParser::ensureValidBytes(), and StreamParser::nextToParse().

Referenced by StreamParser::getBytes(), H264or5VideoStreamParser::parse(), and OggFileParser::parseInitialPage().

00087                                                   { // as above, but doesn't advance ptr
00088     ensureValidBytes(numBytes);
00089     memmove(to, nextToParse(), numBytes);
00090   }

void StreamParser::skipBytes ( unsigned  numBytes  )  [inline, protected, inherited]

Definition at line 91 of file StreamParser.hh.

References StreamParser::ensureValidBytes(), and StreamParser::fCurParserIndex.

Referenced by deliverFrameBytes(), MPEG1or2AudioStreamParser::parse(), H264or5VideoStreamParser::parse(), OggFileParser::parseAndDeliverPage(), parseBlock(), AC3AudioStreamParser::parseFrame(), OggFileParser::parseInitialPage(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), OggFileParser::parseStartOfPage(), MPEGProgramStreamParser::parseSystemHeader(), and skipRemainingHeaderBytes().

00091                                     {
00092     ensureValidBytes(numBytes);
00093     fCurParserIndex += numBytes;
00094   }

void StreamParser::skipBits ( unsigned  numBits  )  [protected, inherited]

Definition at line 68 of file StreamParser.cpp.

References StreamParser::ensureValidBytes(), StreamParser::fCurParserIndex, and StreamParser::fRemainingUnparsedBits.

Referenced by MPEGProgramStreamParser::parsePackHeader().

00068                                             {
00069   if (numBits <= fRemainingUnparsedBits) {
00070     fRemainingUnparsedBits -= numBits;
00071   } else {
00072     numBits -= fRemainingUnparsedBits;
00073 
00074     unsigned numBytesToExamine = (numBits+7)/8; // round up
00075     ensureValidBytes(numBytesToExamine);
00076     fCurParserIndex += numBytesToExamine;
00077 
00078     fRemainingUnparsedBits = 8*numBytesToExamine - numBits;
00079   }
00080 }

unsigned StreamParser::getBits ( unsigned  numBits  )  [protected, inherited]

Definition at line 82 of file StreamParser.cpp.

References StreamParser::fCurParserIndex, StreamParser::fRemainingUnparsedBits, StreamParser::lastParsed(), and StreamParser::test4Bytes().

Referenced by LEBitVector::getBits(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), and LEBitVector::skipBits().

00082                                                {
00083   if (numBits <= fRemainingUnparsedBits) {
00084     unsigned char lastByte = *lastParsed();
00085     lastByte >>= (fRemainingUnparsedBits - numBits);
00086     fRemainingUnparsedBits -= numBits;
00087 
00088     return (unsigned)lastByte &~ ((~0u)<<numBits);
00089   } else {
00090     unsigned char lastByte;
00091     if (fRemainingUnparsedBits > 0) {
00092       lastByte = *lastParsed();
00093     } else {
00094       lastByte = 0;
00095     }
00096 
00097     unsigned remainingBits = numBits - fRemainingUnparsedBits; // > 0
00098 
00099     // For simplicity, read the next 4 bytes, even though we might not
00100     // need all of them here:
00101     unsigned result = test4Bytes();
00102 
00103     result >>= (32 - remainingBits);
00104     result |= (lastByte << remainingBits);
00105     if (numBits < 32) result &=~ ((~0u)<<numBits);
00106 
00107     unsigned const numRemainingBytes = (remainingBits+7)/8;
00108     fCurParserIndex += numRemainingBytes;
00109     fRemainingUnparsedBits = 8*numRemainingBytes - remainingBits;
00110 
00111     return result;
00112   }
00113 }

unsigned StreamParser::curOffset (  )  const [inline, protected, inherited]

Definition at line 100 of file StreamParser.hh.

References StreamParser::fCurParserIndex.

Referenced by H264or5VideoStreamParser::parse(), parseBlock(), and MPEGProgramStreamParser::parsePESPacket().

00100 { return fCurParserIndex; }

unsigned& StreamParser::totNumValidBytes (  )  [inline, protected, inherited]

Definition at line 102 of file StreamParser.hh.

References StreamParser::fTotNumValidBytes.

Referenced by H264or5VideoStreamParser::parse(), and AC3AudioStreamParser::testStreamCode().

00102 { return fTotNumValidBytes; }

Boolean StreamParser::haveSeenEOF (  )  const [inline, protected, inherited]

Definition at line 104 of file StreamParser.hh.

References StreamParser::fHaveSeenEOF.

Referenced by H264or5VideoStreamParser::parse().

00104 { return fHaveSeenEOF; }

unsigned StreamParser::bankSize (  )  const [protected, inherited]

Definition at line 115 of file StreamParser.cpp.

References BANK_SIZE.

Referenced by deliverFrameBytes(), and skipRemainingHeaderBytes().

00115                                       {
00116   return BANK_SIZE;
00117 }


Field Documentation

MatroskaFile& MatroskaFileParser::fOurFile [private]

Definition at line 99 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), lookForNextBlock(), lookForNextTrack(), parse(), parseBlock(), parseCues(), parseStartOfFile(), parseTrack(), and seekToTime().

FramedSource* MatroskaFileParser::fInputSource [private]

Reimplemented from StreamParser.

Definition at line 100 of file MatroskaFileParser.hh.

Referenced by continueParsing(), seekToEndOfFile(), seekToFilePosition(), and ~MatroskaFileParser().

FramedSource::onCloseFunc* MatroskaFileParser::fOnEndFunc [private]

Definition at line 101 of file MatroskaFileParser.hh.

Referenced by continueParsing().

void* MatroskaFileParser::fOnEndClientData [private]

Definition at line 102 of file MatroskaFileParser.hh.

Referenced by continueParsing().

MatroskaDemux* MatroskaFileParser::fOurDemux [private]

Definition at line 103 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and parseBlock().

MatroskaParseState MatroskaFileParser::fCurrentParseState [private]

Definition at line 104 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), lookForNextBlock(), lookForNextTrack(), MatroskaFileParser(), parse(), parseBlock(), parseStartOfFile(), and seekToTime().

u_int64_t MatroskaFileParser::fCurOffsetInFile [private]

Definition at line 105 of file MatroskaFileParser.hh.

Referenced by lookForNextTrack(), parseCues(), parseEBMLNumber(), parseEBMLVal_binary(), parseEBMLVal_string(), parseEBMLVal_unsigned64(), parseTrack(), resetStateAfterSeeking(), restoreSavedParserState(), setParseState(), and skipRemainingHeaderBytes().

u_int64_t MatroskaFileParser::fSavedCurOffsetInFile [private]

Definition at line 105 of file MatroskaFileParser.hh.

Referenced by resetStateAfterSeeking(), restoreSavedParserState(), and setParseState().

u_int64_t MatroskaFileParser::fLimitOffsetInFile [private]

Definition at line 105 of file MatroskaFileParser.hh.

Referenced by lookForNextTrack(), parseCues(), parseEBMLNumber(), parseEBMLVal_binary(), parseEBMLVal_string(), parseEBMLVal_unsigned64(), and parseTrack().

u_int64_t MatroskaFileParser::fNumHeaderBytesToSkip [private]

Definition at line 108 of file MatroskaFileParser.hh.

Referenced by skipHeader(), and skipRemainingHeaderBytes().

EBMLId MatroskaFileParser::fLastSeekId [private]

Definition at line 111 of file MatroskaFileParser.hh.

Referenced by lookForNextTrack().

unsigned MatroskaFileParser::fClusterTimecode [private]

Definition at line 114 of file MatroskaFileParser.hh.

Referenced by deliverFrameWithinBlock(), lookForNextBlock(), and parseBlock().

unsigned MatroskaFileParser::fBlockSize [private]

Definition at line 117 of file MatroskaFileParser.hh.

Referenced by lookForNextBlock(), and parseBlock().

unsigned MatroskaFileParser::fBlockTrackNumber [private]

Definition at line 118 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and parseBlock().

short MatroskaFileParser::fBlockTimecode [private]

Definition at line 119 of file MatroskaFileParser.hh.

Referenced by deliverFrameWithinBlock(), and parseBlock().

unsigned MatroskaFileParser::fNumFramesInBlock [private]

Definition at line 120 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), and parseBlock().

unsigned* MatroskaFileParser::fFrameSizesWithinBlock [private]

Definition at line 121 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), parseBlock(), and ~MatroskaFileParser().

double MatroskaFileParser::fPresentationTimeOffset [private]

Definition at line 124 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), and deliverFrameWithinBlock().

unsigned MatroskaFileParser::fNextFrameNumberToDeliver [private]

Definition at line 125 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and parseBlock().

unsigned MatroskaFileParser::fCurOffsetWithinFrame [private]

Definition at line 126 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), getCommonFrameBytes(), parseBlock(), resetStateAfterSeeking(), restoreSavedParserState(), and setParseState().

unsigned MatroskaFileParser::fSavedCurOffsetWithinFrame [private]

Definition at line 126 of file MatroskaFileParser.hh.

Referenced by resetStateAfterSeeking(), restoreSavedParserState(), and setParseState().

u_int8_t* MatroskaFileParser::fCurFrameTo [private]

Definition at line 129 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), and getCommonFrameBytes().

unsigned MatroskaFileParser::fCurFrameNumBytesToGet [private]

Definition at line 130 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and getCommonFrameBytes().

unsigned MatroskaFileParser::fCurFrameNumBytesToSkip [private]

Definition at line 131 of file MatroskaFileParser.hh.

Referenced by deliverFrameBytes(), and getCommonFrameBytes().


The documentation for this class was generated from the following files:
Generated on Tue Mar 25 14:39:48 2014 for live by  doxygen 1.5.2