aboutsummaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
authorPaul Gilbert2016-09-05 13:34:33 -0400
committerPaul Gilbert2016-09-10 10:07:53 -0400
commit73e79031865a71dd5ced18fe3269f79ceba6e08c (patch)
treefd0a7a29904346f95daf913a8efdb8a58eb3d296 /image
parentd3d0819b00c0dddcb35d99561c2eeadf04791190 (diff)
downloadscummvm-rg350-73e79031865a71dd5ced18fe3269f79ceba6e08c.tar.gz
scummvm-rg350-73e79031865a71dd5ced18fe3269f79ceba6e08c.tar.bz2
scummvm-rg350-73e79031865a71dd5ced18fe3269f79ceba6e08c.zip
IMAGE: Beginning of Indeo 4 decoder, added GetBits class for reading bits
Diffstat (limited to 'image')
-rw-r--r--image/codecs/codec.cpp4
-rw-r--r--image/codecs/indeo/get_bits.cpp462
-rw-r--r--image/codecs/indeo/get_bits.h169
-rw-r--r--image/codecs/indeo4.cpp81
-rw-r--r--image/codecs/indeo4.h64
-rw-r--r--image/module.mk4
6 files changed, 783 insertions, 1 deletions
diff --git a/image/codecs/codec.cpp b/image/codecs/codec.cpp
index 9e5c1bfe08..105e41e4ac 100644
--- a/image/codecs/codec.cpp
+++ b/image/codecs/codec.cpp
@@ -30,6 +30,7 @@
#include "image/codecs/cdtoons.h"
#include "image/codecs/cinepak.h"
#include "image/codecs/indeo3.h"
+#include "image/codecs/indeo4.h"
#include "image/codecs/mjpeg.h"
#include "image/codecs/mpeg.h"
#include "image/codecs/msvideo1.h"
@@ -209,6 +210,9 @@ Codec *createBitmapCodec(uint32 tag, int width, int height, int bitsPerPixel) {
return new CinepakDecoder(bitsPerPixel);
case MKTAG('I','V','3','2'):
return new Indeo3Decoder(width, height);
+ case MKTAG('I', 'V', '4', '1'):
+ case MKTAG('I', 'V', '4', '2'):
+ return new Indeo4Decoder(width, height);
#ifdef IMAGE_CODECS_TRUEMOTION1_H
case MKTAG('D','U','C','K'):
case MKTAG('d','u','c','k'):
diff --git a/image/codecs/indeo/get_bits.cpp b/image/codecs/indeo/get_bits.cpp
new file mode 100644
index 0000000000..4878bc674f
--- /dev/null
+++ b/image/codecs/indeo/get_bits.cpp
@@ -0,0 +1,462 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * 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.
+ *
+ */
+
+#include "image/codecs/indeo/get_bits.h"
+#include "common/endian.h"
+#include "common/textconsole.h"
+
+/* Intel Indeo 4 bitstream reader
+ *
+ * Original copyright note:
+ * Copyright (c) 2004 Michael Niedermayer
+ */
+
+namespace Image {
+namespace Indeo {
+
+/* Macro documentation
+ * name
+ * arbitrary name which is used as prefix for local variables
+ *
+ * OPEN_READER(name)
+ * load index into local variable
+ *
+ * CLOSE_READER(name)
+ * store local index back into class state
+ *
+ * UPDATE_CACHE(name)
+ * Refill the internal cache from the bitstream.
+ * After this call at least MIN_CACHE_BITS will be available.
+ *
+ * GET_CACHE(name)
+ * Will output the contents of the internal cache,
+ * next bit is MSB of 32 or 64 bits (FIXME 64 bits).
+ *
+ * SHOW_UBITS(name, num)
+ * Will return the next num bits.
+ *
+ * SHOW_SBITS(name, num)
+ * Will return the next num bits and do sign extension.
+ *
+ * SKIP_BITS(name, num)
+ * Will skip over the next num bits.
+ * Note, this is equivalent to SKIP_CACHE; SKIP_COUNTER.
+ *
+ * SKIP_CACHE(name, num)
+ * Will remove the next num bits from the cache (note SKIP_COUNTER
+ * MUST be called before UPDATE_CACHE / CLOSE_READER).
+ *
+ * SKIP_COUNTER(name, num)
+ * Will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS).
+ *
+ * LAST_SKIP_BITS(name, num)
+ * Like SKIP_BITS, to be used if next call is UPDATE_CACHE or CLOSE_READER.
+ *
+ * BITS_LEFT(name)
+ * Return the number of bits left
+ *
+ * For examples see getBits, show_bits, skip_bits, get_vlc.
+ */
+#define BITSTREAM_READER_LE
+
+#ifdef LONG_BITSTREAM_READER
+# define MIN_CACHE_BITS 32
+#else
+# define MIN_CACHE_BITS 25
+#endif
+
+#define NEG_USR32(a,s) (((uint32)(a)) >> (32 -(s)))
+
+#define OPEN_READER_NOSIZE(name) \
+ unsigned int name ## _index = _index; \
+ unsigned int name ## _cache
+
+#define OPEN_READER(name) OPEN_READER_NOSIZE(name)
+#define BITS_AVAILABLE(name) 1
+
+#define CLOSE_READER(name) _index = name ## _index
+
+# ifdef LONG_BITSTREAM_READER
+# define UPDATE_CACHE_LE(name) name ## _cache = \
+ AV_RL64(_buffer + (name ## _index >> 3)) >> (name ## _index & 7)
+
+# define UPDATE_CACHE_BE(name) name ## _cache = \
+ AV_RB64(_buffer + (name ## _index >> 3)) >> (32 - (name ## _index & 7))
+#else
+# define UPDATE_CACHE_LE(name) name ## _cache = \
+ READ_LE_UINT32(_buffer + (name ## _index >> 3)) >> (name ## _index & 7)
+
+# define UPDATE_CACHE_BE(name) name ## _cache = \
+ AV_RB32(_buffer + (name ## _index >> 3)) << (name ## _index & 7)
+#endif
+
+#ifdef BITSTREAM_READER_LE
+# define UPDATE_CACHE(name) UPDATE_CACHE_LE(name)
+# define SKIP_CACHE(name, num) name ## _cache >>= (num)
+#else
+# define UPDATE_CACHE(name) UPDATE_CACHE_BE(name)
+# define SKIP_CACHE(name, num) name ## _cache <<= (num)
+#endif
+
+#define SKIP_COUNTER(name, num) name ## _index += (num)
+
+#define BITS_LEFT(name) ((int)(_size_in_bits - name ## _index))
+
+#define SKIP_BITS(name, num) \
+ do { \
+ SKIP_CACHE(name, num); \
+ SKIP_COUNTER(name, num); \
+ } while (0)
+
+#define LAST_SKIP_BITS(name, num) SKIP_COUNTER(name, num)
+
+#define SHOW_UBITS_LE(name, num) zeroExtend(name ## _cache, num)
+#define SHOW_SBITS_LE(name, num) signExtend(name ## _cache, num)
+
+#define SHOW_UBITS_BE(name, num) NEG_USR32(name ## _cache, num)
+#define SHOW_SBITS_BE(name, num) NEG_SSR32(name ## _cache, num)
+
+#ifdef BITSTREAM_READER_LE
+# define SHOW_UBITS(name, num) SHOW_UBITS_LE(name, num)
+# define SHOW_SBITS(name, num) SHOW_SBITS_LE(name, num)
+#else
+# define SHOW_UBITS(name, num) SHOW_UBITS_BE(name, num)
+# define SHOW_SBITS(name, num) SHOW_SBITS_BE(name, num)
+#endif
+
+#define GET_CACHE(name) ((uint32) name ## _cache)
+
+
+static int signExtend(int val, uint bits) {
+ uint shift = 8 * sizeof(int) - bits;
+ union { uint u; int s; } v = { (unsigned)val << shift };
+ return v.s >> shift;
+}
+
+static uint zeroExtend(uint val, uint bits) {
+ return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits);
+}
+
+GetBits::GetBits(const byte *buffer, size_t totalBits) {
+ assert(buffer && totalBits < (INT_MAX - 7));
+
+ _buffer = buffer;
+ _sizeInBits = totalBits;
+ _sizeInBitsPlus8 = totalBits + 8;
+ _index = 0;
+}
+
+
+GetBits::GetBits(const GetBits &src) : _index(src._index), _buffer(src._buffer),
+ _sizeInBits(src._sizeInBits), _sizeInBitsPlus8(src._sizeInBitsPlus8) {
+}
+
+int GetBits::getXbits(int n) {
+ int sign;
+ int cache;
+ OPEN_READER(re);
+ assert(n > 0 && n <= 25);
+ UPDATE_CACHE(re);
+ cache = GET_CACHE(re);
+ sign = ~cache >> 31;
+ LAST_SKIP_BITS(re, n);
+ CLOSE_READER(re);
+ return (NEG_USR32(sign ^ cache, n) ^ sign) - sign;
+}
+
+int GetBits::getSbits(int n) {
+ int tmp;
+ OPEN_READER(re);
+ assert(n > 0 && n <= 25);
+ UPDATE_CACHE(re);
+ tmp = SHOW_SBITS(re, n);
+ LAST_SKIP_BITS(re, n);
+ CLOSE_READER(re);
+ return tmp;
+}
+
+/**
+* Read 1-25 bits.
+*/
+uint GetBits::getBits(int n) {
+ int tmp;
+ OPEN_READER(re);
+ assert(n > 0 && n <= 25);
+ UPDATE_CACHE(re);
+ tmp = SHOW_UBITS(re, n);
+ LAST_SKIP_BITS(re, n);
+ CLOSE_READER(re);
+ return tmp;
+}
+
+int GetBits::getBitsZ(int n) {
+ return n ? getBits(n) : 0;
+}
+
+uint GetBits::getBitsLE(int n) {
+ int tmp;
+ OPEN_READER(re);
+ assert(n > 0 && n <= 25);
+ UPDATE_CACHE_LE(re);
+ tmp = SHOW_UBITS_LE(re, n);
+ LAST_SKIP_BITS(re, n);
+ CLOSE_READER(re);
+ return tmp;
+}
+
+uint GetBits::showBits(int n) {
+ int tmp;
+ OPEN_READER_NOSIZE(re);
+ assert(n > 0 && n <= 25);
+ UPDATE_CACHE(re);
+ tmp = SHOW_UBITS(re, n);
+ return tmp;
+}
+
+void GetBits::skipBits(int n) {
+ OPEN_READER(re);
+ LAST_SKIP_BITS(re, n);
+ CLOSE_READER(re);
+}
+
+uint GetBits::getBits1() {
+ uint index = _index;
+ uint8 result = _buffer[index >> 3];
+#ifdef BITSTREAM_READER_LE
+ result >>= index & 7;
+ result &= 1;
+#else
+ result <<= index & 7;
+ result >>= 8 - 1;
+#endif
+#if !UNCHECKED_BITSTREAM_READER
+ if (_index < _sizeInBitsPlus8)
+#endif
+ index++;
+ _index = index;
+
+ return result;
+}
+
+uint GetBits::showBits1() {
+ return showBits(1);
+}
+
+void GetBits::skipBits1() {
+ skipBits(1);
+}
+
+/**
+* Read 0-32 bits.
+*/
+uint GetBits::getBitsLong(int n) {
+ if (!n) {
+ return 0;
+ } else if (n <= MIN_CACHE_BITS) {
+ return getBits(n);
+ } else {
+#ifdef BITSTREAM_READER_LE
+ unsigned ret = getBits(16);
+ return ret | (getBits(n - 16) << 16);
+#else
+ unsigned ret = getBits(16) << (n - 16);
+ return ret | getBits(n - 16);
+#endif
+ }
+}
+
+/**
+ * Read 0-64 bits.
+ */
+uint64 GetBits::getBits64(int n) {
+ if (n <= 32) {
+ return getBitsLong(n);
+ } else {
+#ifdef BITSTREAM_READER_LE
+ uint64 ret = getBitsLong(32);
+ return ret | (uint64)getBitsLong(n - 32) << 32;
+#else
+ uint64 ret = (uint64)getBitsLong(n - 32) << 32;
+ return ret | getBitsLong(32);
+#endif
+ }
+}
+
+int GetBits::getSbitsLong(int n) {
+ return signExtend(getBitsLong(n), n);
+}
+
+/**
+* Show 0-32 bits.
+*/
+uint GetBits::showBitsLong(int n) {
+ if (n <= MIN_CACHE_BITS) {
+ return showBits(n);
+ } else {
+ GetBits gb(*this);
+ return gb.getBitsLong(n);
+ }
+}
+
+int GetBits::checkMarker(void *logctx, const char *msg) {
+ int bit = getBits1();
+ if (!bit)
+ warning("Marker bit missing at %d of %d %s\n",
+ getBitsCount() - 1, _sizeInBits, msg);
+
+ return bit;
+}
+
+const byte *GetBits::alignGetBits() {
+ int n = -(int)getBitsCount() & 7;
+ if (n)
+ skipBits(n);
+
+ return _buffer + (_index >> 3);
+}
+
+/**
+ * If the vlc code is invalid and max_depth=1, then no bits will be removed.
+ * If the vlc code is invalid and max_depth>1, then the number of bits removed
+ * is undefined.
+ */
+#define GET_VLC(code, name, table, bits, max_depth) \
+ do { \
+ int n, nb_bits; \
+ unsigned int index; \
+ \
+ index = SHOW_UBITS(name, bits); \
+ code = table[index][0]; \
+ n = table[index][1]; \
+ \
+ if (max_depth > 1 && n < 0) { \
+ LAST_SKIP_BITS(name, bits); \
+ UPDATE_CACHE(name); \
+ \
+ nb_bits = -n; \
+ \
+ index = SHOW_UBITS(name, nb_bits) + code; \
+ code = table[index][0]; \
+ n = table[index][1]; \
+ if (max_depth > 2 && n < 0) { \
+ LAST_SKIP_BITS(name, nb_bits); \
+ UPDATE_CACHE(name); \
+ \
+ nb_bits = -n; \
+ \
+ index = SHOW_UBITS(name, nb_bits) + code; \
+ code = table[index][0]; \
+ n = table[index][1]; \
+ } \
+ } \
+ SKIP_BITS(name, n); \
+ } while (0)
+
+#define GET_RL_VLC(level, run, name, table, bits, \
+ max_depth, need_update) \
+ do { \
+ int n, nb_bits; \
+ unsigned int index; \
+ \
+ index = SHOW_UBITS(name, bits); \
+ level = table[index].level; \
+ n = table[index].len; \
+ \
+ if (max_depth > 1 && n < 0) { \
+ SKIP_BITS(name, bits); \
+ if (need_update) { \
+ UPDATE_CACHE(name); \
+ } \
+ \
+ nb_bits = -n; \
+ \
+ index = SHOW_UBITS(name, nb_bits) + level; \
+ level = table[index].level; \
+ n = table[index].len; \
+ if (max_depth > 2 && n < 0) { \
+ LAST_SKIP_BITS(name, nb_bits); \
+ if (need_update) { \
+ UPDATE_CACHE(name); \
+ } \
+ nb_bits = -n; \
+ \
+ index = SHOW_UBITS(name, nb_bits) + level; \
+ level = table[index].level; \
+ n = table[index].len; \
+ } \
+ } \
+ run = table[index].run; \
+ SKIP_BITS(name, n); \
+ } while (0)
+
+/**
+* Parse a vlc code.
+* @param bits is the number of bits which will be read at once, must be
+* identical to nb_bits in init_vlc()
+* @param max_depth is the number of times bits bits must be read to completely
+* read the longest vlc code
+* = (max_vlc_length + bits - 1) / bits
+*/
+int GetBits::getVLC2(int (*table)[2], int bits, int maxDepth) {
+ int code;
+
+ OPEN_READER(re);
+ UPDATE_CACHE(re);
+
+ GET_VLC(code, re, table, bits, maxDepth);
+
+ CLOSE_READER(re);
+
+ return code;
+}
+
+int GetBits::decode012() {
+ int n;
+ n = getBits1();
+ if (n == 0)
+ return 0;
+ else
+ return getBits1() + 1;
+}
+
+int GetBits::decode210() {
+ if (getBits1())
+ return 0;
+ else
+ return 2 - getBits1();
+}
+
+int GetBits::skip1stop8dataBits() {
+ if (getBitsLeft() <= 0)
+ return -1;
+
+ while (getBits1()) {
+ skipBits(8);
+ if (getBitsLeft() <= 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+} // End of namespace Indeo
+} // End of namespace Image
diff --git a/image/codecs/indeo/get_bits.h b/image/codecs/indeo/get_bits.h
new file mode 100644
index 0000000000..dd6ba55dd2
--- /dev/null
+++ b/image/codecs/indeo/get_bits.h
@@ -0,0 +1,169 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * 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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+/* Intel Indeo 4 bitstream reader
+ *
+ * Original copyright note:
+ * Copyright (c) 2004 Michael Niedermayer
+ */
+
+#ifndef IMAGE_CODECS_INDEO_GET_BITS_H
+#define IMAGE_CODECS_INDEO_GET_BITS_H
+
+#include "common/scummsys.h"
+
+namespace Image {
+namespace Indeo {
+
+#define AV_INPUT_BUFFER_PADDING_SIZE 32
+
+/**
+ * Intel Indeo Bitstream reader
+ */
+class GetBits {
+private:
+ const byte *_buffer;
+ uint _index;
+ uint _sizeInBits;
+ uint _sizeInBitsPlus8;
+public:
+ /**
+ * Constructor
+ * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes
+ * larger than the actual read bits because some optimized bitstream
+ * readers read 32 or 64 bit at once and could read over the end
+ * @param bit_size the size of the buffer in bits
+ * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow.
+ */
+ GetBits(const byte *buffer, size_t totalBits);
+
+ GetBits(const GetBits &src);
+
+ /**
+ * Returns the number of bits read
+ */
+ uint getBitsCount() const { return _index; }
+
+ /**
+ * The number of bits left
+ */
+ int getBitsLeft() const { return _sizeInBits - _index; }
+
+ void skipBitsLong(uint n) { _index += n; }
+
+ /**
+ * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB).
+ * if MSB not set it is negative
+ * @param n length in bits
+ */
+ int getXbits(int n);
+
+ /**
+ * Returns the next n bits, and does sign extension
+ */
+ int getSbits(int n);
+
+ /**
+ * Read 1-25 bits.
+ */
+ uint getBits(int n);
+
+ /**
+ * Read 0-25 bits.
+ */
+ int getBitsZ(int n);
+
+ uint getBitsLE(int n);
+
+ /**
+ * Show 1-25 bits.
+ * Returns the data without updating the index
+ */
+ uint showBits(int n);
+
+ /**
+ * Skips a specified number of bits
+ */
+ void skipBits(int n);
+
+ /**
+ * Returns the next bit
+ */
+ uint getBits1();
+
+ /**
+ * Shows the next following bit
+ */
+ uint showBits1();
+
+ /**
+ * Skips the next bit
+ */
+ void skipBits1();
+
+ /**
+ * Read 0-32 bits.
+ */
+ uint getBitsLong(int n);
+
+ /**
+ * Read 0-64 bits.
+ */
+ uint64 getBits64(int n);
+
+ /**
+ * Read 0-32 bits as a signed integer.
+ */
+ int getSbitsLong(int n);
+
+ /**
+ * Show 0-32 bits.
+ */
+ uint showBitsLong(int n);
+
+ int checkMarker(void *logctx, const char *msg);
+
+ /**
+ * Parse a VLC code.
+ * @param bits is the number of bits which will be read at once, must be
+ * identical to nb_bits in init_vlc()
+ * @param max_depth is the number of times bits bits must be read to completely
+ * read the longest vlc code
+ * = (max_vlc_length + bits - 1) / bits
+ */
+ int getVLC2(int(*table)[2], int bits, int maxDepth);
+
+ int decode012();
+
+ int decode210();
+
+ int skip1stop8dataBits();
+
+ const byte *alignGetBits();
+};
+
+} // End of namespace Indeo
+} // End of namespace Image
+
+#endif
diff --git a/image/codecs/indeo4.cpp b/image/codecs/indeo4.cpp
new file mode 100644
index 0000000000..465e3adc49
--- /dev/null
+++ b/image/codecs/indeo4.cpp
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * 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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+/* Intel Indeo 4 decompressor, derived from ffmpeg.
+ *
+ * Original copyright note: * Intel Indeo 3 (IV31, IV32, etc.) video decoder for ffmpeg
+ * written, produced, and directed by Alan Smithee
+ */
+
+#include "common/system.h"
+#include "common/endian.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+#include "common/util.h"
+
+#include "graphics/yuv_to_rgb.h"
+
+#include "image/codecs/indeo4.h"
+#include "image/codecs/indeo/get_bits.h"
+
+namespace Image {
+
+Indeo4Decoder::Indeo4Decoder(uint16 width, uint16 height) {
+ _pixelFormat = g_system->getScreenFormat();
+ _surface = new Graphics::ManagedSurface();
+ _surface->create(width, height, _pixelFormat);
+
+}
+
+Indeo4Decoder::~Indeo4Decoder() {
+ delete _surface;
+}
+
+bool Indeo4Decoder::isIndeo4(Common::SeekableReadStream &stream) {
+ // Less than 16 bytes? This can't be right
+ if (stream.size() < 16)
+ return false;
+
+ // Read in the start of the data
+ byte buffer[16];
+ stream.read(buffer, 16);
+ stream.seek(-16, SEEK_CUR);
+
+ // Validate the first 18-bit word has the correct identifier
+ Indeo::GetBits gb(buffer, 16 * 8);
+ bool isIndeo4 = gb.getBits(18) == 0x3FFF8;
+
+ return isIndeo4;
+}
+
+const Graphics::Surface *Indeo4Decoder::decodeFrame(Common::SeekableReadStream &stream) {
+ // Not Indeo 4? Fail
+ if (!isIndeo4(stream))
+ return 0;
+
+ // TODO
+ return nullptr;
+}
+
+} // End of namespace Image
diff --git a/image/codecs/indeo4.h b/image/codecs/indeo4.h
new file mode 100644
index 0000000000..44007e08b8
--- /dev/null
+++ b/image/codecs/indeo4.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * 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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+/* Intel Indeo 4 decompressor, derived from ffmpeg.
+ *
+ * Original copyright note:
+ * Intel Indeo 4 (IV31, IV32, etc.) video decoder for ffmpeg
+ * written, produced, and directed by Alan Smithee
+ */
+
+#ifndef IMAGE_CODECS_INDEO4_H
+#define IMAGE_CODECS_INDEO4_H
+
+#include "image/codecs/codec.h"
+#include "graphics/managed_surface.h"
+
+namespace Image {
+
+/**
+ * Intel Indeo 4 decoder.
+ *
+ * Used by AVI.
+ *
+ * Used in video:
+ * - AVIDecoder
+ */
+class Indeo4Decoder : public Codec {
+public:
+ Indeo4Decoder(uint16 width, uint16 height);
+ ~Indeo4Decoder();
+
+ const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream);
+ Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+ static bool isIndeo4(Common::SeekableReadStream &stream);
+private:
+ Graphics::PixelFormat _pixelFormat;
+ Graphics::ManagedSurface *_surface;
+};
+
+} // End of namespace Image
+
+#endif
diff --git a/image/module.mk b/image/module.mk
index 3742fb909f..af4284dcdb 100644
--- a/image/module.mk
+++ b/image/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
codecs/cinepak.o \
codecs/codec.o \
codecs/indeo3.o \
+ codecs/indeo4.o \
codecs/mjpeg.o \
codecs/msrle.o \
codecs/msrle4.o \
@@ -21,7 +22,8 @@ MODULE_OBJS := \
codecs/rpza.o \
codecs/smc.o \
codecs/svq1.o \
- codecs/truemotion1.o
+ codecs/truemotion1.o \
+ codecs/indeo/get_bits.o
ifdef USE_MPEG2
MODULE_OBJS += \