VIDEO: Fix reverse playback in AVIDecoder
This commit is contained in:
parent
aba431ca9b
commit
22e24d7c0b
2 changed files with 37 additions and 5 deletions
|
@ -129,6 +129,23 @@ bool AVIDecoder::isSeekable() const {
|
||||||
return isVideoLoaded() && !_indexEntries.empty();
|
return isVideoLoaded() && !_indexEntries.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Graphics::Surface *AVIDecoder::decodeNextFrame() {
|
||||||
|
// When playing in reverse, we need to seek to the correct prior frame
|
||||||
|
AVIVideoTrack *track = nullptr;
|
||||||
|
bool isReversed = false;
|
||||||
|
for (int idx = _videoTracks.size() - 1; idx >= 0; --idx) {
|
||||||
|
track = static_cast<AVIVideoTrack *>(_videoTracks[idx].track);
|
||||||
|
isReversed |= track->isReversed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReversed) {
|
||||||
|
Audio::Timestamp time = track->getFrameTime(getCurFrame());
|
||||||
|
seekIntern(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VideoDecoder::decodeNextFrame();
|
||||||
|
}
|
||||||
|
|
||||||
const Graphics::Surface *AVIDecoder::decodeNextTransparency() {
|
const Graphics::Surface *AVIDecoder::decodeNextTransparency() {
|
||||||
if (!_transparencyTrack.track)
|
if (!_transparencyTrack.track)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -544,11 +561,6 @@ void AVIDecoder::handleNextPacket(TrackStatus &status) {
|
||||||
if (!isReversed) {
|
if (!isReversed) {
|
||||||
// Start us off in this position next time
|
// Start us off in this position next time
|
||||||
status.chunkSearchOffset = _fileStream->pos();
|
status.chunkSearchOffset = _fileStream->pos();
|
||||||
} else {
|
|
||||||
// Seek to the prior frame
|
|
||||||
assert(videoTrack);
|
|
||||||
Audio::Timestamp time = videoTrack->getFrameTime(getCurFrame());
|
|
||||||
seekIntern(time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,26 @@ public:
|
||||||
bool isRewindable() const { return true; }
|
bool isRewindable() const { return true; }
|
||||||
bool isSeekable() const;
|
bool isSeekable() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode the next frame into a surface and return the latter.
|
||||||
|
*
|
||||||
|
* A subclass may override this, but must still call this function. As an
|
||||||
|
* example, a subclass may do this to apply some global video scale to
|
||||||
|
* individual track's frame.
|
||||||
|
*
|
||||||
|
* Note that this will call readNextPacket() internally first before calling
|
||||||
|
* the next video track's decodeNextFrame() function.
|
||||||
|
*
|
||||||
|
* @return a surface containing the decoded frame, or 0
|
||||||
|
* @note Ownership of the returned surface stays with the VideoDecoder,
|
||||||
|
* hence the caller must *not* free it.
|
||||||
|
* @note this may return 0, in which case the last frame should be kept on screen
|
||||||
|
*/
|
||||||
|
virtual const Graphics::Surface *decodeNextFrame();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the next transparency track frame
|
||||||
|
*/
|
||||||
const Graphics::Surface *decodeNextTransparency();
|
const Graphics::Surface *decodeNextTransparency();
|
||||||
protected:
|
protected:
|
||||||
// VideoDecoder API
|
// VideoDecoder API
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue