diff options
-rw-r--r-- | image/codecs/codec.cpp | 2 | ||||
-rw-r--r-- | image/codecs/truemotion1.cpp | 19 | ||||
-rw-r--r-- | image/codecs/truemotion1.h | 2 | ||||
-rw-r--r-- | video/avi_decoder.cpp | 54 | ||||
-rw-r--r-- | video/avi_decoder.h | 4 |
5 files changed, 72 insertions, 9 deletions
diff --git a/image/codecs/codec.cpp b/image/codecs/codec.cpp index 64acf3f169..6b0c7ebcfb 100644 --- a/image/codecs/codec.cpp +++ b/image/codecs/codec.cpp @@ -61,7 +61,7 @@ Codec *createBitmapCodec(uint32 tag, int width, int height, int bitsPerPixel) { #ifdef IMAGE_CODECS_TRUEMOTION1_H case MKTAG('D','U','C','K'): case MKTAG('d','u','c','k'): - return new TrueMotion1Decoder(width, height); + return new TrueMotion1Decoder(); #endif #ifdef USE_MPEG2 case MKTAG('m','p','g','2'): diff --git a/image/codecs/truemotion1.cpp b/image/codecs/truemotion1.cpp index 741b9d51eb..e60ec6c72e 100644 --- a/image/codecs/truemotion1.cpp +++ b/image/codecs/truemotion1.cpp @@ -89,11 +89,8 @@ static const CompressionType compressionTypes[17] = { { ALGO_RGB24H, 2, 2, BLOCK_2x2 } }; -TrueMotion1Decoder::TrueMotion1Decoder(uint16 width, uint16 height) { - _surface = new Graphics::Surface(); - _surface->create(width, height, getPixelFormat()); - _surface->fillRect(Common::Rect(width, height), getPixelFormat().RGBToColor(0, 0, 0)); - +TrueMotion1Decoder::TrueMotion1Decoder() { + _surface = 0; _vertPred = 0; _buf = _mbChangeBits = _indexStream = 0; @@ -101,8 +98,11 @@ TrueMotion1Decoder::TrueMotion1Decoder(uint16 width, uint16 height) { } TrueMotion1Decoder::~TrueMotion1Decoder() { - _surface->free(); - delete _surface; + if (_surface) { + _surface->free(); + delete _surface; + } + delete[] _vertPred; } @@ -194,6 +194,11 @@ void TrueMotion1Decoder::decodeHeader(Common::SeekableReadStream &stream) { _vertPred = new uint32[_header.xsize]; } + if (!_surface) { + _surface = new Graphics::Surface(); + _surface->create(_header.xsize, _header.ysize, getPixelFormat()); + } + // There is 1 change bit per 4 pixels, so each change byte represents // 32 pixels; divide width by 4 to obtain the number of change bits and // then round up to the nearest byte. diff --git a/image/codecs/truemotion1.h b/image/codecs/truemotion1.h index bbbcd6d6be..51daf607d2 100644 --- a/image/codecs/truemotion1.h +++ b/image/codecs/truemotion1.h @@ -39,7 +39,7 @@ namespace Image { */ class TrueMotion1Decoder : public Codec { public: - TrueMotion1Decoder(uint16 width, uint16 height); + TrueMotion1Decoder(); ~TrueMotion1Decoder(); const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream); 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; diff --git a/video/avi_decoder.h b/video/avi_decoder.h index 2f7b267d36..28d87bc3b7 100644 --- a/video/avi_decoder.h +++ b/video/avi_decoder.h @@ -185,6 +185,9 @@ protected: void loadPaletteFromChunk(Common::SeekableReadStream *chunk); void useInitialPalette(); + bool isTruemotion1() const; + void forceDimensions(uint16 width, uint16 height); + bool isRewindable() const { return true; } bool rewind(); @@ -257,6 +260,7 @@ protected: uint16 getStreamType(uint32 tag) const { return tag & 0xFFFF; } byte getStreamIndex(uint32 tag) const; void forceVideoEnd(); + void checkTruemotion1(); public: virtual AVIAudioTrack *createAudioTrack(AVIStreamHeader sHeader, PCMWaveFormat wvInfo); |