aboutsummaryrefslogtreecommitdiff
path: root/graphics/video
diff options
context:
space:
mode:
authorSven Hesse2010-08-27 10:45:19 +0000
committerSven Hesse2010-08-27 10:45:19 +0000
commit4d15e5f31c86d82d0fff31b95aa36cc453d8889c (patch)
treebf1c895e8216af1ca720601a56f12db8b966e5bd /graphics/video
parent03fe16087e514dccddd5417010e5a0723958f6ea (diff)
downloadscummvm-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.cpp109
-rw-r--r--graphics/video/codecs/indeo3.h2
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;