diff options
author | Paul Gilbert | 2016-10-12 20:09:36 -0400 |
---|---|---|
committer | Paul Gilbert | 2016-10-12 20:09:36 -0400 |
commit | a333f3c44ccde58438cb0deb9a6398b3008aeeec (patch) | |
tree | d7d3ea57b5397ceccc606a1aea882f0335daedbf /video | |
parent | 0a186a66d6425212f9e1a340aa84b40709a55527 (diff) | |
download | scummvm-rg350-a333f3c44ccde58438cb0deb9a6398b3008aeeec.tar.gz scummvm-rg350-a333f3c44ccde58438cb0deb9a6398b3008aeeec.tar.bz2 scummvm-rg350-a333f3c44ccde58438cb0deb9a6398b3008aeeec.zip |
VIDEO: Support rewind on AVI files with multiple video tracks
Diffstat (limited to 'video')
-rw-r--r-- | video/avi_decoder.cpp | 67 | ||||
-rw-r--r-- | video/avi_decoder.h | 10 |
2 files changed, 44 insertions, 33 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 2c8efc49a0..7041f428ab 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -392,19 +392,9 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) { } else if (_videoTracks.empty()) { _videoTracks.push_back(status); } else { - // Secondary video track. Figure out the starting chunk offset, - // by iteratiing through the index + // Secondary video track assert(_videoTracks.size() == 1); - - // Find the index entry for the frame and move to it - status.chunkSearchOffset = 0; - for (uint idx = 0; idx < _indexEntries.size(); ++idx) { - if (_indexEntries[idx].id != ID_REC && - getStreamIndex(_indexEntries[idx].id) == index) { - status.chunkSearchOffset = _indexEntries[idx].offset; - break; - } - } + status.chunkSearchOffset = getVideoTrackOffset(index); assert(status.chunkSearchOffset != 0); // Add the video track to the list @@ -558,7 +548,7 @@ bool AVIDecoder::rewind() { return false; for (uint32 i = 0; i < _videoTracks.size(); i++) - _videoTracks[i].chunkSearchOffset = _movieListStart; + _videoTracks[i].chunkSearchOffset = getVideoTrackOffset(_videoTracks[i].index); for (uint32 i = 0; i < _audioTracks.size(); i++) _audioTracks[i].chunkSearchOffset = _movieListStart; @@ -566,6 +556,15 @@ bool AVIDecoder::rewind() { return true; } +uint AVIDecoder::getVideoTrackOffset(uint trackIndex, uint frameNumber) { + if (trackIndex == _videoTracks.front().index && frameNumber == 0) + return _movieListStart; + + OldIndex *entry = _indexEntries.find(trackIndex, frameNumber); + assert(entry); + return entry->offset; +} + bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { // Can't seek beyond the end if (time > getDuration()) @@ -702,28 +701,22 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { // Update any secondary video track for transparencies if (_videoTracks.size() == 2) { - AVIVideoTrack *videoTrack2 = static_cast<AVIVideoTrack *>(_videoTracks.back().track); - // Set it's frame number + AVIVideoTrack *videoTrack2 = static_cast<AVIVideoTrack *>(_videoTracks.back().track); videoTrack2->setCurFrame((int)frame - 1); - // Find the index entry for the frame and move to it - for (uint i = 0, frameNum = 0; i < _indexEntries.size(); ++i) { - if (_indexEntries[i].id != ID_REC && - getStreamIndex(_indexEntries[i].id) == _videoTracks.back().index) { - if (frameNum++ == frame) { - Common::SeekableReadStream *chunk = nullptr; - _fileStream->seek(_indexEntries[i].offset + 8); - _videoTracks.back().chunkSearchOffset = _indexEntries[i].offset; + // Find the index entry for the frame and read it in + OldIndex *entry = _indexEntries.find(_videoTracks.back().index, frame); + assert(entry); - if (_indexEntries[i].size != 0) - chunk = _fileStream->readStream(_indexEntries[i].size); + Common::SeekableReadStream *chunk = nullptr; + _fileStream->seek(entry->offset + 8); + _videoTracks.back().chunkSearchOffset = entry->offset; - videoTrack2->decodeFrame(chunk); - break; - } - } - } + if (entry->size != 0) + chunk = _fileStream->readStream(entry->size); + + videoTrack2->decodeFrame(chunk); } // Set the video track's frame @@ -734,7 +727,7 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { return true; } -byte AVIDecoder::getStreamIndex(uint32 tag) const { +byte AVIDecoder::getStreamIndex(uint32 tag) { char string[3]; WRITE_BE_UINT16(string, tag >> 16); string[2] = 0; @@ -1035,4 +1028,16 @@ void AVIDecoder::AVIAudioTrack::createAudioStream() { AVIDecoder::TrackStatus::TrackStatus() : track(0), chunkSearchOffset(0) { } +AVIDecoder::OldIndex *AVIDecoder::IndexEntries::find(uint index, uint frameNumber) { + for (uint idx = 0, frameCtr = 0; idx < size(); ++idx) { + if ((*this)[idx].id != ID_REC && + AVIDecoder::getStreamIndex((*this)[idx].id) == index) { + if (frameCtr++ == frameNumber) + return &(*this)[idx]; + } + } + + return nullptr; +} + } // End of namespace Video diff --git a/video/avi_decoder.h b/video/avi_decoder.h index db9928d444..4bba07e98f 100644 --- a/video/avi_decoder.h +++ b/video/avi_decoder.h @@ -272,10 +272,15 @@ protected: uint32 chunkSearchOffset; }; + class IndexEntries : public Common::Array<OldIndex> { + public: + OldIndex *find(uint index, uint frameNumber); + }; + AVIHeader _header; void readOldIndex(uint32 size); - Common::Array<OldIndex> _indexEntries; + IndexEntries _indexEntries; Common::SeekableReadStream *_fileStream; bool _decodedHeader; @@ -296,8 +301,9 @@ protected: void handleStreamHeader(uint32 size); void readStreamName(uint32 size); uint16 getStreamType(uint32 tag) const { return tag & 0xFFFF; } - byte getStreamIndex(uint32 tag) const; + static byte getStreamIndex(uint32 tag); void checkTruemotion1(); + uint getVideoTrackOffset(uint trackIndex, uint frameNumber = 0); void handleNextPacket(TrackStatus& status); bool shouldQueueAudio(TrackStatus& status); |