diff options
author | Matthew Hoops | 2012-11-24 01:03:36 -0500 |
---|---|---|
committer | Matthew Hoops | 2012-11-24 01:03:36 -0500 |
commit | db908fcdc40b1b337c1e07ecdb76a326ace005ba (patch) | |
tree | 03c77d7391acae4a62309768790a1d0948844f43 | |
parent | 4d75aa5319479f0c260c08dcbdf945dde41887ce (diff) | |
download | scummvm-rg350-db908fcdc40b1b337c1e07ecdb76a326ace005ba.tar.gz scummvm-rg350-db908fcdc40b1b337c1e07ecdb76a326ace005ba.tar.bz2 scummvm-rg350-db908fcdc40b1b337c1e07ecdb76a326ace005ba.zip |
VIDEO: Add support for playing videos at a modified speed
Currently this only works for positive (forward) playback, but will eventually work for negative (backward).
-rw-r--r-- | video/video_decoder.cpp | 71 | ||||
-rw-r--r-- | video/video_decoder.h | 35 |
2 files changed, 81 insertions, 25 deletions
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp index 110afa7755..6c45cc578f 100644 --- a/video/video_decoder.cpp +++ b/video/video_decoder.cpp @@ -37,7 +37,7 @@ VideoDecoder::VideoDecoder() { _startTime = 0; _dirtyPalette = false; _palette = 0; - _isPlaying = false; + _playbackRate = 0; _audioVolume = Audio::Mixer::kMaxChannelVolume; _audioBalance = 0; _pauseLevel = 0; @@ -212,7 +212,7 @@ uint32 VideoDecoder::getTime() const { return _lastTimeChange.msecs(); if (isPaused()) - return _pauseStartTime - _startTime; + return (_playbackRate * (_pauseStartTime - _startTime)).toInt(); if (useAudioSync()) { for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) { @@ -225,7 +225,7 @@ uint32 VideoDecoder::getTime() const { } } - return g_system->getMillis() - _startTime; + return (_playbackRate * (g_system->getMillis() - _startTime)).toInt(); } uint32 VideoDecoder::getTimeToNextFrame() const { @@ -325,17 +325,8 @@ bool VideoDecoder::seek(const Audio::Timestamp &time) { } void VideoDecoder::start() { - if (isPlaying() || !isVideoLoaded()) - return; - - _isPlaying = true; - _startTime = g_system->getMillis(); - - // Adjust start time if we've seeked to something besides zero time - if (_lastTimeChange.totalNumberOfFrames() != 0) - _startTime -= _lastTimeChange.msecs(); - - startAudio(); + if (!isPlaying()) + setRate(1); } void VideoDecoder::stop() { @@ -346,12 +337,12 @@ void VideoDecoder::stop() { stopAudio(); // Keep the time marked down in case we start up again - // We do this before _isPlaying is set so we don't get + // We do this before _playbackRate is set so we don't get // _lastTimeChange returned, but before _pauseLevel is // reset. _lastTimeChange = getTime(); - _isPlaying = false; + _playbackRate = 0; _startTime = 0; _palette = 0; _dirtyPalette = false; @@ -365,6 +356,46 @@ void VideoDecoder::stop() { (*it)->pause(false); } +void VideoDecoder::setRate(const Common::Rational &rate) { + if (!isVideoLoaded() || _playbackRate == rate) + return; + + if (rate == 0) { + stop(); + return; + } else if (rate != 1 && hasAudio()) { + warning("Cannot set custom rate in videos with audio"); + return; + } + + Common::Rational targetRate = rate; + + if (rate < 0) { + // TODO: Implement support for this + warning("Cannot set custom rate to backwards"); + targetRate = 1; + + if (_playbackRate == targetRate) + return; + } + + if (_playbackRate != 0) + _lastTimeChange = getTime(); + + _playbackRate = targetRate; + _startTime = g_system->getMillis(); + + // Adjust start time if we've seeked to something besides zero time + if (_lastTimeChange.totalNumberOfFrames() != 0) + _startTime -= (_lastTimeChange.msecs() / _playbackRate).toInt(); + + startAudio(); +} + +bool VideoDecoder::isPlaying() const { + return _playbackRate != 0; +} + Audio::Timestamp VideoDecoder::getDuration() const { Audio::Timestamp maxDuration(0, 1000); @@ -676,4 +707,12 @@ bool VideoDecoder::hasFramesLeft() const { return false; } +bool VideoDecoder::hasAudio() const { + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + return true; + + return false; +} + } // End of namespace Video diff --git a/video/video_decoder.h b/video/video_decoder.h index 860caecafe..ca88696b57 100644 --- a/video/video_decoder.h +++ b/video/video_decoder.h @@ -26,6 +26,7 @@ #include "audio/mixer.h" #include "audio/timestamp.h" // TODO: Move this to common/ ? #include "common/array.h" +#include "common/rational.h" #include "common/str.h" #include "graphics/pixelformat.h" @@ -36,7 +37,6 @@ class SeekableAudioStream; } namespace Common { -class Rational; class SeekableReadStream; } @@ -100,7 +100,7 @@ public: ///////////////////////////////////////// /** - * Begin playback of the video. + * Begin playback of the video at normal speed. * * @note This has no effect if the video is already playing. */ @@ -114,6 +114,26 @@ public: void stop(); /** + * Set the rate of playback. + * + * For instance, a rate of 0 would stop the video, while a rate of 1 + * would play the video normally. Passing 2 to this function would + * play the video at twice the normal speed. + * + * @note This function does not work for non-0/1 rates on videos that + * have audio tracks. + * + * @todo This currently does not implement backwards playback, but will + * be implemented soon. + */ + void setRate(const Common::Rational &rate); + + /** + * Returns the rate at which the video is being played. + */ + Common::Rational getRate() const { return _playbackRate; } + + /** * Returns if the video is currently playing or not. * * This is not equivalent to the inverse of endOfVideo(). A video keeps @@ -121,7 +141,7 @@ public: * return true after calling start() and will continue to return true * until stop() (or close()) is called. */ - bool isPlaying() const { return _isPlaying; } + bool isPlaying() const; /** * Returns if a video is rewindable or not. The default implementation @@ -367,11 +387,6 @@ public: */ bool addStreamFileTrack(const Common::String &baseName); - - // Future API - //void setRate(const Common::Rational &rate); - //Common::Rational getRate() const; - protected: /** * An abstract representation of a track in a movie. Since tracks here are designed @@ -764,9 +779,10 @@ private: TrackList _tracks; // Current playback status - bool _isPlaying, _needsUpdate; + bool _needsUpdate; Audio::Timestamp _lastTimeChange, _endTime; bool _endTimeSet; + Common::Rational _playbackRate; // Palette settings from individual tracks mutable bool _dirtyPalette; @@ -780,6 +796,7 @@ private: void startAudio(); void startAudioLimit(const Audio::Timestamp &limit); bool hasFramesLeft() const; + bool hasAudio() const; int32 _startTime; uint32 _pauseLevel; |