diff options
Diffstat (limited to 'video/qt_decoder.cpp')
-rw-r--r-- | video/qt_decoder.cpp | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp index b4dab9ddfb..c5fcab4b49 100644 --- a/video/qt_decoder.cpp +++ b/video/qt_decoder.cpp @@ -348,18 +348,27 @@ bool QuickTimeDecoder::VideoTrackHandler::endOfTrack() const { } bool QuickTimeDecoder::VideoTrackHandler::seek(const Audio::Timestamp &requestedTime) { - // First, figure out what edit we're in - Audio::Timestamp time = requestedTime.convertToFramerate(_parent->timeScale); - - // Continue until we get to where we need to be + uint32 convertedFrames = requestedTime.convertToFramerate(_decoder->_timeScale).totalNumberOfFrames(); for (_curEdit = 0; !endOfTrack(); _curEdit++) - if ((uint32)time.totalNumberOfFrames() >= getCurEditTimeOffset() && (uint32)time.totalNumberOfFrames() < getCurEditTimeOffset() + getCurEditTrackDuration()) + if (convertedFrames >= _parent->editList[_curEdit].timeOffset && convertedFrames < _parent->editList[_curEdit].timeOffset + _parent->editList[_curEdit].trackDuration) break; - // This track is done + // If we did reach the end of the track, break out if (endOfTrack()) return true; + // If this track is in an empty edit, position us at the next non-empty + // edit. There's nothing else to do after this. + if (_parent->editList[_curEdit].mediaTime == -1) { + while (!endOfTrack() && _parent->editList[_curEdit].mediaTime == -1) + _curEdit++; + + if (!endOfTrack()) + enterNewEditList(true); + + return true; + } + enterNewEditList(false); // One extra check for the end of a track @@ -367,6 +376,7 @@ bool QuickTimeDecoder::VideoTrackHandler::seek(const Audio::Timestamp &requested return true; // Now we're in the edit and need to figure out what frame we need + Audio::Timestamp time = requestedTime.convertToFramerate(_parent->timeScale); while (getRateAdjustedFrameTime() < (uint32)time.totalNumberOfFrames()) { _curFrame++; if (_durationOverride >= 0) { @@ -557,6 +567,8 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) { uint32 prevDuration = 0; // Track down where the mediaTime is in the media + // This is basically time -> frame mapping + // Note that this code uses first frame = 0 for (int32 i = 0; i < _parent->timeToSampleCount && !done; i++) { for (int32 j = 0; j < _parent->timeToSample[i].count; j++) { if (totalDuration == (uint32)_parent->editList[_curEdit].mediaTime) { @@ -577,10 +589,13 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) { if (bufferFrames) { // Track down the keyframe + // Then decode until the frame before target _curFrame = findKeyFrame(frameNum) - 1; 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" _curFrame = frameNum - 1; } @@ -589,6 +604,8 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) { // Set an override for the duration since we came up in-between two frames if (prevDuration != totalDuration) _durationOverride = totalDuration - prevDuration; + else + _durationOverride = -1; } const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::bufferNextFrame() { @@ -638,7 +655,19 @@ uint32 QuickTimeDecoder::VideoTrackHandler::getRateAdjustedFrameTime() const { uint32 QuickTimeDecoder::VideoTrackHandler::getCurEditTimeOffset() const { // Need to convert to the track scale - return _parent->editList[_curEdit].timeOffset * _parent->timeScale / _decoder->_timeScale; + + // We have to round the time off to the nearest in the scale, otherwise + // bad things happen. QuickTime docs are pretty silent on all this stuff, + // so this was found from samples. It doesn't help that this is really + // the only open source implementation of QuickTime edits. + + uint32 mult = _parent->editList[_curEdit].timeOffset * _parent->timeScale; + uint32 result = mult / _decoder->_timeScale; + + if ((mult % _decoder->_timeScale) > (_decoder->_timeScale / 2)) + result++; + + return result; } uint32 QuickTimeDecoder::VideoTrackHandler::getCurEditTrackDuration() const { |