[Scummvm-git-logs] scummvm master -> 0c200e833efa863ec810e8d7fbefaa59f9f7603d

dreammaster dreammaster at scummvm.org
Tue Dec 6 05:15:54 CET 2016


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
0c200e833e VIDEO: Add reverse playback support to AviDecoder


Commit: 0c200e833efa863ec810e8d7fbefaa59f9f7603d
    https://github.com/scummvm/scummvm/commit/0c200e833efa863ec810e8d7fbefaa59f9f7603d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-12-05T23:15:44-05:00

Commit Message:
VIDEO: Add reverse playback support to AviDecoder

Changed paths:
    video/avi_decoder.cpp
    video/avi_decoder.h


diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 7041f42..fc73cfa 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);
 }
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 4bba07e..cc5c2c4 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -210,6 +210,25 @@ protected:
 		bool isRewindable() const { return true; }
 		bool rewind();
 
+		/**
+		 * Set the video track to play in reverse or forward.
+		 *
+		 * By default, a VideoTrack must decode forward.
+		 *
+		 * @param reverse true for reverse, false for forward
+		 * @return true for success, false for failure
+		 */
+		virtual bool setReverse(bool reverse);
+
+		/**
+		 * Is the video track set to play in reverse?
+		 */
+		virtual bool isReversed() const { return _reversed; }
+
+		/**
+		 * Returns true if at the end of the video track
+		 */
+		virtual bool endOfTrack() const;
 	protected:
 		Common::Rational getFrameRate() const { return Common::Rational(_vidsHeader.rate, _vidsHeader.scale); }
 
@@ -220,6 +239,7 @@ protected:
 		byte *_initialPalette;
 		mutable bool _dirtyPalette;
 		int _frameCount, _curFrame;
+		bool _reversed;
 
 		Image::Codec *_videoCodec;
 		const Graphics::Surface *_lastFrame;





More information about the Scummvm-git-logs mailing list