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 From 1632d5f39a577b5fe1f6a6d89bd67896dbc54673 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 5 Jan 2014 15:26:38 +0200 Subject: VIDEO: Handle the AVI 'JUNQ' and 'dmlh' chunk headers These are used by Full Pipe's intro videos --- video/avi_decoder.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 36fe83fa19..7f5a557474 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -59,6 +59,8 @@ namespace Video { #define ID_MIDS MKTAG('m','i','d','s') #define ID_TXTS MKTAG('t','x','t','s') #define ID_JUNK MKTAG('J','U','N','K') +#define ID_JUNQ MKTAG('J','U','N','Q') +#define ID_DMLH MKTAG('d','m','l','h') #define ID_STRF MKTAG('s','t','r','f') #define ID_MOVI MKTAG('m','o','v','i') #define ID_REC MKTAG('r','e','c',' ') @@ -155,9 +157,11 @@ bool AVIDecoder::parseNextChunk() { case ID_STRD: // Extra stream info, safe to ignore case ID_VEDT: // Unknown, safe to ignore case ID_JUNK: // Alignment bytes, should be ignored + case ID_JUNQ: // Same as JUNK, safe to ignore case ID_ISFT: // Metadata, safe to ignore case ID_DISP: // Metadata, should be safe to ignore case ID_STRN: // Metadata, safe to ignore + case ID_DMLH: // OpenDML extension, contains an extra total frames field, safe to ignore skipChunk(size); break; case ID_IDX1: -- cgit v1.2.3 From d2e31c8d67417d033b89cabc834cf3a1c363799c Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 9 Jan 2014 21:27:52 -0500 Subject: VIDEO: Improve support for multiple AVI audio tracks --- video/avi_decoder.cpp | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 7f5a557474..a3b45995a1 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -441,12 +441,10 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { if (time > getDuration()) return false; - // Track down our video track (optionally audio too). - // We only support seeking with one track right now. + // Track down our video track. + // We only support seeking with one video track right now. AVIVideoTrack *videoTrack = 0; - AVIAudioTrack *audioTrack = 0; int videoIndex = -1; - int audioIndex = -1; uint trackID = 0; for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++, trackID++) { @@ -459,15 +457,6 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { videoTrack = (AVIVideoTrack *)*it; videoIndex = trackID; - } else if ((*it)->getTrackType() == Track::kTrackTypeAudio) { - if (audioTrack) { - // Already have one - // -> Not supported - return false; - } - - audioTrack = (AVIAudioTrack *)*it; - audioIndex = trackID; } } @@ -480,8 +469,9 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { if (time == getDuration()) { videoTrack->setCurFrame(videoTrack->getFrameCount() - 1); - if (audioTrack) - audioTrack->resetStream(); + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + ((AVIAudioTrack *)*it)->resetStream(); return true; } @@ -542,7 +532,15 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) { if (frameIndex < 0) // This shouldn't happen. return false; - if (audioTrack) { + // Update all the audio tracks + uint audioIndex = 0; + + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++, audioIndex++) { + if ((*it)->getTrackType() != Track::kTrackTypeAudio) + continue; + + AVIAudioTrack *audioTrack = (AVIAudioTrack *)*it; + // We need to find where the start of audio should be. // Which is exactly 'initialFrames' audio chunks back from where // our found frame is. @@ -683,6 +681,16 @@ void AVIDecoder::forceVideoEnd() { ((AVIVideoTrack *)*it)->forceTrackEnd(); } +VideoDecoder::AudioTrack *AVIDecoder::getAudioTrack(int index) { + // AVI audio track indexes are relative to the first track + Track *track = getTrack(index); + + if (!track || track->getTrackType() != Track::kTrackTypeAudio) + return 0; + + return (AudioTrack *)track; +} + 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 d73df0d28cbe91e70affd765cf48d2f8a25943eb Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 17 Jan 2014 20:57:45 -0500 Subject: VIDEO: Add MJPEG support --- video/avi_decoder.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index a3b45995a1..bae5b7babd 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -36,6 +36,7 @@ // Video Codecs #include "video/codecs/cinepak.h" #include "video/codecs/indeo3.h" +#include "video/codecs/mjpeg.h" #include "video/codecs/mpeg.h" #include "video/codecs/msvideo1.h" #include "video/codecs/msrle.h" @@ -82,6 +83,7 @@ namespace Video { #define ID_IV32 MKTAG('i','v','3','2') #define ID_DUCK MKTAG('D','U','C','K') #define ID_MPG2 MKTAG('m','p','g','2') +#define ID_MJPG MKTAG('m','j','p','g') // Stream Types enum { @@ -786,6 +788,8 @@ Codec *AVIDecoder::AVIVideoTrack::createCodec() { case ID_MPG2: return new MPEGDecoder(); #endif + case ID_MJPG: + return new MJPEGDecoder(); default: warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); } -- cgit v1.2.3 From 9b8e6f54fca6e88557ad0815fd71f12fd409cd30 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 7 Feb 2014 09:42:58 +0200 Subject: VIDEO: Add additional FourCC appearing in some Zvision engine game versions --- 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 bae5b7babd..4e561cfddf 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -82,6 +82,7 @@ namespace Video { #define ID_CVID MKTAG('c','v','i','d') #define ID_IV32 MKTAG('i','v','3','2') #define ID_DUCK MKTAG('D','U','C','K') +#define ID_DUCK2 MKTAG('d','u','c','k') // Some videos have DUCK tag in lowercase #define ID_MPG2 MKTAG('m','p','g','2') #define ID_MJPG MKTAG('m','j','p','g') @@ -782,6 +783,7 @@ Codec *AVIDecoder::AVIVideoTrack::createCodec() { return new Indeo3Decoder(_bmInfo.width, _bmInfo.height); #ifdef VIDEO_CODECS_TRUEMOTION1_H case ID_DUCK: + case ID_DUCK2: return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); #endif #ifdef USE_MPEG2 -- cgit v1.2.3 From 8f3a923686a5a29e8affff2b624deff35938d5dc Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:27 +0100 Subject: VIDEO: Make GPL headers consistent in themselves. --- video/avi_decoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 4e561cfddf..c6463269d3 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From b568ac73b9d2e063eb04693e4610a9932035b696 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 27 Feb 2014 21:27:23 -0500 Subject: IMAGE: Move video codecs to image/ --- video/avi_decoder.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index c6463269d3..5e404ecaac 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -34,13 +34,13 @@ #include "audio/decoders/raw.h" // Video Codecs -#include "video/codecs/cinepak.h" -#include "video/codecs/indeo3.h" -#include "video/codecs/mjpeg.h" -#include "video/codecs/mpeg.h" -#include "video/codecs/msvideo1.h" -#include "video/codecs/msrle.h" -#include "video/codecs/truemotion1.h" +#include "image/codecs/cinepak.h" +#include "image/codecs/indeo3.h" +#include "image/codecs/mjpeg.h" +#include "image/codecs/mpeg.h" +#include "image/codecs/msvideo1.h" +#include "image/codecs/msrle.h" +#include "image/codecs/truemotion1.h" namespace Video { @@ -769,29 +769,29 @@ bool AVIDecoder::AVIVideoTrack::rewind() { return true; } -Codec *AVIDecoder::AVIVideoTrack::createCodec() { +Image::Codec *AVIDecoder::AVIVideoTrack::createCodec() { switch (_vidsHeader.streamHandler) { case ID_CRAM: case ID_MSVC: case ID_WHAM: - return new MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); + return new Image::MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); case ID_RLE: - return new MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); + return new Image::MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); case ID_CVID: - return new CinepakDecoder(_bmInfo.bitCount); + return new Image::CinepakDecoder(_bmInfo.bitCount); case ID_IV32: - return new Indeo3Decoder(_bmInfo.width, _bmInfo.height); + return new Image::Indeo3Decoder(_bmInfo.width, _bmInfo.height); #ifdef VIDEO_CODECS_TRUEMOTION1_H case ID_DUCK: case ID_DUCK2: - return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); + return new Image::TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); #endif #ifdef USE_MPEG2 case ID_MPG2: - return new MPEGDecoder(); + return new Image::MPEGDecoder(); #endif case ID_MJPG: - return new MJPEGDecoder(); + return new Image::MJPEGDecoder(); default: warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); } -- cgit v1.2.3 From 08ea14a8d0e1a1478d1f486edeecea3e619e0cd0 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 27 Feb 2014 21:27:24 -0500 Subject: IMAGE: Make Codec take a stream reference; change function name to decodeFrame --- video/avi_decoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 5e404ecaac..e9c6ef93b2 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -711,7 +711,7 @@ AVIDecoder::AVIVideoTrack::~AVIVideoTrack() { void AVIDecoder::AVIVideoTrack::decodeFrame(Common::SeekableReadStream *stream) { if (stream) { if (_videoCodec) - _lastFrame = _videoCodec->decodeImage(stream); + _lastFrame = _videoCodec->decodeFrame(*stream); } else { // Empty frame _lastFrame = 0; -- cgit v1.2.3 From 231a02c759169a5c927018699e1533d267ea8372 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 27 Feb 2014 21:27:24 -0500 Subject: VIDEO: Use the bitmap header compression field for AVI codecs --- video/avi_decoder.cpp | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index e9c6ef93b2..59ee72d7fa 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -74,18 +74,6 @@ namespace Video { #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',' ') -#define ID_CRAM MKTAG('C','R','A','M') -#define ID_MSVC MKTAG('m','s','v','c') -#define ID_WHAM MKTAG('W','H','A','M') -#define ID_CVID MKTAG('c','v','i','d') -#define ID_IV32 MKTAG('i','v','3','2') -#define ID_DUCK MKTAG('D','U','C','K') -#define ID_DUCK2 MKTAG('d','u','c','k') // Some videos have DUCK tag in lowercase -#define ID_MPG2 MKTAG('m','p','g','2') -#define ID_MJPG MKTAG('m','j','p','g') - // Stream Types enum { kStreamTypePaletteChange = MKTAG16('p', 'c'), @@ -266,9 +254,6 @@ void AVIDecoder::handleStreamHeader(uint32 size) { if (bmInfo.clrUsed == 0) bmInfo.clrUsed = 256; - if (sHeader.streamHandler == 0) - sHeader.streamHandler = bmInfo.compression; - byte *initialPalette = 0; if (bmInfo.bitCount == 8) { @@ -770,30 +755,34 @@ bool AVIDecoder::AVIVideoTrack::rewind() { } Image::Codec *AVIDecoder::AVIVideoTrack::createCodec() { - switch (_vidsHeader.streamHandler) { - case ID_CRAM: - case ID_MSVC: - case ID_WHAM: - return new Image::MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); - case ID_RLE: + switch (_bmInfo.compression) { + case SWAP_CONSTANT_32(1): return new Image::MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); - case ID_CVID: + case MKTAG('C','R','A','M'): + case MKTAG('m','s','v','c'): + case MKTAG('W','H','A','M'): + return new Image::MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); + case MKTAG('c','v','i','d'): return new Image::CinepakDecoder(_bmInfo.bitCount); - case ID_IV32: + case MKTAG('I','V','3','2'): return new Image::Indeo3Decoder(_bmInfo.width, _bmInfo.height); #ifdef VIDEO_CODECS_TRUEMOTION1_H - case ID_DUCK: - case ID_DUCK2: + case MKTAG('D','U','C','K'): + case MKTAG('d','u','c','k'): return new Image::TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); #endif #ifdef USE_MPEG2 - case ID_MPG2: + case MKTAG('m','p','g','2'): return new Image::MPEGDecoder(); #endif - case ID_MJPG: + case MKTAG('M','J','P','G'): + case MKTAG('m','j','p','g'): return new Image::MJPEGDecoder(); default: - warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); + if (_bmInfo.compression & 0x00FFFFFF) + warning("Unknown/Unhandled AVI compression format \'%s\'", tag2str(_bmInfo.compression)); + else + warning("Unknown/Unhandled AVI compression format %d", SWAP_BYTES_32(_bmInfo.compression)); } return 0; -- cgit v1.2.3 From 05e9ff136ae059622a0262380be7bc6460d204f0 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 27 Feb 2014 21:27:25 -0500 Subject: IMAGE: Share the same pool of codecs between bitmap and AVI --- video/avi_decoder.cpp | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 59ee72d7fa..0697d89c04 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -34,13 +34,7 @@ #include "audio/decoders/raw.h" // Video Codecs -#include "image/codecs/cinepak.h" -#include "image/codecs/indeo3.h" -#include "image/codecs/mjpeg.h" -#include "image/codecs/mpeg.h" -#include "image/codecs/msvideo1.h" -#include "image/codecs/msrle.h" -#include "image/codecs/truemotion1.h" +#include "image/codecs/codec.h" namespace Video { @@ -755,37 +749,7 @@ bool AVIDecoder::AVIVideoTrack::rewind() { } Image::Codec *AVIDecoder::AVIVideoTrack::createCodec() { - switch (_bmInfo.compression) { - case SWAP_CONSTANT_32(1): - return new Image::MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); - case MKTAG('C','R','A','M'): - case MKTAG('m','s','v','c'): - case MKTAG('W','H','A','M'): - return new Image::MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); - case MKTAG('c','v','i','d'): - return new Image::CinepakDecoder(_bmInfo.bitCount); - case MKTAG('I','V','3','2'): - return new Image::Indeo3Decoder(_bmInfo.width, _bmInfo.height); -#ifdef VIDEO_CODECS_TRUEMOTION1_H - case MKTAG('D','U','C','K'): - case MKTAG('d','u','c','k'): - return new Image::TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); -#endif -#ifdef USE_MPEG2 - case MKTAG('m','p','g','2'): - return new Image::MPEGDecoder(); -#endif - case MKTAG('M','J','P','G'): - case MKTAG('m','j','p','g'): - return new Image::MJPEGDecoder(); - default: - if (_bmInfo.compression & 0x00FFFFFF) - warning("Unknown/Unhandled AVI compression format \'%s\'", tag2str(_bmInfo.compression)); - else - warning("Unknown/Unhandled AVI compression format %d", SWAP_BYTES_32(_bmInfo.compression)); - } - - return 0; + return Image::createBitmapCodec(_bmInfo.compression, _bmInfo.width, _bmInfo.height, _bmInfo.bitCount); } void AVIDecoder::AVIVideoTrack::forceTrackEnd() { -- cgit v1.2.3 From 5e715f244bc2d03d9532d09b87ba5baca8d988ac Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 2 Mar 2014 20:59:00 -0500 Subject: VIDEO: Handle the raw AVI video chunk the same as the others --- video/avi_decoder.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 0697d89c04..9b196fefc9 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -71,7 +71,6 @@ namespace Video { // Stream Types enum { kStreamTypePaletteChange = MKTAG16('p', 'c'), - kStreamTypeRawVideo = MKTAG16('d', 'b'), kStreamTypeAudio = MKTAG16('w', 'b') }; @@ -399,10 +398,6 @@ void AVIDecoder::readNextPacket() { if (getStreamType(nextTag) == kStreamTypePaletteChange) { // Palette Change videoTrack->loadPaletteFromChunk(chunk); - } else if (getStreamType(nextTag) == kStreamTypeRawVideo) { - // TODO: Check if this really is uncompressed. Many videos - // falsely put compressed data in here. - error("Uncompressed AVI frame found"); } else { // Otherwise, assume it's a compressed frame videoTrack->decodeFrame(chunk); -- cgit v1.2.3 From 5891ef4d89936917aaa7edf06f5d1fbc06a1271f Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 27 May 2014 00:09:11 -0400 Subject: VIDEO: Handle Truemotion dimensions specially Truemotion uses its own demuxer and seems to follow its own AVI rules. Work around it by coercing the video's dimensions to use the codec's internal dimensions. --- video/avi_decoder.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 9b196fefc9..3c1c907097 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -322,6 +322,9 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) { // Seek back to the start of the MOVI list _fileStream->seek(_movieListStart); + // Check if this is a special Duck Truemotion video + checkTruemotion1(); + return true; } @@ -658,6 +661,48 @@ void AVIDecoder::forceVideoEnd() { ((AVIVideoTrack *)*it)->forceTrackEnd(); } +void AVIDecoder::checkTruemotion1() { + AVIVideoTrack *track = 0; + + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) { + if ((*it)->getTrackType() == Track::kTrackTypeVideo) { + if (track) { + // Multiple tracks; isn't going to be truemotion 1 + return; + } + + track = (AVIVideoTrack *)*it; + } + } + + // No track found? + if (!track) + return; + + // Ignore non-truemotion tracks + if (!track->isTruemotion1()) + return; + + // Search for a non-empty frame + const Graphics::Surface *frame = 0; + for (int i = 0; i < 10 && !frame; i++) + frame = decodeNextFrame(); + + if (!frame) { + // Probably shouldn't happen + rewind(); + return; + } + + // Fill in the width/height based on the frame's width/height + _header.width = frame->w; + _header.height = frame->h; + track->forceDimensions(frame->w, frame->h); + + // Rewind us back to the beginning + rewind(); +} + VideoDecoder::AudioTrack *AVIDecoder::getAudioTrack(int index) { // AVI audio track indexes are relative to the first track Track *track = getTrack(index); @@ -732,6 +777,15 @@ void AVIDecoder::AVIVideoTrack::useInitialPalette() { } } +bool AVIDecoder::AVIVideoTrack::isTruemotion1() const { + return _bmInfo.compression == MKTAG('D', 'U', 'C', 'K') || _bmInfo.compression == MKTAG('d', 'u', 'c', 'k'); +} + +void AVIDecoder::AVIVideoTrack::forceDimensions(uint16 width, uint16 height) { + _bmInfo.width = width; + _bmInfo.height = height; +} + bool AVIDecoder::AVIVideoTrack::rewind() { _curFrame = -1; -- cgit v1.2.3 From 1ea4b36c3b6f959048cab0c6a5567fefcc390cc3 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 27 May 2014 23:57:39 -0400 Subject: VIDEO: Document PRMI as being Premiere metadata --- video/avi_decoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 3c1c907097..68d6cb6cec 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -183,7 +183,7 @@ void AVIDecoder::handleList(uint32 listSize) { _decodedHeader = true; break; case ID_INFO: // Metadata - case ID_PRMI: // Unknown metadata, should be safe to ignore + case ID_PRMI: // Adobe Premiere metadata, safe to ignore // Ignore metadata _fileStream->skip(listSize); return; -- cgit v1.2.3 From 8d70dd68ac887df8593eb139edaa8f2a084be085 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 8 Jun 2014 22:54:07 +0300 Subject: AUDIO: Added stup for MP3 audiostreams in AVI This is used in German release of Full Pipe. Unfortunately our current MP3 decoder cannot work with streamed MP3s, and bails out at the AVI header since there is no full MP3 header yet. --- video/avi_decoder.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'video/avi_decoder.cpp') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 68d6cb6cec..39deaea204 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -833,6 +833,8 @@ void AVIDecoder::AVIAudioTrack::queueSound(Common::SeekableReadStream *stream) { _audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMSIma, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES); } else if (_wvInfo.tag == kWaveFormatDK3) { _audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES); + } else if (_wvInfo.tag == kWaveFormatMP3) { + warning("AVI: MP3 audio stream is not supported"); } } else { delete stream; @@ -869,7 +871,7 @@ Audio::AudioStream *AVIDecoder::AVIAudioTrack::getAudioStream() const { } Audio::QueuingAudioStream *AVIDecoder::AVIAudioTrack::createAudioStream() { - if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatMSADPCM || _wvInfo.tag == kWaveFormatMSIMAADPCM || _wvInfo.tag == kWaveFormatDK3) + if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatMSADPCM || _wvInfo.tag == kWaveFormatMSIMAADPCM || _wvInfo.tag == kWaveFormatDK3 || _wvInfo.tag == kWaveFormatMP3) return Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2); else if (_wvInfo.tag != kWaveFormatNone) // No sound warning("Unsupported AVI audio format %d", _wvInfo.tag); -- cgit v1.2.3