diff options
Diffstat (limited to 'video/avi_decoder.cpp')
-rw-r--r-- | video/avi_decoder.cpp | 68 |
1 files changed, 48 insertions, 20 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 6fe9c773b8..ff728a8437 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/mpeg.h" #include "video/codecs/msvideo1.h" #include "video/codecs/msrle.h" #include "video/codecs/truemotion1.h" @@ -64,8 +65,8 @@ namespace Video { #define ID_VEDT MKTAG('v','e','d','t') #define ID_IDX1 MKTAG('i','d','x','1') #define ID_STRD MKTAG('s','t','r','d') -#define ID_00AM MKTAG('0','0','A','M') //#define ID_INFO MKTAG('I','N','F','O') +#define ID_ISFT MKTAG('I','S','F','T') // Codec tags #define ID_RLE MKTAG('R','L','E',' ') @@ -75,6 +76,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_MPG2 MKTAG('m','p','g','2') static byte char2num(char c) { c = tolower((byte)c); @@ -89,17 +91,27 @@ static uint16 getStreamType(uint32 tag) { return tag & 0xffff; } -AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _soundType(soundType) { - _decodedHeader = false; - _fileStream = 0; - memset(&_ixInfo, 0, sizeof(_ixInfo)); - memset(&_header, 0, sizeof(_header)); +AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _frameRateOverride(0), _soundType(soundType) { + initCommon(); +} + +AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType) + : _frameRateOverride(frameRateOverride), _soundType(soundType) { + initCommon(); } AVIDecoder::~AVIDecoder() { close(); } +void AVIDecoder::initCommon() { + _decodedHeader = false; + _foundMovieList = false; + _fileStream = 0; + memset(&_ixInfo, 0, sizeof(_ixInfo)); + memset(&_header, 0, sizeof(_header)); +} + void AVIDecoder::runHandle(uint32 tag) { assert(_fileStream); if (_fileStream->eos()) @@ -137,6 +149,7 @@ void AVIDecoder::runHandle(uint32 tag) { 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_ISFT: // Metadata, safe to ignore { uint32 junkSize = _fileStream->readUint32LE(); _fileStream->skip(junkSize + (junkSize & 1)); // Alignment @@ -165,6 +178,13 @@ void AVIDecoder::handleList() { debug(0, "Found LIST of type %s", tag2str(listType)); + if (listType == ID_MOVI) { + // Found the 'movi' list + // We're done parsing everything + _foundMovieList = true; + return; + } + while ((_fileStream->pos() - curPos) < listSize) runHandle(_fileStream->readUint32BE()); @@ -203,6 +223,11 @@ void AVIDecoder::handleStreamHeader() { uint32 startPos = _fileStream->pos(); if (sHeader.streamType == ID_VIDS) { + if (_frameRateOverride != 0) { + sHeader.rate = _frameRateOverride.getNumerator(); + sHeader.scale = _frameRateOverride.getDenominator(); + } + BitmapInfoHeader bmInfo; bmInfo.size = _fileStream->readUint32LE(); bmInfo.width = _fileStream->readUint32LE(); @@ -263,26 +288,24 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) { _fileStream = stream; _decodedHeader = false; + _foundMovieList = false; // Read chunks until we have decoded the header - while (!_decodedHeader) + while (!_decodedHeader && _fileStream->pos() < _fileStream->size()) runHandle(_fileStream->readUint32BE()); - uint32 nextTag = _fileStream->readUint32BE(); - - // Throw out any JUNK section - if (nextTag == ID_JUNK) { - runHandle(ID_JUNK); - nextTag = _fileStream->readUint32BE(); + if (_fileStream->pos() >= _fileStream->size()) { + warning("Failed to find AVI header"); + return false; } - // Ignore the 'movi' LIST - if (nextTag == ID_LIST) { - _fileStream->readUint32BE(); // Skip size - if (_fileStream->readUint32BE() != ID_MOVI) - error("Expected 'movi' LIST"); - } else { - error("Expected 'movi' LIST"); + // Then read until we find the movie list + while (!_foundMovieList && _fileStream->pos() < _fileStream->size()) + runHandle(_fileStream->readUint32BE()); + + if (_fileStream->pos() >= _fileStream->size()) { + warning("Failed to find AVI 'movi' LIST"); + return false; } return true; @@ -294,6 +317,7 @@ void AVIDecoder::close() { delete _fileStream; _fileStream = 0; _decodedHeader = false; + _foundMovieList = false; delete[] _ixInfo.indices; memset(&_ixInfo, 0, sizeof(_ixInfo)); @@ -428,6 +452,10 @@ Codec *AVIDecoder::AVIVideoTrack::createCodec() { case ID_DUCK: return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); #endif +#ifdef USE_MPEG2 + case ID_MPG2: + return new MPEGDecoder(); +#endif default: warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); } |