#include <MatroskaFileParser.hh>
Inheritance diagram for MatroskaFileParser:


Definition at line 46 of file MatroskaFileParser.hh.
typedef void( StreamParser::clientContinueFunc)(void *clientData, unsigned char *ptr, unsigned size, struct timeval presentationTime) [protected, inherited] |
Definition at line 33 of file StreamParser.hh.
| 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 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 }
| 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's 'Track' headers. 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(), and True.
Referenced by continueParsing().
00107 { 00108 Boolean areDone = False; 00109 00110 try { 00111 do { 00112 switch (fCurrentParseState) { 00113 case PARSING_START_OF_FILE: { 00114 areDone = parseStartOfFile(); 00115 break; 00116 } 00117 case LOOKING_FOR_TRACKS: { 00118 lookForNextTrack(); 00119 break; 00120 } 00121 case PARSING_TRACK: { 00122 areDone = parseTrack(); 00123 if (areDone && fOurFile.fCuesOffset > 0) { 00124 // We've finished parsing the 'Track' information. There are also 'Cues' in the file, so parse those before finishing: 00125 // Seek to the specified position in the file. We were already told that the 'Cues' begins there: 00126 #ifdef DEBUG 00127 fprintf(stderr, "Seeking to file position %llu (the previously-reported location of 'Cues')\n", fOurFile.fCuesOffset); 00128 #endif 00129 seekToFilePosition(fOurFile.fCuesOffset); 00130 fCurrentParseState = PARSING_CUES; 00131 areDone = False; 00132 } 00133 break; 00134 } 00135 case PARSING_CUES: { 00136 areDone = parseCues(); 00137 break; 00138 } 00139 case LOOKING_FOR_CLUSTER: { 00140 if (fOurFile.fClusterOffset > 0) { 00141 // Optimization: Seek to the specified position in the file. We were already told that the 'Cluster' begins there: 00142 #ifdef DEBUG 00143 fprintf(stderr, "Optimization: Seeking to file position %llu (the previously-reported location of a 'Cluster')\n", fOurFile.fClusterOffset); 00144 #endif 00145 seekToFilePosition(fOurFile.fClusterOffset); 00146 } 00147 fCurrentParseState = LOOKING_FOR_BLOCK; 00148 break; 00149 } 00150 case LOOKING_FOR_BLOCK: { 00151 lookForNextBlock(); 00152 break; 00153 } 00154 case PARSING_BLOCK: { 00155 parseBlock(); 00156 break; 00157 } 00158 case DELIVERING_FRAME_WITHIN_BLOCK: { 00159 if (!deliverFrameWithinBlock()) return False; 00160 break; 00161 } 00162 case DELIVERING_FRAME_BYTES: { 00163 deliverFrameBytes(); 00164 return False; // Halt parsing for now. A new 'read' from downstream will cause parsing to resume. 00165 break; 00166 } 00167 } 00168 } while (!areDone); 00169 00170 return True; 00171 } catch (int /*e*/) { 00172 #ifdef DEBUG 00173 fprintf(stderr, "MatroskaFileParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n"); 00174 #endif 00175 return False; // the parsing got interrupted 00176 } 00177 }
| Boolean MatroskaFileParser::parseStartOfFile | ( | ) | [private] |
Definition at line 179 of file MatroskaFileParser.cpp.
References Medium::envir(), False, fCurrentParseState, fOurFile, LOOKING_FOR_TRACKS, MATROSKA_ID_EBML, parseEBMLIdAndSize(), size, skipHeader(), and True.
Referenced by parse().
00179 { 00180 #ifdef DEBUG 00181 fprintf(stderr, "parsing start of file\n"); 00182 #endif 00183 EBMLId id; 00184 EBMLDataSize size; 00185 00186 // The file must begin with the standard EBML header (which we skip): 00187 if (!parseEBMLIdAndSize(id, size) || id != MATROSKA_ID_EBML) { 00188 fOurFile.envir() << "ERROR: FIle does not begin with an EBML header\n"; 00189 return True; // We're done with the file, because it's not valid 00190 } 00191 skipHeader(size); 00192 00193 fCurrentParseState = LOOKING_FOR_TRACKS; 00194 return False; // because we have more parsing to do - inside the 'Track' header 00195 }
| void MatroskaFileParser::lookForNextTrack | ( | ) | [private] |
Definition at line 197 of file MatroskaFileParser.cpp.
References MatroskaFile::fClusterOffset, MatroskaFile::fCuesOffset, fCurOffsetInFile, fCurrentParseState, MatroskaFile::fileDuration(), 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_TRACKS, parseEBMLIdAndSize(), parseEBMLNumber(), parseEBMLVal_float(), parseEBMLVal_unsigned(), parseEBMLVal_unsigned64(), PARSING_TRACK, MatroskaFile::segmentDuration(), setParseState(), size, skipHeader(), EBMLId::stringName(), and MatroskaFile::timecodeScale().
Referenced by parse().
00197 { 00198 #ifdef DEBUG 00199 fprintf(stderr, "looking for Track\n"); 00200 #endif 00201 EBMLId id; 00202 EBMLDataSize size; 00203 00204 // Read and skip over (or enter) each Matroska header, until we get to a 'Track'. 00205 while (fCurrentParseState == LOOKING_FOR_TRACKS) { 00206 while (!parseEBMLIdAndSize(id, size)) {} 00207 #ifdef DEBUG 00208 fprintf(stderr, "MatroskaFileParser::lookForNextTrack(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00209 #endif 00210 switch (id.val()) { 00211 case MATROSKA_ID_SEGMENT: { // 'Segment' header: enter this 00212 // Remember the position, within the file, of the start of Segment data, because Seek Positions are relative to this: 00213 fOurFile.fSegmentDataOffset = fCurOffsetInFile; 00214 break; 00215 } 00216 case MATROSKA_ID_SEEK_HEAD: { // 'Seek Head' header: enter this 00217 break; 00218 } 00219 case MATROSKA_ID_SEEK: { // 'Seek' header: enter this 00220 break; 00221 } 00222 case MATROSKA_ID_SEEK_ID: { // 'Seek ID' header: get this value 00223 if (parseEBMLNumber(fLastSeekId)) { 00224 #ifdef DEBUG 00225 fprintf(stderr, "\tSeek ID 0x%s:\t%s\n", fLastSeekId.hexString(), fLastSeekId.stringName()); 00226 #endif 00227 } 00228 break; 00229 } 00230 case MATROSKA_ID_SEEK_POSITION: { // 'Seek Position' header: get this value 00231 u_int64_t seekPosition; 00232 if (parseEBMLVal_unsigned64(size, seekPosition)) { 00233 u_int64_t offsetInFile = fOurFile.fSegmentDataOffset + seekPosition; 00234 #ifdef DEBUG 00235 fprintf(stderr, "\tSeek Position %llu (=> offset within the file: %llu (0x%llx))\n", seekPosition, offsetInFile, offsetInFile); 00236 #endif 00237 // The only 'Seek Position's that we care about are for 'Cluster' and 'Cues': 00238 if (fLastSeekId == MATROSKA_ID_CLUSTER) { 00239 fOurFile.fClusterOffset = offsetInFile; 00240 } else if (fLastSeekId == MATROSKA_ID_CUES) { 00241 fOurFile.fCuesOffset = offsetInFile; 00242 } 00243 } 00244 break; 00245 } 00246 case MATROSKA_ID_INFO: { // 'Segment Info' header: enter this 00247 break; 00248 } 00249 case MATROSKA_ID_TIMECODE_SCALE: { // 'Timecode Scale' header: get this value 00250 unsigned timecodeScale; 00251 if (parseEBMLVal_unsigned(size, timecodeScale) && timecodeScale > 0) { 00252 fOurFile.fTimecodeScale = timecodeScale; 00253 #ifdef DEBUG 00254 fprintf(stderr, "\tTimecode Scale %u ns (=> Segment Duration == %f seconds)\n", fOurFile.timecodeScale(), fOurFile.fileDuration()); 00255 #endif 00256 } 00257 break; 00258 } 00259 case MATROSKA_ID_DURATION: { // 'Segment Duration' header: get this value 00260 if (parseEBMLVal_float(size, fOurFile.fSegmentDuration)) { 00261 #ifdef DEBUG 00262 fprintf(stderr, "\tSegment Duration %f (== %f seconds)\n", fOurFile.segmentDuration(), fOurFile.fileDuration()); 00263 #endif 00264 } 00265 break; 00266 } 00267 case MATROSKA_ID_TRACKS: { // enter this, and move on to parsing 'Tracks' 00268 fLimitOffsetInFile = fCurOffsetInFile + size.val(); // Make sure we don't read past the end of this header 00269 fCurrentParseState = PARSING_TRACK; 00270 break; 00271 } 00272 default: { // skip over this header 00273 skipHeader(size); 00274 #ifdef DEBUG 00275 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00276 #endif 00277 break; 00278 } 00279 } 00280 setParseState(); 00281 } 00282 }
| Boolean MatroskaFileParser::parseTrack | ( | ) | [private] |
Definition at line 284 of file MatroskaFileParser.cpp.
References MatroskaTrack::codecID, MatroskaTrack::codecPrivate, MatroskaTrack::codecPrivateSize, MatroskaTrack::defaultDuration, False, fCurOffsetInFile, fLimitOffsetInFile, fOurFile, MatroskaFile::fTracks, MatroskaTrack::headerStrippedBytes, MatroskaTrack::headerStrippedBytesSize, MatroskaTrack::isDefault, MatroskaTrack::isEnabled, MatroskaTrack::isForced, MatroskaTrack::language, MATROSKA_ID_AUDIO, 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_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::name, NULL, MatroskaTrack::numChannels, parseEBMLIdAndSize(), parseEBMLVal_binary(), parseEBMLVal_float(), parseEBMLVal_string(), parseEBMLVal_unsigned(), MatroskaTrack::samplingFrequency, setParseState(), size, skipHeader(), MatroskaTrack::trackNumber, MatroskaTrack::trackType, and True.
Referenced by parse().
00284 { 00285 #ifdef DEBUG 00286 fprintf(stderr, "parsing Track\n"); 00287 #endif 00288 // Read and process each Matroska header, until we get to the end of the Track: 00289 MatroskaTrack* track = NULL; 00290 EBMLId id; 00291 EBMLDataSize size; 00292 while (fCurOffsetInFile < fLimitOffsetInFile) { 00293 while (!parseEBMLIdAndSize(id, size)) {} 00294 #ifdef DEBUG 00295 if (id == MATROSKA_ID_TRACK_ENTRY) fprintf(stderr, "\n"); // makes debugging output easier to read 00296 fprintf(stderr, "MatroskaFileParser::parseTrack(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00297 #endif 00298 switch (id.val()) { 00299 case MATROSKA_ID_TRACK_ENTRY: { // 'Track Entry' header: enter this 00300 // Create a new "MatroskaTrack" object for this entry: 00301 if (track != NULL && track->trackNumber == 0) delete track; // We had a previous "MatroskaTrack" object that was never used 00302 track = new MatroskaTrack; 00303 break; 00304 } 00305 case MATROSKA_ID_TRACK_NUMBER: { 00306 unsigned trackNumber; 00307 if (parseEBMLVal_unsigned(size, trackNumber)) { 00308 #ifdef DEBUG 00309 fprintf(stderr, "\tTrack Number %d\n", trackNumber); 00310 #endif 00311 if (track != NULL && trackNumber != 0) { 00312 track->trackNumber = trackNumber; 00313 fOurFile.fTracks.add(track, trackNumber); 00314 } 00315 } 00316 break; 00317 } 00318 case MATROSKA_ID_TRACK_TYPE: { 00319 unsigned trackType; 00320 if (parseEBMLVal_unsigned(size, trackType) && track != NULL) { 00321 // We convert the Matroska 'track type' code into our own code (which we can use as a bitmap): 00322 track->trackType 00323 = trackType == 1 ? MATROSKA_TRACK_TYPE_VIDEO : trackType == 2 ? MATROSKA_TRACK_TYPE_AUDIO 00324 : trackType == 0x11 ? MATROSKA_TRACK_TYPE_SUBTITLE : MATROSKA_TRACK_TYPE_OTHER; 00325 #ifdef DEBUG 00326 fprintf(stderr, "\tTrack Type 0x%02x (%s)\n", trackType, 00327 track->trackType == MATROSKA_TRACK_TYPE_VIDEO ? "video" : 00328 track->trackType == MATROSKA_TRACK_TYPE_AUDIO ? "audio" : 00329 track->trackType == MATROSKA_TRACK_TYPE_SUBTITLE ? "subtitle" : 00330 "<other>"); 00331 #endif 00332 } 00333 break; 00334 } 00335 case MATROSKA_ID_FLAG_ENABLED: { 00336 unsigned flagEnabled; 00337 if (parseEBMLVal_unsigned(size, flagEnabled)) { 00338 #ifdef DEBUG 00339 fprintf(stderr, "\tTrack is Enabled: %d\n", flagEnabled); 00340 #endif 00341 if (track != NULL) track->isEnabled = flagEnabled != 0; 00342 } 00343 break; 00344 } 00345 case MATROSKA_ID_FLAG_DEFAULT: { 00346 unsigned flagDefault; 00347 if (parseEBMLVal_unsigned(size, flagDefault)) { 00348 #ifdef DEBUG 00349 fprintf(stderr, "\tTrack is Default: %d\n", flagDefault); 00350 #endif 00351 if (track != NULL) track->isDefault = flagDefault != 0; 00352 } 00353 break; 00354 } 00355 case MATROSKA_ID_FLAG_FORCED: { 00356 unsigned flagForced; 00357 if (parseEBMLVal_unsigned(size, flagForced)) { 00358 #ifdef DEBUG 00359 fprintf(stderr, "\tTrack is Forced: %d\n", flagForced); 00360 #endif 00361 if (track != NULL) track->isForced = flagForced != 0; 00362 } 00363 break; 00364 } 00365 case MATROSKA_ID_DEFAULT_DURATION: { 00366 unsigned defaultDuration; 00367 if (parseEBMLVal_unsigned(size, defaultDuration)) { 00368 #ifdef DEBUG 00369 fprintf(stderr, "\tDefault duration %f ms\n", defaultDuration/1000000.0); 00370 #endif 00371 if (track != NULL) track->defaultDuration = defaultDuration; 00372 } 00373 break; 00374 } 00375 case MATROSKA_ID_MAX_BLOCK_ADDITION_ID: { 00376 unsigned maxBlockAdditionID; 00377 if (parseEBMLVal_unsigned(size, maxBlockAdditionID)) { 00378 #ifdef DEBUG 00379 fprintf(stderr, "\tMax Block Addition ID: %u\n", maxBlockAdditionID); 00380 #endif 00381 } 00382 break; 00383 } 00384 case MATROSKA_ID_NAME: { 00385 char* name; 00386 if (parseEBMLVal_string(size, name)) { 00387 #ifdef DEBUG 00388 fprintf(stderr, "\tName: %s\n", name); 00389 #endif 00390 if (track != NULL) { 00391 delete[] track->name; track->name = name; 00392 } else { 00393 delete[] name; 00394 } 00395 } 00396 break; 00397 } 00398 case MATROSKA_ID_LANGUAGE: { 00399 char* language; 00400 if (parseEBMLVal_string(size, language)) { 00401 #ifdef DEBUG 00402 fprintf(stderr, "\tLanguage: %s\n", language); 00403 #endif 00404 if (track != NULL) { 00405 delete[] track->language; track->language = language; 00406 } else { 00407 delete[] language; 00408 } 00409 } 00410 break; 00411 } 00412 case MATROSKA_ID_CODEC: { 00413 char* codecID; 00414 if (parseEBMLVal_string(size, codecID)) { 00415 #ifdef DEBUG 00416 fprintf(stderr, "\tCodec ID: %s\n", codecID); 00417 #endif 00418 if (track != NULL) { 00419 delete[] track->codecID; track->codecID = codecID; 00420 } else { 00421 delete[] codecID; 00422 } 00423 } 00424 break; 00425 } 00426 case MATROSKA_ID_CODEC_PRIVATE: { 00427 u_int8_t* codecPrivate; 00428 unsigned codecPrivateSize; 00429 if (parseEBMLVal_binary(size, codecPrivate)) { 00430 codecPrivateSize = (unsigned)size.val(); 00431 #ifdef DEBUG 00432 fprintf(stderr, "\tCodec Private: "); 00433 for (unsigned i = 0; i < codecPrivateSize; ++i) fprintf(stderr, "%02x:", codecPrivate[i]); 00434 fprintf(stderr, "\n"); 00435 #endif 00436 if (track != NULL) { 00437 delete[] track->codecPrivate; track->codecPrivate = codecPrivate; 00438 track->codecPrivateSize = codecPrivateSize; 00439 } else { 00440 delete[] codecPrivate; 00441 } 00442 } 00443 break; 00444 } 00445 case MATROSKA_ID_VIDEO: { // 'Video settings' header: enter this 00446 break; 00447 } 00448 case MATROSKA_ID_PIXEL_WIDTH: { 00449 unsigned pixelWidth; 00450 if (parseEBMLVal_unsigned(size, pixelWidth)) { 00451 #ifdef DEBUG 00452 fprintf(stderr, "\tPixel Width %d\n", pixelWidth); 00453 #endif 00454 } 00455 break; 00456 } 00457 case MATROSKA_ID_PIXEL_HEIGHT: { 00458 unsigned pixelHeight; 00459 if (parseEBMLVal_unsigned(size, pixelHeight)) { 00460 #ifdef DEBUG 00461 fprintf(stderr, "\tPixel Height %d\n", pixelHeight); 00462 #endif 00463 } 00464 break; 00465 } 00466 case MATROSKA_ID_DISPLAY_WIDTH: { 00467 unsigned displayWidth; 00468 if (parseEBMLVal_unsigned(size, displayWidth)) { 00469 #ifdef DEBUG 00470 fprintf(stderr, "\tDisplay Width %d\n", displayWidth); 00471 #endif 00472 } 00473 break; 00474 } 00475 case MATROSKA_ID_DISPLAY_HEIGHT: { 00476 unsigned displayHeight; 00477 if (parseEBMLVal_unsigned(size, displayHeight)) { 00478 #ifdef DEBUG 00479 fprintf(stderr, "\tDisplay Height %d\n", displayHeight); 00480 #endif 00481 } 00482 break; 00483 } 00484 case MATROSKA_ID_AUDIO: { // 'Audio settings' header: enter this 00485 break; 00486 } 00487 case MATROSKA_ID_SAMPLING_FREQUENCY: { 00488 float samplingFrequency; 00489 if (parseEBMLVal_float(size, samplingFrequency)) { 00490 if (track != NULL) { 00491 track->samplingFrequency = (unsigned)samplingFrequency; 00492 #ifdef DEBUG 00493 fprintf(stderr, "\tSampling frequency %f (->%d)\n", samplingFrequency, track->samplingFrequency); 00494 #endif 00495 } 00496 } 00497 break; 00498 } 00499 case MATROSKA_ID_OUTPUT_SAMPLING_FREQUENCY: { 00500 float outputSamplingFrequency; 00501 if (parseEBMLVal_float(size, outputSamplingFrequency)) { 00502 #ifdef DEBUG 00503 fprintf(stderr, "\tOutput sampling frequency %f\n", outputSamplingFrequency); 00504 #endif 00505 } 00506 break; 00507 } 00508 case MATROSKA_ID_CHANNELS: { 00509 unsigned numChannels; 00510 if (parseEBMLVal_unsigned(size, numChannels)) { 00511 #ifdef DEBUG 00512 fprintf(stderr, "\tChannels %d\n", numChannels); 00513 #endif 00514 if (track != NULL) track->numChannels = numChannels; 00515 } 00516 break; 00517 } 00518 case MATROSKA_ID_CONTENT_ENCODINGS: 00519 case MATROSKA_ID_CONTENT_ENCODING: { // 'Content Encodings' or 'Content Encoding' header: enter this 00520 break; 00521 } 00522 case MATROSKA_ID_CONTENT_COMPRESSION: { // 'Content Compression' header: enter this 00523 // Note: We currently support only 'Header Stripping' compression, not 'zlib' compression (the default algorithm). 00524 // Therefore, we disable this track, unless/until we later see that 'Header Stripping' is supported: 00525 if (track != NULL) track->isEnabled = False; 00526 break; 00527 } 00528 case MATROSKA_ID_CONTENT_COMP_ALGO: { 00529 unsigned contentCompAlgo; 00530 if (parseEBMLVal_unsigned(size, contentCompAlgo)) { 00531 #ifdef DEBUG 00532 fprintf(stderr, "\tContent Compression Algorithm %d (%s)\n", contentCompAlgo, 00533 contentCompAlgo == 0 ? "zlib" : contentCompAlgo == 3 ? "Header Stripping" : "<unknown>"); 00534 #endif 00535 // The only compression algorithm that we support is #3: Header Stripping; disable the track otherwise 00536 if (track != NULL) track->isEnabled = contentCompAlgo == 3; 00537 } 00538 break; 00539 } 00540 case MATROSKA_ID_CONTENT_COMP_SETTINGS: { 00541 u_int8_t* headerStrippedBytes; 00542 unsigned headerStrippedBytesSize; 00543 if (parseEBMLVal_binary(size, headerStrippedBytes)) { 00544 headerStrippedBytesSize = (unsigned)size.val(); 00545 #ifdef DEBUG 00546 fprintf(stderr, "\tHeader Stripped Bytes: "); 00547 for (unsigned i = 0; i < headerStrippedBytesSize; ++i) fprintf(stderr, "%02x:", headerStrippedBytes[i]); 00548 fprintf(stderr, "\n"); 00549 #endif 00550 if (track != NULL) { 00551 delete[] track->headerStrippedBytes; track->headerStrippedBytes = headerStrippedBytes; 00552 track->headerStrippedBytesSize = headerStrippedBytesSize; 00553 } else { 00554 delete[] headerStrippedBytes; 00555 } 00556 } 00557 break; 00558 } 00559 case MATROSKA_ID_CONTENT_ENCRYPTION: { // 'Content Encrpytion' header: skip this 00560 // Note: We don't currently support encryption at all. Therefore, we disable this track: 00561 if (track != NULL) track->isEnabled = False; 00562 // Fall through to... 00563 } 00564 default: { // We don't process this header, so just skip over it: 00565 skipHeader(size); 00566 #ifdef DEBUG 00567 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00568 #endif 00569 break; 00570 } 00571 } 00572 setParseState(); 00573 } 00574 00575 fLimitOffsetInFile = 0; // reset 00576 if (track != NULL && track->trackNumber == 0) delete track; // We had a previous "MatroskaTrack" object that was never used 00577 return True; // we're done parsing track entries 00578 }
| Boolean MatroskaFileParser::parseCues | ( | ) | [private] |
Definition at line 639 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().
00639 { 00640 #if defined(DEBUG) || defined(DEBUG_CUES) 00641 fprintf(stderr, "parsing Cues\n"); 00642 #endif 00643 EBMLId id; 00644 EBMLDataSize size; 00645 00646 // Read the next header, which should be MATROSKA_ID_CUES: 00647 if (!parseEBMLIdAndSize(id, size) || id != MATROSKA_ID_CUES) return True; // The header wasn't what we expected, so we're done 00648 fLimitOffsetInFile = fCurOffsetInFile + size.val(); // Make sure we don't read past the end of this header 00649 00650 double currentCueTime = 0.0; 00651 u_int64_t currentClusterOffsetInFile = 0; 00652 00653 while (fCurOffsetInFile < fLimitOffsetInFile) { 00654 while (!parseEBMLIdAndSize(id, size)) {} 00655 #ifdef DEBUG_CUES 00656 if (id == MATROSKA_ID_CUE_POINT) fprintf(stderr, "\n"); // makes debugging output easier to read 00657 fprintf(stderr, "MatroskaFileParser::parseCues(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00658 #endif 00659 switch (id.val()) { 00660 case MATROSKA_ID_CUE_POINT: { // 'Cue Point' header: enter this 00661 break; 00662 } 00663 case MATROSKA_ID_CUE_TIME: { // 'Cue Time' header: get this value 00664 unsigned cueTime; 00665 if (parseEBMLVal_unsigned(size, cueTime)) { 00666 currentCueTime = cueTime*(fOurFile.fTimecodeScale/1000000000.0); 00667 #ifdef DEBUG_CUES 00668 fprintf(stderr, "\tCue Time %d (== %f seconds)\n", cueTime, currentCueTime); 00669 #endif 00670 } 00671 break; 00672 } 00673 case MATROSKA_ID_CUE_TRACK_POSITIONS: { // 'Cue Track Positions' header: enter this 00674 break; 00675 } 00676 case MATROSKA_ID_CUE_TRACK: { // 'Cue Track' header: get this value (but only for debugging; we don't do anything with it) 00677 unsigned cueTrack; 00678 if (parseEBMLVal_unsigned(size, cueTrack)) { 00679 #ifdef DEBUG_CUES 00680 fprintf(stderr, "\tCue Track %d\n", cueTrack); 00681 #endif 00682 } 00683 break; 00684 } 00685 case MATROSKA_ID_CUE_CLUSTER_POSITION: { // 'Cue Cluster Position' header: get this value 00686 u_int64_t cueClusterPosition; 00687 if (parseEBMLVal_unsigned64(size, cueClusterPosition)) { 00688 currentClusterOffsetInFile = fOurFile.fSegmentDataOffset + cueClusterPosition; 00689 #ifdef DEBUG_CUES 00690 fprintf(stderr, "\tCue Cluster Position %llu (=> offset within the file: %llu (0x%llx))\n", cueClusterPosition, currentClusterOffsetInFile, currentClusterOffsetInFile); 00691 #endif 00692 // Record this cue point: 00693 fOurFile.addCuePoint(currentCueTime, currentClusterOffsetInFile, 1/*default block number within cluster*/); 00694 } 00695 break; 00696 } 00697 case MATROSKA_ID_CUE_BLOCK_NUMBER: { // 'Cue Block Number' header: get this value 00698 unsigned cueBlockNumber; 00699 if (parseEBMLVal_unsigned(size, cueBlockNumber) && cueBlockNumber != 0) { 00700 #ifdef DEBUG_CUES 00701 fprintf(stderr, "\tCue Block Number %d\n", cueBlockNumber); 00702 #endif 00703 // Record this cue point (overwriting any existing entry for this cue time): 00704 fOurFile.addCuePoint(currentCueTime, currentClusterOffsetInFile, cueBlockNumber); 00705 } 00706 break; 00707 } 00708 default: { // We don't process this header, so just skip over it: 00709 skipHeader(size); 00710 #ifdef DEBUG_CUES 00711 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00712 #endif 00713 break; 00714 } 00715 } 00716 setParseState(); 00717 } 00718 00719 fLimitOffsetInFile = 0; // reset 00720 #if defined(DEBUG) || defined(DEBUG_CUES) 00721 fprintf(stderr, "done parsing Cues\n"); 00722 #endif 00723 #ifdef DEBUG_CUES 00724 fprintf(stderr, "Cue Point tree: "); 00725 fOurFile.printCuePoints(stderr); 00726 fprintf(stderr, "\n"); 00727 #endif 00728 return True; // we're done parsing Cues 00729 }
| void MatroskaFileParser::lookForNextBlock | ( | ) | [private] |
Definition at line 580 of file MatroskaFileParser.cpp.
References fBlockSize, fClusterTimecode, fCurrentParseState, fOurFile, MatroskaFile::fTimecodeScale, LOOKING_FOR_BLOCK, MATROSKA_ID_BLOCK, MATROSKA_ID_BLOCK_DURATION, MATROSKA_ID_BLOCK_GROUP, MATROSKA_ID_CLUSTER, MATROSKA_ID_SEGMENT, MATROSKA_ID_SIMPLEBLOCK, MATROSKA_ID_TIMECODE, parseEBMLIdAndSize(), parseEBMLVal_unsigned(), PARSING_BLOCK, setParseState(), size, and skipHeader().
Referenced by parse().
00580 { 00581 #ifdef DEBUG 00582 fprintf(stderr, "looking for Block\n"); 00583 #endif 00584 // Read and skip over each Matroska header, until we get to a 'Cluster': 00585 EBMLId id; 00586 EBMLDataSize size; 00587 while (fCurrentParseState == LOOKING_FOR_BLOCK) { 00588 while (!parseEBMLIdAndSize(id, size)) {} 00589 #ifdef DEBUG 00590 fprintf(stderr, "MatroskaFileParser::lookForNextBlock(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00591 #endif 00592 switch (id.val()) { 00593 case MATROSKA_ID_SEGMENT: { // 'Segment' header: enter this 00594 break; 00595 } 00596 case MATROSKA_ID_CLUSTER: { // 'Cluster' header: enter this 00597 break; 00598 } 00599 case MATROSKA_ID_TIMECODE: { // 'Timecode' header: get this value 00600 unsigned timecode; 00601 if (parseEBMLVal_unsigned(size, timecode)) { 00602 fClusterTimecode = timecode; 00603 #ifdef DEBUG 00604 fprintf(stderr, "\tCluster timecode: %d (== %f seconds)\n", fClusterTimecode, fClusterTimecode*(fOurFile.fTimecodeScale/1000000000.0)); 00605 #endif 00606 } 00607 break; 00608 } 00609 case MATROSKA_ID_BLOCK_GROUP: { // 'Block Group' header: enter this 00610 break; 00611 } 00612 case MATROSKA_ID_SIMPLEBLOCK: 00613 case MATROSKA_ID_BLOCK: { // 'SimpleBlock' or 'Block' header: enter this (and we're done) 00614 fBlockSize = (unsigned)size.val(); 00615 fCurrentParseState = PARSING_BLOCK; 00616 break; 00617 } 00618 case MATROSKA_ID_BLOCK_DURATION: { // 'Block Duration' header: get this value (but we currently don't do anything with it) 00619 unsigned blockDuration; 00620 if (parseEBMLVal_unsigned(size, blockDuration)) { 00621 #ifdef DEBUG 00622 fprintf(stderr, "\tblock duration: %d (== %f ms)\n", blockDuration, (float)(blockDuration*fOurFile.fTimecodeScale/1000000.0)); 00623 #endif 00624 } 00625 break; 00626 } 00627 default: { // skip over this header 00628 skipHeader(size); 00629 #ifdef DEBUG 00630 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00631 #endif 00632 break; 00633 } 00634 } 00635 setParseState(); 00636 } 00637 }
| void MatroskaFileParser::parseBlock | ( | ) | [private] |
Definition at line 733 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(), EBMLNumber::val(), and XiphLacing.
Referenced by parse().
00733 { 00734 #ifdef DEBUG 00735 fprintf(stderr, "parsing SimpleBlock or Block\n"); 00736 #endif 00737 do { 00738 unsigned blockStartPos = curOffset(); 00739 00740 // The block begins with the track number: 00741 EBMLNumber trackNumber; 00742 if (!parseEBMLNumber(trackNumber)) break; 00743 fBlockTrackNumber = (unsigned)trackNumber.val(); 00744 00745 // If this track is not being read, then skip the rest of this block, and look for another one: 00746 if (fOurDemux->lookupDemuxedTrack(fBlockTrackNumber) == NULL) { 00747 unsigned headerBytesSeen = curOffset() - blockStartPos; 00748 if (headerBytesSeen < fBlockSize) { 00749 skipBytes(fBlockSize - headerBytesSeen); 00750 } 00751 #ifdef DEBUG 00752 fprintf(stderr, "\tSkipped block for unused track number %d\n", fBlockTrackNumber); 00753 #endif 00754 fCurrentParseState = LOOKING_FOR_BLOCK; 00755 setParseState(); 00756 return; 00757 } 00758 00759 MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber); 00760 if (track == NULL) break; // shouldn't happen 00761 00762 // The next two bytes are the block's timecode (relative to the cluster timecode) 00763 fBlockTimecode = (get1Byte()<<8)|get1Byte(); 00764 00765 // The next byte indicates the type of 'lacing' used: 00766 u_int8_t c = get1Byte(); 00767 c &= 0x6; // we're interested in bits 5-6 only 00768 MatroskaLacingType lacingType = (c==0x0)?NoLacing : (c==0x02)?XiphLacing : (c==0x04)?FixedSizeLacing : EBMLLacing; 00769 #ifdef DEBUG 00770 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"); 00771 #endif 00772 00773 if (lacingType == NoLacing) { 00774 fNumFramesInBlock = 1; 00775 } else { 00776 // The next byte tells us how many frames are present in this block 00777 fNumFramesInBlock = get1Byte() + 1; 00778 } 00779 delete[] fFrameSizesWithinBlock; fFrameSizesWithinBlock = new unsigned[fNumFramesInBlock]; 00780 if (fFrameSizesWithinBlock == NULL) break; 00781 00782 if (lacingType == NoLacing) { 00783 unsigned headerBytesSeen = curOffset() - blockStartPos; 00784 if (headerBytesSeen > fBlockSize) break; 00785 00786 fFrameSizesWithinBlock[0] = fBlockSize - headerBytesSeen; 00787 } else if (lacingType == FixedSizeLacing) { 00788 unsigned headerBytesSeen = curOffset() - blockStartPos; 00789 if (headerBytesSeen > fBlockSize) break; 00790 00791 unsigned frameBytesAvailable = fBlockSize - headerBytesSeen; 00792 unsigned constantFrameSize = frameBytesAvailable/fNumFramesInBlock; 00793 00794 for (unsigned i = 0; i < fNumFramesInBlock; ++i) { 00795 fFrameSizesWithinBlock[i] = constantFrameSize; 00796 } 00797 // If there are any bytes left over, assign them to the last frame: 00798 fFrameSizesWithinBlock[fNumFramesInBlock-1] += frameBytesAvailable%fNumFramesInBlock; 00799 } else { // EBML or Xiph lacing 00800 unsigned curFrameSize = 0; 00801 unsigned frameSizesTotal = 0; 00802 unsigned i; 00803 00804 for (i = 0; i < fNumFramesInBlock-1; ++i) { 00805 if (lacingType == EBMLLacing) { 00806 EBMLNumber frameSize; 00807 if (!parseEBMLNumber(frameSize)) break; 00808 unsigned fsv = (unsigned)frameSize.val(); 00809 00810 if (i == 0) { 00811 curFrameSize = fsv; 00812 } else { 00813 // The value we read is a signed value, that's added to the previous frame size, to get the current frame size: 00814 unsigned toSubtract = (fsv>0xFFFFFF)?0x07FFFFFF : (fsv>0xFFFF)?0x0FFFFF : (fsv>0xFF)?0x1FFF : 0x3F; 00815 int fsv_signed = fsv - toSubtract; 00816 curFrameSize += fsv_signed; 00817 if ((int)curFrameSize < 0) break; 00818 } 00819 } else { // Xiph lacing 00820 curFrameSize = 0; 00821 u_int8_t c; 00822 do { 00823 c = get1Byte(); 00824 curFrameSize += c; 00825 } while (c == 0xFF); 00826 } 00827 fFrameSizesWithinBlock[i] = curFrameSize; 00828 frameSizesTotal += curFrameSize; 00829 } 00830 if (i != fNumFramesInBlock-1) break; // an error occurred within the "for" loop 00831 00832 // Compute the size of the final frame within the block (from the block's size, and the frame sizes already computed):) 00833 unsigned headerBytesSeen = curOffset() - blockStartPos; 00834 if (headerBytesSeen + frameSizesTotal > fBlockSize) break; 00835 fFrameSizesWithinBlock[i] = fBlockSize - (headerBytesSeen + frameSizesTotal); 00836 } 00837 00838 // We're done parsing headers within the block, and (as a result) we now know the sizes of all frames within the block. 00839 // If we have 'stripped bytes' that are common to (the front of) all frames, then count them now: 00840 if (track->headerStrippedBytesSize != 0) { 00841 for (unsigned i = 0; i < fNumFramesInBlock; ++i) fFrameSizesWithinBlock[i] += track->headerStrippedBytesSize; 00842 } 00843 #ifdef DEBUG 00844 fprintf(stderr, "\tThis block contains %d frame(s); size(s):", fNumFramesInBlock); 00845 unsigned frameSizesTotal = 0; 00846 for (unsigned i = 0; i < fNumFramesInBlock; ++i) { 00847 fprintf(stderr, " %d", fFrameSizesWithinBlock[i]); 00848 frameSizesTotal += fFrameSizesWithinBlock[i]; 00849 } 00850 if (fNumFramesInBlock > 1) fprintf(stderr, " (total: %u)", frameSizesTotal); 00851 fprintf(stderr, " bytes\n"); 00852 #endif 00853 // Next, start delivering these frames: 00854 fCurrentParseState = DELIVERING_FRAME_WITHIN_BLOCK; 00855 fCurOffsetWithinFrame = fNextFrameNumberToDeliver = 0; 00856 setParseState(); 00857 return; 00858 } while (0); 00859 00860 // An error occurred. Try to recover: 00861 #ifdef DEBUG 00862 fprintf(stderr, "parseBlock(): Error parsing data; trying to recover...\n"); 00863 #endif 00864 fCurrentParseState = LOOKING_FOR_BLOCK; 00865 }
| Boolean MatroskaFileParser::deliverFrameWithinBlock | ( | ) | [private] |
Definition at line 867 of file MatroskaFileParser.cpp.
References MatroskaTrack::defaultDuration, DELIVERING_FRAME_BYTES, MatroskaDemuxedTrack::durationImbalance(), MatroskaDemuxedTrack::durationInMicroseconds(), False, fBlockTimecode, fBlockTrackNumber, fClusterTimecode, fCurFrameNumBytesToGet, fCurOffsetWithinFrame, fCurrentParseState, fFrameSizesWithinBlock, fNextFrameNumberToDeliver, 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().
00867 { 00868 #ifdef DEBUG 00869 fprintf(stderr, "delivering frame within SimpleBlock or Block\n"); 00870 #endif 00871 do { 00872 MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber); 00873 if (track == NULL) break; // shouldn't happen 00874 00875 MatroskaDemuxedTrack* demuxedTrack = fOurDemux->lookupDemuxedTrack(fBlockTrackNumber); 00876 if (demuxedTrack == NULL) break; // shouldn't happen 00877 if (!demuxedTrack->isCurrentlyAwaitingData()) { 00878 // Someone has been reading this stream, but isn't right now. 00879 // We can't deliver this frame until he asks for it, so punt for now. 00880 // The next time he asks for a frame, he'll get it. 00881 #ifdef DEBUG 00882 fprintf(stderr, "\tdeferring delivery of frame #%d (%d bytes)", fNextFrameNumberToDeliver, fFrameSizesWithinBlock[fNextFrameNumberToDeliver]); 00883 if (track->haveSubframes()) fprintf(stderr, "[offset %d]", fCurOffsetWithinFrame); 00884 fprintf(stderr, "\n"); 00885 #endif 00886 restoreSavedParserState(); // so we read from the beginning next time 00887 return False; 00888 } 00889 00890 unsigned frameSize = fFrameSizesWithinBlock[fNextFrameNumberToDeliver]; 00891 if (track->haveSubframes()) { 00892 // The next "track->subframeSizeSize" bytes contain the length of a 'subframe': 00893 if (fCurOffsetWithinFrame + track->subframeSizeSize > frameSize) break; // sanity check 00894 unsigned subframeSize = 0; 00895 for (unsigned i = 0; i < track->subframeSizeSize; ++i) { 00896 u_int8_t c; 00897 getCommonFrameBytes(track, &c, 1, 0); 00898 if (fCurFrameNumBytesToGet > 0) { // it'll be 1 00899 c = get1Byte(); 00900 ++fCurOffsetWithinFrame; 00901 } 00902 subframeSize = subframeSize*256 + c; 00903 } 00904 if (subframeSize == 0 || fCurOffsetWithinFrame + subframeSize > frameSize) break; // sanity check 00905 frameSize = subframeSize; 00906 } 00907 00908 // Compute the presentation time of this frame (from the cluster timecode, the block timecode, and the default duration): 00909 double pt = (fClusterTimecode+fBlockTimecode)*(fOurFile.fTimecodeScale/1000000000.0) 00910 + fNextFrameNumberToDeliver*(track->defaultDuration/1000000000.0); 00911 if (fPresentationTimeOffset == 0.0) { 00912 // This is the first time we've computed a presentation time. Compute an offset to make the presentation times aligned 00913 // with 'wall clock' time: 00914 struct timeval timeNow; 00915 gettimeofday(&timeNow, NULL); 00916 double ptNow = timeNow.tv_sec + timeNow.tv_usec/1000000.0; 00917 fPresentationTimeOffset = ptNow - pt; 00918 } 00919 pt += fPresentationTimeOffset; 00920 struct timeval presentationTime; 00921 presentationTime.tv_sec = (unsigned)pt; 00922 presentationTime.tv_usec = (unsigned)((pt - presentationTime.tv_sec)*1000000); 00923 unsigned durationInMicroseconds = track->defaultDuration/1000; 00924 if (track->haveSubframes()) { 00925 // If this is a 'subframe', use a duration of 0 instead (unless it's the last 'subframe'): 00926 if (fCurOffsetWithinFrame + frameSize + track->subframeSizeSize < fFrameSizesWithinBlock[fNextFrameNumberToDeliver]) { 00927 // There's room for at least one more subframe after this, so give this subframe a duration of 0 00928 durationInMicroseconds = 0; 00929 } 00930 } 00931 00932 if (track->defaultDuration == 0) { 00933 // Adjust the frame duration to keep the sum of frame durations aligned with presentation times. 00934 if (demuxedTrack->prevPresentationTime().tv_sec != 0) { // not the first time for this track 00935 demuxedTrack->durationImbalance() 00936 += (presentationTime.tv_sec - demuxedTrack->prevPresentationTime().tv_sec)*1000000 00937 + (presentationTime.tv_usec - demuxedTrack->prevPresentationTime().tv_usec); 00938 } 00939 int adjustment = 0; 00940 if (demuxedTrack->durationImbalance() > 0) { 00941 // The duration needs to be increased. 00942 int const adjustmentThreshold = 100000; // don't increase the duration by more than this amount (in case there's a mistake) 00943 adjustment = demuxedTrack->durationImbalance() > adjustmentThreshold 00944 ? adjustmentThreshold : demuxedTrack->durationImbalance(); 00945 } else if (demuxedTrack->durationImbalance() < 0) { 00946 // The duration needs to be decreased. 00947 adjustment = (unsigned)(-demuxedTrack->durationImbalance()) < durationInMicroseconds 00948 ? demuxedTrack->durationImbalance() : -(int)durationInMicroseconds; 00949 } 00950 durationInMicroseconds += adjustment; 00951 demuxedTrack->durationImbalance() -= durationInMicroseconds; // for next time 00952 demuxedTrack->prevPresentationTime() = presentationTime; // for next time 00953 } 00954 00955 demuxedTrack->presentationTime() = presentationTime; 00956 demuxedTrack->durationInMicroseconds() = durationInMicroseconds; 00957 00958 // Deliver the next block now: 00959 if (frameSize > demuxedTrack->maxSize()) { 00960 demuxedTrack->numTruncatedBytes() = frameSize - demuxedTrack->maxSize(); 00961 demuxedTrack->frameSize() = demuxedTrack->maxSize(); 00962 } else { // normal case 00963 demuxedTrack->numTruncatedBytes() = 0; 00964 demuxedTrack->frameSize() = frameSize; 00965 } 00966 getCommonFrameBytes(track, demuxedTrack->to(), demuxedTrack->frameSize(), demuxedTrack->numTruncatedBytes()); 00967 00968 // Next, deliver (and/or skip) bytes from the input file: 00969 fCurrentParseState = DELIVERING_FRAME_BYTES; 00970 setParseState(); 00971 return True; 00972 } while (0); 00973 00974 // An error occurred. Try to recover: 00975 #ifdef DEBUG 00976 fprintf(stderr, "deliverFrameWithinBlock(): Error parsing data; trying to recover...\n"); 00977 #endif 00978 fCurrentParseState = LOOKING_FOR_BLOCK; 00979 return True; 00980 }
| void MatroskaFileParser::deliverFrameBytes | ( | ) | [private] |
Definition at line 982 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().
00982 { 00983 do { 00984 MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber); 00985 if (track == NULL) break; // shouldn't happen 00986 00987 MatroskaDemuxedTrack* demuxedTrack = fOurDemux->lookupDemuxedTrack(fBlockTrackNumber); 00988 if (demuxedTrack == NULL) break; // shouldn't happen 00989 00990 unsigned const BANK_SIZE = bankSize(); 00991 while (fCurFrameNumBytesToGet > 0) { 00992 // Hack: We can get no more than BANK_SIZE bytes at a time: 00993 unsigned numBytesToGet = fCurFrameNumBytesToGet > BANK_SIZE ? BANK_SIZE : fCurFrameNumBytesToGet; 00994 getBytes(fCurFrameTo, numBytesToGet); 00995 fCurFrameTo += numBytesToGet; 00996 fCurFrameNumBytesToGet -= numBytesToGet; 00997 fCurOffsetWithinFrame += numBytesToGet; 00998 setParseState(); 00999 } 01000 while (fCurFrameNumBytesToSkip > 0) { 01001 // Hack: We can skip no more than BANK_SIZE bytes at a time: 01002 unsigned numBytesToSkip = fCurFrameNumBytesToSkip > BANK_SIZE ? BANK_SIZE : fCurFrameNumBytesToSkip; 01003 skipBytes(numBytesToSkip); 01004 fCurFrameNumBytesToSkip -= numBytesToSkip; 01005 fCurOffsetWithinFrame += numBytesToSkip; 01006 setParseState(); 01007 } 01008 #ifdef DEBUG 01009 fprintf(stderr, "\tdelivered frame #%d: %d bytes", fNextFrameNumberToDeliver, demuxedTrack->frameSize()); 01010 if (track->haveSubframes()) fprintf(stderr, "[offset %d]", fCurOffsetWithinFrame - track->subframeSizeSize - demuxedTrack->frameSize() - demuxedTrack->numTruncatedBytes()); 01011 if (demuxedTrack->numTruncatedBytes() > 0) fprintf(stderr, " (%d bytes truncated)", demuxedTrack->numTruncatedBytes()); 01012 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()); 01013 #endif 01014 01015 if (!track->haveSubframes() 01016 || fCurOffsetWithinFrame + track->subframeSizeSize >= fFrameSizesWithinBlock[fNextFrameNumberToDeliver]) { 01017 // Either we don't have subframes, or there's no more room for another subframe => We're completely done with this frame now: 01018 ++fNextFrameNumberToDeliver; 01019 fCurOffsetWithinFrame = 0; 01020 } 01021 if (fNextFrameNumberToDeliver == fNumFramesInBlock) { 01022 // We've delivered all of the frames from this block. Look for another block next: 01023 fCurrentParseState = LOOKING_FOR_BLOCK; 01024 } else { 01025 fCurrentParseState = DELIVERING_FRAME_WITHIN_BLOCK; 01026 } 01027 01028 setParseState(); 01029 FramedSource::afterGetting(demuxedTrack); // completes delivery 01030 return; 01031 } while (0); 01032 01033 // An error occurred. Try to recover: 01034 #ifdef DEBUG 01035 fprintf(stderr, "deliverFrameBytes(): Error parsing data; trying to recover...\n"); 01036 #endif 01037 fCurrentParseState = LOOKING_FOR_BLOCK; 01038 }
| void MatroskaFileParser::getCommonFrameBytes | ( | MatroskaTrack * | track, | |
| u_int8_t * | to, | |||
| unsigned | numBytesToGet, | |||
| unsigned | numBytesToSkip | |||
| ) | [private] |
Definition at line 1041 of file MatroskaFileParser.cpp.
References fCurFrameNumBytesToGet, fCurFrameNumBytesToSkip, fCurFrameTo, fCurOffsetWithinFrame, MatroskaTrack::headerStrippedBytes, and MatroskaTrack::headerStrippedBytesSize.
Referenced by deliverFrameWithinBlock().
01041 { 01042 if (track->headerStrippedBytesSize > fCurOffsetWithinFrame) { 01043 // We have some common 'header stripped' bytes that remain to be prepended to the frame. Use these first: 01044 unsigned numRemainingHeaderStrippedBytes = track->headerStrippedBytesSize - fCurOffsetWithinFrame; 01045 unsigned numHeaderStrippedBytesToGet; 01046 if (numBytesToGet <= numRemainingHeaderStrippedBytes) { 01047 numHeaderStrippedBytesToGet = numBytesToGet; 01048 numBytesToGet = 0; 01049 if (numBytesToGet + numBytesToSkip <= numRemainingHeaderStrippedBytes) { 01050 numBytesToSkip = 0; 01051 } else { 01052 numBytesToSkip = numBytesToGet + numBytesToSkip - numRemainingHeaderStrippedBytes; 01053 } 01054 } else { 01055 numHeaderStrippedBytesToGet = numRemainingHeaderStrippedBytes; 01056 numBytesToGet = numBytesToGet - numRemainingHeaderStrippedBytes; 01057 } 01058 01059 if (numHeaderStrippedBytesToGet > 0) { 01060 memmove(to, &track->headerStrippedBytes[fCurOffsetWithinFrame], numHeaderStrippedBytesToGet); 01061 to += numHeaderStrippedBytesToGet; 01062 fCurOffsetWithinFrame += numHeaderStrippedBytesToGet; 01063 } 01064 } 01065 01066 fCurFrameTo = to; 01067 fCurFrameNumBytesToGet = numBytesToGet; 01068 fCurFrameNumBytesToSkip = numBytesToSkip; 01069 }
| Boolean MatroskaFileParser::parseEBMLNumber | ( | EBMLNumber & | num | ) | [private] |
Definition at line 1071 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().
01071 { 01072 unsigned i; 01073 u_int8_t bitmask = 0x80; 01074 for (i = 0; i < EBML_NUMBER_MAX_LEN; ++i) { 01075 while (1) { 01076 if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) return False; // We've hit our pre-set limit 01077 num.data[i] = get1Byte(); 01078 ++fCurOffsetInFile; 01079 01080 // If we're looking for an id, skip any leading bytes that don't contain a '1' in the first 4 bits: 01081 if (i == 0/*we're a leading byte*/ && !num.stripLeading1/*we're looking for an id*/ && (num.data[i]&0xF0) == 0) { 01082 setParseState(); // ensures that we make forward progress if the parsing gets interrupted 01083 continue; 01084 } 01085 break; 01086 } 01087 if ((num.data[0]&bitmask) != 0) { 01088 // num[i] is the last byte of the id 01089 if (num.stripLeading1) num.data[0] &=~ bitmask; 01090 break; 01091 } 01092 bitmask >>= 1; 01093 } 01094 if (i == EBML_NUMBER_MAX_LEN) return False; 01095 01096 num.len = i+1; 01097 return True; 01098 }
| Boolean MatroskaFileParser::parseEBMLIdAndSize | ( | EBMLId & | id, | |
| EBMLDataSize & | size | |||
| ) | [private] |
Definition at line 1100 of file MatroskaFileParser.cpp.
References parseEBMLNumber(), and size.
Referenced by lookForNextBlock(), lookForNextTrack(), parseCues(), parseStartOfFile(), and parseTrack().
01100 { 01101 return parseEBMLNumber(id) && parseEBMLNumber(size); 01102 }
| Boolean MatroskaFileParser::parseEBMLVal_unsigned64 | ( | EBMLDataSize & | size, | |
| u_int64_t & | result | |||
| ) | [private] |
Definition at line 1104 of file MatroskaFileParser.cpp.
References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), size, and True.
Referenced by lookForNextTrack(), parseCues(), and parseEBMLVal_unsigned().
01104 { 01105 u_int64_t sv = size.val(); 01106 if (sv > 8) return False; // size too large 01107 01108 result = 0; // initially 01109 for (unsigned i = (unsigned)sv; i > 0; --i) { 01110 if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) return False; // We've hit our pre-set limit 01111 01112 u_int8_t c = get1Byte(); 01113 ++fCurOffsetInFile; 01114 01115 result = result*256 + c; 01116 } 01117 01118 return True; 01119 }
| Boolean MatroskaFileParser::parseEBMLVal_unsigned | ( | EBMLDataSize & | size, | |
| unsigned & | result | |||
| ) | [private] |
Definition at line 1121 of file MatroskaFileParser.cpp.
References False, parseEBMLVal_unsigned64(), size, and True.
Referenced by lookForNextBlock(), lookForNextTrack(), parseCues(), parseEBMLVal_float(), and parseTrack().
01121 { 01122 if (size.val() > 4) return False; // size too large 01123 01124 u_int64_t result64; 01125 if (!parseEBMLVal_unsigned64(size, result64)) return False; 01126 01127 result = (unsigned)result64; 01128 01129 return True; 01130 }
| Boolean MatroskaFileParser::parseEBMLVal_float | ( | EBMLDataSize & | size, | |
| float & | result | |||
| ) | [private] |
Definition at line 1132 of file MatroskaFileParser.cpp.
References False, parseEBMLVal_unsigned(), size, and True.
Referenced by lookForNextTrack(), and parseTrack().
01132 { 01133 unsigned resultAsUnsigned; 01134 if (!parseEBMLVal_unsigned(size, resultAsUnsigned)) return False; 01135 01136 if (sizeof result != sizeof resultAsUnsigned) return False; 01137 memcpy(&result, &resultAsUnsigned, sizeof result); 01138 return True; 01139 }
| Boolean MatroskaFileParser::parseEBMLVal_string | ( | EBMLDataSize & | size, | |
| char *& | result | |||
| ) | [private] |
Definition at line 1141 of file MatroskaFileParser.cpp.
References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), NULL, size, and True.
Referenced by parseTrack().
01141 { 01142 unsigned resultLength = (unsigned)size.val(); 01143 result = new char[resultLength + 1]; // allow for the trailing '\0' 01144 if (result == NULL) return False; 01145 01146 char* p = result; 01147 unsigned i; 01148 for (i = 0; i < resultLength; ++i) { 01149 if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) break; // We've hit our pre-set limit 01150 01151 u_int8_t c = get1Byte(); 01152 ++fCurOffsetInFile; 01153 01154 *p++ = c; 01155 } 01156 if (i < resultLength) { // an error occurred 01157 delete[] result; 01158 result = NULL; 01159 return False; 01160 } 01161 *p = '\0'; 01162 01163 return True; 01164 }
| Boolean MatroskaFileParser::parseEBMLVal_binary | ( | EBMLDataSize & | size, | |
| u_int8_t *& | result | |||
| ) | [private] |
Definition at line 1166 of file MatroskaFileParser.cpp.
References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), NULL, size, and True.
Referenced by parseTrack().
01166 { 01167 unsigned resultLength = (unsigned)size.val(); 01168 result = new u_int8_t[resultLength]; 01169 if (result == NULL) return False; 01170 01171 u_int8_t* p = result; 01172 unsigned i; 01173 for (i = 0; i < resultLength; ++i) { 01174 if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) break; // We've hit our pre-set limit 01175 01176 u_int8_t c = get1Byte(); 01177 ++fCurOffsetInFile; 01178 01179 *p++ = c; 01180 } 01181 if (i < resultLength) { // an error occurred 01182 delete[] result; 01183 result = NULL; 01184 return False; 01185 } 01186 01187 return True; 01188 }
| void MatroskaFileParser::skipHeader | ( | EBMLDataSize const & | size | ) | [private] |
Definition at line 1190 of file MatroskaFileParser.cpp.
References StreamParser::bankSize(), fCurOffsetInFile, size, and StreamParser::skipBytes().
Referenced by lookForNextBlock(), lookForNextTrack(), parseCues(), parseStartOfFile(), and parseTrack().
01190 { 01191 unsigned sv = (unsigned)size.val(); 01192 01193 // Hack: To avoid tripping into a parser 'internal error' if we try to skip an excessively large distance. 01194 // (Such large distances are likely caused by erroneous data. We might not be able to recover from this, but at least we won't 01195 // generate a parser 'internal error'.) 01196 if (sv > bankSize()-12) sv = bankSize()-12; 01197 01198 skipBytes(sv); 01199 fCurOffsetInFile += sv; 01200 }
| void MatroskaFileParser::setParseState | ( | ) | [private] |
Definition at line 1202 of file MatroskaFileParser.cpp.
References fCurOffsetInFile, fCurOffsetWithinFrame, fSavedCurOffsetInFile, fSavedCurOffsetWithinFrame, and StreamParser::saveParserState().
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), lookForNextBlock(), lookForNextTrack(), parseBlock(), parseCues(), parseEBMLNumber(), and parseTrack().
01202 { 01203 fSavedCurOffsetInFile = fCurOffsetInFile; 01204 fSavedCurOffsetWithinFrame = fCurOffsetWithinFrame; 01205 saveParserState(); 01206 }
| void MatroskaFileParser::seekToFilePosition | ( | u_int64_t | offsetInFile | ) | [private] |
Definition at line 1214 of file MatroskaFileParser.cpp.
References fInputSource, NULL, resetStateAfterSeeking(), and ByteStreamFileSource::seekToByteAbsolute().
Referenced by parse(), and seekToTime().
01214 { 01215 ByteStreamFileSource* fileSource = (ByteStreamFileSource*)fInputSource; // we know it's a "ByteStreamFileSource" 01216 if (fileSource != NULL) { 01217 fileSource->seekToByteAbsolute(offsetInFile); 01218 resetStateAfterSeeking(); 01219 } 01220 }
| void MatroskaFileParser::seekToEndOfFile | ( | ) | [private] |
Definition at line 1222 of file MatroskaFileParser.cpp.
References fInputSource, NULL, resetStateAfterSeeking(), and ByteStreamFileSource::seekToEnd().
Referenced by seekToTime().
01222 { 01223 ByteStreamFileSource* fileSource = (ByteStreamFileSource*)fInputSource; // we know it's a "ByteStreamFileSource" 01224 if (fileSource != NULL) { 01225 fileSource->seekToEnd(); 01226 resetStateAfterSeeking(); 01227 } 01228 }
| void MatroskaFileParser::resetStateAfterSeeking | ( | ) | [private] |
Definition at line 1230 of file MatroskaFileParser.cpp.
References fCurOffsetInFile, fCurOffsetWithinFrame, StreamParser::flushInput(), fSavedCurOffsetInFile, and fSavedCurOffsetWithinFrame.
Referenced by seekToEndOfFile(), and seekToFilePosition().
01230 { 01231 // Because we're resuming parsing after seeking to a new position in the file, reset the parser state: 01232 fCurOffsetInFile = fSavedCurOffsetInFile = 0; 01233 fCurOffsetWithinFrame = fSavedCurOffsetWithinFrame = 0; 01234 flushInput(); 01235 }
| void MatroskaFileParser::restoreSavedParserState | ( | ) | [private, virtual] |
Reimplemented from StreamParser.
Definition at line 1208 of file MatroskaFileParser.cpp.
References fCurOffsetInFile, fCurOffsetWithinFrame, fSavedCurOffsetInFile, fSavedCurOffsetWithinFrame, and StreamParser::restoreSavedParserState().
Referenced by deliverFrameWithinBlock().
01208 { 01209 StreamParser::restoreSavedParserState(); 01210 fCurOffsetInFile = fSavedCurOffsetInFile; 01211 fCurOffsetWithinFrame = fSavedCurOffsetWithinFrame; 01212 }
| void StreamParser::flushInput | ( | ) | [virtual, inherited] |
Reimplemented in H264VideoStreamParser, 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(), H264VideoStreamParser::flushInput(), AC3AudioStreamFramer::flushInput(), and resetStateAfterSeeking().
00028 { 00029 fCurParserIndex = fSavedParserIndex = 0; 00030 fSavedRemainingUnparsedBits = fRemainingUnparsedBits = 0; 00031 fTotNumValidBytes = 0; 00032 }
| 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 MPEG1or2AudioStreamParser::parse(), AC3AudioStreamParser::parseFrame(), MPEGVideoStreamParser::setParseState(), MPEGProgramStreamParser::setParseState(), setParseState(), and H263plusVideoStreamParser::setParseState().
00058 { 00059 fSavedParserIndex = fCurParserIndex; 00060 fSavedRemainingUnparsedBits = fRemainingUnparsedBits; 00061 }
| 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(), 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(), H264VideoStreamParser::parse(), AC3AudioStreamParser::parseFrame(), MPEG1or2VideoStreamParser::parseGOPHeader(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), 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(), H264VideoStreamParser::parse(), parseBlock(), parseEBMLNumber(), parseEBMLVal_binary(), parseEBMLVal_string(), parseEBMLVal_unsigned64(), MPEG1or2VideoStreamParser::parseGOPHeader(), H263plusVideoStreamParser::parseH263Frame(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), 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 | ( | unsigned | numBytes | ) | [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(), MPEG1or2AudioStreamParser::parse(), AC3AudioStreamParser::parseFrame(), MPEG4VideoStreamParser::parseGroupOfVideoObjectPlane(), H263plusVideoStreamParser::parseH263Frame(), 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(), and H264VideoStreamParser::parse().
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(), H264VideoStreamParser::parse(), parseBlock(), AC3AudioStreamParser::parseFrame(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), MPEGProgramStreamParser::parseSystemHeader(), and skipHeader().
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 MPEGProgramStreamParser::parsePackHeader(), and MPEGProgramStreamParser::parsePESPacket().
00082 { 00083 if (numBits <= fRemainingUnparsedBits) { 00084 unsigned char lastByte = *lastParsed(); 00085 lastByte >>= (fRemainingUnparsedBits - numBits); 00086 fRemainingUnparsedBits -= numBits; 00087 00088 return (unsigned)lastByte &~ ((~0)<<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 &=~ ((~0)<<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 H264VideoStreamParser::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 H264VideoStreamParser::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 H264VideoStreamParser::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 skipHeader().
00115 { 00116 return BANK_SIZE; 00117 }
MatroskaFile& MatroskaFileParser::fOurFile [private] |
Definition at line 98 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 99 of file MatroskaFileParser.hh.
Referenced by continueParsing(), seekToEndOfFile(), seekToFilePosition(), and ~MatroskaFileParser().
void* MatroskaFileParser::fOnEndClientData [private] |
MatroskaDemux* MatroskaFileParser::fOurDemux [private] |
Definition at line 102 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and parseBlock().
Definition at line 103 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 104 of file MatroskaFileParser.hh.
Referenced by lookForNextTrack(), parseCues(), parseEBMLNumber(), parseEBMLVal_binary(), parseEBMLVal_string(), parseEBMLVal_unsigned64(), parseTrack(), resetStateAfterSeeking(), restoreSavedParserState(), setParseState(), and skipHeader().
u_int64_t MatroskaFileParser::fSavedCurOffsetInFile [private] |
Definition at line 104 of file MatroskaFileParser.hh.
Referenced by resetStateAfterSeeking(), restoreSavedParserState(), and setParseState().
u_int64_t MatroskaFileParser::fLimitOffsetInFile [private] |
Definition at line 104 of file MatroskaFileParser.hh.
Referenced by lookForNextTrack(), parseCues(), parseEBMLNumber(), parseEBMLVal_binary(), parseEBMLVal_string(), parseEBMLVal_unsigned64(), and parseTrack().
EBMLId MatroskaFileParser::fLastSeekId [private] |
unsigned MatroskaFileParser::fClusterTimecode [private] |
Definition at line 110 of file MatroskaFileParser.hh.
Referenced by deliverFrameWithinBlock(), lookForNextBlock(), and parseBlock().
unsigned MatroskaFileParser::fBlockSize [private] |
Definition at line 113 of file MatroskaFileParser.hh.
Referenced by lookForNextBlock(), and parseBlock().
unsigned MatroskaFileParser::fBlockTrackNumber [private] |
Definition at line 114 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and parseBlock().
short MatroskaFileParser::fBlockTimecode [private] |
Definition at line 115 of file MatroskaFileParser.hh.
Referenced by deliverFrameWithinBlock(), and parseBlock().
unsigned MatroskaFileParser::fNumFramesInBlock [private] |
Definition at line 116 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), and parseBlock().
unsigned* MatroskaFileParser::fFrameSizesWithinBlock [private] |
Definition at line 117 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), parseBlock(), and ~MatroskaFileParser().
double MatroskaFileParser::fPresentationTimeOffset [private] |
Definition at line 120 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), and deliverFrameWithinBlock().
unsigned MatroskaFileParser::fNextFrameNumberToDeliver [private] |
Definition at line 121 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and parseBlock().
unsigned MatroskaFileParser::fCurOffsetWithinFrame [private] |
Definition at line 122 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), getCommonFrameBytes(), parseBlock(), resetStateAfterSeeking(), restoreSavedParserState(), and setParseState().
unsigned MatroskaFileParser::fSavedCurOffsetWithinFrame [private] |
Definition at line 122 of file MatroskaFileParser.hh.
Referenced by resetStateAfterSeeking(), restoreSavedParserState(), and setParseState().
u_int8_t* MatroskaFileParser::fCurFrameTo [private] |
Definition at line 125 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), and getCommonFrameBytes().
unsigned MatroskaFileParser::fCurFrameNumBytesToGet [private] |
Definition at line 126 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), and getCommonFrameBytes().
unsigned MatroskaFileParser::fCurFrameNumBytesToSkip [private] |
Definition at line 127 of file MatroskaFileParser.hh.
Referenced by deliverFrameBytes(), and getCommonFrameBytes().
1.5.2