aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
authorPaul Gilbert2017-06-30 21:31:17 -0400
committerPaul Gilbert2017-06-30 21:31:17 -0400
commit2838776c4bf60556b73e74c7d481d9e4af718fbb (patch)
tree29cf0391d354468d1741ad57186c95183dc66bab /video
parenta897ad9e7222a3f8af1d75bc9c787da3bd464c33 (diff)
downloadscummvm-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.cpp102
-rw-r--r--video/avi_decoder.h4
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);