aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2012-11-24 01:03:36 -0500
committerMatthew Hoops2012-11-24 01:03:36 -0500
commitdb908fcdc40b1b337c1e07ecdb76a326ace005ba (patch)
tree03c77d7391acae4a62309768790a1d0948844f43
parent4d75aa5319479f0c260c08dcbdf945dde41887ce (diff)
downloadscummvm-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.cpp71
-rw-r--r--video/video_decoder.h35
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;