aboutsummaryrefslogtreecommitdiff
path: root/video/avi_decoder.cpp
diff options
context:
space:
mode:
authorPaul Gilbert2016-12-05 23:15:44 -0500
committerPaul Gilbert2016-12-05 23:15:44 -0500
commit0c200e833efa863ec810e8d7fbefaa59f9f7603d (patch)
tree8b8c7d0dda9b91a55e4b1b068cad8e8c50487193 /video/avi_decoder.cpp
parente6e7d6e2f790cfc652597affd72179a1f6cd6274 (diff)
downloadscummvm-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.cpp63
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);
}