Initial commit
This commit is contained in:
89
image/codecs/indeo/get_bits.h
Normal file
89
image/codecs/indeo/get_bits.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_CODECS_INDEO_GET_BITS_H
|
||||
#define IMAGE_CODECS_INDEO_GET_BITS_H
|
||||
|
||||
#include "common/bitstream.h"
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
/**
|
||||
* Intel Indeo Bitstream reader
|
||||
*/
|
||||
class GetBits : public Common::BitStreamMemory8LSB {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
GetBits(const byte *dataPtr, uint32 dataSize) : Common::BitStreamMemory8LSB(new Common::BitStreamMemoryStream(dataPtr, dataSize), DisposeAfterUse::YES) {}
|
||||
|
||||
/**
|
||||
* The number of bits left
|
||||
*/
|
||||
int getBitsLeft() const { return size() - pos(); }
|
||||
|
||||
/**
|
||||
* Parse a VLC code.
|
||||
* @param bits is the number of bits which will be read at once, must be
|
||||
* identical to nbBits in init_vlc()
|
||||
* @param maxDepth is the number of times bits bits must be read to completely
|
||||
* read the longest vlc code
|
||||
* = (max_vlc_length + bits - 1) / bits
|
||||
*/
|
||||
template <int maxDepth, int bits>
|
||||
int getVLC2(int16 (*table)[2]) {
|
||||
int code;
|
||||
int n, nbBits;
|
||||
unsigned int index;
|
||||
|
||||
index = peekBits<bits>();
|
||||
code = table[index][0];
|
||||
n = table[index][1];
|
||||
|
||||
if (maxDepth > 1 && n < 0) {
|
||||
skip(bits);
|
||||
nbBits = -n;
|
||||
|
||||
index = peekBits(nbBits) + code;
|
||||
code = table[index][0];
|
||||
n = table[index][1];
|
||||
|
||||
if (maxDepth > 2 && n < 0) {
|
||||
skip(nbBits);
|
||||
nbBits = -n;
|
||||
|
||||
index = peekBits(nbBits) + code;
|
||||
code = table[index][0];
|
||||
n = table[index][1];
|
||||
}
|
||||
}
|
||||
|
||||
skip(n);
|
||||
return code;
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
|
||||
#endif
|
||||
1719
image/codecs/indeo/indeo.cpp
Normal file
1719
image/codecs/indeo/indeo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
604
image/codecs/indeo/indeo.h
Normal file
604
image/codecs/indeo/indeo.h
Normal file
@@ -0,0 +1,604 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "image/codecs/codec.h"
|
||||
|
||||
/* Common structures, macros, and base class shared by both Indeo4 and
|
||||
* Indeo5 decoders, derived from ffmpeg. We don't currently support Indeo5
|
||||
* decoding, but just in case we eventually need it, this is kept as a separate
|
||||
* file like it is in ffmpeg.
|
||||
*
|
||||
* Original copyright note: * Intel Indeo 4 (IV41, IV42, etc.) video decoder for ffmpeg
|
||||
* written, produced, and directed by Alan Smithee
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_CODECS_INDEO_INDEO_H
|
||||
#define IMAGE_CODECS_INDEO_INDEO_H
|
||||
|
||||
#include "image/codecs/indeo/get_bits.h"
|
||||
#include "image/codecs/indeo/vlc.h"
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
/**
|
||||
* Indeo 4 frame types.
|
||||
*/
|
||||
enum {
|
||||
IVI4_FRAMETYPE_INTRA = 0,
|
||||
IVI4_FRAMETYPE_INTRA1 = 1, ///< intra frame with slightly different bitstream coding
|
||||
IVI4_FRAMETYPE_INTER = 2, ///< non-droppable P-frame
|
||||
IVI4_FRAMETYPE_BIDIR = 3, ///< bidirectional frame
|
||||
IVI4_FRAMETYPE_INTER_NOREF = 4, ///< droppable P-frame
|
||||
IVI4_FRAMETYPE_NULL_FIRST = 5, ///< empty frame with no data
|
||||
IVI4_FRAMETYPE_NULL_LAST = 6 ///< empty frame with no data
|
||||
};
|
||||
|
||||
enum {
|
||||
IVI_MB_HUFF = 0, /// Huffman table is used for coding macroblocks
|
||||
IVI_BLK_HUFF = 1 /// Huffman table is used for coding blocks
|
||||
};
|
||||
|
||||
/**
|
||||
* Declare inverse transform function types
|
||||
*/
|
||||
typedef void (InvTransformPtr)(const int32 *in, int16 *out, uint32 pitch, const uint8 *flags);
|
||||
typedef void (DCTransformPtr)(const int32 *in, int16 *out, uint32 pitch, int blkSize);
|
||||
|
||||
typedef void (*IviMCFunc)(int16 *buf, const int16 *refBuf, uint32 pitch, int mcType);
|
||||
typedef void (*IviMCAvgFunc)(int16 *buf, const int16 *refBuf1, const int16 *refBuf2,
|
||||
uint32 pitch, int mcType, int mcType2);
|
||||
|
||||
///< max number of bits of the ivi's huffman codes
|
||||
#define IVI_VLC_BITS 13
|
||||
#define IVI5_IS_PROTECTED 0x20
|
||||
|
||||
/**
|
||||
* convert unsigned values into signed ones (the sign is in the LSB)
|
||||
*/
|
||||
#define IVI_TOSIGNED(val) (-(((val) >> 1) ^ -((val) & 1)))
|
||||
|
||||
/**
|
||||
* calculate number of macroblocks in a tile
|
||||
*/
|
||||
#define IVI_MBs_PER_TILE(tileWidth, tileHeight, mbSize) \
|
||||
((((tileWidth) + (mbSize) - 1) / (mbSize)) * (((tileHeight) + (mbSize) - 1) / (mbSize)))
|
||||
|
||||
/**
|
||||
* huffman codebook descriptor
|
||||
*/
|
||||
struct IVIHuffDesc {
|
||||
int32 _numRows;
|
||||
uint8 _xBits[16];
|
||||
|
||||
/**
|
||||
* Generate a huffman codebook from the given descriptor
|
||||
* and convert it into the FFmpeg VLC table.
|
||||
*
|
||||
* @param[out] vlc Where to place the generated VLC table
|
||||
* @param[in] flag Flag: true - for static or false for dynamic tables
|
||||
* @returns result code: 0 - OK, -1 = error (invalid codebook descriptor)
|
||||
*/
|
||||
int createHuffFromDesc(VLC *vlc, bool flag) const;
|
||||
|
||||
/**
|
||||
* Compare two huffman codebook descriptors.
|
||||
*
|
||||
* @param[in] desc2 Ptr to the 2nd descriptor to compare
|
||||
* @returns comparison result: 0 - equal, 1 - not equal
|
||||
*/
|
||||
bool huffDescCompare(const IVIHuffDesc *desc2) const;
|
||||
|
||||
/**
|
||||
* Copy huffman codebook descriptors.
|
||||
*
|
||||
* @param[in] src ptr to the source descriptor
|
||||
*/
|
||||
void huffDescCopy(const IVIHuffDesc *src);
|
||||
};
|
||||
|
||||
struct IVI45DecContext;
|
||||
|
||||
/**
|
||||
* Macroblock/block huffman table descriptor
|
||||
*/
|
||||
struct IVIHuffTab {
|
||||
public:
|
||||
int32 _tabSel; /// index of one of the predefined tables
|
||||
/// or "7" for custom one
|
||||
VLC * _tab; /// pointer to the table associated with tab_sel
|
||||
|
||||
/// the following are used only when tab_sel == 7
|
||||
IVIHuffDesc _custDesc; /// custom Huffman codebook descriptor
|
||||
VLC _custTab; /// vlc table for custom codebook
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
IVIHuffTab();
|
||||
|
||||
/**
|
||||
* Decode a huffman codebook descriptor from the bitstream
|
||||
* and select specified huffman table.
|
||||
*
|
||||
* @param[in] ctx Decoder context
|
||||
* @param[in] descCoded Flag signalling if table descriptor was coded
|
||||
* @param[in] whichTab Codebook purpose (IVI_MB_HUFF or IVI_BLK_HUFF)
|
||||
* @returns Zero on success, negative value otherwise
|
||||
*/
|
||||
int decodeHuffDesc(IVI45DecContext *ctx, int descCoded, int whichTab);
|
||||
};
|
||||
|
||||
/**
|
||||
* run-value (RLE) table descriptor
|
||||
*/
|
||||
struct RVMapDesc {
|
||||
uint8 _eobSym; ///< end of block symbol
|
||||
uint8 _escSym; ///< escape symbol
|
||||
uint8 _runtab[256];
|
||||
int8 _valtab[256];
|
||||
};
|
||||
|
||||
/**
|
||||
* information for Indeo macroblock (16x16, 8x8 or 4x4)
|
||||
*/
|
||||
struct IVIMbInfo {
|
||||
int16 _xPos;
|
||||
int16 _yPos;
|
||||
uint32 _bufOffs; ///< address in the output buffer for this mb
|
||||
uint8 _type; ///< macroblock type: 0 - INTRA, 1 - INTER
|
||||
uint8 _cbp; ///< coded block pattern
|
||||
int8 _qDelta; ///< quant delta
|
||||
int8 _mvX; ///< motion vector (x component)
|
||||
int8 _mvY; ///< motion vector (y component)
|
||||
int8 _bMvX; ///< second motion vector (x component)
|
||||
int8 _bMvY; ///< second motion vector (y component)
|
||||
|
||||
IVIMbInfo();
|
||||
};
|
||||
|
||||
/**
|
||||
* information for Indeo tile
|
||||
*/
|
||||
struct IVITile {
|
||||
int _xPos;
|
||||
int _yPos;
|
||||
int _width;
|
||||
int _height;
|
||||
int _mbSize;
|
||||
bool _isEmpty;
|
||||
int _dataSize; ///< size of the data in bytes
|
||||
int _numMBs; ///< number of macroblocks in this tile
|
||||
IVIMbInfo * _mbs; ///< array of macroblock descriptors
|
||||
IVIMbInfo * _refMbs; ///< ptr to the macroblock descriptors of the reference tile
|
||||
|
||||
IVITile();
|
||||
};
|
||||
|
||||
/**
|
||||
* information for Indeo wavelet band
|
||||
*/
|
||||
struct IVIBandDesc {
|
||||
int _plane; ///< plane number this band belongs to
|
||||
int _bandNum; ///< band number
|
||||
int _width;
|
||||
int _height;
|
||||
int _aHeight; ///< aligned band height
|
||||
const uint8 * _dataPtr; ///< ptr to the first byte of the band data
|
||||
int _dataSize; ///< size of the band data
|
||||
int16 * _buf; ///< pointer to the output buffer for this band
|
||||
int16 * _refBuf; ///< pointer to the reference frame buffer (for motion compensation)
|
||||
int16 * _bRefBuf; ///< pointer to the second reference frame buffer (for motion compensation)
|
||||
int16 * _bufs[4]; ///< array of pointers to the band buffers
|
||||
int _pitch; ///< _pitch associated with the buffers above
|
||||
bool _isEmpty;
|
||||
int _mbSize; ///< macroblock size
|
||||
int _blkSize; ///< block size
|
||||
uint8 _isHalfpel; ///< precision of the motion compensation: 0 - fullpel, 1 - halfpel
|
||||
bool _inheritMv; ///< tells if motion vector is inherited from reference macroblock
|
||||
bool _inheritQDelta; ///< tells if quantiser delta is inherited from reference macroblock
|
||||
bool _qdeltaPresent; ///< tells if Qdelta signal is present in the bitstream (Indeo5 only)
|
||||
int _quantMat; ///< dequant matrix index
|
||||
int _globQuant; ///< quant base for this band
|
||||
const uint8 * _scan; ///< ptr to the scan pattern
|
||||
int _scanSize; ///< size of the scantable
|
||||
|
||||
IVIHuffTab _blkVlc; ///< vlc table for decoding block data
|
||||
|
||||
int _numCorr; ///< number of correction entries
|
||||
uint8 _corr[61 * 2]; ///< rvmap correction pairs
|
||||
int _rvmapSel; ///< rvmap table selector
|
||||
RVMapDesc * _rvMap; ///< ptr to the RLE table for this band
|
||||
int _numTiles; ///< number of tiles in this band
|
||||
IVITile * _tiles; ///< array of tile descriptors
|
||||
InvTransformPtr *_invTransform;
|
||||
int _transformSize;
|
||||
DCTransformPtr *_dcTransform;
|
||||
bool _is2dTrans;
|
||||
int32 _checksum; ///< for debug purposes
|
||||
int _checksumPresent;
|
||||
int _bufSize; ///< band buffer size in bytes
|
||||
const uint16 * _intraBase; ///< quantization matrix for intra blocks
|
||||
const uint16 * _interBase; ///< quantization matrix for inter blocks
|
||||
const uint8 * _intraScale; ///< quantization coefficient for intra blocks
|
||||
const uint8 * _interScale; ///< quantization coefficient for inter blocks
|
||||
|
||||
IVIBandDesc();
|
||||
|
||||
int initTiles(IVITile *refTile, int p, int b, int tHeight, int tWidth);
|
||||
};
|
||||
|
||||
struct IVIPicConfig {
|
||||
uint16 _picWidth;
|
||||
uint16 _picHeight;
|
||||
uint16 _chromaWidth;
|
||||
uint16 _chromaHeight;
|
||||
uint16 _tileWidth;
|
||||
uint16 _tileHeight;
|
||||
uint8 _lumaBands;
|
||||
uint8 _chromaBands;
|
||||
|
||||
IVIPicConfig();
|
||||
|
||||
/**
|
||||
* Compare some properties of two pictures
|
||||
*/
|
||||
bool ivi_pic_config_cmp(const IVIPicConfig &cfg2);
|
||||
};
|
||||
|
||||
/**
|
||||
* color plane (luma or chroma) information
|
||||
*/
|
||||
struct IVIPlaneDesc {
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
uint8 _numBands; ///< number of bands this plane subdivided into
|
||||
IVIBandDesc * _bands; ///< array of band descriptors
|
||||
|
||||
IVIPlaneDesc();
|
||||
|
||||
static int initPlanes(IVIPlaneDesc *planes, const IVIPicConfig *cfg, bool isIndeo4);
|
||||
|
||||
static int initTiles(IVIPlaneDesc *planes, int tileWidth, int tileHeight);
|
||||
|
||||
/**
|
||||
* Free planes, bands and macroblocks buffers.
|
||||
*
|
||||
* @param[in] planes pointer to the array of the plane descriptors
|
||||
*/
|
||||
static void freeBuffers(IVIPlaneDesc *planes);
|
||||
|
||||
/**
|
||||
* Check if the given dimension of an image is valid, meaning that all
|
||||
* bytes of the image can be addressed with a signed int.
|
||||
*
|
||||
* @param w the width of the picture
|
||||
* @param h the height of the picture
|
||||
* @param log_offset the offset to sum to the log level for logging with log_ctx
|
||||
* @returns >= 0 if valid, a negative error code otherwise
|
||||
*/
|
||||
static int checkImageSize(unsigned int w, unsigned int h, int logOffset);
|
||||
};
|
||||
|
||||
struct AVFrame {
|
||||
/**
|
||||
* Dimensions
|
||||
*/
|
||||
int _width, _height;
|
||||
|
||||
#define AV_NUM_DATA_POINTERS 3
|
||||
/**
|
||||
* pointer to the picture/channel planes.
|
||||
* This might be different from the first allocated byte
|
||||
*
|
||||
* Some decoders access areas outside 0,0 - width,height, please
|
||||
* see avcodec_align_dimensions2(). Some filters and swscale can read
|
||||
* up to 16 bytes beyond the planes, if these filters are to be used,
|
||||
* then 16 extra bytes must be allocated.
|
||||
*
|
||||
* NOTE: Except for hwaccel formats, pointers not needed by the format
|
||||
* MUST be set to NULL.
|
||||
*/
|
||||
uint8 *_data[AV_NUM_DATA_POINTERS];
|
||||
|
||||
/**
|
||||
* For video, size in bytes of each picture line.
|
||||
* For audio, size in bytes of each plane.
|
||||
*
|
||||
* For audio, only linesize[0] may be set. For planar audio, each channel
|
||||
* plane must be the same size.
|
||||
*
|
||||
* For video the linesizes should be multiples of the CPUs alignment
|
||||
* preference, this is 16 or 32 for modern desktop CPUs.
|
||||
* Some code requires such alignment other code can be slower without
|
||||
* correct alignment, for yet other it makes no difference.
|
||||
*
|
||||
* @note The linesize may be larger than the size of usable data -- there
|
||||
* may be extra padding present for performance reasons.
|
||||
*/
|
||||
int _linesize[AV_NUM_DATA_POINTERS];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
AVFrame();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~AVFrame() { freeFrame(); }
|
||||
|
||||
/**
|
||||
* Sets the frame dimensions
|
||||
*/
|
||||
int setDimensions(uint16 width, uint16 height);
|
||||
|
||||
/**
|
||||
* Get a buffer for a frame
|
||||
*/
|
||||
int getBuffer(int flags);
|
||||
|
||||
/**
|
||||
* Frees any data loaded for the frame
|
||||
*/
|
||||
void freeFrame();
|
||||
};
|
||||
|
||||
struct IVI45DecContext {
|
||||
friend struct IVIHuffTab;
|
||||
private:
|
||||
VLC_TYPE _tableData[8192 * 16][2];
|
||||
VLC _iviMbVlcTabs[8]; ///< static macroblock Huffman tables
|
||||
VLC _iviBlkVlcTabs[8]; ///< static block Huffman tables
|
||||
public:
|
||||
GetBits * _gb;
|
||||
RVMapDesc _rvmapTabs[9]; ///< local corrected copy of the static rvmap tables
|
||||
|
||||
uint32 _frameNum;
|
||||
int _frameType;
|
||||
int _prevFrameType; ///< frame type of the previous frame
|
||||
uint32 _dataSize; ///< size of the frame data in bytes from picture header
|
||||
int _isScalable;
|
||||
const uint8 * _frameData; ///< input frame data pointer
|
||||
int _interScal; ///< signals a sequence of scalable inter frames
|
||||
uint32 _frameSize; ///< frame size in bytes
|
||||
uint32 _picHdrSize; ///< picture header size in bytes
|
||||
uint8 _frameFlags;
|
||||
uint16 _checksum; ///< frame _checksum
|
||||
|
||||
IVIPicConfig _picConf;
|
||||
IVIPlaneDesc _planes[3]; ///< color planes
|
||||
|
||||
int _bufSwitch; ///< used to switch between three buffers
|
||||
int _dstBuf; ///< buffer index for the currently decoded frame
|
||||
int _refBuf; ///< inter frame reference buffer index
|
||||
int _ref2Buf; ///< temporal storage for switching buffers
|
||||
int _bRefBuf; ///< second reference frame buffer index
|
||||
|
||||
IVIHuffTab _mbVlc; ///< current macroblock table descriptor
|
||||
IVIHuffTab _blkVlc; ///< current block table descriptor
|
||||
IVIHuffTab _transVlc; ///< current transparency table descriptor
|
||||
|
||||
uint8 _rvmapSel;
|
||||
bool _inImf;
|
||||
bool _inQ; ///< flag for explicitly stored quantiser delta
|
||||
uint8 _picGlobQuant;
|
||||
uint8 _unknown1;
|
||||
|
||||
uint16 _gopHdrSize;
|
||||
uint8 _gopFlags;
|
||||
uint32 _lockWord;
|
||||
|
||||
bool _hasBFrames;
|
||||
bool _hasTransp; ///< transparency mode enabled
|
||||
bool _usesTiling;
|
||||
bool _usesHaar;
|
||||
bool _usesFullpel;
|
||||
|
||||
bool _gopInvalid;
|
||||
int _bufInvalid[4];
|
||||
|
||||
bool _isIndeo4;
|
||||
uint32 _transKeyColor;
|
||||
|
||||
AVFrame * _pFrame;
|
||||
bool _gotPFrame;
|
||||
|
||||
IVI45DecContext();
|
||||
private:
|
||||
/**
|
||||
* Initial Run-value (RLE) tables.
|
||||
*/
|
||||
static const RVMapDesc _ff_ivi_rvmap_tabs[9];
|
||||
};
|
||||
|
||||
class IndeoDecoderBase : public Codec {
|
||||
private:
|
||||
/**
|
||||
* Decode an Indeo 4 or 5 band.
|
||||
*
|
||||
* @param[in,out] band ptr to the band descriptor
|
||||
* @returns result code: 0 = OK, -1 = error
|
||||
*/
|
||||
int decode_band(IVIBandDesc *band);
|
||||
|
||||
/**
|
||||
* Haar wavelet recomposition filter for Indeo 4
|
||||
*
|
||||
* @param[in] plane Pointer to the descriptor of the plane being processed
|
||||
* @param[out] dst pointer to the destination buffer
|
||||
* @param[in] dstPitch Pitch of the destination buffer
|
||||
*/
|
||||
void recomposeHaar(const IVIPlaneDesc *plane, uint8 *dst, const int dstPitch);
|
||||
|
||||
/**
|
||||
* 5/3 wavelet recomposition filter for Indeo5
|
||||
*
|
||||
* @param[in] plane Pointer to the descriptor of the plane being processed
|
||||
* @param[out] dst Pointer to the destination buffer
|
||||
* @param[in] dstPitch Pitch of the destination buffer
|
||||
*/
|
||||
void recompose53(const IVIPlaneDesc *plane, uint8 *dst, const int dstPitch);
|
||||
|
||||
/*
|
||||
* Convert and output the current plane.
|
||||
* This conversion is done by adding back the bias value of 128
|
||||
* (subtracted in the encoder) and clipping the result.
|
||||
*
|
||||
* @param[in] plane Pointer to the descriptor of the plane being processed
|
||||
* @param[out] dst Pointer to the buffer receiving converted pixels
|
||||
* @param[in] dstPitch Pitch for moving to the next y line
|
||||
*/
|
||||
void outputPlane(IVIPlaneDesc *plane, uint8 *dst, int dstPitch);
|
||||
|
||||
/**
|
||||
* Handle empty tiles by performing data copying and motion
|
||||
* compensation respectively.
|
||||
*
|
||||
* @param[in] band Pointer to the band descriptor
|
||||
* @param[in] tile Pointer to the tile descriptor
|
||||
* @param[in] mvScale Scaling factor for motion vectors
|
||||
*/
|
||||
int processEmptyTile(IVIBandDesc *band, IVITile *tile, int32 mvScale);
|
||||
|
||||
/*
|
||||
* Decode size of the tile data.
|
||||
* The size is stored as a variable-length field having the following format:
|
||||
* if (tile_data_size < 255) than this field is only one byte long
|
||||
* if (tile_data_size >= 255) than this field four is byte long: 0xFF X1 X2 X3
|
||||
* where X1-X3 is size of the tile data
|
||||
*
|
||||
* @param[in,out] gb the GetBit context
|
||||
* @returns Size of the tile data in bytes
|
||||
*/
|
||||
int decodeTileDataSize(GetBits *gb);
|
||||
|
||||
/*
|
||||
* Decode block data:
|
||||
* extract huffman-coded transform coefficients from the bitstream,
|
||||
* dequantize them, apply inverse transform and motion compensation
|
||||
* in order to reconstruct the picture.
|
||||
*
|
||||
* @param[in,out] gb The GetBit context
|
||||
* @param[in] band Pointer to the band descriptor
|
||||
* @param[in] tile Pointer to the tile descriptor
|
||||
* @returns Result code: 0 - OK, -1 = error (corrupted blocks data)
|
||||
*/
|
||||
int decodeBlocks(GetBits *gb, IVIBandDesc *band, IVITile *tile);
|
||||
|
||||
int iviMc(IVIBandDesc *band, IviMCFunc mc, IviMCAvgFunc mcAvg,
|
||||
int offs, int mvX, int mvY, int mvX2, int mvY2, int mcType, int mcType2);
|
||||
|
||||
int decodeCodedBlocks(GetBits *gb, IVIBandDesc *band,
|
||||
IviMCFunc mc, IviMCAvgFunc mcAvg, int mvX, int mvY,
|
||||
int mvX2, int mvY2, int32 *prevDc, int isIntra,
|
||||
int mcType, int mcType2, uint32 quant, int offs);
|
||||
|
||||
int iviDcTransform(IVIBandDesc *band, int32 *prevDc, int bufOffs,
|
||||
int blkSize);
|
||||
protected:
|
||||
IVI45DecContext _ctx;
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
uint _bitsPerPixel;
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
Graphics::Surface *_surface;
|
||||
|
||||
/**
|
||||
* Scan patterns shared between indeo4 and indeo5
|
||||
*/
|
||||
static const uint8 _ffIviVerticalScan8x8[64];
|
||||
static const uint8 _ffIviHorizontalScan8x8[64];
|
||||
static const uint8 _ffIviDirectScan4x4[16];
|
||||
protected:
|
||||
/**
|
||||
* Returns the pixel format for the decoder's surface
|
||||
*/
|
||||
Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
|
||||
|
||||
/**
|
||||
* Select the preferred format to use, for codecs where this is faster than converting
|
||||
* the image afterwards. Returns true if supported, and false otherwise.
|
||||
*/
|
||||
bool setOutputPixelFormat(const Graphics::PixelFormat &format) override {
|
||||
if (format.bytesPerPixel != 2 && format.bytesPerPixel != 4)
|
||||
return false;
|
||||
_pixelFormat = format;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the Indeo picture header.
|
||||
* @returns 0 = Ok, negative number = error
|
||||
*/
|
||||
virtual int decodePictureHeader() = 0;
|
||||
|
||||
/**
|
||||
* Rearrange decoding and reference buffers.
|
||||
*/
|
||||
virtual void switchBuffers() = 0;
|
||||
|
||||
virtual bool isNonNullFrame() const = 0;
|
||||
|
||||
/**
|
||||
* Decode Indeo band header.
|
||||
*
|
||||
* @param[in,out] band Pointer to the band descriptor
|
||||
* @returns Result code: 0 = OK, negative number = error
|
||||
*/
|
||||
virtual int decodeBandHeader(IVIBandDesc *band) = 0;
|
||||
|
||||
/**
|
||||
* Decode information (block type, _cbp, quant delta, motion vector)
|
||||
* for all macroblocks in the current tile.
|
||||
*
|
||||
* @param[in,out] band Pointer to the band descriptor
|
||||
* @param[in,out] tile Pointer to the tile descriptor
|
||||
* @returns Result code: 0 = OK, negative number = error
|
||||
*/
|
||||
virtual int decodeMbInfo(IVIBandDesc *band, IVITile *tile) = 0;
|
||||
|
||||
/**
|
||||
* Decodes optional transparency data within Indeo frames
|
||||
*/
|
||||
virtual int decodeTransparency() { return -1; }
|
||||
|
||||
/**
|
||||
* Decodes the Indeo frame from the bit reader already
|
||||
* loaded into the context
|
||||
*/
|
||||
int decodeIndeoFrame();
|
||||
|
||||
/**
|
||||
* scale motion vector
|
||||
*/
|
||||
int scaleMV(int mv, int mvScale);
|
||||
public:
|
||||
IndeoDecoderBase(uint16 width, uint16 height, uint bitsPerPixel);
|
||||
~IndeoDecoderBase() override;
|
||||
};
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
|
||||
#endif
|
||||
607
image/codecs/indeo/indeo_dsp.cpp
Normal file
607
image/codecs/indeo/indeo_dsp.cpp
Normal file
@@ -0,0 +1,607 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* VLC code
|
||||
*
|
||||
* Original copyright note: * Intel Indeo 4 (IV41, IV42, etc.) video decoder for ffmpeg
|
||||
* written, produced, and directed by Alan Smithee
|
||||
*/
|
||||
|
||||
#include "image/codecs/indeo/indeo_dsp.h"
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
/**
|
||||
* butterfly operation for the inverse Haar transform
|
||||
*/
|
||||
#define IVI_HAAR_BFLY(s1, s2, o1, o2, t) \
|
||||
t = ((s1) - (s2)) >> 1;\
|
||||
o1 = ((s1) + (s2)) >> 1;\
|
||||
o2 = (t);\
|
||||
|
||||
/**
|
||||
* inverse 8-point Haar transform
|
||||
*/
|
||||
#define INV_HAAR8(s1, s5, s3, s7, s2, s4, s6, s8,\
|
||||
d1, d2, d3, d4, d5, d6, d7, d8,\
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8) {\
|
||||
t1 = (s1) << 1; t5 = (s5) << 1;\
|
||||
IVI_HAAR_BFLY(t1, t5, t1, t5, t0); IVI_HAAR_BFLY(t1, s3, t1, t3, t0);\
|
||||
IVI_HAAR_BFLY(t5, s7, t5, t7, t0); IVI_HAAR_BFLY(t1, s2, t1, t2, t0);\
|
||||
IVI_HAAR_BFLY(t3, s4, t3, t4, t0); IVI_HAAR_BFLY(t5, s6, t5, t6, t0);\
|
||||
IVI_HAAR_BFLY(t7, s8, t7, t8, t0);\
|
||||
d1 = COMPENSATE(t1);\
|
||||
d2 = COMPENSATE(t2);\
|
||||
d3 = COMPENSATE(t3);\
|
||||
d4 = COMPENSATE(t4);\
|
||||
d5 = COMPENSATE(t5);\
|
||||
d6 = COMPENSATE(t6);\
|
||||
d7 = COMPENSATE(t7);\
|
||||
d8 = COMPENSATE(t8); }
|
||||
|
||||
/**
|
||||
* inverse 4-point Haar transform
|
||||
*/
|
||||
#define INV_HAAR4(s1, s3, s5, s7, d1, d2, d3, d4, t0, t1, t2, t3, t4) {\
|
||||
IVI_HAAR_BFLY(s1, s3, t0, t1, t4);\
|
||||
IVI_HAAR_BFLY(t0, s5, t2, t3, t4);\
|
||||
d1 = COMPENSATE(t2);\
|
||||
d2 = COMPENSATE(t3);\
|
||||
IVI_HAAR_BFLY(t1, s7, t2, t3, t4);\
|
||||
d3 = COMPENSATE(t2);\
|
||||
d4 = COMPENSATE(t3); }
|
||||
|
||||
void IndeoDSP::ffIviInverseHaar8x8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int32 tmp[64];
|
||||
int t0, t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
// apply the InvHaar8 to all columns
|
||||
#define COMPENSATE(x) (x)
|
||||
const int32 *src = in;
|
||||
int32 *dst = tmp;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags[i]) {
|
||||
// pre-scaling
|
||||
int shift = !(i & 4);
|
||||
int sp1 = src[ 0] << shift;
|
||||
int sp2 = src[ 8] << shift;
|
||||
int sp3 = src[16] << shift;
|
||||
int sp4 = src[24] << shift;
|
||||
INV_HAAR8( sp1, sp2, sp3, sp4,
|
||||
src[32], src[40], src[48], src[56],
|
||||
dst[ 0], dst[ 8], dst[16], dst[24],
|
||||
dst[32], dst[40], dst[48], dst[56],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
} else {
|
||||
dst[ 0] = dst[ 8] = dst[16] = dst[24] =
|
||||
dst[32] = dst[40] = dst[48] = dst[56] = 0;
|
||||
}
|
||||
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
|
||||
// apply the InvHaar8 to all rows
|
||||
#define COMPENSATE(x) (x)
|
||||
src = tmp;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (!src[0] && !src[1] && !src[2] && !src[3] &&
|
||||
!src[4] && !src[5] && !src[6] && !src[7]) {
|
||||
memset(out, 0, 8 * sizeof(out[0]));
|
||||
} else {
|
||||
INV_HAAR8(src[0], src[1], src[2], src[3],
|
||||
src[4], src[5], src[6], src[7],
|
||||
out[0], out[1], out[2], out[3],
|
||||
out[4], out[5], out[6], out[7],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
}
|
||||
src += 8;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviRowHaar8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
// apply the InvHaar8 to all rows
|
||||
#define COMPENSATE(x) (x)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if ( !in[0] && !in[1] && !in[2] && !in[3]
|
||||
&& !in[4] && !in[5] && !in[6] && !in[7]) {
|
||||
memset(out, 0, 8 * sizeof(out[0]));
|
||||
} else {
|
||||
INV_HAAR8(in[0], in[1], in[2], in[3],
|
||||
in[4], in[5], in[6], in[7],
|
||||
out[0], out[1], out[2], out[3],
|
||||
out[4], out[5], out[6], out[7],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
}
|
||||
in += 8;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviColHaar8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
// apply the InvHaar8 to all columns
|
||||
#define COMPENSATE(x) (x)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags[i]) {
|
||||
INV_HAAR8(in[ 0], in[ 8], in[16], in[24],
|
||||
in[32], in[40], in[48], in[56],
|
||||
out[0 * pitch], out[1 * pitch],
|
||||
out[2 * pitch], out[3 * pitch],
|
||||
out[4 * pitch], out[5 * pitch],
|
||||
out[6 * pitch], out[7 * pitch],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
} else {
|
||||
out[0 * pitch] = out[1 * pitch] =
|
||||
out[2 * pitch] = out[3 * pitch] =
|
||||
out[4 * pitch] = out[5 * pitch] =
|
||||
out[6 * pitch] = out[7 * pitch] = 0;
|
||||
}
|
||||
|
||||
in++;
|
||||
out++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviInverseHaar4x4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int32 tmp[16];
|
||||
int t0, t1, t2, t3, t4;
|
||||
|
||||
// apply the InvHaar4 to all columns
|
||||
#define COMPENSATE(x) (x)
|
||||
const int32 *src = in;
|
||||
int32 *dst = tmp;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (flags[i]) {
|
||||
// pre-scaling
|
||||
int shift = !(i & 2);
|
||||
int sp1 = src[0] << shift;
|
||||
int sp2 = src[4] << shift;
|
||||
INV_HAAR4( sp1, sp2, src[8], src[12],
|
||||
dst[0], dst[4], dst[8], dst[12],
|
||||
t0, t1, t2, t3, t4);
|
||||
} else {
|
||||
dst[0] = dst[4] = dst[8] = dst[12] = 0;
|
||||
}
|
||||
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
|
||||
// apply the InvHaar8 to all rows
|
||||
#define COMPENSATE(x) (x)
|
||||
src = tmp;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!src[0] && !src[1] && !src[2] && !src[3]) {
|
||||
memset(out, 0, 4 * sizeof(out[0]));
|
||||
} else {
|
||||
INV_HAAR4(src[0], src[1], src[2], src[3],
|
||||
out[0], out[1], out[2], out[3],
|
||||
t0, t1, t2, t3, t4);
|
||||
}
|
||||
src += 4;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviRowHaar4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4;
|
||||
|
||||
// apply the InvHaar4 to all rows
|
||||
#define COMPENSATE(x) (x)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!in[0] && !in[1] && !in[2] && !in[3]) {
|
||||
memset(out, 0, 4 * sizeof(out[0]));
|
||||
} else {
|
||||
INV_HAAR4(in[0], in[1], in[2], in[3],
|
||||
out[0], out[1], out[2], out[3],
|
||||
t0, t1, t2, t3, t4);
|
||||
}
|
||||
in += 4;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviColHaar4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4;
|
||||
|
||||
// apply the InvHaar8 to all columns
|
||||
#define COMPENSATE(x) (x)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (flags[i]) {
|
||||
INV_HAAR4(in[0], in[4], in[8], in[12],
|
||||
out[0 * pitch], out[1 * pitch],
|
||||
out[2 * pitch], out[3 * pitch],
|
||||
t0, t1, t2, t3, t4);
|
||||
} else {
|
||||
out[0 * pitch] = out[1 * pitch] =
|
||||
out[2 * pitch] = out[3 * pitch] = 0;
|
||||
}
|
||||
|
||||
in++;
|
||||
out++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviDcHaar2d(const int32 *in, int16 *out, uint32 pitch,
|
||||
int blkSize) {
|
||||
int16 dcCoeff = (*in + 0) >> 3;
|
||||
|
||||
for (int y = 0; y < blkSize; out += pitch, y++) {
|
||||
for (int x = 0; x < blkSize; x++)
|
||||
out[x] = dcCoeff;
|
||||
}
|
||||
}
|
||||
|
||||
//* butterfly operation for the inverse slant transform
|
||||
#define IVI_SLANT_BFLY(s1, s2, o1, o2, t) \
|
||||
t = (s1) - (s2);\
|
||||
o1 = (s1) + (s2);\
|
||||
o2 = (t);\
|
||||
|
||||
//* This is a reflection a,b = 1/2, 5/4 for the inverse slant transform
|
||||
#define IVI_IREFLECT(s1, s2, o1, o2, t) \
|
||||
t = (((s1) + (s2)*2 + 2) >> 2) + (s1);\
|
||||
o2 = (((s1)*2 - (s2) + 2) >> 2) - (s2);\
|
||||
o1 = (t);\
|
||||
|
||||
//* This is a reflection a,b = 1/2, 7/8 for the inverse slant transform
|
||||
#define IVI_SLANT_PART4(s1, s2, o1, o2, t) \
|
||||
t = (s2) + (((s1)*4 - (s2) + 4) >> 3);\
|
||||
o2 = (s1) + ((-(s1) - (s2)*4 + 4) >> 3);\
|
||||
o1 = (t);\
|
||||
|
||||
//* inverse slant8 transform
|
||||
#define IVI_INV_SLANT8(s1, s4, s8, s5, s2, s6, s3, s7,\
|
||||
d1, d2, d3, d4, d5, d6, d7, d8,\
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8) {\
|
||||
IVI_SLANT_PART4(s4, s5, t4, t5, t0);\
|
||||
\
|
||||
IVI_SLANT_BFLY(s1, t5, t1, t5, t0); IVI_SLANT_BFLY(s2, s6, t2, t6, t0);\
|
||||
IVI_SLANT_BFLY(s7, s3, t7, t3, t0); IVI_SLANT_BFLY(t4, s8, t4, t8, t0);\
|
||||
\
|
||||
IVI_SLANT_BFLY(t1, t2, t1, t2, t0); IVI_IREFLECT (t4, t3, t4, t3, t0);\
|
||||
IVI_SLANT_BFLY(t5, t6, t5, t6, t0); IVI_IREFLECT (t8, t7, t8, t7, t0);\
|
||||
IVI_SLANT_BFLY(t1, t4, t1, t4, t0); IVI_SLANT_BFLY(t2, t3, t2, t3, t0);\
|
||||
IVI_SLANT_BFLY(t5, t8, t5, t8, t0); IVI_SLANT_BFLY(t6, t7, t6, t7, t0);\
|
||||
d1 = COMPENSATE(t1);\
|
||||
d2 = COMPENSATE(t2);\
|
||||
d3 = COMPENSATE(t3);\
|
||||
d4 = COMPENSATE(t4);\
|
||||
d5 = COMPENSATE(t5);\
|
||||
d6 = COMPENSATE(t6);\
|
||||
d7 = COMPENSATE(t7);\
|
||||
d8 = COMPENSATE(t8);}
|
||||
|
||||
//* inverse slant4 transform
|
||||
#define IVI_INV_SLANT4(s1, s4, s2, s3, d1, d2, d3, d4, t0, t1, t2, t3, t4) {\
|
||||
IVI_SLANT_BFLY(s1, s2, t1, t2, t0); IVI_IREFLECT (s4, s3, t4, t3, t0);\
|
||||
\
|
||||
IVI_SLANT_BFLY(t1, t4, t1, t4, t0); IVI_SLANT_BFLY(t2, t3, t2, t3, t0);\
|
||||
d1 = COMPENSATE(t1);\
|
||||
d2 = COMPENSATE(t2);\
|
||||
d3 = COMPENSATE(t3);\
|
||||
d4 = COMPENSATE(t4);}
|
||||
|
||||
void IndeoDSP::ffIviInverseSlant8x8(const int32 *in, int16 *out, uint32 pitch, const uint8 *flags) {
|
||||
int32 tmp[64];
|
||||
int t0, t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
#define COMPENSATE(x) (x)
|
||||
const int32 *src = in;
|
||||
int32 *dst = tmp;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags[i]) {
|
||||
IVI_INV_SLANT8(src[0], src[8], src[16], src[24], src[32], src[40], src[48], src[56],
|
||||
dst[0], dst[8], dst[16], dst[24], dst[32], dst[40], dst[48], dst[56],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
} else {
|
||||
dst[0] = dst[8] = dst[16] = dst[24] = dst[32] = dst[40] = dst[48] = dst[56] = 0;
|
||||
}
|
||||
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
|
||||
#define COMPENSATE(x) (((x) + 1)>>1)
|
||||
src = tmp;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (!src[0] && !src[1] && !src[2] && !src[3] && !src[4] && !src[5] && !src[6] && !src[7]) {
|
||||
memset(out, 0, 8*sizeof(out[0]));
|
||||
} else {
|
||||
IVI_INV_SLANT8(src[0], src[1], src[2], src[3], src[4], src[5], src[6], src[7],
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
}
|
||||
src += 8;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviInverseSlant4x4(const int32 *in, int16 *out, uint32 pitch, const uint8 *flags) {
|
||||
int32 tmp[16];
|
||||
int t0, t1, t2, t3, t4;
|
||||
|
||||
#define COMPENSATE(x) (x)
|
||||
const int32 *src = in;
|
||||
int32 *dst = tmp;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (flags[i]) {
|
||||
IVI_INV_SLANT4(src[0], src[4], src[8], src[12],
|
||||
dst[0], dst[4], dst[8], dst[12],
|
||||
t0, t1, t2, t3, t4);
|
||||
} else {
|
||||
dst[0] = dst[4] = dst[8] = dst[12] = 0;
|
||||
}
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
|
||||
#define COMPENSATE(x) (((x) + 1)>>1)
|
||||
src = tmp;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!src[0] && !src[1] && !src[2] && !src[3]) {
|
||||
out[0] = out[1] = out[2] = out[3] = 0;
|
||||
} else {
|
||||
IVI_INV_SLANT4(src[0], src[1], src[2], src[3],
|
||||
out[0], out[1], out[2], out[3],
|
||||
t0, t1, t2, t3, t4);
|
||||
}
|
||||
src += 4;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviDcSlant2d(const int32 *in, int16 *out, uint32 pitch,
|
||||
int blkSize) {
|
||||
int16 dcCoeff = (*in + 1) >> 1;
|
||||
|
||||
for (int y = 0; y < blkSize; out += pitch, y++) {
|
||||
for (int x = 0; x < blkSize; x++)
|
||||
out[x] = dcCoeff;
|
||||
}
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviRowSlant8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
#define COMPENSATE(x) (((x) + 1)>>1)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (!in[0] && !in[1] && !in[2] && !in[3] && !in[4] && !in[5] && !in[6] && !in[7]) {
|
||||
memset(out, 0, 8*sizeof(out[0]));
|
||||
} else {
|
||||
IVI_INV_SLANT8( in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7],
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
}
|
||||
in += 8;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviDcRowSlant(const int32 *in, int16 *out, uint32 pitch, int blkSize) {
|
||||
int16 dcCoeff = (*in + 1) >> 1;
|
||||
|
||||
for (int x = 0; x < blkSize; x++)
|
||||
out[x] = dcCoeff;
|
||||
|
||||
out += pitch;
|
||||
|
||||
for (int y = 1; y < blkSize; out += pitch, y++) {
|
||||
for (int x = 0; x < blkSize; x++)
|
||||
out[x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviColSlant8(const int32 *in, int16 *out, uint32 pitch, const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
int row2 = pitch << 1;
|
||||
int row4 = pitch << 2;
|
||||
int row8 = pitch << 3;
|
||||
|
||||
#define COMPENSATE(x) (((x) + 1)>>1)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags[i]) {
|
||||
IVI_INV_SLANT8(in[0], in[8], in[16], in[24], in[32], in[40], in[48], in[56],
|
||||
out[0], out[pitch], out[row2], out[row2 + pitch], out[row4],
|
||||
out[row4 + pitch], out[row4 + row2], out[row8 - pitch],
|
||||
t0, t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
} else {
|
||||
out[0] = out[pitch] = out[row2] = out[row2 + pitch] = out[row4] =
|
||||
out[row4 + pitch] = out[row4 + row2] = out[row8 - pitch] = 0;
|
||||
}
|
||||
|
||||
in++;
|
||||
out++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviDcColSlant(const int32 *in, int16 *out, uint32 pitch, int blkSize) {
|
||||
int16 dcCoeff = (*in + 1) >> 1;
|
||||
|
||||
for (int y = 0; y < blkSize; out += pitch, y++) {
|
||||
out[0] = dcCoeff;
|
||||
for (int x = 1; x < blkSize; x++)
|
||||
out[x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviRowSlant4(const int32 *in, int16 *out,
|
||||
uint32 pitch, const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4;
|
||||
|
||||
#define COMPENSATE(x) (((x) + 1)>>1)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!in[0] && !in[1] && !in[2] && !in[3]) {
|
||||
memset(out, 0, 4*sizeof(out[0]));
|
||||
} else {
|
||||
IVI_INV_SLANT4( in[0], in[1], in[2], in[3],
|
||||
out[0], out[1], out[2], out[3],
|
||||
t0, t1, t2, t3, t4);
|
||||
}
|
||||
in += 4;
|
||||
out += pitch;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviColSlant4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
int t0, t1, t2, t3, t4;
|
||||
|
||||
int row2 = pitch << 1;
|
||||
|
||||
#define COMPENSATE(x) (((x) + 1)>>1)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (flags[i]) {
|
||||
IVI_INV_SLANT4(in[0], in[4], in[8], in[12],
|
||||
out[0], out[pitch], out[row2], out[row2 + pitch],
|
||||
t0, t1, t2, t3, t4);
|
||||
} else {
|
||||
out[0] = out[pitch] = out[row2] = out[row2 + pitch] = 0;
|
||||
}
|
||||
|
||||
in++;
|
||||
out++;
|
||||
}
|
||||
#undef COMPENSATE
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviPutPixels8x8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags) {
|
||||
for (int y = 0; y < 8; out += pitch, in += 8, y++)
|
||||
for (int x = 0; x < 8; x++)
|
||||
out[x] = in[x];
|
||||
}
|
||||
|
||||
void IndeoDSP::ffIviPutDcPixel8x8(const int32 *in, int16 *out, uint32 pitch,
|
||||
int blkSize) {
|
||||
out[0] = in[0];
|
||||
memset(out + 1, 0, 7 * sizeof(out[0]));
|
||||
out += pitch;
|
||||
|
||||
for (int y = 1; y < 8; out += pitch, y++)
|
||||
memset(out, 0, 8 * sizeof(out[0]));
|
||||
}
|
||||
|
||||
#define IVI_MC_TEMPLATE(size, suffix, OP) \
|
||||
static void iviMc ## size ##x## size ## suffix(int16 *buf, \
|
||||
uint32 dpitch, \
|
||||
const int16 *refBuf, \
|
||||
uint32 pitch, int mcType) \
|
||||
{ \
|
||||
const int16 *wptr; \
|
||||
\
|
||||
switch (mcType) { \
|
||||
case 0: /* fullpel (no interpolation) */ \
|
||||
for (int i = 0; i < size; i++, buf += dpitch, refBuf += pitch) { \
|
||||
for (int j = 0; j < size; j++) {\
|
||||
OP(buf[j], refBuf[j]); \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case 1: /* horizontal halfpel interpolation */ \
|
||||
for (int i = 0; i < size; i++, buf += dpitch, refBuf += pitch) \
|
||||
for (int j = 0; j < size; j++) \
|
||||
OP(buf[j], (refBuf[j] + refBuf[j+1]) >> 1); \
|
||||
break; \
|
||||
case 2: /* vertical halfpel interpolation */ \
|
||||
wptr = refBuf + pitch; \
|
||||
for (int i = 0; i < size; i++, buf += dpitch, wptr += pitch, refBuf += pitch) \
|
||||
for (int j = 0; j < size; j++) \
|
||||
OP(buf[j], (refBuf[j] + wptr[j]) >> 1); \
|
||||
break; \
|
||||
case 3: /* vertical and horizontal halfpel interpolation */ \
|
||||
wptr = refBuf + pitch; \
|
||||
for (int i = 0; i < size; i++, buf += dpitch, wptr += pitch, refBuf += pitch) \
|
||||
for (int j = 0; j < size; j++) \
|
||||
OP(buf[j], (refBuf[j] + refBuf[j+1] + wptr[j] + wptr[j+1]) >> 2); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void IndeoDSP::ffIviMc ## size ##x## size ## suffix(int16 *buf, const int16 *refBuf, \
|
||||
uint32 pitch, int mcType) \
|
||||
{ \
|
||||
iviMc ## size ##x## size ## suffix(buf, pitch, refBuf, pitch, mcType); \
|
||||
}
|
||||
|
||||
#define IVI_MC_AVG_TEMPLATE(size, suffix, OP) \
|
||||
void IndeoDSP::ffIviMcAvg ## size ##x## size ## suffix(int16 *buf, \
|
||||
const int16 *refBuf, \
|
||||
const int16 *refBuf2, \
|
||||
uint32 pitch, \
|
||||
int mcType, int mcType2) \
|
||||
{ \
|
||||
int16 tmp[size * size]; \
|
||||
\
|
||||
iviMc ## size ##x## size ## NoDelta(tmp, size, refBuf, pitch, mcType); \
|
||||
iviMc ## size ##x## size ## Delta(tmp, size, refBuf2, pitch, mcType2); \
|
||||
for (int i = 0; i < size; i++, buf += pitch) { \
|
||||
for (int j = 0; j < size; j++) {\
|
||||
OP(buf[j], tmp[i * size + j] >> 1); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define OP_PUT(a, b) (a) = (b)
|
||||
#define OP_ADD(a, b) (a) += (b)
|
||||
|
||||
IVI_MC_TEMPLATE(8, NoDelta, OP_PUT)
|
||||
IVI_MC_TEMPLATE(8, Delta, OP_ADD)
|
||||
IVI_MC_TEMPLATE(4, NoDelta, OP_PUT)
|
||||
IVI_MC_TEMPLATE(4, Delta, OP_ADD)
|
||||
IVI_MC_AVG_TEMPLATE(8, NoDelta, OP_PUT)
|
||||
IVI_MC_AVG_TEMPLATE(8, Delta, OP_ADD)
|
||||
IVI_MC_AVG_TEMPLATE(4, NoDelta, OP_PUT)
|
||||
IVI_MC_AVG_TEMPLATE(4, Delta, OP_ADD)
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
335
image/codecs/indeo/indeo_dsp.h
Normal file
335
image/codecs/indeo/indeo_dsp.h
Normal file
@@ -0,0 +1,335 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* VLC code
|
||||
*
|
||||
* Original copyright note:
|
||||
* DSP functions (inverse transforms, motion compensation, wavelet recompositions)
|
||||
* for Indeo Video Interactive codecs.
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_CODECS_INDEO_INDEO_DSP_H
|
||||
#define IMAGE_CODECS_INDEO_INDEO_DSP_H
|
||||
|
||||
#include "image/codecs/indeo/mem.h"
|
||||
#include "image/codecs/indeo/indeo.h"
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
class IndeoDSP {
|
||||
public:
|
||||
/**
|
||||
* two-dimensional inverse Haar 8x8 transform for Indeo 4
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviInverseHaar8x8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
static void ffIviInverseHaar8x1(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
static void ffIviInverseHaar1x8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* one-dimensional inverse 8-point Haar transform on rows for Indeo 4
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviRowHaar8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* one-dimensional inverse 8-point Haar transform on columns for Indeo 4
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviColHaar8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* two-dimensional inverse Haar 4x4 transform for Indeo 4
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviInverseHaar4x4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* one-dimensional inverse 4-point Haar transform on rows for Indeo 4
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviRowHaar4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* one-dimensional inverse 4-point Haar transform on columns for Indeo 4
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviColHaar4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* DC-only two-dimensional inverse Haar transform for Indeo 4.
|
||||
* Performing the inverse transform in this case is equivalent to
|
||||
* spreading dcCoeff >> 3 over the whole block.
|
||||
*
|
||||
* @param[in] in Pointer to the dc coefficient
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] blkSize Transform block size
|
||||
*/
|
||||
static void ffIviDcHaar2d(const int32 *in, int16 *out, uint32 pitch,
|
||||
int blkSize);
|
||||
|
||||
/**
|
||||
* two-dimensional inverse slant 8x8 transform
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviInverseSlant8x8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* two-dimensional inverse slant 4x4 transform
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviInverseSlant4x4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* DC-only two-dimensional inverse slant transform.
|
||||
* Performing the inverse slant transform in this case is equivalent to
|
||||
* spreading (dcCoeff + 1)/2 over the whole block.
|
||||
* It works much faster than performing the slant transform on a vector of zeroes.
|
||||
*
|
||||
* @param[in] in Pointer to the dc coefficient
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] blkSize Transform block size
|
||||
*/
|
||||
static void ffIviDcSlant2d(const int32 *in, int16 *out, uint32 pitch, int blkSize);
|
||||
|
||||
/**
|
||||
* inverse 1D row slant transform
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags (unused here)
|
||||
*/
|
||||
static void ffIviRowSlant8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* inverse 1D column slant transform
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviColSlant8(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* inverse 1D row slant transform
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags (unused here)
|
||||
*/
|
||||
static void ffIviRowSlant4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* inverse 1D column slant transform
|
||||
*
|
||||
* @param[in] in Pointer to the vector of transform coefficients
|
||||
* @param[out] out Pointer to the output buffer (frame)
|
||||
* @param[in] pitch Pitch to move to the next y line
|
||||
* @param[in] flags Pointer to the array of column flags:
|
||||
* != 0 - non_empty column, 0 - empty one
|
||||
* (this array must be filled by caller)
|
||||
*/
|
||||
static void ffIviColSlant4(const int32 *in, int16 *out, uint32 pitch,
|
||||
const uint8 *flags);
|
||||
|
||||
/**
|
||||
* DC-only inverse row slant transform
|
||||
*/
|
||||
static void ffIviDcRowSlant(const int32 *in, int16 *out, uint32 pitch, int blkSize);
|
||||
|
||||
/**
|
||||
* DC-only inverse column slant transform
|
||||
*/
|
||||
static void ffIviDcColSlant(const int32 *in, int16 *out, uint32 pitch, int blkSize);
|
||||
|
||||
/**
|
||||
* Copy the pixels into the frame buffer.
|
||||
*/
|
||||
static void ffIviPutPixels8x8(const int32 *in, int16 *out, uint32 pitch, const uint8 *flags);
|
||||
|
||||
/**
|
||||
* Copy the DC coefficient into the first pixel of the block and
|
||||
* zero all others.
|
||||
*/
|
||||
static void ffIviPutDcPixel8x8(const int32 *in, int16 *out, uint32 pitch, int blkSize);
|
||||
|
||||
/**
|
||||
* 8x8 block motion compensation with adding delta
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame buffer containing delta
|
||||
* @param[in] refBuf Pointer to the corresponding block in the reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type
|
||||
*/
|
||||
static void ffIviMc8x8Delta(int16 *buf, const int16 *refBuf, uint32 pitch, int mcType);
|
||||
|
||||
/**
|
||||
* 4x4 block motion compensation with adding delta
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame buffer containing delta
|
||||
* @param[in] refBuf Pointer to the corresponding block in the reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type
|
||||
*/
|
||||
static void ffIviMc4x4Delta(int16 *buf, const int16 *refBuf, uint32 pitch, int mcType);
|
||||
|
||||
/**
|
||||
* motion compensation without adding delta
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame buffer containing delta
|
||||
* @param[in] refBuf Pointer to the corresponding block in the reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type
|
||||
*/
|
||||
static void ffIviMc8x8NoDelta(int16 *buf, const int16 *refBuf, uint32 pitch, int mcType);
|
||||
|
||||
/**
|
||||
* 4x4 block motion compensation without adding delta
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame receiving the result
|
||||
* @param[in] refBuf Pointer to the corresponding block in the reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type
|
||||
*/
|
||||
static void ffIviMc4x4NoDelta(int16 *buf, const int16 *refBuf, uint32 pitch, int mcType);
|
||||
|
||||
/**
|
||||
* 8x8 block motion compensation with adding delta
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame buffer containing delta
|
||||
* @param[in] refBuf Pointer to the corresponding block in the backward reference frame
|
||||
* @param[in] refBuf2 Pointer to the corresponding block in the forward reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type for backward reference
|
||||
* @param[in] mcType2 Interpolation type for forward reference
|
||||
*/
|
||||
static void ffIviMcAvg8x8Delta(int16 *buf, const int16 *refBuf, const int16 *refBuf2, uint32 pitch, int mcType, int mcType2);
|
||||
|
||||
/**
|
||||
* 4x4 block motion compensation with adding delta
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame buffer containing delta
|
||||
* @param[in] refBuf Pointer to the corresponding block in the backward reference frame
|
||||
* @param[in] refBuf2 Pointer to the corresponding block in the forward reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type for backward reference
|
||||
* @param[in] mcType2 Interpolation type for forward reference
|
||||
*/
|
||||
static void ffIviMcAvg4x4Delta(int16 *buf, const int16 *refBuf, const int16 *refBuf2, uint32 pitch, int mcType, int mcType2);
|
||||
|
||||
/**
|
||||
* motion compensation without adding delta for B-frames
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame buffer containing delta
|
||||
* @param[in] refBuf Pointer to the corresponding block in the backward reference frame
|
||||
* @param[in] refBuf2 Pointer to the corresponding block in the forward reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type for backward reference
|
||||
* @param[in] mcType2 Interpolation type for forward reference
|
||||
*/
|
||||
static void ffIviMcAvg8x8NoDelta(int16 *buf, const int16 *refBuf, const int16 *refBuf2, uint32 pitch, int mcType, int mcType2);
|
||||
|
||||
/**
|
||||
* 4x4 block motion compensation without adding delta for B-frames
|
||||
*
|
||||
* @param[in,out] buf Pointer to the block in the current frame buffer containing delta
|
||||
* @param[in] refBuf Pointer to the corresponding block in the backward reference frame
|
||||
* @param[in] refBuf2 Pointer to the corresponding block in the forward reference frame
|
||||
* @param[in] pitch Pitch for moving to the next y line
|
||||
* @param[in] mcType Interpolation type for backward reference
|
||||
* @param[in] mcType2 Interpolation type for forward reference
|
||||
*/
|
||||
static void ffIviMcAvg4x4NoDelta(int16 *buf, const int16 *refBuf, const int16 *refBuf2, uint32 pitch, int mcType, int mcType2);
|
||||
};
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
|
||||
#endif
|
||||
135
image/codecs/indeo/mem.cpp
Normal file
135
image/codecs/indeo/mem.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* VLC code
|
||||
*
|
||||
* Original copyright note: * Intel Indeo 4 (IV41, IV42, etc.) video decoder for ffmpeg
|
||||
* written, produced, and directed by Alan Smithee
|
||||
*/
|
||||
|
||||
#include "image/codecs/indeo/mem.h"
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
const uint8 ffReverse[256] = {
|
||||
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
|
||||
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
|
||||
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
|
||||
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
|
||||
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
|
||||
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
|
||||
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
|
||||
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
|
||||
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
|
||||
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
|
||||
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
|
||||
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
|
||||
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
|
||||
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
|
||||
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
|
||||
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,
|
||||
};
|
||||
|
||||
const uint8 ffZigZagDirect[64] = {
|
||||
0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Multiply two `size_t` values checking for overflow.
|
||||
*
|
||||
* @param[in] a,b Operands of multiplication
|
||||
* @param[out] r Pointer to the result of the operation
|
||||
* @return 0 on success, AVERROR(EINVAL) on overflow
|
||||
*/
|
||||
static inline int avSizeMult(size_t a, size_t b, size_t *r) {
|
||||
size_t t = a * b;
|
||||
|
||||
// Hack inspired from glibc: don't try the division if nelem and elsize
|
||||
// are both less than sqrt(SIZE_MAX).
|
||||
if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b)
|
||||
return -1;
|
||||
*r = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void avFreeP(void *arg) {
|
||||
void **ptr = (void **)arg;
|
||||
free(*ptr);
|
||||
*ptr = nullptr;
|
||||
}
|
||||
|
||||
void *avReallocF(void *ptr, size_t nelem, size_t elsize) {
|
||||
size_t size;
|
||||
void *r;
|
||||
|
||||
if (avSizeMult(elsize, nelem, &size)) {
|
||||
free(ptr);
|
||||
return nullptr;
|
||||
}
|
||||
r = realloc(ptr, size);
|
||||
if (!r)
|
||||
free(ptr);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Swap the order of the bytes in the passed value
|
||||
*/
|
||||
uint32 bitswap32(uint32 x) {
|
||||
return (uint32)ffReverse[x & 0xFF] << 24 |
|
||||
(uint32)ffReverse[(x >> 8) & 0xFF] << 16 |
|
||||
(uint32)ffReverse[(x >> 16) & 0xFF] << 8 |
|
||||
(uint32)ffReverse[x >> 24];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse "nbits" bits of the value "val" and return the result
|
||||
* in the least significant bits.
|
||||
*/
|
||||
uint16 invertBits(uint16 val, int nbits) {
|
||||
uint16 res;
|
||||
|
||||
if (nbits <= 8) {
|
||||
res = ffReverse[val] >> (8 - nbits);
|
||||
} else {
|
||||
res = ((ffReverse[val & 0xFF] << 8) +
|
||||
(ffReverse[val >> 8])) >> (16 - nbits);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
109
image/codecs/indeo/mem.h
Normal file
109
image/codecs/indeo/mem.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
/* Common memory code used by the Indeo decoder
|
||||
*
|
||||
* Original copyright note: * Intel Indeo 4 (IV41, IV42, etc.) video decoder for ffmpeg
|
||||
* written, produced, and directed by Alan Smithee
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_CODECS_INDEO_MEM_H
|
||||
#define IMAGE_CODECS_INDEO_MEM_H
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define FFALIGN(x, a) (((x) + (a)-1) & ~((a)-1))
|
||||
#define FFSIGN(a) ((a) > 0 ? 1 : -1)
|
||||
#define MAX_INTEGER 0x7ffffff
|
||||
|
||||
/**
|
||||
* Free a memory block which has been allocated with a function of av_malloc()
|
||||
* or av_realloc() family, and set the pointer pointing to it to `NULL`.
|
||||
*
|
||||
* @param ptr Pointer to the pointer to the memory block which should be freed
|
||||
* @note `*ptr = NULL` is safe and leads to no action.
|
||||
*/
|
||||
extern void avFreeP(void *arg);
|
||||
|
||||
|
||||
/**
|
||||
* Allocate, reallocate, or free a block of memory.
|
||||
*
|
||||
* This function does the same thing as av_realloc(), except:
|
||||
* - It takes two size arguments and allocates `nelem * elsize` bytes,
|
||||
* after checking the result of the multiplication for integer overflow.
|
||||
* - It frees the input block in case of failure, thus avoiding the memory
|
||||
* leak with the classic
|
||||
* @code{.c}
|
||||
* buf = realloc(buf);
|
||||
* if (!buf)
|
||||
* return -1;
|
||||
* @endcode
|
||||
* pattern.
|
||||
*/
|
||||
extern void *avReallocF(void *ptr, size_t nelem, size_t elsize);
|
||||
|
||||
/**
|
||||
* Reverse "nbits" bits of the value "val" and return the result
|
||||
* in the least significant bits.
|
||||
*/
|
||||
extern uint16 invertBits(uint16 val, int nbits);
|
||||
|
||||
/**
|
||||
* Swap the order of the bytes in the passed value
|
||||
*/
|
||||
extern uint32 bitswap32(uint32 x);
|
||||
|
||||
/**
|
||||
* Clip a signed integer value into the 0-255 range.
|
||||
* @param a value to clip
|
||||
* @return clipped value
|
||||
*/
|
||||
inline uint8 avClipUint8(int a) {
|
||||
if (a & (~0xFF))
|
||||
return (-a) >> 31;
|
||||
else
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clip a signed integer to an unsigned power of two range.
|
||||
* @param a value to clip
|
||||
* @param p bit position to clip at
|
||||
* @return clipped value
|
||||
*/
|
||||
inline unsigned avClipUintp2(int a, int p) {
|
||||
if (a & ~((1 << p) - 1))
|
||||
return -a >> 31 & ((1 << p) - 1);
|
||||
else
|
||||
return a;
|
||||
}
|
||||
|
||||
extern const uint8 ffZigZagDirect[64];
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
|
||||
#endif
|
||||
335
image/codecs/indeo/vlc.cpp
Normal file
335
image/codecs/indeo/vlc.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* VLC code
|
||||
*
|
||||
* Original copyright note: * Intel Indeo 4 (IV41, IV42, etc.) video decoder for ffmpeg
|
||||
* written, produced, and directed by Alan Smithee
|
||||
*/
|
||||
|
||||
#include "image/codecs/indeo/vlc.h"
|
||||
#include "image/codecs/indeo/mem.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
/**
|
||||
* Quicksort
|
||||
* This sort is fast, and fully inplace but not stable and it is possible
|
||||
* to construct input that requires O(n^2) time but this is very unlikely to
|
||||
* happen with non constructed input.
|
||||
*/
|
||||
#define AV_QSORT(p, num, type, cmp) do {\
|
||||
void *stack[64][2];\
|
||||
int sp = 1;\
|
||||
stack[0][0] = p;\
|
||||
stack[0][1] = (p)+(num)-1;\
|
||||
while(sp){\
|
||||
type *start = (type *)stack[--sp][0];\
|
||||
type *end = (type *)stack[ sp][1];\
|
||||
while (start < end) {\
|
||||
if (start < end-1) {\
|
||||
int checksort = 0;\
|
||||
type *right = end - 2;\
|
||||
type *left = start + 1;\
|
||||
type *mid = start + ((end - start) >> 1);\
|
||||
if(cmp(start, end) > 0) {\
|
||||
if(cmp( end, mid) > 0) SWAP(*start, *mid);\
|
||||
else SWAP(*start, *end);\
|
||||
} else {\
|
||||
if(cmp(start, mid) > 0) SWAP(*start, *mid);\
|
||||
else checksort = 1;\
|
||||
}\
|
||||
if (cmp(mid, end) > 0) { \
|
||||
SWAP(*mid, *end);\
|
||||
checksort = 0;\
|
||||
}\
|
||||
if(start == end - 2) break;\
|
||||
SWAP(end[-1], *mid);\
|
||||
while (left <= right) {\
|
||||
while (left<=right && cmp(left, end - 1) < 0)\
|
||||
left++;\
|
||||
while (left<=right && cmp(right, end - 1) > 0)\
|
||||
right--;\
|
||||
if (left <= right) {\
|
||||
SWAP(*left, *right);\
|
||||
left++;\
|
||||
right--;\
|
||||
}\
|
||||
}\
|
||||
SWAP(end[-1], *left);\
|
||||
if(checksort && (mid == left - 1 || mid == left)){\
|
||||
mid= start;\
|
||||
while(mid<end && cmp(mid, mid+1) <= 0)\
|
||||
mid++;\
|
||||
if(mid==end)\
|
||||
break;\
|
||||
}\
|
||||
if (end - left < left - start){\
|
||||
stack[sp ][0] = start;\
|
||||
stack[sp++][1] = right;\
|
||||
start = left + 1;\
|
||||
} else {\
|
||||
stack[sp ][0] = left+1;\
|
||||
stack[sp++][1] = end;\
|
||||
end = right;\
|
||||
}\
|
||||
} else {\
|
||||
if (cmp(start, end) > 0)\
|
||||
SWAP(*start, *end);\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
#define COPY(condition)\
|
||||
for (i = 0; i < nbCodes; i++) { \
|
||||
buf[j].bits = getData(p_bits, i, bitsWrap, bitsSize); \
|
||||
if (!(condition)) \
|
||||
continue; \
|
||||
if (buf[j].bits > (3 * nbBits) || buf[j].bits > 32) { \
|
||||
warning("Too long VLC (%d) in init_vlc", buf[j].bits); \
|
||||
if (!(flags & INIT_VLC_USE_NEW_STATIC)) \
|
||||
free(buf); \
|
||||
return -1; \
|
||||
} \
|
||||
buf[j].code = getData(codes, i, codesWrap, codesSize); \
|
||||
if (buf[j].code >= (1LL << buf[j].bits)) { \
|
||||
warning("Invalid code %x for %d in init_vlc", buf[j].code, i); \
|
||||
if (!(flags & INIT_VLC_USE_NEW_STATIC)) \
|
||||
free(buf); \
|
||||
return -1; \
|
||||
} \
|
||||
if (flags & INIT_VLC_LE) \
|
||||
buf[j].code = bitswap32(buf[j].code); \
|
||||
else \
|
||||
buf[j].code <<= 32 - buf[j].bits; \
|
||||
if (symbols) \
|
||||
buf[j].symbol = getData(symbols, i, symbolsWrap, symbolsSize); \
|
||||
else \
|
||||
buf[j].symbol = i; \
|
||||
j++; \
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
VLC::VLC() : _bits(0), _tableSize(0), _tableAllocated(0), _table(nullptr) {
|
||||
}
|
||||
|
||||
int VLC::init_vlc(int nbBits, int nbCodes, const void *bits, int bitsWrap, int bitsSize,
|
||||
const void *codes, int codesWrap, int codesSize, int flags) {
|
||||
return init_vlc(nbBits, nbCodes, bits, bitsWrap, bitsSize, codes, codesWrap,
|
||||
codesSize, nullptr, 0, 0, flags);
|
||||
}
|
||||
|
||||
int VLC::init_vlc(int nbBits, int nbCodes, const void *p_bits, int bitsWrap,
|
||||
int bitsSize, const void *codes, int codesWrap, int codesSize,
|
||||
const void *symbols, int symbolsWrap, int symbolsSize, int flags) {
|
||||
VLCcode *buf;
|
||||
int i, j, ret;
|
||||
VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34
|
||||
VLC localvlc, *vlc;
|
||||
|
||||
vlc = this;
|
||||
vlc->_bits = nbBits;
|
||||
if (flags & INIT_VLC_USE_NEW_STATIC) {
|
||||
assert((nbCodes + 1) <= (int)FF_ARRAY_ELEMS(localbuf));
|
||||
buf = localbuf;
|
||||
localvlc = *this;
|
||||
vlc = &localvlc;
|
||||
vlc->_tableSize = 0;
|
||||
} else {
|
||||
vlc->_table = NULL;
|
||||
vlc->_tableAllocated = 0;
|
||||
vlc->_tableSize = 0;
|
||||
|
||||
buf = (VLCcode *)malloc((nbCodes + 1) * sizeof(VLCcode));
|
||||
assert(buf);
|
||||
}
|
||||
|
||||
assert(symbolsSize <= 2 || !symbols);
|
||||
j = 0;
|
||||
|
||||
COPY(buf[j].bits > nbBits);
|
||||
|
||||
// qsort is the slowest part of init_vlc, and could probably be improved or avoided
|
||||
AV_QSORT(buf, j, VLCcode, compareVlcSpec);
|
||||
COPY(buf[j].bits && buf[j].bits <= nbBits);
|
||||
nbCodes = j;
|
||||
|
||||
ret = vlc->buildTable(nbBits, nbCodes, buf, flags);
|
||||
|
||||
if (flags & INIT_VLC_USE_NEW_STATIC) {
|
||||
if (vlc->_tableSize != vlc->_tableAllocated)
|
||||
warning("needed %d had %d", vlc->_tableSize, vlc->_tableAllocated);
|
||||
|
||||
assert(ret >= 0);
|
||||
*this = *vlc;
|
||||
} else {
|
||||
free(buf);
|
||||
if (ret < 0) {
|
||||
avFreeP(&vlc->_table);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VLC::freeVlc() {
|
||||
free(_table);
|
||||
}
|
||||
|
||||
int VLC::compareVlcSpec(const void *a, const void *b) {
|
||||
const VLCcode *sa = (const VLCcode *)a, *sb = (const VLCcode *)b;
|
||||
return (sa->code >> 1) - (sb->code >> 1);
|
||||
}
|
||||
|
||||
int VLC::buildTable(int tableNbBits, int nbCodes,
|
||||
VLCcode *codes, int flags) {
|
||||
VLC *vlc = this;
|
||||
int tableSize, tableIndex, index, codePrefix, symbol, subtableBits;
|
||||
int i, j, k, n, nb, inc;
|
||||
uint32 code;
|
||||
VLC_TYPE (*table)[2];
|
||||
|
||||
tableSize = 1 << tableNbBits;
|
||||
if (tableNbBits > 30)
|
||||
return -1;
|
||||
tableIndex = allocTable(tableSize, flags & INIT_VLC_USE_NEW_STATIC);
|
||||
//warning("new table index=%d size=%d", tableIndex, tableSize);
|
||||
if (tableIndex < 0)
|
||||
return tableIndex;
|
||||
table = &vlc->_table[tableIndex];
|
||||
|
||||
// first pass: map codes and compute auxiliary table sizes
|
||||
for (i = 0; i < nbCodes; i++) {
|
||||
n = codes[i].bits;
|
||||
code = codes[i].code;
|
||||
symbol = codes[i].symbol;
|
||||
//warning("i=%d n=%d code=0x%x", i, n, code);
|
||||
|
||||
if (n <= tableNbBits) {
|
||||
// no need to add another table
|
||||
j = code >> (32 - tableNbBits);
|
||||
nb = 1 << (tableNbBits - n);
|
||||
inc = 1;
|
||||
if (flags & INIT_VLC_LE) {
|
||||
j = bitswap32(code);
|
||||
inc = 1 << n;
|
||||
}
|
||||
for (k = 0; k < nb; k++) {
|
||||
int bits = table[j][1];
|
||||
//warning("%4x: code=%d n=%d", j, i, n);
|
||||
|
||||
if (bits != 0 && bits != n) {
|
||||
warning("incorrect codes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
table[j][1] = n; //bits
|
||||
table[j][0] = symbol;
|
||||
j += inc;
|
||||
}
|
||||
} else {
|
||||
// fill auxiliary table recursively
|
||||
n -= tableNbBits;
|
||||
codePrefix = code >> (32 - tableNbBits);
|
||||
subtableBits = n;
|
||||
codes[i].bits = n;
|
||||
codes[i].code = code << tableNbBits;
|
||||
for (k = i + 1; k < nbCodes; k++) {
|
||||
n = codes[k].bits - tableNbBits;
|
||||
if (n <= 0)
|
||||
break;
|
||||
code = codes[k].code;
|
||||
if (code >> (32 - tableNbBits) != (uint)codePrefix)
|
||||
break;
|
||||
codes[k].bits = n;
|
||||
codes[k].code = code << tableNbBits;
|
||||
subtableBits = MAX(subtableBits, n);
|
||||
}
|
||||
subtableBits = MIN(subtableBits, tableNbBits);
|
||||
j = (flags & INIT_VLC_LE) ? bitswap32(codePrefix) >> (32 - tableNbBits) : codePrefix;
|
||||
table[j][1] = -subtableBits;
|
||||
//warning("%4x: n=%d (subtable)", j, codes[i].bits + tableNbBits);
|
||||
index = vlc->buildTable(subtableBits, k - i, codes + i, flags);
|
||||
if (index < 0)
|
||||
return index;
|
||||
|
||||
// note: realloc has been done, so reload tables
|
||||
table = (VLC_TYPE (*)[2])&vlc->_table[tableIndex];
|
||||
table[j][0] = index; //code
|
||||
i = k - 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < tableSize; i++) {
|
||||
if (table[i][1] == 0) //bits
|
||||
table[i][0] = -1; //codes
|
||||
}
|
||||
|
||||
return tableIndex;
|
||||
}
|
||||
|
||||
int VLC::allocTable(int size, int useStatic) {
|
||||
VLC *vlc = this;
|
||||
int index = vlc->_tableSize;
|
||||
|
||||
vlc->_tableSize += size;
|
||||
if (vlc->_tableSize > vlc->_tableAllocated) {
|
||||
// cannot do anything, init_vlc() is used with too little memory
|
||||
assert(!useStatic);
|
||||
|
||||
vlc->_tableAllocated += (1 << vlc->_bits);
|
||||
vlc->_table = (int16(*)[2])avReallocF(vlc->_table, vlc->_tableAllocated, sizeof(VLC_TYPE) * 2);
|
||||
if (!vlc->_table) {
|
||||
vlc->_tableAllocated = 0;
|
||||
vlc->_tableSize = 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
memset(vlc->_table + vlc->_tableAllocated - (static_cast<ptrdiff_t>(1) << vlc->_bits), 0, sizeof(VLC_TYPE) * 2 << vlc->_bits);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
uint VLC::getData(const void *table, uint idx, uint wrap, uint size) {
|
||||
const uint8 *ptr = (const uint8 *)table + idx * wrap;
|
||||
|
||||
switch(size) {
|
||||
case 1:
|
||||
return *(const uint8 *)ptr;
|
||||
|
||||
case 2:
|
||||
return *(const uint16 *)ptr;
|
||||
|
||||
default:
|
||||
return *(const uint32 *)ptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
134
image/codecs/indeo/vlc.h
Normal file
134
image/codecs/indeo/vlc.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
/* VLC code
|
||||
*
|
||||
* Original copyright note: * Intel Indeo 4 (IV41, IV42, etc.) video decoder for ffmpeg
|
||||
* written, produced, and directed by Alan Smithee
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_CODECS_INDEO_VLC_H
|
||||
#define IMAGE_CODECS_INDEO_VLC_H
|
||||
|
||||
#include "image/codecs/indeo/get_bits.h"
|
||||
|
||||
namespace Image {
|
||||
namespace Indeo {
|
||||
|
||||
#define VLC_TYPE int16
|
||||
|
||||
enum VLCFlag {
|
||||
INIT_VLC_LE = 2,
|
||||
INIT_VLC_USE_NEW_STATIC = 4
|
||||
};
|
||||
|
||||
struct VLCcode {
|
||||
uint8 bits;
|
||||
uint16 symbol;
|
||||
|
||||
/**
|
||||
* codeword, with the first bit-to-be-read in the msb
|
||||
* (even if intended for a little-endian bitstream reader)
|
||||
*/
|
||||
uint32 code;
|
||||
};
|
||||
|
||||
struct VLC {
|
||||
private:
|
||||
static int compareVlcSpec(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* Gets a value of a given size from a table
|
||||
* @param table Table to get data from
|
||||
* @param idx Index of value to retrieve
|
||||
* @param wrap Size of elements with alignment
|
||||
* @param size Size of elements
|
||||
*/
|
||||
static uint getData(const void *table, uint idx, uint wrap, uint size);
|
||||
public:
|
||||
int _bits;
|
||||
VLC_TYPE (*_table)[2]; ///< code, bits
|
||||
int _tableSize, _tableAllocated;
|
||||
|
||||
VLC();
|
||||
|
||||
/* Build VLC decoding tables suitable for use with get_vlc().
|
||||
|
||||
'nbBits' sets the decoding table size (2^nbBits) entries. The
|
||||
bigger it is, the faster is the decoding. But it should not be too
|
||||
big to save memory and L1 cache. '9' is a good compromise.
|
||||
|
||||
'nbCodes' : number of vlcs codes
|
||||
|
||||
'bits' : table which gives the size (in bits) of each vlc code.
|
||||
|
||||
'codes' : table which gives the bit pattern of of each vlc code.
|
||||
|
||||
'symbols' : table which gives the values to be returned from get_vlc().
|
||||
|
||||
'xxx_wrap' : give the number of bytes between each entry of the
|
||||
'bits' or 'codes' tables.
|
||||
|
||||
'xxx_size' : gives the number of bytes of each entry of the 'bits'
|
||||
or 'codes' tables.
|
||||
|
||||
'wrap' and 'size' make it possible to use any memory configuration and types
|
||||
(byte/word/long) to store the 'bits', 'codes', and 'symbols' tables.
|
||||
|
||||
'useStatic' should be set to 1 for tables, which should be freed
|
||||
with av_free_static(), 0 if freeVlc() will be used.
|
||||
*/
|
||||
int init_vlc(int nbBits, int nbCodes, const void *bits, int bitsWrap,
|
||||
int bitsSize, const void *codes, int codesWrap, int codesSize,
|
||||
const void *symbols, int symbolsWrap, int symbolsSize, int flags);
|
||||
|
||||
int init_vlc(int nbBits, int nbCodes, const void *bits, int bitsWrap, int bitsSize,
|
||||
const void *codes, int codesWrap, int codesSize, int flags);
|
||||
|
||||
/**
|
||||
* Free VLC data
|
||||
*/
|
||||
void freeVlc();
|
||||
|
||||
|
||||
/**
|
||||
* Build VLC decoding tables suitable for use with get_vlc().
|
||||
*
|
||||
* @param tableNbBits max length of vlc codes to store directly in this table
|
||||
* (Longer codes are delegated to subtables.)
|
||||
*
|
||||
* @param nbCodes number of elements in codes[]
|
||||
*
|
||||
* @param codes descriptions of the vlc codes
|
||||
* These must be ordered such that codes going into the same subtable are contiguous.
|
||||
* Sorting by VLCcode.code is sufficient, though not necessary.
|
||||
*/
|
||||
int buildTable(int tableNbBits, int nbCodes, VLCcode *codes, int flags);
|
||||
|
||||
int allocTable(int size, int useStatic);
|
||||
};
|
||||
|
||||
} // End of namespace Indeo
|
||||
} // End of namespace Image
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user