mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-30 12:50:51 +00:00
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).
This commit is contained in:
parent
4d75aa5319
commit
db908fcdc4
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
@ -113,6 +113,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.
|
||||
*
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user