aboutsummaryrefslogtreecommitdiff
path: root/video/avi_decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'video/avi_decoder.cpp')
-rw-r--r--video/avi_decoder.cpp107
1 files changed, 83 insertions, 24 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 980ce3a3ea..c4b091d240 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -76,13 +76,13 @@ enum {
};
-AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType, SelectTrackFn trackFn) :
- _frameRateOverride(0), _soundType(soundType), _selectTrackFn(trackFn) {
+AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) :
+ _frameRateOverride(0), _soundType(soundType) {
initCommon();
}
-AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType,
- SelectTrackFn trackFn) : _frameRateOverride(frameRateOverride), _soundType(soundType), _selectTrackFn(trackFn) {
+AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType) :
+ _frameRateOverride(frameRateOverride), _soundType(soundType) {
initCommon();
}
@@ -94,6 +94,23 @@ AVIDecoder::AVIAudioTrack *AVIDecoder::createAudioTrack(AVIStreamHeader sHeader,
return new AVIAudioTrack(sHeader, wvInfo, _soundType);
}
+bool AVIDecoder::seekToFrame(uint frame) {
+ if (!isSeekable())
+ return false;
+
+ // If we didn't find a video track, we can't seek by frame (of course)
+ if (_videoTracks.empty())
+ return false;
+
+ AVIVideoTrack *track = static_cast<AVIVideoTrack *>(_videoTracks.front().track);
+ Audio::Timestamp time = track->getFrameTime(frame);
+
+ if (time < 0)
+ return false;
+
+ return seek(time);
+}
+
void AVIDecoder::initCommon() {
_decodedHeader = false;
_foundMovieList = false;
@@ -111,6 +128,14 @@ bool AVIDecoder::isSeekable() const {
return isVideoLoaded() && !_indexEntries.empty();
}
+const Graphics::Surface *AVIDecoder::decodeNextTransparency() {
+ if (_videoTracks.size() != 2)
+ return nullptr;
+
+ AVIVideoTrack *track = static_cast<AVIVideoTrack *>(_videoTracks[1].track);
+ return track->decodeNextFrame();
+}
+
bool AVIDecoder::parseNextChunk() {
uint32 tag = _fileStream->readUint32BE();
uint32 size = _fileStream->readUint32LE();
@@ -293,14 +318,8 @@ void AVIDecoder::handleStreamHeader(uint32 size) {
}
void AVIDecoder::addTrack(Track *track, bool isExternal) {
- if (!_selectTrackFn ||
- (dynamic_cast<AVIVideoTrack *>(track) && _selectTrackFn(true, _videoTrackCounter++)) ||
- (dynamic_cast<AVIAudioTrack *>(track) && _selectTrackFn(false, _audioTrackCounter++))) {
- VideoDecoder::addTrack(track, isExternal);
- _lastAddedTrack = track;
- } else {
- _lastAddedTrack = nullptr;
- }
+ VideoDecoder::addTrack(track, isExternal);
+ _lastAddedTrack = track;
}
void AVIDecoder::readStreamName(uint32 size) {
@@ -366,17 +385,30 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
TrackStatus status;
status.track = *it;
status.index = index;
- status.chunkSearchOffset = _movieListStart;
+ status.chunkSearchOffset = 0;
- if ((*it)->getTrackType() == Track::kTrackTypeVideo)
- _videoTracks.push_back(status);
- else
+ if ((*it)->getTrackType() == Track::kTrackTypeAudio) {
_audioTracks.push_back(status);
- }
+ } else if (_videoTracks.empty()) {
+ _videoTracks.push_back(status);
+ } else {
+ // Secondary video track. Figure out the starting chunk offset,
+ // by iteratiing through the index
+ assert(_videoTracks.size() == 1);
+
+ // Find the index entry for the frame and move to it
+ 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;
+ }
+ }
+ assert(status.chunkSearchOffset != 0);
- if (_videoTracks.size() != 1) {
- close();
- return false;
+ // Add the video track to the list
+ _videoTracks.push_back(status);
+ }
}
// Check if this is a special Duck Truemotion video
@@ -407,12 +439,13 @@ void AVIDecoder::readNextPacket() {
if (_videoTracks.empty())
return;
- // Get the video frame first
- handleNextPacket(_videoTracks[0]);
+ // Handle the video first
+ for (uint idx = 0; idx < _videoTracks.size(); ++idx)
+ handleNextPacket(_videoTracks[idx]);
// Handle audio tracks next
- for (uint32 i = 0; i < _audioTracks.size(); i++)
- handleNextPacket(_audioTracks[i]);
+ for (uint idx = 0; idx < _audioTracks.size(); ++idx)
+ handleNextPacket(_audioTracks[idx]);
}
void AVIDecoder::handleNextPacket(TrackStatus &status) {
@@ -666,6 +699,32 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) {
videoTrack->decodeFrame(chunk);
}
+ // Update any secondary video track for transparencies
+ if (_videoTracks.size() == 2) {
+ AVIVideoTrack *videoTrack2 = static_cast<AVIVideoTrack *>(_videoTracks.back().track);
+
+ // Set it's frame number
+ 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;
+
+ if (_indexEntries[i].size != 0)
+ chunk = _fileStream->readStream(_indexEntries[i].size);
+
+ videoTrack2->decodeFrame(chunk);
+ break;
+ }
+ }
+ }
+ }
+
// Set the video track's frame
videoTrack->setCurFrame((int)frame - 1);