aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
authorMatthew Hoops2012-12-15 20:41:41 -0500
committerMatthew Hoops2012-12-15 20:41:41 -0500
commit9ae56146bbe1daab3f8919ec67dc458d864651cb (patch)
treefb8c48958ef305807e11fa7e37ddfd5dd8014137 /video
parent1214b7a7e4c38c7e676351512a4c6d7a2bb46610 (diff)
downloadscummvm-rg350-9ae56146bbe1daab3f8919ec67dc458d864651cb.tar.gz
scummvm-rg350-9ae56146bbe1daab3f8919ec67dc458d864651cb.tar.bz2
scummvm-rg350-9ae56146bbe1daab3f8919ec67dc458d864651cb.zip
VIDEO: Add API changes to allow videos to be played backwards
Diffstat (limited to 'video')
-rw-r--r--video/video_decoder.cpp44
-rw-r--r--video/video_decoder.h26
2 files changed, 63 insertions, 7 deletions
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index ab12cfd971..ebe15c5fc1 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -188,6 +188,25 @@ const Graphics::Surface *VideoDecoder::decodeNextFrame() {
return frame;
}
+bool VideoDecoder::setReverse(bool reverse) {
+ // Can only reverse video-only videos
+ if (reverse && hasAudio())
+ return false;
+
+ // Attempt to make sure all the tracks are in the requested direction
+ for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) {
+ if ((*it)->getTrackType() == Track::kTrackTypeVideo && ((VideoTrack *)*it)->isReversed() != reverse) {
+ if (!((VideoTrack *)*it)->setReverse(reverse))
+ return false;
+
+ _needsUpdate = true; // force an update
+ }
+ }
+
+ findNextVideoTrack();
+ return true;
+}
+
const byte *VideoDecoder::getPalette() {
_dirtyPalette = false;
return _palette;
@@ -218,7 +237,7 @@ uint32 VideoDecoder::getTime() const {
return _lastTimeChange.msecs();
if (isPaused())
- return (_playbackRate * (_pauseStartTime - _startTime)).toInt();
+ return MAX<int>((_playbackRate * (_pauseStartTime - _startTime)).toInt(), 0);
if (useAudioSync()) {
for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) {
@@ -231,20 +250,29 @@ uint32 VideoDecoder::getTime() const {
}
}
- return (_playbackRate * (g_system->getMillis() - _startTime)).toInt();
+ return MAX<int>((_playbackRate * (g_system->getMillis() - _startTime)).toInt(), 0);
}
uint32 VideoDecoder::getTimeToNextFrame() const {
if (endOfVideo() || _needsUpdate || !_nextVideoTrack)
return 0;
- uint32 elapsedTime = getTime();
+ uint32 currentTime = getTime();
uint32 nextFrameStartTime = _nextVideoTrack->getNextFrameStartTime();
- if (nextFrameStartTime <= elapsedTime)
+ if (_nextVideoTrack->isReversed()) {
+ // For reversed videos, we need to handle the time difference the opposite way.
+ if (nextFrameStartTime >= currentTime)
+ return 0;
+
+ return currentTime - nextFrameStartTime;
+ }
+
+ // Otherwise, handle it normally.
+ if (nextFrameStartTime <= currentTime)
return 0;
- return nextFrameStartTime - elapsedTime;
+ return nextFrameStartTime - currentTime;
}
bool VideoDecoder::endOfVideo() const {
@@ -402,9 +430,11 @@ void VideoDecoder::setRate(const Common::Rational &rate) {
Common::Rational targetRate = rate;
- if (rate < 0) {
- // TODO: Implement support for this
+ // Attempt to set the reverse
+ if (!setReverse(rate < 0)) {
+ assert(rate < 0); // We shouldn't fail for forward.
warning("Cannot set custom rate to backwards");
+ setReverse(false);
targetRate = 1;
if (_playbackRate == targetRate)
diff --git a/video/video_decoder.h b/video/video_decoder.h
index 5fec52cf42..d0a6e08005 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -353,6 +353,17 @@ public:
*/
void setDefaultHighColorFormat(const Graphics::PixelFormat &format) { _defaultHighColorFormat = format; }
+ /**
+ * Set the video to decode frames in reverse.
+ *
+ * By default, VideoDecoder will decode forward.
+ *
+ * @note This is used by setRate()
+ * @note This will not work if an audio track is present
+ * @param reverse true for reverse, false for forward
+ * @return true on success, false otherwise
+ */
+ bool setReverse(bool reverse);
/////////////////////////////////////////
// Audio Control
@@ -551,6 +562,21 @@ protected:
* should only be used by VideoDecoder::seekToFrame().
*/
virtual Audio::Timestamp getFrameTime(uint frame) const;
+
+ /**
+ * 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) { return !reverse; }
+
+ /**
+ * Is the video track set to play in reverse?
+ */
+ virtual bool isReversed() const { return false; }
};
/**