mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-04 16:26:53 +00:00
1001 lines
30 KiB
C++
1001 lines
30 KiB
C++
/* 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.
|
|
*
|
|
*/
|
|
|
|
/* Intel Indeo 4 decompressor, derived from ffmpeg.
|
|
*
|
|
* Original copyright note: * Intel Indeo 4 (IV41, IV42, etc.) video decoder for ffmpeg
|
|
* written, produced, and directed by Alan Smithee
|
|
*/
|
|
|
|
#include "common/memstream.h"
|
|
#include "common/textconsole.h"
|
|
#include "graphics/yuv_to_rgb.h"
|
|
#include "image/codecs/indeo4.h"
|
|
#include "image/codecs/indeo/indeo_dsp.h"
|
|
#include "image/codecs/indeo/mem.h"
|
|
|
|
namespace Image {
|
|
|
|
#define IVI4_PIC_SIZE_ESC 7
|
|
|
|
Indeo4Decoder::Indeo4Decoder(uint16 width, uint16 height, uint bitsPerPixel) :
|
|
IndeoDecoderBase(width, height, bitsPerPixel) {
|
|
_ctx._isIndeo4 = true;
|
|
_ctx._refBuf = 1;
|
|
_ctx._bRefBuf = 3;
|
|
_ctx._pFrame = new AVFrame();
|
|
}
|
|
|
|
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(new Common::MemoryReadStream(buffer, 16 * 8), DisposeAfterUse::YES);
|
|
bool isIndeo4 = gb.getBits(18) == 0x3FFF8;
|
|
|
|
return isIndeo4;
|
|
}
|
|
|
|
const Graphics::Surface *Indeo4Decoder::decodeFrame(Common::SeekableReadStream &stream) {
|
|
// Not Indeo 4? Fail
|
|
if (!isIndeo4(stream))
|
|
return nullptr;
|
|
|
|
// Set up the frame data buffer
|
|
byte *frameData = new byte[stream.size()];
|
|
stream.read(frameData, stream.size());
|
|
_ctx._frameData = frameData;
|
|
_ctx._frameSize = stream.size();
|
|
|
|
// Set up the GetBits instance for reading the data
|
|
_ctx._gb = new GetBits(new Common::MemoryReadStream(_ctx._frameData, _ctx._frameSize));
|
|
|
|
// Decode the frame
|
|
int err = decodeIndeoFrame();
|
|
|
|
// Free the bit reader and frame buffer
|
|
delete _ctx._gb;
|
|
_ctx._gb = nullptr;
|
|
delete[] frameData;
|
|
_ctx._frameData = nullptr;
|
|
_ctx._frameSize = 0;
|
|
|
|
return (err < 0) ? nullptr : _surface;
|
|
}
|
|
|
|
int Indeo4Decoder::decodePictureHeader() {
|
|
int pic_size_indx, i, p;
|
|
IVIPicConfig picConf;
|
|
|
|
if (_ctx._gb->getBits(18) != 0x3FFF8) {
|
|
warning("Invalid picture start code!");
|
|
return -1;
|
|
}
|
|
|
|
_ctx._prevFrameType = _ctx._frameType;
|
|
_ctx._frameType = _ctx._gb->getBits(3);
|
|
if (_ctx._frameType == 7) {
|
|
warning("Invalid frame type: %d", _ctx._frameType);
|
|
return -1;
|
|
}
|
|
|
|
if (_ctx._frameType == IVI4_FRAMETYPE_BIDIR)
|
|
_ctx._hasBFrames = true;
|
|
|
|
_ctx._hasTransp = _ctx._gb->getBit();
|
|
|
|
// unknown bit: Mac decoder ignores this bit, XANIM returns error
|
|
if (_ctx._gb->getBit()) {
|
|
warning("Sync bit is set!");
|
|
return -1;
|
|
}
|
|
|
|
_ctx._dataSize = _ctx._gb->getBit() ? _ctx._gb->getBits(24) : 0;
|
|
|
|
// null frames don't contain anything else so we just return
|
|
if (_ctx._frameType >= IVI4_FRAMETYPE_NULL_FIRST) {
|
|
warning("Null frame encountered!");
|
|
return 0;
|
|
}
|
|
|
|
// Check key lock status. If enabled - ignore lock word.
|
|
// Usually we have to prompt the user for the password, but
|
|
// we don't do that because Indeo 4 videos can be decoded anyway
|
|
if (_ctx._gb->getBit()) {
|
|
_ctx._gb->skip(32);
|
|
warning("Password-protected clip!");
|
|
}
|
|
|
|
pic_size_indx = _ctx._gb->getBits(3);
|
|
if (pic_size_indx == IVI4_PIC_SIZE_ESC) {
|
|
picConf._picHeight = _ctx._gb->getBits(16);
|
|
picConf._picWidth = _ctx._gb->getBits(16);
|
|
} else {
|
|
picConf._picHeight = _ivi4_common_pic_sizes[pic_size_indx * 2 + 1];
|
|
picConf._picWidth = _ivi4_common_pic_sizes[pic_size_indx * 2];
|
|
}
|
|
|
|
// Decode tile dimensions.
|
|
_ctx._usesTiling = _ctx._gb->getBit();
|
|
if (_ctx._usesTiling) {
|
|
picConf._tileHeight = scaleTileSize(picConf._picHeight, _ctx._gb->getBits(4));
|
|
picConf._tileWidth = scaleTileSize(picConf._picWidth, _ctx._gb->getBits(4));
|
|
} else {
|
|
picConf._tileHeight = picConf._picHeight;
|
|
picConf._tileWidth = picConf._picWidth;
|
|
}
|
|
|
|
// Decode chroma subsampling. We support only 4:4 aka YVU9.
|
|
if (_ctx._gb->getBits(2)) {
|
|
warning("Only YVU9 picture format is supported!");
|
|
return -1;
|
|
}
|
|
picConf._chromaHeight = (picConf._picHeight + 3) >> 2;
|
|
picConf._chromaWidth = (picConf._picWidth + 3) >> 2;
|
|
|
|
// decode subdivision of the planes
|
|
picConf._lumaBands = decodePlaneSubdivision();
|
|
picConf._chromaBands = 0;
|
|
if (picConf._lumaBands)
|
|
picConf._chromaBands = decodePlaneSubdivision();
|
|
_ctx._isScalable = picConf._lumaBands != 1 || picConf._chromaBands != 1;
|
|
if (_ctx._isScalable && (picConf._lumaBands != 4 || picConf._chromaBands != 1)) {
|
|
warning("Scalability: unsupported subdivision! Luma bands: %d, chroma bands: %d",
|
|
picConf._lumaBands, picConf._chromaBands);
|
|
return -1;
|
|
}
|
|
|
|
// check if picture layout was changed and reallocate buffers
|
|
if (picConf.ivi_pic_config_cmp(_ctx._picConf)) {
|
|
if (IVIPlaneDesc::initPlanes(_ctx._planes, &picConf, 1)) {
|
|
warning("Couldn't reallocate color planes!");
|
|
_ctx._picConf._lumaBands = 0;
|
|
return -2;
|
|
}
|
|
|
|
_ctx._picConf = picConf;
|
|
|
|
// set default macroblock/block dimensions
|
|
for (p = 0; p <= 2; p++) {
|
|
for (i = 0; i < (!p ? picConf._lumaBands : picConf._chromaBands); i++) {
|
|
_ctx._planes[p]._bands[i]._mbSize = !p ? (!_ctx._isScalable ? 16 : 8) : 4;
|
|
_ctx._planes[p]._bands[i]._blkSize = !p ? 8 : 4;
|
|
}
|
|
}
|
|
|
|
if (IVIPlaneDesc::initTiles(_ctx._planes, _ctx._picConf._tileWidth,
|
|
_ctx._picConf._tileHeight)) {
|
|
warning("Couldn't reallocate internal structures!");
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
_ctx._frameNum = _ctx._gb->getBit() ? _ctx._gb->getBits(20) : 0;
|
|
|
|
// skip decTimeEst field if present
|
|
if (_ctx._gb->getBit())
|
|
_ctx._gb->skip(8);
|
|
|
|
// decode macroblock and block huffman codebooks
|
|
if (_ctx._mbVlc.decodeHuffDesc(&_ctx, _ctx._gb->getBit(), IVI_MB_HUFF) ||
|
|
_ctx._blkVlc.decodeHuffDesc(&_ctx, _ctx._gb->getBit(), IVI_BLK_HUFF))
|
|
return -1;
|
|
|
|
_ctx._rvmapSel = _ctx._gb->getBit() ? _ctx._gb->getBits(3) : 8;
|
|
|
|
_ctx._inImf = _ctx._gb->getBit();
|
|
_ctx._inQ = _ctx._gb->getBit();
|
|
|
|
_ctx._picGlobQuant = _ctx._gb->getBits(5);
|
|
|
|
// TODO: ignore this parameter if unused
|
|
_ctx._unknown1 = _ctx._gb->getBit() ? _ctx._gb->getBits(3) : 0;
|
|
|
|
_ctx._checksum = _ctx._gb->getBit() ? _ctx._gb->getBits(16) : 0;
|
|
|
|
// skip picture header extension if any
|
|
while (_ctx._gb->getBit()) {
|
|
_ctx._gb->skip(8);
|
|
}
|
|
|
|
if (_ctx._gb->getBit()) {
|
|
warning("Bad blocks bits encountered!");
|
|
}
|
|
|
|
_ctx._gb->align();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Indeo4Decoder::switchBuffers() {
|
|
int isPrevRef = 0, isRef = 0;
|
|
|
|
switch (_ctx._prevFrameType) {
|
|
case IVI4_FRAMETYPE_INTRA:
|
|
case IVI4_FRAMETYPE_INTRA1:
|
|
case IVI4_FRAMETYPE_INTER:
|
|
isPrevRef = 1;
|
|
break;
|
|
}
|
|
|
|
switch (_ctx._frameType) {
|
|
case IVI4_FRAMETYPE_INTRA:
|
|
case IVI4_FRAMETYPE_INTRA1:
|
|
case IVI4_FRAMETYPE_INTER:
|
|
isRef = 1;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (isPrevRef && isRef) {
|
|
SWAP(_ctx._dstBuf, _ctx._refBuf);
|
|
} else if (isPrevRef) {
|
|
SWAP(_ctx._refBuf, _ctx._bRefBuf);
|
|
SWAP(_ctx._dstBuf, _ctx._refBuf);
|
|
}
|
|
}
|
|
|
|
bool Indeo4Decoder::isNonNullFrame() const {
|
|
return _ctx._frameType < IVI4_FRAMETYPE_NULL_FIRST;
|
|
}
|
|
|
|
int Indeo4Decoder::decodeBandHeader(IVIBandDesc *band) {
|
|
int plane, bandNum, indx, transformId, scanIndx;
|
|
int i;
|
|
int quantMat;
|
|
|
|
plane = _ctx._gb->getBits(2);
|
|
bandNum = _ctx._gb->getBits(4);
|
|
if (band->_plane != plane || band->_bandNum != bandNum) {
|
|
warning("Invalid band header sequence!");
|
|
return -1;
|
|
}
|
|
|
|
band->_isEmpty = _ctx._gb->getBit();
|
|
if (!band->_isEmpty) {
|
|
int old_blk_size = band->_blkSize;
|
|
// skip header size
|
|
// If header size is not given, header size is 4 bytes.
|
|
if (_ctx._gb->getBit())
|
|
_ctx._gb->skip(16);
|
|
|
|
band->_isHalfpel = _ctx._gb->getBits(2);
|
|
if (band->_isHalfpel >= 2) {
|
|
warning("Invalid/unsupported mv resolution: %d!",
|
|
band->_isHalfpel);
|
|
return -1;
|
|
}
|
|
if (!band->_isHalfpel)
|
|
_ctx._usesFullpel = true;
|
|
|
|
band->_checksumPresent = _ctx._gb->getBit();
|
|
if (band->_checksumPresent)
|
|
band->_checksum = _ctx._gb->getBits(16);
|
|
|
|
indx = _ctx._gb->getBits(2);
|
|
if (indx == 3) {
|
|
warning("Invalid block size!");
|
|
return -1;
|
|
}
|
|
band->_mbSize = 16 >> indx;
|
|
band->_blkSize = 8 >> (indx >> 1);
|
|
|
|
band->_inheritMv = _ctx._gb->getBit();
|
|
band->_inheritQDelta = _ctx._gb->getBit();
|
|
|
|
band->_globQuant = _ctx._gb->getBits(5);
|
|
|
|
if (!_ctx._gb->getBit() || _ctx._frameType == IVI4_FRAMETYPE_INTRA) {
|
|
transformId = _ctx._gb->getBits(5);
|
|
if ((uint)transformId >= FF_ARRAY_ELEMS(_transforms) ||
|
|
!_transforms[transformId]._invTrans) {
|
|
warning("Transform %d", transformId);
|
|
return -3;
|
|
}
|
|
if ((transformId >= 7 && transformId <= 9) ||
|
|
transformId == 17) {
|
|
warning("DCT transform");
|
|
return -3;
|
|
}
|
|
|
|
if (transformId < 10 && band->_blkSize < 8) {
|
|
warning("wrong transform size!");
|
|
return -1;
|
|
}
|
|
if ((transformId >= 0 && transformId <= 2) || transformId == 10)
|
|
_ctx._usesHaar = true;
|
|
|
|
band->_invTransform = _transforms[transformId]._invTrans;
|
|
band->_dcTransform = _transforms[transformId]._dcTrans;
|
|
band->_is2dTrans = _transforms[transformId]._is2dTrans;
|
|
|
|
if (transformId < 10)
|
|
band->_transformSize = 8;
|
|
else
|
|
band->_transformSize = 4;
|
|
|
|
if (band->_blkSize != band->_transformSize) {
|
|
warning("transform and block size mismatch (%d != %d)", band->_transformSize, band->_blkSize);
|
|
return -1;
|
|
}
|
|
|
|
scanIndx = _ctx._gb->getBits(4);
|
|
if (scanIndx == 15) {
|
|
warning("Custom scan pattern encountered!");
|
|
return -1;
|
|
}
|
|
if (scanIndx > 4 && scanIndx < 10) {
|
|
if (band->_blkSize != 4) {
|
|
warning("mismatching scan table!");
|
|
return -1;
|
|
}
|
|
} else if (band->_blkSize != 8) {
|
|
warning("mismatching scan table!");
|
|
return -1;
|
|
}
|
|
|
|
band->_scan = _scan_index_to_tab[scanIndx];
|
|
band->_scanSize = band->_blkSize;
|
|
|
|
quantMat = _ctx._gb->getBits(5);
|
|
if (quantMat == 31) {
|
|
warning("Custom quant matrix encountered!");
|
|
return -1;
|
|
}
|
|
if ((uint)quantMat >= FF_ARRAY_ELEMS(_quant_index_to_tab)) {
|
|
warning("Quantization matrix %d", quantMat);
|
|
return -1;
|
|
}
|
|
band->_quantMat = quantMat;
|
|
} else {
|
|
if (old_blk_size != band->_blkSize) {
|
|
warning("The band block size does not match the configuration inherited");
|
|
return -1;
|
|
}
|
|
}
|
|
if (_quant_index_to_tab[band->_quantMat] > 4 && band->_blkSize == 4) {
|
|
warning("Invalid quant matrix for 4x4 block encountered!");
|
|
band->_quantMat = 0;
|
|
return -1;
|
|
}
|
|
if (band->_scanSize != band->_blkSize) {
|
|
warning("mismatching scan table!");
|
|
return -1;
|
|
}
|
|
if (band->_transformSize == 8 && band->_blkSize < 8) {
|
|
warning("mismatching _transformSize!");
|
|
return -1;
|
|
}
|
|
|
|
// decode block huffman codebook
|
|
if (!_ctx._gb->getBit())
|
|
band->_blkVlc._tab = _ctx._blkVlc._tab;
|
|
else
|
|
if (band->_blkVlc.decodeHuffDesc(&_ctx, 1, IVI_BLK_HUFF))
|
|
return -1;
|
|
|
|
// select appropriate rvmap table for this band
|
|
band->_rvmapSel = _ctx._gb->getBit() ? _ctx._gb->getBits(3) : 8;
|
|
|
|
// decode rvmap probability corrections if any
|
|
band->_numCorr = 0; // there is no corrections
|
|
if (_ctx._gb->getBit()) {
|
|
band->_numCorr = _ctx._gb->getBits(8); // get number of correction pairs
|
|
if (band->_numCorr > 61) {
|
|
warning("Too many corrections: %d",
|
|
band->_numCorr);
|
|
return -1;
|
|
}
|
|
|
|
// read correction pairs
|
|
for (i = 0; i < band->_numCorr * 2; i++)
|
|
band->_corr[i] = _ctx._gb->getBits(8);
|
|
}
|
|
}
|
|
|
|
if (band->_blkSize == 8) {
|
|
band->_intraBase = &_ivi4_quant_8x8_intra[_quant_index_to_tab[band->_quantMat]][0];
|
|
band->_interBase = &_ivi4_quant_8x8_inter[_quant_index_to_tab[band->_quantMat]][0];
|
|
} else {
|
|
band->_intraBase = &_ivi4_quant_4x4_intra[_quant_index_to_tab[band->_quantMat]][0];
|
|
band->_interBase = &_ivi4_quant_4x4_inter[_quant_index_to_tab[band->_quantMat]][0];
|
|
}
|
|
|
|
// Indeo 4 doesn't use scale tables
|
|
band->_intraScale = NULL;
|
|
band->_interScale = NULL;
|
|
|
|
_ctx._gb->align();
|
|
|
|
if (!band->_scan) {
|
|
warning("band->_scan not set");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Indeo4Decoder::decodeMbInfo(IVIBandDesc *band, IVITile *tile) {
|
|
int x, y, mvX, mvY, mvDelta, offs, mbOffset, blksPerMb,
|
|
mvScale, mbTypeBits, s;
|
|
IVIMbInfo *mb, *refMb;
|
|
int row_offset = band->_mbSize * band->_pitch;
|
|
|
|
mb = tile->_mbs;
|
|
refMb = tile->_refMbs;
|
|
offs = tile->_yPos * band->_pitch + tile->_xPos;
|
|
|
|
blksPerMb = band->_mbSize != band->_blkSize ? 4 : 1;
|
|
mbTypeBits = _ctx._frameType == IVI4_FRAMETYPE_BIDIR ? 2 : 1;
|
|
|
|
// scale factor for motion vectors
|
|
mvScale = (_ctx._planes[0]._bands[0]._mbSize >> 3) - (band->_mbSize >> 3);
|
|
mvX = mvY = 0;
|
|
|
|
if (((tile->_width + band->_mbSize - 1) / band->_mbSize) * ((tile->_height + band->_mbSize - 1) / band->_mbSize) != tile->_numMBs) {
|
|
warning("numMBs mismatch %d %d %d %d", tile->_width, tile->_height, band->_mbSize, tile->_numMBs);
|
|
return -1;
|
|
}
|
|
|
|
for (y = tile->_yPos; y < tile->_yPos + tile->_height; y += band->_mbSize) {
|
|
mbOffset = offs;
|
|
|
|
for (x = tile->_xPos; x < tile->_xPos + tile->_width; x += band->_mbSize) {
|
|
mb->_xPos = x;
|
|
mb->_yPos = y;
|
|
mb->_bufOffs = mbOffset;
|
|
mb->_bMvX = mb->_bMvY = 0;
|
|
|
|
if (_ctx._gb->getBit()) {
|
|
if (_ctx._frameType == IVI4_FRAMETYPE_INTRA) {
|
|
warning("Empty macroblock in an INTRA picture!");
|
|
return -1;
|
|
}
|
|
mb->_type = 1; // empty macroblocks are always INTER
|
|
mb->_cbp = 0; // all blocks are empty
|
|
|
|
mb->_qDelta = 0;
|
|
if (!band->_plane && !band->_bandNum && _ctx._inQ) {
|
|
mb->_qDelta = _ctx._gb->getVLC2(_ctx._mbVlc._tab->_table,
|
|
IVI_VLC_BITS, 1);
|
|
mb->_qDelta = IVI_TOSIGNED(mb->_qDelta);
|
|
}
|
|
|
|
mb->_mvX = mb->_mvY = 0; // no motion vector coded
|
|
if (band->_inheritMv && refMb) {
|
|
// motion vector inheritance
|
|
if (mvScale) {
|
|
mb->_mvX = scaleMV(refMb->_mvX, mvScale);
|
|
mb->_mvY = scaleMV(refMb->_mvY, mvScale);
|
|
} else {
|
|
mb->_mvX = refMb->_mvX;
|
|
mb->_mvY = refMb->_mvY;
|
|
}
|
|
}
|
|
} else {
|
|
if (band->_inheritMv) {
|
|
// copy mb_type from corresponding reference mb
|
|
if (!refMb) {
|
|
warning("refMb unavailable");
|
|
return -1;
|
|
}
|
|
mb->_type = refMb->_type;
|
|
} else if (_ctx._frameType == IVI4_FRAMETYPE_INTRA ||
|
|
_ctx._frameType == IVI4_FRAMETYPE_INTRA1) {
|
|
mb->_type = 0; // mb_type is always INTRA for intra-frames
|
|
} else {
|
|
mb->_type = _ctx._gb->getBits(mbTypeBits);
|
|
}
|
|
|
|
mb->_cbp = _ctx._gb->getBits(blksPerMb);
|
|
|
|
mb->_qDelta = 0;
|
|
if (band->_inheritQDelta) {
|
|
if (refMb) mb->_qDelta = refMb->_qDelta;
|
|
} else if (mb->_cbp || (!band->_plane && !band->_bandNum &&
|
|
_ctx._inQ)) {
|
|
mb->_qDelta = _ctx._gb->getVLC2(_ctx._mbVlc._tab->_table,
|
|
IVI_VLC_BITS, 1);
|
|
mb->_qDelta = IVI_TOSIGNED(mb->_qDelta);
|
|
}
|
|
|
|
if (!mb->_type) {
|
|
mb->_mvX = mb->_mvY = 0; // there is no motion vector in intra-macroblocks
|
|
} else {
|
|
if (band->_inheritMv) {
|
|
if (refMb) {
|
|
// motion vector inheritance
|
|
if (mvScale) {
|
|
mb->_mvX = scaleMV(refMb->_mvX, mvScale);
|
|
mb->_mvY = scaleMV(refMb->_mvY, mvScale);
|
|
} else {
|
|
mb->_mvX = refMb->_mvX;
|
|
mb->_mvY = refMb->_mvY;
|
|
}
|
|
}
|
|
} else {
|
|
// decode motion vector deltas
|
|
mvDelta = _ctx._gb->getVLC2(_ctx._mbVlc._tab->_table,
|
|
IVI_VLC_BITS, 1);
|
|
mvY += IVI_TOSIGNED(mvDelta);
|
|
mvDelta = _ctx._gb->getVLC2(_ctx._mbVlc._tab->_table,
|
|
IVI_VLC_BITS, 1);
|
|
mvX += IVI_TOSIGNED(mvDelta);
|
|
mb->_mvX = mvX;
|
|
mb->_mvY = mvY;
|
|
if (mb->_type == 3) {
|
|
mvDelta = _ctx._gb->getVLC2(
|
|
_ctx._mbVlc._tab->_table,
|
|
IVI_VLC_BITS, 1);
|
|
mvY += IVI_TOSIGNED(mvDelta);
|
|
mvDelta = _ctx._gb->getVLC2(
|
|
_ctx._mbVlc._tab->_table,
|
|
IVI_VLC_BITS, 1);
|
|
mvX += IVI_TOSIGNED(mvDelta);
|
|
mb->_bMvX = -mvX;
|
|
mb->_bMvY = -mvY;
|
|
}
|
|
}
|
|
if (mb->_type == 2) {
|
|
mb->_bMvX = -mb->_mvX;
|
|
mb->_bMvY = -mb->_mvY;
|
|
mb->_mvX = 0;
|
|
mb->_mvY = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
s = band->_isHalfpel;
|
|
if (mb->_type)
|
|
if (x + (mb->_mvX >> s) + (y + (mb->_mvY >> s))*band->_pitch < 0 ||
|
|
x + ((mb->_mvX + s) >> s) + band->_mbSize - 1
|
|
+ (y + band->_mbSize - 1 + ((mb->_mvY + s) >> s))*band->_pitch > band->_bufSize - 1) {
|
|
warning("motion vector %d %d outside reference", x*s + mb->_mvX, y*s + mb->_mvY);
|
|
return -1;
|
|
}
|
|
|
|
mb++;
|
|
if (refMb)
|
|
refMb++;
|
|
mbOffset += band->_mbSize;
|
|
}
|
|
|
|
offs += row_offset;
|
|
}
|
|
|
|
_ctx._gb->align();
|
|
return 0;
|
|
}
|
|
|
|
void Indeo4Decoder::decodeTransparency() {
|
|
// FIXME: Since I don't currently know how to decode the transparency layer,
|
|
// I'm currently doing a hack where I take the color of the top left corner,
|
|
// and mark the range of pixels of that color from the start and end of
|
|
// each line as transparent
|
|
assert(_surface->format.bytesPerPixel == 4);
|
|
byte r, g, b;
|
|
|
|
if (_surface->format.aBits() == 0) {
|
|
// Surface is 4 bytes per pixel, but only RGB. So promote the
|
|
// surface to full RGBA, and convert all the existing pixels
|
|
Graphics::PixelFormat oldFormat = _pixelFormat;
|
|
_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
|
_surface->format = _pixelFormat;
|
|
|
|
for (int y = 0; y < _surface->h; ++y) {
|
|
uint32 *lineP = (uint32 *)_surface->getBasePtr(0, y);
|
|
for (int x = 0; x < _surface->w; ++x, ++lineP) {
|
|
oldFormat.colorToRGB(*lineP, r, g, b);
|
|
*lineP = _pixelFormat.ARGBToColor(0xff, r, g, b);
|
|
}
|
|
}
|
|
} else {
|
|
// Working on a frame when the surface is already RGBA. In which case,
|
|
// start of by defaulting all pixels of the frame to fully opaque
|
|
for (int y = 0; y < _surface->h; ++y) {
|
|
uint32 *lineP = (uint32 *)_surface->getBasePtr(0, y);
|
|
for (int x = 0; x < _surface->w; ++x, ++lineP)
|
|
*lineP |= 0xff;
|
|
}
|
|
}
|
|
|
|
// Use the top-left pixel as the key color, and figure out the
|
|
// equivalent value as fully transparent
|
|
uint32 keyColor = *(const uint32 *)_surface->getPixels();
|
|
uint32 transColor = keyColor & ~0xff;
|
|
|
|
for (int y = 0; y < _surface->h; ++y) {
|
|
uint32 *startP = (uint32 *)_surface->getBasePtr(0, y);
|
|
uint32 *endP = (uint32 *)_surface->getBasePtr(_surface->w - 1, y);
|
|
|
|
while (startP <= endP && *startP == keyColor)
|
|
*startP++ = transColor;
|
|
while (endP > startP && *endP == keyColor)
|
|
*endP-- = transColor;
|
|
}
|
|
}
|
|
|
|
int Indeo4Decoder::scaleTileSize(int defSize, int sizeFactor) {
|
|
return sizeFactor == 15 ? defSize : (sizeFactor + 1) << 5;
|
|
}
|
|
|
|
int Indeo4Decoder::decodePlaneSubdivision() {
|
|
int i;
|
|
|
|
switch (_ctx._gb->getBits(2)) {
|
|
case 3:
|
|
return 1;
|
|
|
|
case 2:
|
|
for (i = 0; i < 4; i++)
|
|
if (_ctx._gb->getBits(2) != 3)
|
|
return 0;
|
|
return 4;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Indeo 4 8x8 scan (zigzag) patterns
|
|
*/
|
|
static const uint8 ivi4AlternateScan8x8[64] = {
|
|
0, 8, 1, 9, 16, 24, 2, 3, 17, 25, 10, 11, 32, 40, 48, 56,
|
|
4, 5, 6, 7, 33, 41, 49, 57, 18, 19, 26, 27, 12, 13, 14, 15,
|
|
34, 35, 43, 42, 50, 51, 59, 58, 20, 21, 22, 23, 31, 30, 29, 28,
|
|
36, 37, 38, 39, 47, 46, 45, 44, 52, 53, 54, 55, 63, 62, 61, 60
|
|
};
|
|
|
|
static const uint8 ivi4AlternateScan4x4[16] = {
|
|
0, 1, 4, 5, 8, 12, 2, 3, 9, 13, 6, 7, 10, 11, 14, 15
|
|
};
|
|
|
|
static const uint8 ivi4VerticalScan4x4[16] = {
|
|
0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15
|
|
};
|
|
|
|
static const uint8 ivi4HorizontalScan4x4[16] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
|
};
|
|
|
|
const uint Indeo4Decoder::_ivi4_common_pic_sizes[14] = {
|
|
640, 480, 320, 240, 160, 120, 704, 480, 352, 240, 352, 288, 176, 144
|
|
};
|
|
|
|
Indeo4Decoder::Transform Indeo4Decoder::_transforms[18] = {
|
|
{ IndeoDSP::ffIviInverseHaar8x8, IndeoDSP::ffIviDcHaar2d, 1 },
|
|
{ IndeoDSP::ffIviRowHaar8, IndeoDSP::ffIviDcHaar2d, 0 },
|
|
{ IndeoDSP::ffIviColHaar8, IndeoDSP::ffIviDcHaar2d, 0 },
|
|
{ IndeoDSP::ffIviPutPixels8x8, IndeoDSP::ffIviPutDcPixel8x8, 1 },
|
|
{ IndeoDSP::ffIviInverseSlant8x8, IndeoDSP::ffIviDcSlant2d, 1 },
|
|
{ IndeoDSP::ffIviRowSlant8, IndeoDSP::ffIviDcRowSlant, 1 },
|
|
{ IndeoDSP::ffIviColSlant8, IndeoDSP::ffIviDcColSlant, 1 },
|
|
{ NULL, NULL, 0 }, // inverse DCT 8x8
|
|
{ NULL, NULL, 0 }, // inverse DCT 8x1
|
|
{ NULL, NULL, 0 }, // inverse DCT 1x8
|
|
{ IndeoDSP::ffIviInverseHaar4x4, IndeoDSP::ffIviDcHaar2d, 1 },
|
|
{ IndeoDSP::ffIviInverseSlant4x4, IndeoDSP::ffIviDcSlant2d, 1 },
|
|
{ NULL, NULL, 0 }, // no transform 4x4
|
|
{ IndeoDSP::ffIviRowHaar4, IndeoDSP::ffIviDcHaar2d, 0 },
|
|
{ IndeoDSP::ffIviColHaar4, IndeoDSP::ffIviDcHaar2d, 0 },
|
|
{ IndeoDSP::ffIviRowSlant4, IndeoDSP::ffIviDcRowSlant, 0 },
|
|
{ IndeoDSP::ffIviColSlant4, IndeoDSP::ffIviDcColSlant, 0 },
|
|
{ NULL, NULL, 0 }, // inverse DCT 4x4
|
|
};
|
|
|
|
const uint8 *const Indeo4Decoder::_scan_index_to_tab[15] = {
|
|
// for 8x8 transforms
|
|
ffZigZagDirect,
|
|
ivi4AlternateScan8x8,
|
|
_ffIviHorizontalScan8x8,
|
|
_ffIviVerticalScan8x8,
|
|
ffZigZagDirect,
|
|
|
|
// for 4x4 transforms
|
|
_ffIviDirectScan4x4,
|
|
ivi4AlternateScan4x4,
|
|
ivi4VerticalScan4x4,
|
|
ivi4HorizontalScan4x4,
|
|
_ffIviDirectScan4x4,
|
|
|
|
// TODO: check if those are needed
|
|
_ffIviHorizontalScan8x8,
|
|
_ffIviHorizontalScan8x8,
|
|
_ffIviHorizontalScan8x8,
|
|
_ffIviHorizontalScan8x8,
|
|
_ffIviHorizontalScan8x8
|
|
};
|
|
|
|
/**
|
|
* Indeo 4 dequant tables
|
|
*/
|
|
const uint16 Indeo4Decoder::_ivi4_quant_8x8_intra[9][64] = {
|
|
{
|
|
43, 342, 385, 470, 555, 555, 598, 726,
|
|
342, 342, 470, 513, 555, 598, 726, 769,
|
|
385, 470, 555, 555, 598, 726, 726, 811,
|
|
470, 470, 555, 555, 598, 726, 769, 854,
|
|
470, 555, 555, 598, 683, 726, 854, 1025,
|
|
555, 555, 598, 683, 726, 854, 1025, 1153,
|
|
555, 555, 598, 726, 811, 982, 1195, 1451,
|
|
555, 598, 726, 811, 982, 1195, 1451, 1793
|
|
},
|
|
{
|
|
86, 1195, 2390, 2390, 4865, 4865, 4865, 4865,
|
|
1195, 1195, 2390, 2390, 4865, 4865, 4865, 4865,
|
|
2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827,
|
|
2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827,
|
|
4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
|
|
4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
|
|
4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
|
|
4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827
|
|
},
|
|
{
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
|
|
235, 1067, 1195, 1323, 1451, 1579, 1707, 1835
|
|
},
|
|
{
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414
|
|
},
|
|
{
|
|
897, 897, 897, 897, 897, 897, 897, 897,
|
|
1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067,
|
|
1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238,
|
|
1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409,
|
|
1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579,
|
|
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
|
|
1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921,
|
|
2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091
|
|
},
|
|
{
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414
|
|
},
|
|
{
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
|
|
2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390
|
|
},
|
|
{
|
|
22, 171, 214, 257, 257, 299, 299, 342,
|
|
171, 171, 257, 257, 299, 299, 342, 385,
|
|
214, 257, 257, 299, 299, 342, 342, 385,
|
|
257, 257, 257, 299, 299, 342, 385, 427,
|
|
257, 257, 299, 299, 342, 385, 427, 513,
|
|
257, 299, 299, 342, 385, 427, 513, 598,
|
|
299, 299, 299, 385, 385, 470, 598, 726,
|
|
299, 299, 385, 385, 470, 598, 726, 897
|
|
},
|
|
{
|
|
86, 598, 1195, 1195, 2390, 2390, 2390, 2390,
|
|
598, 598, 1195, 1195, 2390, 2390, 2390, 2390,
|
|
1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414,
|
|
1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414,
|
|
2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414
|
|
}
|
|
};
|
|
|
|
const uint16 Indeo4Decoder::_ivi4_quant_8x8_inter[9][64] = {
|
|
{
|
|
427, 427, 470, 427, 427, 427, 470, 470,
|
|
427, 427, 470, 427, 427, 427, 470, 470,
|
|
470, 470, 470, 470, 470, 470, 470, 470,
|
|
427, 427, 470, 470, 427, 427, 470, 470,
|
|
427, 427, 470, 427, 427, 427, 470, 470,
|
|
427, 427, 470, 427, 427, 427, 470, 470,
|
|
470, 470, 470, 470, 470, 470, 470, 470,
|
|
470, 470, 470, 470, 470, 470, 470, 470
|
|
},
|
|
{
|
|
1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414,
|
|
1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414,
|
|
2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822,
|
|
2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822,
|
|
3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414
|
|
},
|
|
{
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
|
|
1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281
|
|
},
|
|
{
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433
|
|
},
|
|
{
|
|
1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
|
|
1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
|
|
1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
|
|
1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238,
|
|
1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
|
|
1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
|
|
1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
|
|
1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281
|
|
},
|
|
{
|
|
2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
|
|
2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
|
|
2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433
|
|
},
|
|
{
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707
|
|
},
|
|
{
|
|
86, 171, 171, 214, 214, 214, 214, 257,
|
|
171, 171, 214, 214, 214, 214, 257, 257,
|
|
171, 214, 214, 214, 214, 257, 257, 257,
|
|
214, 214, 214, 214, 257, 257, 257, 299,
|
|
214, 214, 214, 257, 257, 257, 299, 299,
|
|
214, 214, 257, 257, 257, 299, 299, 299,
|
|
214, 257, 257, 257, 299, 299, 299, 342,
|
|
257, 257, 257, 299, 299, 299, 342, 342
|
|
},
|
|
{
|
|
854, 854, 1195, 1195, 1707, 1707, 1707, 1707,
|
|
854, 854, 1195, 1195, 1707, 1707, 1707, 1707,
|
|
1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390,
|
|
1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390,
|
|
1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
|
|
1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707
|
|
}
|
|
};
|
|
|
|
const uint16 Indeo4Decoder::_ivi4_quant_4x4_intra[5][16] = {
|
|
{
|
|
22, 214, 257, 299,
|
|
214, 257, 299, 342,
|
|
257, 299, 342, 427,
|
|
299, 342, 427, 513
|
|
},
|
|
{
|
|
129, 1025, 1451, 1451,
|
|
1025, 1025, 1451, 1451,
|
|
1451, 1451, 2049, 2049,
|
|
1451, 1451, 2049, 2049
|
|
},
|
|
{
|
|
43, 171, 171, 171,
|
|
43, 171, 171, 171,
|
|
43, 171, 171, 171,
|
|
43, 171, 171, 171
|
|
},
|
|
{
|
|
43, 43, 43, 43,
|
|
171, 171, 171, 171,
|
|
171, 171, 171, 171,
|
|
171, 171, 171, 171
|
|
},
|
|
{
|
|
43, 43, 43, 43,
|
|
43, 43, 43, 43,
|
|
43, 43, 43, 43,
|
|
43, 43, 43, 43
|
|
}
|
|
};
|
|
|
|
const uint16 Indeo4Decoder::_ivi4_quant_4x4_inter[5][16] = {
|
|
{
|
|
107, 214, 257, 299,
|
|
214, 257, 299, 299,
|
|
257, 299, 299, 342,
|
|
299, 299, 342, 342
|
|
},
|
|
{
|
|
513, 1025, 1238, 1238,
|
|
1025, 1025, 1238, 1238,
|
|
1238, 1238, 1451, 1451,
|
|
1238, 1238, 1451, 1451
|
|
},
|
|
{
|
|
43, 171, 171, 171,
|
|
43, 171, 171, 171,
|
|
43, 171, 171, 171,
|
|
43, 171, 171, 171
|
|
},
|
|
{
|
|
43, 43, 43, 43,
|
|
171, 171, 171, 171,
|
|
171, 171, 171, 171,
|
|
171, 171, 171, 171
|
|
},
|
|
{
|
|
43, 43, 43, 43,
|
|
43, 43, 43, 43,
|
|
43, 43, 43, 43,
|
|
43, 43, 43, 43
|
|
}
|
|
};
|
|
|
|
const uint8 Indeo4Decoder::_quant_index_to_tab[22] = {
|
|
0, 1, 0, 2, 1, 3, 0, 4, 1, 5, 0, 1, 6, 7, 8, // for 8x8 quant matrixes
|
|
0, 1, 2, 2, 3, 3, 4 // for 4x4 quant matrixes
|
|
};
|
|
|
|
} // End of namespace Image
|