diff options
author | Paul Gilbert | 2017-06-30 21:31:17 -0400 |
---|---|---|
committer | Paul Gilbert | 2017-06-30 21:31:17 -0400 |
commit | 2838776c4bf60556b73e74c7d481d9e4af718fbb (patch) | |
tree | 29cf0391d354468d1741ad57186c95183dc66bab /video | |
parent | a897ad9e7222a3f8af1d75bc9c787da3bd464c33 (diff) | |
download | scummvm-rg350-2838776c4bf60556b73e74c7d481d9e4af718fbb.tar.gz scummvm-rg350-2838776c4bf60556b73e74c7d481d9e4af718fbb.tar.bz2 scummvm-rg350-2838776c4bf60556b73e74c7d481d9e4af718fbb.zip |
VIDEO: Refactor AVIDecoder for better handling of transparency track
A lot of the standard VideoDecoder methods were still treating the
transparency track as part of the video, so methods like getFrameCount
would return double the amount it should be. This refactoring properly
separates the transparency track into a separate field entirely.
Diffstat (limited to 'video')
-rw-r--r-- | video/avi_decoder.cpp | 102 | ||||
-rw-r--r-- | video/avi_decoder.h | 4 |
2 files changed, 64 insertions, 42 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 9f97ffd5c8..910a4092aa 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -120,6 +120,7 @@ void AVIDecoder::initCommon() { _videoTrackCounter = _audioTrackCounter = 0; _lastAddedTrack = nullptr; memset(&_header, 0, sizeof(_header)); + _transparencyTrack.track = nullptr; } bool AVIDecoder::isSeekable() const { @@ -129,10 +130,10 @@ bool AVIDecoder::isSeekable() const { } const Graphics::Surface *AVIDecoder::decodeNextTransparency() { - if (_videoTracks.size() != 2) + if (!_transparencyTrack.track) return nullptr; - AVIVideoTrack *track = static_cast<AVIVideoTrack *>(_videoTracks[1].track); + AVIVideoTrack *track = static_cast<AVIVideoTrack *>(_transparencyTrack.track); return track->decodeNextFrame(); } @@ -392,16 +393,22 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) { } else if (_videoTracks.empty()) { _videoTracks.push_back(status); } else { - // Secondary video track - assert(_videoTracks.size() == 1); + // Secondary video track. For now we assume it will always be a + // transparency information track status.chunkSearchOffset = getVideoTrackOffset(index); + assert(!_transparencyTrack.track); assert(status.chunkSearchOffset != 0); - // Add the video track to the list - _videoTracks.push_back(status); + // Copy the track status information into the transparency track field + _transparencyTrack = status; } } + // If there is a transparency track, remove it from the video decoder's track list. + // This is to stop it being included in calls like getFrameCount + if (_transparencyTrack.track) + eraseTrack(_transparencyTrack.track); + // Check if this is a special Duck Truemotion video checkTruemotion1(); @@ -423,6 +430,9 @@ void AVIDecoder::close() { _videoTracks.clear(); _audioTracks.clear(); + + delete _transparencyTrack.track; + _transparencyTrack.track = nullptr; } void AVIDecoder::readNextPacket() { @@ -434,6 +444,10 @@ void AVIDecoder::readNextPacket() { for (uint idx = 0; idx < _videoTracks.size(); ++idx) handleNextPacket(_videoTracks[idx]); + // Handle any transparency track + if (_transparencyTrack.track) + handleNextPacket(_transparencyTrack); + // Handle audio tracks next for (uint idx = 0; idx < _audioTracks.size(); ++idx) handleNextPacket(_audioTracks[idx]); @@ -715,41 +729,9 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { videoTrack->decodeFrame(chunk); } - // Update any secondary video track for transparencies - if (_videoTracks.size() == 2) { - // Find the index entry for the frame - int indexFrame = frame; - OldIndex *entry = nullptr; - do { - entry = _indexEntries.find(_videoTracks.back().index, indexFrame); - } while (!entry && indexFrame-- > 0); - assert(entry); - - // Set it's frame number - AVIVideoTrack *videoTrack2 = static_cast<AVIVideoTrack *>(_videoTracks.back().track); - videoTrack2->setCurFrame(indexFrame - 1); - - // Read in the frame - Common::SeekableReadStream *chunk = nullptr; - _fileStream->seek(entry->offset + 8); - _videoTracks.back().chunkSearchOffset = entry->offset; - - if (entry->size != 0) - chunk = _fileStream->readStream(entry->size); - videoTrack2->decodeFrame(chunk); - - if (indexFrame < (int)frame) { - TrackStatus &status = _videoTracks.back(); - while (status.chunkSearchOffset < _movieListEnd && indexFrame++ < (int)frame) { - // There was no index entry for the desired frame, so an earlier one was decoded. - // We now have to sequentially decode frames until we get to the desired frame - handleNextPacket(status); - } - } - - videoTrack2->setCurFrame((int)frame - 1); - videoTrack2->setFrameRate(videoTrack->getFrameRate()); - } + // Update any transparency track if present + if (_transparencyTrack.track) + seekTransparencyFrame(frame); // Set the video track's frame videoTrack->setCurFrame((int)frame - 1); @@ -759,6 +741,44 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { return true; } +void AVIDecoder::seekTransparencyFrame(int frame) { + TrackStatus &status = _transparencyTrack; + AVIVideoTrack *transTrack = static_cast<AVIVideoTrack *>(status.track); + + // Find the index entry for the frame + int indexFrame = frame; + OldIndex *entry = nullptr; + do { + entry = _indexEntries.find(status.index, indexFrame); + } while (!entry && indexFrame-- > 0); + assert(entry); + + // Set it's frame number + transTrack->setCurFrame(indexFrame - 1); + + // Read in the frame + Common::SeekableReadStream *chunk = nullptr; + _fileStream->seek(entry->offset + 8); + status.chunkSearchOffset = entry->offset; + + if (entry->size != 0) + chunk = _fileStream->readStream(entry->size); + transTrack->decodeFrame(chunk); + + if (indexFrame < (int)frame) { + while (status.chunkSearchOffset < _movieListEnd && indexFrame++ < (int)frame) { + // There was no index entry for the desired frame, so an earlier one was decoded. + // We now have to sequentially skip frames until we get to the desired frame + _fileStream->readUint32BE(); + uint32 size = _fileStream->readUint32LE() - 8; + _fileStream->skip(size & 1); + status.chunkSearchOffset = _fileStream->pos(); + } + } + + transTrack->setCurFrame((int)frame - 1); +} + byte AVIDecoder::getStreamIndex(uint32 tag) { char string[3]; WRITE_BE_UINT16(string, tag >> 16); diff --git a/video/avi_decoder.h b/video/avi_decoder.h index 541c73e068..a3dbddf015 100644 --- a/video/avi_decoder.h +++ b/video/avi_decoder.h @@ -337,8 +337,10 @@ protected: void handleNextPacket(TrackStatus& status); bool shouldQueueAudio(TrackStatus& status); - Common::Array<TrackStatus> _videoTracks, _audioTracks; + void seekTransparencyFrame(int frame); + Common::Array<TrackStatus> _videoTracks, _audioTracks; + TrackStatus _transparencyTrack; public: virtual AVIAudioTrack *createAudioTrack(AVIStreamHeader sHeader, PCMWaveFormat wvInfo); |