#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 (or else there was no input source, because the specified file name 00104 // didn't exist). Call our 'done' function now: 00105 if (fOnEndFunc != NULL) (*fOnEndFunc)(fOnEndClientData); 00106 }
| Boolean MatroskaFileParser::parse | ( | ) | [private] |
Definition at line 108 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().
00108 { 00109 Boolean areDone = False; 00110 00111 try { 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 skipHeader(size); 00193 00194 fCurrentParseState = LOOKING_FOR_TRACKS; 00195 return False; // because we have more parsing to do - inside the 'Track' header 00196 }
| void MatroskaFileParser::lookForNextTrack | ( | ) | [private] |
Definition at line 198 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().
00198 { 00199 #ifdef DEBUG 00200 fprintf(stderr, "looking for Track\n"); 00201 #endif 00202 EBMLId id; 00203 EBMLDataSize size; 00204 00205 // Read and skip over (or enter) each Matroska header, until we get to a 'Track'. 00206 while (fCurrentParseState == LOOKING_FOR_TRACKS) { 00207 while (!parseEBMLIdAndSize(id, size)) {} 00208 #ifdef DEBUG 00209 fprintf(stderr, "MatroskaFileParser::lookForNextTrack(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00210 #endif 00211 switch (id.val()) { 00212 case MATROSKA_ID_SEGMENT: { // 'Segment' header: enter this 00213 // Remember the position, within the file, of the start of Segment data, because Seek Positions are relative to this: 00214 fOurFile.fSegmentDataOffset = fCurOffsetInFile; 00215 break; 00216 } 00217 case MATROSKA_ID_SEEK_HEAD: { // 'Seek Head' header: enter this 00218 break; 00219 } 00220 case MATROSKA_ID_SEEK: { // 'Seek' header: enter this 00221 break; 00222 } 00223 case MATROSKA_ID_SEEK_ID: { // 'Seek ID' header: get this value 00224 if (parseEBMLNumber(fLastSeekId)) { 00225 #ifdef DEBUG 00226 fprintf(stderr, "\tSeek ID 0x%s:\t%s\n", fLastSeekId.hexString(), fLastSeekId.stringName()); 00227 #endif 00228 } 00229 break; 00230 } 00231 case MATROSKA_ID_SEEK_POSITION: { // 'Seek Position' header: get this value 00232 u_int64_t seekPosition; 00233 if (parseEBMLVal_unsigned64(size, seekPosition)) { 00234 u_int64_t offsetInFile = fOurFile.fSegmentDataOffset + seekPosition; 00235 #ifdef DEBUG 00236 fprintf(stderr, "\tSeek Position %llu (=> offset within the file: %llu (0x%llx))\n", seekPosition, offsetInFile, offsetInFile); 00237 #endif 00238 // The only 'Seek Position's that we care about are for 'Cluster' and 'Cues': 00239 if (fLastSeekId == MATROSKA_ID_CLUSTER) { 00240 fOurFile.fClusterOffset = offsetInFile; 00241 } else if (fLastSeekId == MATROSKA_ID_CUES) { 00242 fOurFile.fCuesOffset = offsetInFile; 00243 } 00244 } 00245 break; 00246 } 00247 case MATROSKA_ID_INFO: { // 'Segment Info' header: enter this 00248 break; 00249 } 00250 case MATROSKA_ID_TIMECODE_SCALE: { // 'Timecode Scale' header: get this value 00251 unsigned timecodeScale; 00252 if (parseEBMLVal_unsigned(size, timecodeScale) && timecodeScale > 0) { 00253 fOurFile.fTimecodeScale = timecodeScale; 00254 #ifdef DEBUG 00255 fprintf(stderr, "\tTimecode Scale %u ns (=> Segment Duration == %f seconds)\n", fOurFile.timecodeScale(), fOurFile.fileDuration()); 00256 #endif 00257 } 00258 break; 00259 } 00260 case MATROSKA_ID_DURATION: { // 'Segment Duration' header: get this value 00261 if (parseEBMLVal_float(size, fOurFile.fSegmentDuration)) { 00262 #ifdef DEBUG 00263 fprintf(stderr, "\tSegment Duration %f (== %f seconds)\n", fOurFile.segmentDuration(), fOurFile.fileDuration()); 00264 #endif 00265 } 00266 break; 00267 } 00268 case MATROSKA_ID_TRACKS: { // enter this, and move on to parsing 'Tracks' 00269 fLimitOffsetInFile = fCurOffsetInFile + size.val(); // Make sure we don't read past the end of this header 00270 fCurrentParseState = PARSING_TRACK; 00271 break; 00272 } 00273 default: { // skip over this header 00274 skipHeader(size); 00275 #ifdef DEBUG 00276 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00277 #endif 00278 break; 00279 } 00280 } 00281 setParseState(); 00282 } 00283 }
| Boolean MatroskaFileParser::parseTrack | ( | ) | [private] |
Definition at line 285 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().
00285 { 00286 #ifdef DEBUG 00287 fprintf(stderr, "parsing Track\n"); 00288 #endif 00289 // Read and process each Matroska header, until we get to the end of the Track: 00290 MatroskaTrack* track = NULL; 00291 EBMLId id; 00292 EBMLDataSize size; 00293 while (fCurOffsetInFile < fLimitOffsetInFile) { 00294 while (!parseEBMLIdAndSize(id, size)) {} 00295 #ifdef DEBUG 00296 if (id == MATROSKA_ID_TRACK_ENTRY) fprintf(stderr, "\n"); // makes debugging output easier to read 00297 fprintf(stderr, "MatroskaFileParser::parseTrack(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00298 #endif 00299 switch (id.val()) { 00300 case MATROSKA_ID_TRACK_ENTRY: { // 'Track Entry' header: enter this 00301 // Create a new "MatroskaTrack" object for this entry: 00302 if (track != NULL && track->trackNumber == 0) delete track; // We had a previous "MatroskaTrack" object that was never used 00303 track = new MatroskaTrack; 00304 break; 00305 } 00306 case MATROSKA_ID_TRACK_NUMBER: { 00307 unsigned trackNumber; 00308 if (parseEBMLVal_unsigned(size, trackNumber)) { 00309 #ifdef DEBUG 00310 fprintf(stderr, "\tTrack Number %d\n", trackNumber); 00311 #endif 00312 if (track != NULL && trackNumber != 0) { 00313 track->trackNumber = trackNumber; 00314 fOurFile.fTracks.add(track, trackNumber); 00315 } 00316 } 00317 break; 00318 } 00319 case MATROSKA_ID_TRACK_TYPE: { 00320 unsigned trackType; 00321 if (parseEBMLVal_unsigned(size, trackType) && track != NULL) { 00322 // We convert the Matroska 'track type' code into our own code (which we can use as a bitmap): 00323 track->trackType 00324 = trackType == 1 ? MATROSKA_TRACK_TYPE_VIDEO : trackType == 2 ? MATROSKA_TRACK_TYPE_AUDIO 00325 : trackType == 0x11 ? MATROSKA_TRACK_TYPE_SUBTITLE : MATROSKA_TRACK_TYPE_OTHER; 00326 #ifdef DEBUG 00327 fprintf(stderr, "\tTrack Type 0x%02x (%s)\n", trackType, 00328 track->trackType == MATROSKA_TRACK_TYPE_VIDEO ? "video" : 00329 track->trackType == MATROSKA_TRACK_TYPE_AUDIO ? "audio" : 00330 track->trackType == MATROSKA_TRACK_TYPE_SUBTITLE ? "subtitle" : 00331 "<other>"); 00332 #endif 00333 } 00334 break; 00335 } 00336 case MATROSKA_ID_FLAG_ENABLED: { 00337 unsigned flagEnabled; 00338 if (parseEBMLVal_unsigned(size, flagEnabled)) { 00339 #ifdef DEBUG 00340 fprintf(stderr, "\tTrack is Enabled: %d\n", flagEnabled); 00341 #endif 00342 if (track != NULL) track->isEnabled = flagEnabled != 0; 00343 } 00344 break; 00345 } 00346 case MATROSKA_ID_FLAG_DEFAULT: { 00347 unsigned flagDefault; 00348 if (parseEBMLVal_unsigned(size, flagDefault)) { 00349 #ifdef DEBUG 00350 fprintf(stderr, "\tTrack is Default: %d\n", flagDefault); 00351 #endif 00352 if (track != NULL) track->isDefault = flagDefault != 0; 00353 } 00354 break; 00355 } 00356 case MATROSKA_ID_FLAG_FORCED: { 00357 unsigned flagForced; 00358 if (parseEBMLVal_unsigned(size, flagForced)) { 00359 #ifdef DEBUG 00360 fprintf(stderr, "\tTrack is Forced: %d\n", flagForced); 00361 #endif 00362 if (track != NULL) track->isForced = flagForced != 0; 00363 } 00364 break; 00365 } 00366 case MATROSKA_ID_DEFAULT_DURATION: { 00367 unsigned defaultDuration; 00368 if (parseEBMLVal_unsigned(size, defaultDuration)) { 00369 #ifdef DEBUG 00370 fprintf(stderr, "\tDefault duration %f ms\n", defaultDuration/1000000.0); 00371 #endif 00372 if (track != NULL) track->defaultDuration = defaultDuration; 00373 } 00374 break; 00375 } 00376 case MATROSKA_ID_MAX_BLOCK_ADDITION_ID: { 00377 unsigned maxBlockAdditionID; 00378 if (parseEBMLVal_unsigned(size, maxBlockAdditionID)) { 00379 #ifdef DEBUG 00380 fprintf(stderr, "\tMax Block Addition ID: %u\n", maxBlockAdditionID); 00381 #endif 00382 } 00383 break; 00384 } 00385 case MATROSKA_ID_NAME: { 00386 char* name; 00387 if (parseEBMLVal_string(size, name)) { 00388 #ifdef DEBUG 00389 fprintf(stderr, "\tName: %s\n", name); 00390 #endif 00391 if (track != NULL) { 00392 delete[] track->name; track->name = name; 00393 } else { 00394 delete[] name; 00395 } 00396 } 00397 break; 00398 } 00399 case MATROSKA_ID_LANGUAGE: { 00400 char* language; 00401 if (parseEBMLVal_string(size, language)) { 00402 #ifdef DEBUG 00403 fprintf(stderr, "\tLanguage: %s\n", language); 00404 #endif 00405 if (track != NULL) { 00406 delete[] track->language; track->language = language; 00407 } else { 00408 delete[] language; 00409 } 00410 } 00411 break; 00412 } 00413 case MATROSKA_ID_CODEC: { 00414 char* codecID; 00415 if (parseEBMLVal_string(size, codecID)) { 00416 #ifdef DEBUG 00417 fprintf(stderr, "\tCodec ID: %s\n", codecID); 00418 #endif 00419 if (track != NULL) { 00420 delete[] track->codecID; track->codecID = codecID; 00421 } else { 00422 delete[] codecID; 00423 } 00424 } 00425 break; 00426 } 00427 case MATROSKA_ID_CODEC_PRIVATE: { 00428 u_int8_t* codecPrivate; 00429 unsigned codecPrivateSize; 00430 if (parseEBMLVal_binary(size, codecPrivate)) { 00431 codecPrivateSize = (unsigned)size.val(); 00432 #ifdef DEBUG 00433 fprintf(stderr, "\tCodec Private: "); 00434 for (unsigned i = 0; i < codecPrivateSize; ++i) fprintf(stderr, "%02x:", codecPrivate[i]); 00435 fprintf(stderr, "\n"); 00436 #endif 00437 if (track != NULL) { 00438 delete[] track->codecPrivate; track->codecPrivate = codecPrivate; 00439 track->codecPrivateSize = codecPrivateSize; 00440 } else { 00441 delete[] codecPrivate; 00442 } 00443 } 00444 break; 00445 } 00446 case MATROSKA_ID_VIDEO: { // 'Video settings' header: enter this 00447 break; 00448 } 00449 case MATROSKA_ID_PIXEL_WIDTH: { 00450 unsigned pixelWidth; 00451 if (parseEBMLVal_unsigned(size, pixelWidth)) { 00452 #ifdef DEBUG 00453 fprintf(stderr, "\tPixel Width %d\n", pixelWidth); 00454 #endif 00455 } 00456 break; 00457 } 00458 case MATROSKA_ID_PIXEL_HEIGHT: { 00459 unsigned pixelHeight; 00460 if (parseEBMLVal_unsigned(size, pixelHeight)) { 00461 #ifdef DEBUG 00462 fprintf(stderr, "\tPixel Height %d\n", pixelHeight); 00463 #endif 00464 } 00465 break; 00466 } 00467 case MATROSKA_ID_DISPLAY_WIDTH: { 00468 unsigned displayWidth; 00469 if (parseEBMLVal_unsigned(size, displayWidth)) { 00470 #ifdef DEBUG 00471 fprintf(stderr, "\tDisplay Width %d\n", displayWidth); 00472 #endif 00473 } 00474 break; 00475 } 00476 case MATROSKA_ID_DISPLAY_HEIGHT: { 00477 unsigned displayHeight; 00478 if (parseEBMLVal_unsigned(size, displayHeight)) { 00479 #ifdef DEBUG 00480 fprintf(stderr, "\tDisplay Height %d\n", displayHeight); 00481 #endif 00482 } 00483 break; 00484 } 00485 case MATROSKA_ID_AUDIO: { // 'Audio settings' header: enter this 00486 break; 00487 } 00488 case MATROSKA_ID_SAMPLING_FREQUENCY: { 00489 float samplingFrequency; 00490 if (parseEBMLVal_float(size, samplingFrequency)) { 00491 if (track != NULL) { 00492 track->samplingFrequency = (unsigned)samplingFrequency; 00493 #ifdef DEBUG 00494 fprintf(stderr, "\tSampling frequency %f (->%d)\n", samplingFrequency, track->samplingFrequency); 00495 #endif 00496 } 00497 } 00498 break; 00499 } 00500 case MATROSKA_ID_OUTPUT_SAMPLING_FREQUENCY: { 00501 float outputSamplingFrequency; 00502 if (parseEBMLVal_float(size, outputSamplingFrequency)) { 00503 #ifdef DEBUG 00504 fprintf(stderr, "\tOutput sampling frequency %f\n", outputSamplingFrequency); 00505 #endif 00506 } 00507 break; 00508 } 00509 case MATROSKA_ID_CHANNELS: { 00510 unsigned numChannels; 00511 if (parseEBMLVal_unsigned(size, numChannels)) { 00512 #ifdef DEBUG 00513 fprintf(stderr, "\tChannels %d\n", numChannels); 00514 #endif 00515 if (track != NULL) track->numChannels = numChannels; 00516 } 00517 break; 00518 } 00519 case MATROSKA_ID_CONTENT_ENCODINGS: 00520 case MATROSKA_ID_CONTENT_ENCODING: { // 'Content Encodings' or 'Content Encoding' header: enter this 00521 break; 00522 } 00523 case MATROSKA_ID_CONTENT_COMPRESSION: { // 'Content Compression' header: enter this 00524 // Note: We currently support only 'Header Stripping' compression, not 'zlib' compression (the default algorithm). 00525 // Therefore, we disable this track, unless/until we later see that 'Header Stripping' is supported: 00526 if (track != NULL) track->isEnabled = False; 00527 break; 00528 } 00529 case MATROSKA_ID_CONTENT_COMP_ALGO: { 00530 unsigned contentCompAlgo; 00531 if (parseEBMLVal_unsigned(size, contentCompAlgo)) { 00532 #ifdef DEBUG 00533 fprintf(stderr, "\tContent Compression Algorithm %d (%s)\n", contentCompAlgo, 00534 contentCompAlgo == 0 ? "zlib" : contentCompAlgo == 3 ? "Header Stripping" : "<unknown>"); 00535 #endif 00536 // The only compression algorithm that we support is #3: Header Stripping; disable the track otherwise 00537 if (track != NULL) track->isEnabled = contentCompAlgo == 3; 00538 } 00539 break; 00540 } 00541 case MATROSKA_ID_CONTENT_COMP_SETTINGS: { 00542 u_int8_t* headerStrippedBytes; 00543 unsigned headerStrippedBytesSize; 00544 if (parseEBMLVal_binary(size, headerStrippedBytes)) { 00545 headerStrippedBytesSize = (unsigned)size.val(); 00546 #ifdef DEBUG 00547 fprintf(stderr, "\tHeader Stripped Bytes: "); 00548 for (unsigned i = 0; i < headerStrippedBytesSize; ++i) fprintf(stderr, "%02x:", headerStrippedBytes[i]); 00549 fprintf(stderr, "\n"); 00550 #endif 00551 if (track != NULL) { 00552 delete[] track->headerStrippedBytes; track->headerStrippedBytes = headerStrippedBytes; 00553 track->headerStrippedBytesSize = headerStrippedBytesSize; 00554 } else { 00555 delete[] headerStrippedBytes; 00556 } 00557 } 00558 break; 00559 } 00560 case MATROSKA_ID_CONTENT_ENCRYPTION: { // 'Content Encrpytion' header: skip this 00561 // Note: We don't currently support encryption at all. Therefore, we disable this track: 00562 if (track != NULL) track->isEnabled = False; 00563 // Fall through to... 00564 } 00565 default: { // We don't process this header, so just skip over it: 00566 skipHeader(size); 00567 #ifdef DEBUG 00568 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00569 #endif 00570 break; 00571 } 00572 } 00573 setParseState(); 00574 } 00575 00576 fLimitOffsetInFile = 0; // reset 00577 if (track != NULL && track->trackNumber == 0) delete track; // We had a previous "MatroskaTrack" object that was never used 00578 return True; // we're done parsing track entries 00579 }
| Boolean MatroskaFileParser::parseCues | ( | ) | [private] |
Definition at line 640 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().
00640 { 00641 #if defined(DEBUG) || defined(DEBUG_CUES) 00642 fprintf(stderr, "parsing Cues\n"); 00643 #endif 00644 EBMLId id; 00645 EBMLDataSize size; 00646 00647 // Read the next header, which should be MATROSKA_ID_CUES: 00648 if (!parseEBMLIdAndSize(id, size) || id != MATROSKA_ID_CUES) return True; // The header wasn't what we expected, so we're done 00649 fLimitOffsetInFile = fCurOffsetInFile + size.val(); // Make sure we don't read past the end of this header 00650 00651 double currentCueTime = 0.0; 00652 u_int64_t currentClusterOffsetInFile = 0; 00653 00654 while (fCurOffsetInFile < fLimitOffsetInFile) { 00655 while (!parseEBMLIdAndSize(id, size)) {} 00656 #ifdef DEBUG_CUES 00657 if (id == MATROSKA_ID_CUE_POINT) fprintf(stderr, "\n"); // makes debugging output easier to read 00658 fprintf(stderr, "MatroskaFileParser::parseCues(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00659 #endif 00660 switch (id.val()) { 00661 case MATROSKA_ID_CUE_POINT: { // 'Cue Point' header: enter this 00662 break; 00663 } 00664 case MATROSKA_ID_CUE_TIME: { // 'Cue Time' header: get this value 00665 unsigned cueTime; 00666 if (parseEBMLVal_unsigned(size, cueTime)) { 00667 currentCueTime = cueTime*(fOurFile.fTimecodeScale/1000000000.0); 00668 #ifdef DEBUG_CUES 00669 fprintf(stderr, "\tCue Time %d (== %f seconds)\n", cueTime, currentCueTime); 00670 #endif 00671 } 00672 break; 00673 } 00674 case MATROSKA_ID_CUE_TRACK_POSITIONS: { // 'Cue Track Positions' header: enter this 00675 break; 00676 } 00677 case MATROSKA_ID_CUE_TRACK: { // 'Cue Track' header: get this value (but only for debugging; we don't do anything with it) 00678 unsigned cueTrack; 00679 if (parseEBMLVal_unsigned(size, cueTrack)) { 00680 #ifdef DEBUG_CUES 00681 fprintf(stderr, "\tCue Track %d\n", cueTrack); 00682 #endif 00683 } 00684 break; 00685 } 00686 case MATROSKA_ID_CUE_CLUSTER_POSITION: { // 'Cue Cluster Position' header: get this value 00687 u_int64_t cueClusterPosition; 00688 if (parseEBMLVal_unsigned64(size, cueClusterPosition)) { 00689 currentClusterOffsetInFile = fOurFile.fSegmentDataOffset + cueClusterPosition; 00690 #ifdef DEBUG_CUES 00691 fprintf(stderr, "\tCue Cluster Position %llu (=> offset within the file: %llu (0x%llx))\n", cueClusterPosition, currentClusterOffsetInFile, currentClusterOffsetInFile); 00692 #endif 00693 // Record this cue point: 00694 fOurFile.addCuePoint(currentCueTime, currentClusterOffsetInFile, 1/*default block number within cluster*/); 00695 } 00696 break; 00697 } 00698 case MATROSKA_ID_CUE_BLOCK_NUMBER: { // 'Cue Block Number' header: get this value 00699 unsigned cueBlockNumber; 00700 if (parseEBMLVal_unsigned(size, cueBlockNumber) && cueBlockNumber != 0) { 00701 #ifdef DEBUG_CUES 00702 fprintf(stderr, "\tCue Block Number %d\n", cueBlockNumber); 00703 #endif 00704 // Record this cue point (overwriting any existing entry for this cue time): 00705 fOurFile.addCuePoint(currentCueTime, currentClusterOffsetInFile, cueBlockNumber); 00706 } 00707 break; 00708 } 00709 default: { // We don't process this header, so just skip over it: 00710 skipHeader(size); 00711 #ifdef DEBUG_CUES 00712 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00713 #endif 00714 break; 00715 } 00716 } 00717 setParseState(); 00718 } 00719 00720 fLimitOffsetInFile = 0; // reset 00721 #if defined(DEBUG) || defined(DEBUG_CUES) 00722 fprintf(stderr, "done parsing Cues\n"); 00723 #endif 00724 #ifdef DEBUG_CUES 00725 fprintf(stderr, "Cue Point tree: "); 00726 fOurFile.printCuePoints(stderr); 00727 fprintf(stderr, "\n"); 00728 #endif 00729 return True; // we're done parsing Cues 00730 }
| void MatroskaFileParser::lookForNextBlock | ( | ) | [private] |
Definition at line 581 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().
00581 { 00582 #ifdef DEBUG 00583 fprintf(stderr, "looking for Block\n"); 00584 #endif 00585 // Read and skip over each Matroska header, until we get to a 'Cluster': 00586 EBMLId id; 00587 EBMLDataSize size; 00588 while (fCurrentParseState == LOOKING_FOR_BLOCK) { 00589 while (!parseEBMLIdAndSize(id, size)) {} 00590 #ifdef DEBUG 00591 fprintf(stderr, "MatroskaFileParser::lookForNextBlock(): Parsed id 0x%s (%s), size: %lld\n", id.hexString(), id.stringName(), size.val()); 00592 #endif 00593 switch (id.val()) { 00594 case MATROSKA_ID_SEGMENT: { // 'Segment' header: enter this 00595 break; 00596 } 00597 case MATROSKA_ID_CLUSTER: { // 'Cluster' header: enter this 00598 break; 00599 } 00600 case MATROSKA_ID_TIMECODE: { // 'Timecode' header: get this value 00601 unsigned timecode; 00602 if (parseEBMLVal_unsigned(size, timecode)) { 00603 fClusterTimecode = timecode; 00604 #ifdef DEBUG 00605 fprintf(stderr, "\tCluster timecode: %d (== %f seconds)\n", fClusterTimecode, fClusterTimecode*(fOurFile.fTimecodeScale/1000000000.0)); 00606 #endif 00607 } 00608 break; 00609 } 00610 case MATROSKA_ID_BLOCK_GROUP: { // 'Block Group' header: enter this 00611 break; 00612 } 00613 case MATROSKA_ID_SIMPLEBLOCK: 00614 case MATROSKA_ID_BLOCK: { // 'SimpleBlock' or 'Block' header: enter this (and we're done) 00615 fBlockSize = (unsigned)size.val(); 00616 fCurrentParseState = PARSING_BLOCK; 00617 break; 00618 } 00619 case MATROSKA_ID_BLOCK_DURATION: { // 'Block Duration' header: get this value (but we currently don't do anything with it) 00620 unsigned blockDuration; 00621 if (parseEBMLVal_unsigned(size, blockDuration)) { 00622 #ifdef DEBUG 00623 fprintf(stderr, "\tblock duration: %d (== %f ms)\n", blockDuration, (float)(blockDuration*fOurFile.fTimecodeScale/1000000.0)); 00624 #endif 00625 } 00626 break; 00627 } 00628 default: { // skip over this header 00629 skipHeader(size); 00630 #ifdef DEBUG 00631 fprintf(stderr, "\tskipped %lld bytes\n", size.val()); 00632 #endif 00633 break; 00634 } 00635 } 00636 setParseState(); 00637 } 00638 }
| void MatroskaFileParser::parseBlock | ( | ) | [private] |
Definition at line 734 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().
00734 { 00735 #ifdef DEBUG 00736 fprintf(stderr, "parsing SimpleBlock or Block\n"); 00737 #endif 00738 do { 00739 unsigned blockStartPos = curOffset(); 00740 00741 // The block begins with the track number: 00742 EBMLNumber trackNumber; 00743 if (!parseEBMLNumber(trackNumber)) break; 00744 fBlockTrackNumber = (unsigned)trackNumber.val(); 00745 00746 // If this track is not being read, then skip the rest of this block, and look for another one: 00747 if (fOurDemux->lookupDemuxedTrack(fBlockTrackNumber) == NULL) { 00748 unsigned headerBytesSeen = curOffset() - blockStartPos; 00749 if (headerBytesSeen < fBlockSize) { 00750 skipBytes(fBlockSize - headerBytesSeen); 00751 } 00752 #ifdef DEBUG 00753 fprintf(stderr, "\tSkipped block for unused track number %d\n", fBlockTrackNumber); 00754 #endif 00755 fCurrentParseState = LOOKING_FOR_BLOCK; 00756 setParseState(); 00757 return; 00758 } 00759 00760 MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber); 00761 if (track == NULL) break; // shouldn't happen 00762 00763 // The next two bytes are the block's timecode (relative to the cluster timecode) 00764 fBlockTimecode = (get1Byte()<<8)|get1Byte(); 00765 00766 // The next byte indicates the type of 'lacing' used: 00767 u_int8_t c = get1Byte(); 00768 c &= 0x6; // we're interested in bits 5-6 only 00769 MatroskaLacingType lacingType = (c==0x0)?NoLacing : (c==0x02)?XiphLacing : (c==0x04)?FixedSizeLacing : EBMLLacing; 00770 #ifdef DEBUG 00771 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"); 00772 #endif 00773 00774 if (lacingType == NoLacing) { 00775 fNumFramesInBlock = 1; 00776 } else { 00777 // The next byte tells us how many frames are present in this block 00778 fNumFramesInBlock = get1Byte() + 1; 00779 } 00780 delete[] fFrameSizesWithinBlock; fFrameSizesWithinBlock = new unsigned[fNumFramesInBlock]; 00781 if (fFrameSizesWithinBlock == NULL) break; 00782 00783 if (lacingType == NoLacing) { 00784 unsigned headerBytesSeen = curOffset() - blockStartPos; 00785 if (headerBytesSeen > fBlockSize) break; 00786 00787 fFrameSizesWithinBlock[0] = fBlockSize - headerBytesSeen; 00788 } else if (lacingType == FixedSizeLacing) { 00789 unsigned headerBytesSeen = curOffset() - blockStartPos; 00790 if (headerBytesSeen > fBlockSize) break; 00791 00792 unsigned frameBytesAvailable = fBlockSize - headerBytesSeen; 00793 unsigned constantFrameSize = frameBytesAvailable/fNumFramesInBlock; 00794 00795 for (unsigned i = 0; i < fNumFramesInBlock; ++i) { 00796 fFrameSizesWithinBlock[i] = constantFrameSize; 00797 } 00798 // If there are any bytes left over, assign them to the last frame: 00799 fFrameSizesWithinBlock[fNumFramesInBlock-1] += frameBytesAvailable%fNumFramesInBlock; 00800 } else { // EBML or Xiph lacing 00801 unsigned curFrameSize = 0; 00802 unsigned frameSizesTotal = 0; 00803 unsigned i; 00804 00805 for (i = 0; i < fNumFramesInBlock-1; ++i) { 00806 if (lacingType == EBMLLacing) { 00807 EBMLNumber frameSize; 00808 if (!parseEBMLNumber(frameSize)) break; 00809 unsigned fsv = (unsigned)frameSize.val(); 00810 00811 if (i == 0) { 00812 curFrameSize = fsv; 00813 } else { 00814 // The value we read is a signed value, that's added to the previous frame size, to get the current frame size: 00815 unsigned toSubtract = (fsv>0xFFFFFF)?0x07FFFFFF : (fsv>0xFFFF)?0x0FFFFF : (fsv>0xFF)?0x1FFF : 0x3F; 00816 int fsv_signed = fsv - toSubtract; 00817 curFrameSize += fsv_signed; 00818 if ((int)curFrameSize < 0) break; 00819 } 00820 } else { // Xiph lacing 00821 curFrameSize = 0; 00822 u_int8_t c; 00823 do { 00824 c = get1Byte(); 00825 curFrameSize += c; 00826 } while (c == 0xFF); 00827 } 00828 fFrameSizesWithinBlock[i] = curFrameSize; 00829 frameSizesTotal += curFrameSize; 00830 } 00831 if (i != fNumFramesInBlock-1) break; // an error occurred within the "for" loop 00832 00833 // Compute the size of the final frame within the block (from the block's size, and the frame sizes already computed):) 00834 unsigned headerBytesSeen = curOffset() - blockStartPos; 00835 if (headerBytesSeen + frameSizesTotal > fBlockSize) break; 00836 fFrameSizesWithinBlock[i] = fBlockSize - (headerBytesSeen + frameSizesTotal); 00837 } 00838 00839 // We're done parsing headers within the block, and (as a result) we now know the sizes of all frames within the block. 00840 // If we have 'stripped bytes' that are common to (the front of) all frames, then count them now: 00841 if (track->headerStrippedBytesSize != 0) { 00842 for (unsigned i = 0; i < fNumFramesInBlock; ++i) fFrameSizesWithinBlock[i] += track->headerStrippedBytesSize; 00843 } 00844 #ifdef DEBUG 00845 fprintf(stderr, "\tThis block contains %d frame(s); size(s):", fNumFramesInBlock); 00846 unsigned frameSizesTotal = 0; 00847 for (unsigned i = 0; i < fNumFramesInBlock; ++i) { 00848 fprintf(stderr, " %d", fFrameSizesWithinBlock[i]); 00849 frameSizesTotal += fFrameSizesWithinBlock[i]; 00850 } 00851 if (fNumFramesInBlock > 1) fprintf(stderr, " (total: %u)", frameSizesTotal); 00852 fprintf(stderr, " bytes\n"); 00853 #endif 00854 // Next, start delivering these frames: 00855 fCurrentParseState = DELIVERING_FRAME_WITHIN_BLOCK; 00856 fCurOffsetWithinFrame = fNextFrameNumberToDeliver = 0; 00857 setParseState(); 00858 return; 00859 } while (0); 00860 00861 // An error occurred. Try to recover: 00862 #ifdef DEBUG 00863 fprintf(stderr, "parseBlock(): Error parsing data; trying to recover...\n"); 00864 #endif 00865 fCurrentParseState = LOOKING_FOR_BLOCK; 00866 }
| Boolean MatroskaFileParser::deliverFrameWithinBlock | ( | ) | [private] |
Definition at line 868 of file MatroskaFileParser.cpp.
References MatroskaTrack::defaultDuration, DELIVERING_FRAME_BYTES, MatroskaTrack::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(), MatroskaTrack::prevPresentationTime, restoreSavedParserState(), setParseState(), MatroskaTrack::subframeSizeSize, MatroskaDemuxedTrack::to(), and True.
Referenced by parse().
00868 { 00869 #ifdef DEBUG 00870 fprintf(stderr, "delivering frame within SimpleBlock or Block\n"); 00871 #endif 00872 do { 00873 MatroskaTrack* track = fOurFile.lookup(fBlockTrackNumber); 00874 if (track == NULL) break; // shouldn't happen 00875 00876 MatroskaDemuxedTrack* demuxedTrack = fOurDemux->lookupDemuxedTrack(fBlockTrackNumber); 00877 if (demuxedTrack == NULL) break; // shouldn't happen 00878 if (!demuxedTrack->isCurrentlyAwaitingData()) { 00879 // Someone has been reading this stream, but isn't right now. 00880 // We can't deliver this frame until he asks for it, so punt for now. 00881 // The next time he asks for a frame, he'll get it. 00882 #ifdef DEBUG 00883 fprintf(stderr, "\tdeferring delivery of frame #%d (%d bytes)", fNextFrameNumberToDeliver, fFrameSizesWithinBlock[fNextFrameNumberToDeliver]); 00884 if (track->haveSubframes()) fprintf(stderr, "[offset %d]", fCurOffsetWithinFrame); 00885 fprintf(stderr, "\n"); 00886 #endif 00887 restoreSavedParserState(); // so we read from the beginning next time 00888 return False; 00889 } 00890 00891 unsigned frameSize = fFrameSizesWithinBlock[fNextFrameNumberToDeliver]; 00892 if (track->haveSubframes()) { 00893 // The next "track->subframeSizeSize" bytes contain the length of a 'subframe': 00894 if (fCurOffsetWithinFrame + track->subframeSizeSize > frameSize) break; // sanity check 00895 unsigned subframeSize = 0; 00896 for (unsigned i = 0; i < track->subframeSizeSize; ++i) { 00897 u_int8_t c; 00898 getCommonFrameBytes(track, &c, 1, 0); 00899 if (fCurFrameNumBytesToGet > 0) { // it'll be 1 00900 c = get1Byte(); 00901 ++fCurOffsetWithinFrame; 00902 } 00903 subframeSize = subframeSize*256 + c; 00904 } 00905 if (subframeSize == 0 || fCurOffsetWithinFrame + subframeSize > frameSize) break; // sanity check 00906 frameSize = subframeSize; 00907 } 00908 00909 // Compute the presentation time of this frame (from the cluster timecode, the block timecode, and the default duration): 00910 double pt = (fClusterTimecode+fBlockTimecode)*(fOurFile.fTimecodeScale/1000000000.0) 00911 + fNextFrameNumberToDeliver*(track->defaultDuration/1000000000.0); 00912 if (fPresentationTimeOffset == 0.0) { 00913 // This is the first time we've computed a presentation time. Compute an offset to make the presentation times aligned 00914 // with 'wall clock' time: 00915 struct timeval timeNow; 00916 gettimeofday(&timeNow, NULL); 00917 double ptNow = timeNow.tv_sec + timeNow.tv_usec/1000000.0; 00918 fPresentationTimeOffset = ptNow - pt; 00919 } 00920 pt += fPresentationTimeOffset; 00921 struct timeval presentationTime; 00922 presentationTime.tv_sec = (unsigned)pt; 00923 presentationTime.tv_usec = (unsigned)((pt - presentationTime.tv_sec)*1000000); 00924 unsigned durationInMicroseconds = track->defaultDuration/1000; 00925 if (track->haveSubframes()) { 00926 // If this is a 'subframe', use a duration of 0 instead (unless it's the last 'subframe'): 00927 if (fCurOffsetWithinFrame + frameSize + track->subframeSizeSize < fFrameSizesWithinBlock[fNextFrameNumberToDeliver]) { 00928 // There's room for at least one more subframe after this, so give this subframe a duration of 0 00929 durationInMicroseconds = 0; 00930 } 00931 } 00932 00933 if (track->defaultDuration == 0) { 00934 // Adjust the frame duration to keep the sum of frame durations aligned with presentation times. 00935 if (track->prevPresentationTime.tv_sec != 0) { // not the first time for this track 00936 track->durationImbalance 00937 += (presentationTime.tv_sec - track->prevPresentationTime.tv_sec)*1000000 00938 + (presentationTime.tv_usec - track->prevPresentationTime.tv_usec); 00939 } 00940 int adjustment = 0; 00941 if (track->durationImbalance > 0) { 00942 // The duration needs to be increased. 00943 int const adjustmentThreshold = 100000; // don't increase the duration by more than this amount (in case there's a mistake) 00944 adjustment = track->durationImbalance > adjustmentThreshold ? adjustmentThreshold : track->durationImbalance; 00945 } else if (track->durationImbalance < 0) { 00946 // The duration needs to be decreased. 00947 adjustment 00948 = (unsigned)(-track->durationImbalance) < durationInMicroseconds ? track->durationImbalance : -(int)durationInMicroseconds; 00949 } 00950 durationInMicroseconds += adjustment; 00951 track->durationImbalance -= durationInMicroseconds; // for next time 00952 track->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 result = *(float*)&resultAsUnsigned; 01137 return True; 01138 }
| Boolean MatroskaFileParser::parseEBMLVal_string | ( | EBMLDataSize & | size, | |
| char *& | result | |||
| ) | [private] |
Definition at line 1140 of file MatroskaFileParser.cpp.
References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), NULL, size, and True.
Referenced by parseTrack().
01140 { 01141 unsigned resultLength = (unsigned)size.val(); 01142 result = new char[resultLength + 1]; // allow for the trailing '\0' 01143 if (result == NULL) return False; 01144 01145 char* p = result; 01146 unsigned i; 01147 for (i = 0; i < resultLength; ++i) { 01148 if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) break; // We've hit our pre-set limit 01149 01150 u_int8_t c = get1Byte(); 01151 ++fCurOffsetInFile; 01152 01153 *p++ = c; 01154 } 01155 if (i < resultLength) { // an error occurred 01156 delete[] result; 01157 result = NULL; 01158 return False; 01159 } 01160 *p = '\0'; 01161 01162 return True; 01163 }
| Boolean MatroskaFileParser::parseEBMLVal_binary | ( | EBMLDataSize & | size, | |
| u_int8_t *& | result | |||
| ) | [private] |
Definition at line 1165 of file MatroskaFileParser.cpp.
References False, fCurOffsetInFile, fLimitOffsetInFile, StreamParser::get1Byte(), NULL, size, and True.
Referenced by parseTrack().
01165 { 01166 unsigned resultLength = (unsigned)size.val(); 01167 result = new u_int8_t[resultLength]; 01168 if (result == NULL) return False; 01169 01170 u_int8_t* p = result; 01171 unsigned i; 01172 for (i = 0; i < resultLength; ++i) { 01173 if (fLimitOffsetInFile > 0 && fCurOffsetInFile > fLimitOffsetInFile) break; // We've hit our pre-set limit 01174 01175 u_int8_t c = get1Byte(); 01176 ++fCurOffsetInFile; 01177 01178 *p++ = c; 01179 } 01180 if (i < resultLength) { // an error occurred 01181 delete[] result; 01182 result = NULL; 01183 return False; 01184 } 01185 01186 return True; 01187 }
| void MatroskaFileParser::skipHeader | ( | EBMLDataSize const & | size | ) | [private] |
Definition at line 1189 of file MatroskaFileParser.cpp.
References StreamParser::bankSize(), fCurOffsetInFile, size, and StreamParser::skipBytes().
Referenced by lookForNextBlock(), lookForNextTrack(), parseCues(), parseStartOfFile(), and parseTrack().
01189 { 01190 unsigned sv = (unsigned)size.val(); 01191 01192 // Hack: To avoid tripping into a parser 'internal error' if we try to skip an excessively large distance. 01193 // (Such large distances are likely caused by erroneous data. We might not be able to recover from this, but at least we won't 01194 // generate a parser 'internal error'.) 01195 if (sv > bankSize()-12) sv = bankSize()-12; 01196 01197 skipBytes(sv); 01198 fCurOffsetInFile += sv; 01199 }
| void MatroskaFileParser::setParseState | ( | ) | [private] |
Definition at line 1201 of file MatroskaFileParser.cpp.
References fCurOffsetInFile, fCurOffsetWithinFrame, fSavedCurOffsetInFile, fSavedCurOffsetWithinFrame, and StreamParser::saveParserState().
Referenced by deliverFrameBytes(), deliverFrameWithinBlock(), lookForNextBlock(), lookForNextTrack(), parseBlock(), parseCues(), parseEBMLNumber(), and parseTrack().
01201 { 01202 fSavedCurOffsetInFile = fCurOffsetInFile; 01203 fSavedCurOffsetWithinFrame = fCurOffsetWithinFrame; 01204 saveParserState(); 01205 }
| void MatroskaFileParser::seekToFilePosition | ( | u_int64_t | offsetInFile | ) | [private] |
Definition at line 1213 of file MatroskaFileParser.cpp.
References fInputSource, NULL, resetStateAfterSeeking(), and ByteStreamFileSource::seekToByteAbsolute().
Referenced by parse(), and seekToTime().
01213 { 01214 ByteStreamFileSource* fileSource = (ByteStreamFileSource*)fInputSource; // we know it's a "ByteStreamFileSource" 01215 if (fileSource != NULL) { 01216 fileSource->seekToByteAbsolute(offsetInFile); 01217 resetStateAfterSeeking(); 01218 } 01219 }
| void MatroskaFileParser::seekToEndOfFile | ( | ) | [private] |
Definition at line 1221 of file MatroskaFileParser.cpp.
References fInputSource, NULL, resetStateAfterSeeking(), and ByteStreamFileSource::seekToEnd().
Referenced by seekToTime().
01221 { 01222 ByteStreamFileSource* fileSource = (ByteStreamFileSource*)fInputSource; // we know it's a "ByteStreamFileSource" 01223 if (fileSource != NULL) { 01224 fileSource->seekToEnd(); 01225 resetStateAfterSeeking(); 01226 } 01227 }
| void MatroskaFileParser::resetStateAfterSeeking | ( | ) | [private] |
Definition at line 1229 of file MatroskaFileParser.cpp.
References fCurOffsetInFile, fCurOffsetWithinFrame, StreamParser::flushInput(), fSavedCurOffsetInFile, and fSavedCurOffsetWithinFrame.
Referenced by seekToEndOfFile(), and seekToFilePosition().
01229 { 01230 // Because we're resuming parsing after seeking to a new position in the file, reset the parser state: 01231 fCurOffsetInFile = fSavedCurOffsetInFile = 0; 01232 fCurOffsetWithinFrame = fSavedCurOffsetWithinFrame = 0; 01233 flushInput(); 01234 }
| void MatroskaFileParser::restoreSavedParserState | ( | ) | [private, virtual] |
Reimplemented from StreamParser.
Definition at line 1207 of file MatroskaFileParser.cpp.
References fCurOffsetInFile, fCurOffsetWithinFrame, fSavedCurOffsetInFile, fSavedCurOffsetWithinFrame, and StreamParser::restoreSavedParserState().
Referenced by deliverFrameWithinBlock().
01207 { 01208 StreamParser::restoreSavedParserState(); 01209 fCurOffsetInFile = fSavedCurOffsetInFile; 01210 fCurOffsetWithinFrame = fSavedCurOffsetWithinFrame; 01211 }
| 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 }
| void StreamParser::getBytes | ( | u_int8_t * | to, | |
| unsigned | numBytes | |||
| ) | [inline, protected, inherited] |
Definition at line 78 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().
00078 { 00079 testBytes(to, numBytes); 00080 fCurParserIndex += numBytes; 00081 fRemainingUnparsedBits = 0; 00082 }
| void StreamParser::testBytes | ( | u_int8_t * | to, | |
| unsigned | numBytes | |||
| ) | [inline, protected, inherited] |
Definition at line 83 of file StreamParser.hh.
References StreamParser::ensureValidBytes(), and StreamParser::nextToParse().
Referenced by StreamParser::getBytes(), and H264VideoStreamParser::parse().
00083 { // as above, but doesn't advance ptr 00084 ensureValidBytes(numBytes); 00085 memmove(to, nextToParse(), numBytes); 00086 }
| void StreamParser::skipBytes | ( | unsigned | numBytes | ) | [inline, protected, inherited] |
Definition at line 87 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().
00087 { 00088 ensureValidBytes(numBytes); 00089 fCurParserIndex += numBytes; 00090 }
| 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 96 of file StreamParser.hh.
References StreamParser::fCurParserIndex.
Referenced by H264VideoStreamParser::parse(), parseBlock(), and MPEGProgramStreamParser::parsePESPacket().
00096 { return fCurParserIndex; }
| unsigned& StreamParser::totNumValidBytes | ( | ) | [inline, protected, inherited] |
Definition at line 98 of file StreamParser.hh.
References StreamParser::fTotNumValidBytes.
Referenced by H264VideoStreamParser::parse(), and AC3AudioStreamParser::testStreamCode().
00098 { return fTotNumValidBytes; }
| Boolean StreamParser::haveSeenEOF | ( | ) | const [inline, protected, inherited] |
Definition at line 100 of file StreamParser.hh.
References StreamParser::fHaveSeenEOF.
Referenced by H264VideoStreamParser::parse().
00100 { 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