aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
authorPaul Gilbert2017-09-03 17:29:09 -0400
committerPaul Gilbert2017-09-03 17:29:09 -0400
commit22e24d7c0b78801d813294718d6a320fd46fc8d9 (patch)
tree263977c4c813d1f460a7a9af03c91875d17ba0f2 /video
parentaba431ca9b4f5a78ed2ee2a95e48def52257f391 (diff)
downloadscummvm-rg350-22e24d7c0b78801d813294718d6a320fd46fc8d9.tar.gz
scummvm-rg350-22e24d7c0b78801d813294718d6a320fd46fc8d9.tar.bz2
scummvm-rg350-22e24d7c0b78801d813294718d6a320fd46fc8d9.zip
VIDEO: Fix reverse playback in AVIDecoder
Diffstat (limited to 'video')
-rw-r--r--video/avi_decoder.cpp22
-rw-r--r--video/avi_decoder.h20
2 files changed, 37 insertions, 5 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 2f45a003f5..13b2c98994 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -129,6 +129,23 @@ bool AVIDecoder::isSeekable() const {
return isVideoLoaded() && !_indexEntries.empty();
}
+const Graphics::Surface *AVIDecoder::decodeNextFrame() {
+ // When playing in reverse, we need to seek to the correct prior frame
+ AVIVideoTrack *track = nullptr;
+ bool isReversed = false;
+ for (int idx = _videoTracks.size() - 1; idx >= 0; --idx) {
+ track = static_cast<AVIVideoTrack *>(_videoTracks[idx].track);
+ isReversed |= track->isReversed();
+ }
+
+ if (isReversed) {
+ Audio::Timestamp time = track->getFrameTime(getCurFrame());
+ seekIntern(time);
+ }
+
+ return VideoDecoder::decodeNextFrame();
+}
+
const Graphics::Surface *AVIDecoder::decodeNextTransparency() {
if (!_transparencyTrack.track)
return nullptr;
@@ -544,11 +561,6 @@ void AVIDecoder::handleNextPacket(TrackStatus &status) {
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);
}
}
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index dd5773fb7f..5a6864f52e 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -75,6 +75,26 @@ public:
bool isRewindable() const { return true; }
bool isSeekable() const;
+ /**
+ * Decode the next frame into a surface and return the latter.
+ *
+ * A subclass may override this, but must still call this function. As an
+ * example, a subclass may do this to apply some global video scale to
+ * individual track's frame.
+ *
+ * Note that this will call readNextPacket() internally first before calling
+ * the next video track's decodeNextFrame() function.
+ *
+ * @return a surface containing the decoded frame, or 0
+ * @note Ownership of the returned surface stays with the VideoDecoder,
+ * hence the caller must *not* free it.
+ * @note this may return 0, in which case the last frame should be kept on screen
+ */
+ virtual const Graphics::Surface *decodeNextFrame();
+
+ /**
+ * Decodes the next transparency track frame
+ */
const Graphics::Surface *decodeNextTransparency();
protected:
// VideoDecoder API