diff options
author | Paul Gilbert | 2016-12-05 23:15:44 -0500 |
---|---|---|
committer | Paul Gilbert | 2016-12-05 23:15:44 -0500 |
commit | 0c200e833efa863ec810e8d7fbefaa59f9f7603d (patch) | |
tree | 8b8c7d0dda9b91a55e4b1b068cad8e8c50487193 /video/avi_decoder.cpp | |
parent | e6e7d6e2f790cfc652597affd72179a1f6cd6274 (diff) | |
download | scummvm-rg350-0c200e833efa863ec810e8d7fbefaa59f9f7603d.tar.gz scummvm-rg350-0c200e833efa863ec810e8d7fbefaa59f9f7603d.tar.bz2 scummvm-rg350-0c200e833efa863ec810e8d7fbefaa59f9f7603d.zip |
VIDEO: Add reverse playback support to AviDecoder
Diffstat (limited to 'video/avi_decoder.cpp')
-rw-r--r-- | video/avi_decoder.cpp | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 7041f428ab..fc73cfaeac 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -458,6 +458,8 @@ void AVIDecoder::handleNextPacket(TrackStatus &status) { // Seek to where we shall start searching _fileStream->seek(status.chunkSearchOffset); + bool isReversed = false; + AVIVideoTrack *videoTrack = nullptr; for (;;) { // If there's no more to search, bail out @@ -511,7 +513,8 @@ void AVIDecoder::handleNextPacket(TrackStatus &status) { if (!shouldQueueAudio(status)) break; } else { - AVIVideoTrack *videoTrack = (AVIVideoTrack *)status.track; + videoTrack = (AVIVideoTrack *)status.track; + isReversed = videoTrack->isReversed(); if (getStreamType(nextTag) == kStreamTypePaletteChange) { // Palette Change @@ -524,8 +527,15 @@ void AVIDecoder::handleNextPacket(TrackStatus &status) { } } - // Start us off in this position next time - status.chunkSearchOffset = _fileStream->pos(); + if (!isReversed) { + // Start us off in this position next time + status.chunkSearchOffset = _fileStream->pos(); + } else { + // Seek to the prior frame + assert(videoTrack); + Audio::Timestamp time = videoTrack->getFrameTime(getCurFrame()); + seekIntern(time); + } } bool AVIDecoder::shouldQueueAudio(TrackStatus& status) { @@ -566,6 +576,8 @@ uint AVIDecoder::getVideoTrackOffset(uint trackIndex, uint frameNumber) { } bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { + uint frame; + // Can't seek beyond the end if (time > getDuration()) return false; @@ -574,19 +586,23 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { AVIVideoTrack *videoTrack = (AVIVideoTrack *)_videoTracks[0].track; uint32 videoIndex = _videoTracks[0].index; - // If we seek directly to the end, just mark the tracks as over if (time == getDuration()) { videoTrack->setCurFrame(videoTrack->getFrameCount() - 1); - for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) - if ((*it)->getTrackType() == Track::kTrackTypeAudio) - ((AVIAudioTrack *)*it)->resetStream(); + if (!videoTrack->isReversed()) { + // Since we're at the end, just mark the tracks as over + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + ((AVIAudioTrack *)*it)->resetStream(); - return true; - } + return true; + } - // Get the frame we should be on at this time - uint frame = videoTrack->getFrameAtTime(time); + frame = videoTrack->getFrameCount() - 1; + } else { + // Get the frame we should be on at this time + frame = videoTrack->getFrameAtTime(time); + } // Reset any palette, if necessary videoTrack->useInitialPalette(); @@ -821,6 +837,7 @@ AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader & _videoCodec = createCodec(); _lastFrame = 0; _curFrame = -1; + _reversed = false; useInitialPalette(); } @@ -840,7 +857,12 @@ void AVIDecoder::AVIVideoTrack::decodeFrame(Common::SeekableReadStream *stream) } delete stream; - _curFrame++; + + if (!_reversed) { + _curFrame++; + } else { + _curFrame--; + } } Graphics::PixelFormat AVIDecoder::AVIVideoTrack::getPixelFormat() const { @@ -923,6 +945,23 @@ bool AVIDecoder::AVIVideoTrack::hasDirtyPalette() const { return _dirtyPalette; } +bool AVIDecoder::AVIVideoTrack::setReverse(bool reverse) { + if (isRewindable()) { + // Track is rewindable, so reversing is allowed + _reversed = reverse; + return true; + } + + return !reverse; +} + +bool AVIDecoder::AVIVideoTrack::endOfTrack() const { + if (_reversed) + return _curFrame < 0; + + return _curFrame >= (getFrameCount() - 1); +} + bool AVIDecoder::AVIVideoTrack::canDither() const { return _videoCodec && _videoCodec->canDither(Image::Codec::kDitherTypeVFW); } |