aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
authorPaul Gilbert2016-10-12 20:09:36 -0400
committerPaul Gilbert2016-10-12 20:09:36 -0400
commita333f3c44ccde58438cb0deb9a6398b3008aeeec (patch)
treed7d3ea57b5397ceccc606a1aea882f0335daedbf /video
parent0a186a66d6425212f9e1a340aa84b40709a55527 (diff)
downloadscummvm-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.cpp67
-rw-r--r--video/avi_decoder.h10
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);