Skip to content

Commit

Permalink
VIDEO: Add API changes to allow videos to be played backwards
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Hoops committed Dec 16, 2012
1 parent 1214b7a commit 9ae5614
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 7 deletions.
44 changes: 37 additions & 7 deletions video/video_decoder.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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++) {
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
26 changes: 26 additions & 0 deletions video/video_decoder.h
Expand Up @@ -353,6 +353,17 @@ class VideoDecoder {
*/
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
Expand Down Expand Up @@ -551,6 +562,21 @@ class VideoDecoder {
* 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; }
};

/**
Expand Down

0 comments on commit 9ae5614

Please sign in to comment.