From 55791d5fc15f00d8dfba8b67d9d3f76bac63704a Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 23 Nov 2013 10:58:01 -0500 Subject: VIDEO: Fix AVI indexes with absolute offsets --- video/avi_decoder.cpp | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index aee2d88988..3987d492da 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -158,16 +158,7 @@ bool AVIDecoder::parseNextChunk() { skipChunk(size); break; case ID_IDX1: - debug(0, "%d Indices", size / 16); - for (uint32 i = 0; i < size / 16; i++) { - OldIndex indexEntry; - indexEntry.id = _fileStream->readUint32BE(); - indexEntry.flags = _fileStream->readUint32LE(); - indexEntry.offset = _fileStream->readUint32LE() + _movieListStart - 4; // Adjust to absolute - indexEntry.size = _fileStream->readUint32LE(); - _indexEntries.push_back(indexEntry); - debug(0, "Index %d == Tag \'%s\', Offset = %d, Size = %d (Flags = %d)", i, tag2str(indexEntry.id), indexEntry.offset, indexEntry.size, indexEntry.flags); - } + readOldIndex(size); break; default: error("Unknown tag \'%s\' found", tag2str(tag)); @@ -621,6 +612,46 @@ byte AVIDecoder::getStreamIndex(uint32 tag) const { return strtol(string, 0, 16); } +void AVIDecoder::readOldIndex(uint32 size) { + uint32 entryCount = size / 16; + + debug(0, "Old Index: %d entries", entryCount); + + if (entryCount == 0) + return; + + // Read the first index separately + OldIndex firstEntry; + firstEntry.id = _fileStream->readUint32BE(); + firstEntry.flags = _fileStream->readUint32LE(); + firstEntry.offset = _fileStream->readUint32LE(); + firstEntry.size = _fileStream->readUint32LE(); + + // Check if the offset is already absolute + // If it's absolute, the offset will equal the start of the movie list + bool isAbsolute = firstEntry.offset == _movieListStart; + + debug(1, "Old index is %s", isAbsolute ? "absolute" : "relative"); + + if (!isAbsolute) + firstEntry.offset += _movieListStart - 4; + + for (uint32 i = 1; i < entryCount; i++) { + OldIndex indexEntry; + indexEntry.id = _fileStream->readUint32BE(); + indexEntry.flags = _fileStream->readUint32LE(); + indexEntry.offset = _fileStream->readUint32LE(); + indexEntry.size = _fileStream->readUint32LE(); + + // Adjust to absolute, if necessary + if (!isAbsolute) + indexEntry.offset += _movieListStart - 4; + + _indexEntries.push_back(indexEntry); + debug(0, "Index %d: Tag '%s', Offset = %d, Size = %d (Flags = %d)", i, tag2str(indexEntry.id), indexEntry.offset, indexEntry.size, indexEntry.flags); + } +} + AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader, byte *initialPalette) : _frameCount(frameCount), _vidsHeader(streamHeader), _bmInfo(bitmapInfoHeader), _initialPalette(initialPalette) { _videoCodec = createCodec(); -- cgit v1.2.3 From 4708a1969b27e0ffd814beacf66c1de6ebb70178 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 23 Nov 2013 13:43:20 -0500 Subject: VIDEO: Fix awful thinko from 55791d5fc1 --- video/avi_decoder.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 3987d492da..eb5a71cdbe 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -636,6 +636,8 @@ void AVIDecoder::readOldIndex(uint32 size) { if (!isAbsolute) firstEntry.offset += _movieListStart - 4; + _indexEntries.push_back(firstEntry); + for (uint32 i = 1; i < entryCount; i++) { OldIndex indexEntry; indexEntry.id = _fileStream->readUint32BE(); -- cgit v1.2.3 From fa350f9c1f9acd2e36fedceb7520b2723d3ff604 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 25 Nov 2013 19:54:21 -0500 Subject: VIDEO: Ignore AVI strn metadata --- video/avi_decoder.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index eb5a71cdbe..41102f019d 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -69,6 +69,7 @@ namespace Video { #define ID_ISFT MKTAG('I','S','F','T') #define ID_DISP MKTAG('D','I','S','P') #define ID_PRMI MKTAG('P','R','M','I') +#define ID_STRN MKTAG('s','t','r','n') // Codec tags #define ID_RLE MKTAG('R','L','E',' ') @@ -155,6 +156,7 @@ bool AVIDecoder::parseNextChunk() { case ID_JUNK: // Alignment bytes, should be ignored case ID_ISFT: // Metadata, safe to ignore case ID_DISP: // Metadata, should be safe to ignore + case ID_STRN: // Metadata, safe to ignore skipChunk(size); break; case ID_IDX1: -- cgit v1.2.3 From 6fb6ffd77ba93cc46a2674b8ee94ab3f7d9966fa Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 25 Nov 2013 20:32:53 -0500 Subject: VIDEO: Handle prematurely ending AVI videos --- video/avi_decoder.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 41102f019d..db8538e5a2 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -110,6 +110,7 @@ void AVIDecoder::initCommon() { _decodedHeader = false; _foundMovieList = false; _movieListStart = 0; + _movieListEnd = 0; _fileStream = 0; memset(&_header, 0, sizeof(_header)); } @@ -186,6 +187,7 @@ void AVIDecoder::handleList(uint32 listSize) { // We found the movie block _foundMovieList = true; _movieListStart = curPos; + _movieListEnd = _movieListStart + listSize + (listSize & 1); _fileStream->skip(listSize); return; case ID_HDRL: // Header List @@ -346,17 +348,27 @@ void AVIDecoder::close() { _decodedHeader = false; _foundMovieList = false; _movieListStart = 0; + _movieListEnd = 0; _indexEntries.clear(); memset(&_header, 0, sizeof(_header)); } void AVIDecoder::readNextPacket() { + if ((uint32)_fileStream->pos() >= _movieListEnd) { + // Ugh, reached the end premature. + forceVideoEnd(); + return; + } + uint32 nextTag = _fileStream->readUint32BE(); uint32 size = _fileStream->readUint32LE(); - if (_fileStream->eos()) + if (_fileStream->eos()) { + // Also premature end. + forceVideoEnd(); return; + } if (nextTag == ID_LIST) { // A list of audio/video chunks @@ -656,6 +668,16 @@ void AVIDecoder::readOldIndex(uint32 size) { } } +void AVIDecoder::forceVideoEnd() { + // Horrible AVI video has a premature end + // Force the frame to be the last frame + debug(0, "Forcing end of AVI video"); + + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo) + ((AVIVideoTrack *)*it)->forceTrackEnd(); +} + AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader, byte *initialPalette) : _frameCount(frameCount), _vidsHeader(streamHeader), _bmInfo(bitmapInfoHeader), _initialPalette(initialPalette) { _videoCodec = createCodec(); @@ -758,6 +780,10 @@ Codec *AVIDecoder::AVIVideoTrack::createCodec() { return 0; } +void AVIDecoder::AVIVideoTrack::forceTrackEnd() { + _curFrame = _frameCount - 1; +} + AVIDecoder::AVIAudioTrack::AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) : _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType) { _audStream = createAudioStream(); -- cgit v1.2.3 From e28544d6d16edff0ca5355cf5ebbde5f7b0cf0d8 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 25 Nov 2013 20:20:11 -0500 Subject: VIDEO: Ensure debug output of the first AVI index --- video/avi_decoder.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index db8538e5a2..36fe83fa19 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -650,6 +650,7 @@ void AVIDecoder::readOldIndex(uint32 size) { if (!isAbsolute) firstEntry.offset += _movieListStart - 4; + debug(0, "Index 0: Tag '%s', Offset = %d, Size = %d (Flags = %d)", tag2str(firstEntry.id), firstEntry.offset, firstEntry.size, firstEntry.flags); _indexEntries.push_back(firstEntry); for (uint32 i = 1; i < entryCount; i++) { -- cgit v1.2.3