diff options
author | Eugene Sandulenko | 2016-09-11 16:58:54 +0200 |
---|---|---|
committer | GitHub | 2016-09-11 16:58:54 +0200 |
commit | 0733cf65ba8f6babdf35547b49cd2d57c9daf646 (patch) | |
tree | 61c24edbc0a1080711c93c674b9848f4a16efb50 /image/codecs/indeo4.cpp | |
parent | 49bc276ea3e297c23098d4f0e6ab331f0b89f6ee (diff) | |
parent | 08143af48293b007027d11271d3f66f7ad3107e6 (diff) | |
download | scummvm-rg350-0733cf65ba8f6babdf35547b49cd2d57c9daf646.tar.gz scummvm-rg350-0733cf65ba8f6babdf35547b49cd2d57c9daf646.tar.bz2 scummvm-rg350-0733cf65ba8f6babdf35547b49cd2d57c9daf646.zip |
Merge pull request #826 from dreammaster/indeo
IMAGE: Indeo 4 & 5 decoders
Diffstat (limited to 'image/codecs/indeo4.cpp')
-rw-r--r-- | image/codecs/indeo4.cpp | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/image/codecs/indeo4.cpp b/image/codecs/indeo4.cpp new file mode 100644 index 0000000000..3e4c37bbab --- /dev/null +++ b/image/codecs/indeo4.cpp @@ -0,0 +1,951 @@ +/* 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 3 (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) : IndeoDecoderBase(width, height) { + _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 * 8)); + + // 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->rawSurface(); +} + +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; +} + +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 |