diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp index a226f9fb374..dd26b137c17 100644 --- a/video/qt_decoder.cpp +++ b/video/qt_decoder.cpp @@ -299,7 +299,8 @@ QuickTimeDecoder::VideoTrackHandler::VideoTrackHandler(QuickTimeDecoder *decoder _curEdit = 0; _curFrame = -1; - enterNewEditListEntry(true); // might set _curFrame + _delayedFrameToBufferTo = -1; + enterNewEditListEntry(true, true); // might set _curFrame _durationOverride = -1; _scaledSurface = 0; @@ -369,6 +370,8 @@ bool QuickTimeDecoder::VideoTrackHandler::endOfTrack() const { } bool QuickTimeDecoder::VideoTrackHandler::seek(const Audio::Timestamp &requestedTime) { + _delayedFrameToBufferTo = -1; // abort any delayed buffering + uint32 convertedFrames = requestedTime.convertToFramerate(_decoder->_timeScale).totalNumberOfFrames(); for (_curEdit = 0; !atLastEdit(); _curEdit++) if (convertedFrames >= _parent->editList[_curEdit].timeOffset && convertedFrames < _parent->editList[_curEdit].timeOffset + _parent->editList[_curEdit].trackDuration) @@ -564,6 +567,8 @@ const byte *QuickTimeDecoder::VideoTrackHandler::getPalette() const { } bool QuickTimeDecoder::VideoTrackHandler::setReverse(bool reverse) { + _delayedFrameToBufferTo = -1; // abort any delayed buffering + _reversed = reverse; if (_reversed) { @@ -705,7 +710,7 @@ bool QuickTimeDecoder::VideoTrackHandler::isEmptyEdit() const { return (_parent->editList[_curEdit].mediaTime == -1); } -void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrames) { +void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrames, bool initializingTrack) { if (atLastEdit()) return; @@ -749,8 +754,15 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrame // Track down the keyframe // Then decode until the frame before target _curFrame = findKeyFrame(frameNum) - 1; - while (_curFrame < (int32)frameNum - 1) - bufferNextFrame(); + if (initializingTrack) { + // We can't decode frames during track initialization, + // so delay buffering until the first decode. + _delayedFrameToBufferTo = (int32)frameNum - 1; + } else { + while (_curFrame < (int32)frameNum - 1) { + bufferNextFrame(); + } + } } else { // Since frameNum is the frame that needs to be displayed // we'll set _curFrame to be the "last frame displayed" @@ -761,6 +773,16 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrame } const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::bufferNextFrame() { + // Buffer any frames that were identified during track initialization + // and delayed until decoding. + if (_delayedFrameToBufferTo != -1) { + int32 frameNum = _delayedFrameToBufferTo; + _delayedFrameToBufferTo = -1; + while (_curFrame < frameNum) { + bufferNextFrame(); + } + } + _curFrame++; // Get the next packet diff --git a/video/qt_decoder.h b/video/qt_decoder.h index 62496629e1f..581949cca09 100644 --- a/video/qt_decoder.h +++ b/video/qt_decoder.h @@ -154,6 +154,7 @@ private: Common::QuickTimeParser::Track *_parent; uint32 _curEdit; int32 _curFrame; + int32 _delayedFrameToBufferTo; uint32 _nextFrameStartTime; // media time Graphics::Surface *_scaledSurface; int32 _durationOverride; // media time @@ -171,7 +172,7 @@ private: uint32 getCurFrameDuration(); // media time uint32 findKeyFrame(uint32 frame) const; bool isEmptyEdit() const; - void enterNewEditListEntry(bool bufferFrames); + void enterNewEditListEntry(bool bufferFrames, bool intializingTrack = false); const Graphics::Surface *bufferNextFrame(); uint32 getRateAdjustedFrameTime() const; // media time uint32 getCurEditTimeOffset() const; // media time