diff options
author | Sven Hesse | 2010-08-27 10:45:19 +0000 |
---|---|---|
committer | Sven Hesse | 2010-08-27 10:45:19 +0000 |
commit | 4d15e5f31c86d82d0fff31b95aa36cc453d8889c (patch) | |
tree | bf1c895e8216af1ca720601a56f12db8b966e5bd /graphics/video | |
parent | 03fe16087e514dccddd5417010e5a0723958f6ea (diff) | |
download | scummvm-rg350-4d15e5f31c86d82d0fff31b95aa36cc453d8889c.tar.gz scummvm-rg350-4d15e5f31c86d82d0fff31b95aa36cc453d8889c.tar.bz2 scummvm-rg350-4d15e5f31c86d82d0fff31b95aa36cc453d8889c.zip |
VIDEO: Change decodeImage() around a bit, plug a leak
Indeo3Decoder::decoderImage() was leaking inData
svn-id: r52408
Diffstat (limited to 'graphics/video')
-rw-r--r-- | graphics/video/codecs/indeo3.cpp | 109 | ||||
-rw-r--r-- | graphics/video/codecs/indeo3.h | 2 |
2 files changed, 61 insertions, 50 deletions
diff --git a/graphics/video/codecs/indeo3.cpp b/graphics/video/codecs/indeo3.cpp index f59ae81e81..c99afbd0d3 100644 --- a/graphics/video/codecs/indeo3.cpp +++ b/graphics/video/codecs/indeo3.cpp @@ -69,27 +69,22 @@ PixelFormat Indeo3Decoder::getPixelFormat() const { return _pixelFormat; } -bool Indeo3Decoder::isIndeo3(byte *data, uint32 dataLen) { - // No data, no Indeo 3 - if (!data) - return false; - +bool Indeo3Decoder::isIndeo3(Common::SeekableReadStream &stream) { // Less than 16 bytes? This can't be right - if (dataLen < 16) + if (stream.size() < 16) return false; + uint32 id0 = stream.readUint32LE(); + uint32 id1 = stream.readUint32LE(); + uint32 id2 = stream.readUint32LE(); + uint32 id3 = stream.readUint32LE(); + // Unknown, but according to the docs, always 0 - if (READ_LE_UINT32(data + 4) != 0) + if (id1 != 0) return false; - uint32 id; - id = READ_LE_UINT32(data ); // frame number - id ^= READ_LE_UINT32(data + 4); // unknown - id ^= READ_LE_UINT32(data + 8); // checksum - id ^= READ_LE_UINT32(data + 12); // frame data length - // These 4 uint32s XOR'd need to spell "FRMH" - if (id != MKID_BE('FRMH')) + if ((id0 ^ id1 ^ id2 ^ id3) != MKID_BE('FRMH')) return false; return true; @@ -174,31 +169,23 @@ void Indeo3Decoder::allocFrames() { } Surface *Indeo3Decoder::decodeImage(Common::SeekableReadStream *stream) { - uint32 dataLen = stream->size(); - - byte *inData = new byte[dataLen]; - - if (stream->read(inData, dataLen) != dataLen) - return 0; - // Not Indeo 3? Fail - if (!isIndeo3(inData, dataLen)) + if (!isIndeo3(*stream)) return 0; - uint32 frameDataLen = READ_LE_UINT32(inData + 12); + stream->seek(12); + uint32 frameDataLen = stream->readUint32LE(); // Less data than the frame should have? Fail - if (dataLen < (frameDataLen - 16)) + if (stream->size() < (int)(frameDataLen - 16)) return 0; - Common::MemoryReadStream frame(inData, dataLen); - - frame.skip(16); // Header - frame.skip(2); // Unknown + stream->seek(16); // Behind header + stream->skip(2); // Unknown - uint16 flags1 = frame.readUint16LE(); - uint32 flags3 = frame.readUint32LE(); - uint8 flags2 = frame.readByte(); + uint16 flags1 = stream->readUint16LE(); + uint32 flags3 = stream->readUint32LE(); + uint8 flags2 = stream->readByte(); // Finding the reference frame if (flags1 & 0x200) { @@ -212,47 +199,71 @@ Surface *Indeo3Decoder::decodeImage(Common::SeekableReadStream *stream) { if (flags3 == 0x80) return _surface; - frame.skip(3); + stream->skip(3); - uint16 fHeight = frame.readUint16LE(); - uint16 fWidth = frame.readUint16LE(); + uint16 fHeight = stream->readUint16LE(); + uint16 fWidth = stream->readUint16LE(); uint32 chromaHeight = ((fHeight >> 2) + 3) & 0x7FFC; uint32 chromaWidth = ((fWidth >> 2) + 3) & 0x7FFC; uint32 offs; - uint32 offsY = frame.readUint32LE() + 16; - uint32 offsU = frame.readUint32LE() + 16; - uint32 offsV = frame.readUint32LE() + 16; + uint32 offsY = stream->readUint32LE() + 16; + uint32 offsU = stream->readUint32LE() + 16; + uint32 offsV = stream->readUint32LE() + 16; + + stream->skip(4); + + uint32 hPos = stream->pos(); - frame.skip(4); + if (offsY < hPos) { + warning("Indeo3Decoder::decodeImage: offsY < hPos"); + return 0; + } + if (offsU < hPos) { + warning("Indeo3Decoder::decodeImage: offsY < hPos"); + return 0; + } + if (offsV < hPos) { + warning("Indeo3Decoder::decodeImage: offsY < hPos"); + return 0; + } - uint32 hPos = frame.pos(); + uint32 dataSize = stream->size() - hPos; - byte *hdr_pos = inData + hPos; + byte *inData = new byte[dataSize]; + + if (stream->read(inData, dataSize) != dataSize) { + delete[] inData; + return 0; + } + + byte *hdr_pos = inData; byte *buf_pos; // Luminance Y - frame.seek(offsY); - buf_pos = inData + offsY + 4; - offs = frame.readUint32LE(); + stream->seek(offsY); + buf_pos = inData + offsY + 4 - hPos; + offs = stream->readUint32LE(); decodeChunk(_cur_frame->Ybuf, _ref_frame->Ybuf, fWidth, fHeight, buf_pos + offs * 2, flags2, hdr_pos, buf_pos, MIN<int>(fWidth, 160)); // Chrominance U - frame.seek(offsU); - buf_pos = inData + offsU + 4; - offs = frame.readUint32LE(); + stream->seek(offsU); + buf_pos = inData + offsU + 4 - hPos; + offs = stream->readUint32LE(); decodeChunk(_cur_frame->Vbuf, _ref_frame->Vbuf, chromaWidth, chromaHeight, buf_pos + offs * 2, flags2, hdr_pos, buf_pos, MIN<int>(chromaWidth, 40)); // Chrominance V - frame.seek(offsV); - buf_pos = inData + offsV + 4; - offs = frame.readUint32LE(); + stream->seek(offsV); + buf_pos = inData + offsV + 4 - hPos; + offs = stream->readUint32LE(); decodeChunk(_cur_frame->Ubuf, _ref_frame->Ubuf, chromaWidth, chromaHeight, buf_pos + offs * 2, flags2, hdr_pos, buf_pos, MIN<int>(chromaWidth, 40)); + delete[] inData; + // Blit the frame onto the surface const byte *srcY = _cur_frame->Ybuf; const byte *srcU = _cur_frame->Ubuf; diff --git a/graphics/video/codecs/indeo3.h b/graphics/video/codecs/indeo3.h index 8d50b74b1e..319a8e5d42 100644 --- a/graphics/video/codecs/indeo3.h +++ b/graphics/video/codecs/indeo3.h @@ -49,7 +49,7 @@ public: Surface *decodeImage(Common::SeekableReadStream *stream); PixelFormat getPixelFormat() const; - static bool isIndeo3(byte *data, uint32 dataLen); + static bool isIndeo3(Common::SeekableReadStream &stream); private: Surface *_surface; |