Here's a new hit from Elvis Presley - You're The Devil in Disguise.
Nothing to do with Apple this time though.
/*
* Indeo Video v3 compatible decoder
* Copyright (c) 2009 - 2011 Maxim Poliakovski
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* This is a decoder for Intel Indeo Video v3.
* It's based on vector quantization, run-length coding and motion compensation.
* Known container formats: .avi and .mov
* Known FOURCCs: 'IV31', 'IV32'
* For documentation see:
* http://wiki.multimedia.cx/index.php?title=Indeo_3
*/
#include "libavutil/imgutils.h"
#include "avcodec.h"
#include "dsputil.h"
#include "bytestream.h"
#include "get_bits.h"
#include "indeo3data.h"
/**
* RLE opcodes.
*/
enum {
RLE_ESC_F9 = 249, ///< same as RLE_ESC_FA + do the same with next block
RLE_ESC_FA = 250, ///< INTRA: skip block, INTER: copy data from reference
RLE_ESC_FB = 251, ///< apply null delta to N blocks / skip N blocks
RLE_ESC_FC = 252, ///< same as RLE_ESC_FD + do the same with next block
RLE_ESC_FD = 253, ///< apply null delta to all remaining lines of this block
RLE_ESC_FE = 254, ///< apply null delta to all lines up to the 3rd line
RLE_ESC_FF = 255 ///< apply null delta to all lines up to the 2nd line
};
/**
* Some constants for parsing frame bitstream flags.
*/
#define BS_8BIT_PEL (1<<1) ///< 8bit pixel bitdepth indicator
#define BS_KEYFRAME (1<<2) ///< intra frame indicator
#define BS_MV_Y_HALF (1<<4) ///< vertical mv halfpel resolution indicator
#define BS_MV_X_HALF (1<<5) ///< horizontal mv halfpel resolution indicator
#define BS_NONREF (1<<8) ///< nonref (discardable) frame indicator
#define BS_BUFFER 9 ///< indicates which of two frame buffers should be used
typedef struct Plane {
uint8_t *buffers[2];
uint8_t *pixels[2]; ///< pointer to the actual pixel data of the buffers above
uint32_t width;
uint32_t height;
uint32_t pitch;
} Plane;
#define CELL_STACK_MAX 20
typedef struct Cell {
int16_t xpos; ///< cell coordinates in 4x4 blocks
int16_t ypos;
int16_t width; ///< cell width in 4x4 blocks
int16_t height; ///< cell height in 4x4 blocks
uint8_t tree; ///< tree id: 0- MC tree, 1 - VQ tree
const int8_t *mv_ptr; ///< ptr to the motion vector if any
} Cell;
typedef struct Indeo3DecodeContext {
AVCodecContext *avctx;
AVFrame frame;
DSPContext dsp;
GetBitContext gb;
int need_resync;
int skip_bits;
const uint8_t *next_cell_data;
const uint8_t *last_byte;
const int8_t *mc_vectors;
int16_t width, height;
uint32_t frame_num; ///< current frame number (zero-based)
uint32_t data_size; ///< size of the frame data in bytes
uint16_t frame_flags; ///< frame properties
uint8_t cb_offset; ///< needed for selecting VQ tables
uint8_t buf_sel; ///< active frame buffer: 0 - primary, 1 -secondary
const uint8_t *y_data_ptr;
const uint8_t *v_data_ptr;
const uint8_t *u_data_ptr;
int32_t y_data_size;
int32_t v_data_size;
int32_t u_data_size;
const uint8_t *alt_quant; ///< secondary VQ table set for the modes 1 and 4
Plane planes[3];
} Indeo3DecodeContext;
static uint8_t requant_tab[8][128];
/**
* Build the static requantization table.
* This table is used to remap pixel values according to a specific
* quant index and thus avoid overflows while adding deltas.
*/
static av_cold void build_requant_tab(void)
{
static int8_t offsets[8] = { 1, 1, 2, -3, -3, 3, 4, 4 };
static int8_t deltas [8] = { 0, 1, 0, 4, 4, 1, 0, 1 };
int i, j, step;
for (i = 0; i < 8; i++) {
step = i + 2;
for (j = 0; j < 128; j++)
requant_tab[i][j] = (j + offsets[i]) / step * step + deltas[i];
}
/* some last elements calculated above will have values >= 128 */
/* pixel values shall never exceed 127 so set them to non-overflowing values */
/* according with the quantization step of the respective section */
requant_tab[0][127] = 126;
requant_tab[1][119] = 118;
requant_tab[1][120] = 118;
requant_tab[2][126] = 124;
requant_tab[2][127] = 124;
requant_tab[6][124] = 120;
requant_tab[6][125] = 120;
requant_tab[6][126] = 120;
requant_tab[6][127] = 120;
/* Patch for compatibility with the Intel's binary decoders */
requant_tab[1][7] = 10;
requant_tab[4][8] = 10;
}
/**
* Allocate frame buffers and initialize plane descriptors.
*/
static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx, AVCodecContext *avctx)
{
int p, luma_width, luma_height, chroma_width, chroma_height;
int luma_pitch, chroma_pitch, luma_size, chroma_size;
luma_width = ctx->width;
luma_height = ctx->height;
if (luma_width < 16 || luma_width > 640 ||
luma_height < 16 || luma_height > 480 ||
luma_width & 3 || luma_height & 3) {
av_log(avctx, AV_LOG_ERROR, "Invalid picture dimensions: %d x %d!\n",
luma_width, luma_height);
return -1;
}
chroma_width = FFALIGN(luma_width >> 2, 4);
chroma_height = FFALIGN(luma_height >> 2, 4);
luma_pitch = FFALIGN(luma_width, 16);
chroma_pitch = FFALIGN(chroma_width, 16);
/* Calculate size of the luminance plane. */
/* Add one line more for INTRA prediction. */
luma_size = luma_pitch * (luma_height + 1);
/* Calculate size of a chrominance planes. */
/* Add one line more for INTRA prediction. */
chroma_size = chroma_pitch * (chroma_height + 1);
/* allocate frame buffers */
for (p = 0; p < 3; p++) {
ctx->planes[p].pitch = (!p ? luma_pitch : chroma_pitch);
ctx->planes[p].width = (!p ? luma_width : chroma_width);
ctx->planes[p].height = (!p ? luma_height : chroma_height);
ctx->planes[p].buffers[0] = av_malloc(!p ? luma_size : chroma_size);
ctx->planes[p].buffers[1] = av_malloc(!p ? luma_size : chroma_size);
/* fill the INTRA prediction lines with the middle pixel value = 64 */
memset(ctx->planes[p].buffers[0], 0x40, ctx->planes[p].pitch);
memset(ctx->planes[p].buffers[1], 0x40, ctx->planes[p].pitch);
/* set buffer pointers = buf_ptr + pitch and thus skip the INTRA prediction line */
ctx->planes[p].pixels[0] = ctx->planes[p].buffers[0] + ctx->planes[p].pitch;
ctx->planes[p].pixels[1] = ctx->planes[p].buffers[1] + ctx->planes[p].pitch;
}
return 0;
}
/**
* Dispose frame buffers.
*/
static av_cold void free_frame_buffers(Indeo3DecodeContext *ctx)
{
int p;
for (p = 0; p < 3; p++) {
av_freep(&ctx->planes[p].buffers[0]);
av_freep(&ctx->planes[p].buffers[1]);
}
}
/**
* Copy pixels of the cell(x + mv_x, y + mv_y) from the previous frame into
* the cell(x, y) in the current frame.
*
* @param ctx [in] pointer to the decoder context
* @param plane [in] pointer to the plane descriptor
* @param cell [in] pointer to the cell descriptor
*/
static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell)
{
int h, w, mv_x, mv_y, offset, offset_dst;
uint8_t *src, *dst;
/* setup output and reference pointers */
offset_dst = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2);
dst = plane->pixels[ctx->buf_sel] + offset_dst;
mv_y = cell->mv_ptr[0];
mv_x = cell->mv_ptr[1];
offset = offset_dst + mv_y * plane->pitch + mv_x;
src = plane->pixels[ctx->buf_sel ^ 1] + offset;
h = cell->height << 2;
for (w = cell->width; w > 0;) {
/* copy using 16xH blocks */
if (!((cell->xpos << 2) & 15) && w >= 4) {
for (; w >= 4; src += 16, dst += 16, w -= 4)
ctx->dsp.put_no_rnd_pixels_tab[0][0](dst, src, plane->pitch, h);
}
/* copy using 8xH blocks */
if (!((cell->xpos << 2) & 7) && w >= 2) {
ctx->dsp.put_no_rnd_pixels_tab[1][0](dst, src, plane->pitch, h);
w -= 2;
src += 8;
dst += 8;
}
if (w >= 1) {
copy_block4(dst, src, plane->pitch, plane->pitch, h);
w--;
src += 4;
dst += 4;
}
}
}
/**
* Average 4/8 pixels at once without rounding using softSIMD
*/
#define AVG_32(dst, src, ref) \
*((uint32_t *)((dst))) = ((*((uint32_t *)((src))) + *((uint32_t *)((ref)))) >> 1) & 0x7F7F7F7F
#define AVG_64(dst, src, ref) \
*((uint64_t *)((dst))) = ((*((uint64_t *)((src))) + *((uint64_t *)((ref)))) >> 1) & 0x7F7F7F7F7F7F7F7F
/**
* Replicate each even pixel as follows:
* ABCDEFGH -> AACCEEGG
*/
static inline uint64_t replicate64(uint64_t a) {
#if HAVE_BIGENDIAN
a &= 0xFF00FF00FF00FF00;
a |= a >> 8;
#else
a &= 0x00FF00FF00FF00FF;
a |= a << 8;
#endif
return a;
}
static inline uint32_t replicate32(uint32_t a) {
#if HAVE_BIGENDIAN
a &= 0xFF00FF00;
a |= a >> 8;
#else
a &= 0x00FF00FF;
a |= a << 8;
#endif
return a;
}
/**
* Fill n lines with 64bit pixel value pix
*/
static inline void fill_64(uint8_t *dst, const uint64_t pix, int32_t n, int32_t row_offset)
{
for (; n > 0; dst += row_offset, n--)
*((uint64_t *)(dst)) = pix;
}
/**
* Error codes for cell decoding.
*/
enum {
IV3_NOERR = 0,
IV3_BAD_RLE = 1,
IV3_BAD_DATA = 2,
IV3_BAD_COUNTER = 3,
IV3_UNSUPPORTED = 4,
IV3_OUT_OF_DATA = 5
};
#define BUFFER_PRECHECK \
if (data_ptr >= last_ptr) { \
error = IV3_OUT_OF_DATA; \
goto fail; \
}
#define DECODE_CELL_TEMPLATE(h_zoom, v_zoom, PREPARE_DELTA, APPLY_DELTA,\
RLE_BLOCK_ACTION, RLE_CODE_ACTION)\
for (y = 0, is_first_row = 1; y < cell->height; is_first_row = 0, y += 1 + (v_zoom)) {\
for (x = 0; x < cell->width; x += 1 + (h_zoom)) {\
ref = ref_block;\
dst = block;\
\
if (rle_blocks > 0) {\
RLE_BLOCK_ACTION; /* mode-dependent block skip/copy action */ \
rle_blocks--;\
} else {\
for (line = 0; line < 4;) {\
num_lines = 1;\
is_top_of_cell = is_first_row & !line;\
\
PREPARE_DELTA;\
BUFFER_PRECHECK; \
code = *data_ptr++; \
if (code < 248) {\
if (code < delta_tab->num_dyads) {\
BUFFER_PRECHECK; \
dyad1 = *data_ptr++; \
dyad2 = code; \
if (dyad1 > delta_tab->num_dyads || dyad1 >= 248) {\
error = IV3_BAD_DATA; \
goto fail; \
}\
} else {\
/* process QUADS */ \
code -= delta_tab->num_dyads; \
dyad1 = code / delta_tab->quad_exp; \
dyad2 = code % delta_tab->quad_exp; \
if (swap_quads[line & 1]) \
FFSWAP(unsigned int, dyad1, dyad2); \
}\
APPLY_DELTA;\
} else {\
/* process RLE codes */ \
switch (code) {\
case RLE_ESC_FC: \
skip_flag = 0; \
rle_blocks = 1; \
code = 253; \
/* FALLTHROUGH */ \
\
case RLE_ESC_FF: \
case RLE_ESC_FE: \
case RLE_ESC_FD: \
num_lines = 257 - code - line; \
if (num_lines <= 0) {\
error = IV3_BAD_RLE; \
goto fail; \
}\
RLE_CODE_ACTION; \
break; \
\
case RLE_ESC_FB: \
BUFFER_PRECHECK; \
code = *data_ptr++; \
rle_blocks = (code & 0x1F) - 1; /* set block counter */ \
if (code >= 64 || rle_blocks < 0) {\
error = IV3_BAD_COUNTER;\
goto fail;\
}\
skip_flag = code & 0x20;\
num_lines = 4 - line; /* enforce next block processing */\
if (mode >= 10 || (cell->mv_ptr || !skip_flag))\
RLE_CODE_ACTION;\
break;\
\
case RLE_ESC_F9: \
skip_flag = 1; \
rle_blocks = 1; \
/* FALLTHROUGH */\
\
case RLE_ESC_FA: \
if (line) {\
error = IV3_BAD_RLE; \
goto fail; \
}\
num_lines = 4; /* enforce next block processing */\
if (cell->mv_ptr)\
RLE_CODE_ACTION;\
break;\
\
default: \
error = IV3_UNSUPPORTED;\
goto fail;\
}\
}\
\
line += num_lines;\
ref += row_offset * (num_lines << (v_zoom));\
dst += row_offset * (num_lines << (v_zoom));\
}\
}\
\
/* move to next horizontal block */\
block += 4 << (h_zoom);\
ref_block += 4 << (h_zoom);\
}\
\
/* move to next line of blocks */\
ref_block += blk_row_offset;\
block += blk_row_offset;\
}
#define NO_ACTION
#define RLE_BLOCK_COPY \
if (cell->mv_ptr || !skip_flag) \
copy_block4(dst, ref, row_offset, row_offset, 4 << (zoom_fac))
#define RLE_BLOCK_COPY_8 \
pix64 = *((uint64_t *)(ref));\
if (is_first_row) {/* special prediction case: top line of a cell */\
pix64 = replicate64(pix64);\
fill_64(dst + row_offset, pix64, 7, row_offset);\
AVG_64(dst, ref, dst + row_offset);\
} else \
fill_64(dst, pix64, 8, row_offset)
#define RLE_LINES_COPY \
copy_block4(dst, ref, row_offset, row_offset, num_lines << (zoom_fac))
#define RLE_LINES_COPY_M10 \
pix64 = *((uint64_t *)(ref));\
if (is_top_of_cell) {\
pix64 = replicate64(pix64);\
fill_64(dst + row_offset, pix64, (num_lines << 1) - 1, row_offset);\
AVG_64(dst, ref, dst + row_offset);\
} else \
fill_64(dst, pix64, num_lines << 1, row_offset)
/* select primary VQ table for odd, secondary for even lines */
#define SELECT_DELTA_TAB \
delta_tab = delta[line & 1]
#define APPLY_DELTA_4 \
*((uint16_t *)(dst+line_offset )) = *((uint16_t *)(ref )) + delta_tab->deltas[dyad1];\
*((uint16_t *)(dst+line_offset+2)) = *((uint16_t *)(ref+2)) + delta_tab->deltas[dyad2];\
if (mode >= 3) {\
if (is_top_of_cell && !cell->ypos) {\
*((uint32_t *)(dst)) = *((uint32_t *)(dst+row_offset));\
} else \
AVG_32(dst, ref, dst + row_offset);\
}
#define APPLY_DELTA_8 \
/* apply two 32-bit VQ deltas to next even line */\
if (is_top_of_cell) { \
*((uint32_t *)(dst+row_offset )) = \
replicate32(*((uint32_t *)(ref ))) + delta_tab->deltas_m10[dyad1];\
*((uint32_t *)(dst+row_offset+4)) = \
replicate32(*((uint32_t *)(ref+4))) + delta_tab->deltas_m10[dyad2];\
} else { \
*((uint32_t *)(dst+row_offset )) = \
*((uint32_t *)(ref )) + delta_tab->deltas_m10[dyad1];\
*((uint32_t *)(dst+row_offset+4)) = \
*((uint32_t *)(ref+4)) + delta_tab->deltas_m10[dyad2];\
} \
/* odd lines are not coded but rather interpolated/replicated */\
/* first line of the cell on the top of image? - replicate */\
/* otherwise - interpolate */\
if (is_top_of_cell && !cell->ypos) {\
*((uint64_t *)(dst)) = *((uint64_t *)(dst+row_offset));\
} else \
AVG_64(dst, ref, dst + row_offset);
#define APPLY_DELTA_1011_INTER \
if (mode == 10) { \
*((uint32_t *)(dst )) += delta_tab->deltas_m10[dyad1];\
*((uint32_t *)(dst+4 )) += delta_tab->deltas_m10[dyad2];\
*((uint32_t *)(dst+row_offset )) += delta_tab->deltas_m10[dyad1];\
*((uint32_t *)(dst+row_offset+4)) += delta_tab->deltas_m10[dyad2];\
} else { \
*((uint16_t *)(dst )) += delta_tab->deltas[dyad1];\
*((uint16_t *)(dst+2 )) += delta_tab->deltas[dyad2];\
*((uint16_t *)(dst+row_offset )) += delta_tab->deltas[dyad1];\
*((uint16_t *)(dst+row_offset+2)) += delta_tab->deltas[dyad2];\
}
/**
* Decode a vector-quantized cell.
* It consists of several routines, each of which handles one or more "modes"
* with which a cell can be encoded.
*
* @param ctx [in] pointer to the decoder context
* @param avctx [in] ptr to the AVCodecContext
* @param plane [in] pointer to the plane descriptor
* @param cell [in] pointer to the cell descriptor
* @param data_ptr [in] pointer to the compressed data
* @param last_ptr [in] pointer to the last byte to catch reads past end of buffer
* @return number of cunsumed bytes or -1 if error
*/
static int decode_cell(Indeo3DecodeContext *ctx, AVCodecContext *avctx, Plane *plane,
Cell *cell, const uint8_t *data_ptr, const uint8_t *last_ptr)
{
int x, y, mv_x, mv_y, mode, vq_index, prim_indx, second_indx;
int rle_blocks, row_offset, blk_row_offset, line, num_lines;
int is_first_row, is_top_of_cell, skip_flag, zoom_fac;
int offset, line_offset, error, swap_quads[2];
unsigned int dyad1, dyad2;
uint8_t code, *block, *ref_block = 0, *ref, *dst;
const vqEntry *delta[2], *delta_tab;
uint64_t pix64;
const uint8_t *data_start = data_ptr;
/* get coding mode and VQ table index from the VQ descriptor byte */
code = *data_ptr++;
mode = code >> 4;
vq_index = code & 0xF;
/* setup output and reference pointers */
offset = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2);
block = plane->pixels[ctx->buf_sel] + offset;
if (!cell->mv_ptr) {
/* use previous line as reference for INTRA cells */
ref_block = block - plane->pitch;
} else {
if (mode >= 10) {
/* for mode 10 and 11 INTER first copy the predicted cell into the current one */
/* so we don't need to do data copying for each RLE code later */
copy_cell(ctx, plane, cell);
} else {
/* set the pointer to the reference pixels for modes 0-4 INTER */
mv_y = cell->mv_ptr[0];
mv_x = cell->mv_ptr[1];
offset += mv_y * plane->pitch + mv_x;
ref_block = plane->pixels[ctx->buf_sel ^ 1] + offset;
}
}
/* select VQ tables as follows: */
/* modes 0 and 3 use only the primary table for all lines in a block */
/* while modes 1 and 4 switch between primary and secondary tables on alternate lines */
if (mode == 1 || mode == 4) {
code = ctx->alt_quant[vq_index];
prim_indx = (code >> 4) + ctx->cb_offset;
second_indx = (code & 0xF) + ctx->cb_offset;
} else {
vq_index += ctx->cb_offset;
prim_indx = second_indx = vq_index;
}
if (prim_indx >= 24 || second_indx >= 24) {
av_log(avctx, AV_LOG_ERROR, "Invalid VQ table indexes! Primary: %d, secondary: %d!\n",
prim_indx, second_indx);
return -1;
}
delta[0] = &vq_tab[second_indx];
delta[1] = &vq_tab[prim_indx];
swap_quads[0] = second_indx >= 16;
swap_quads[1] = prim_indx >= 16;
/* requantize the prediction if VQ index of this cell differs from VQ index */
/* of the predicted cell in order to avoid overflows. */
if (vq_index >= 8 && ref_block) {
for (x = 0; x < cell->width << 2; x++)
ref_block[x] = requant_tab[vq_index & 7][ref_block[x]];
}
row_offset = plane->pitch;
blk_row_offset = (row_offset << 3) - (cell->width << 2);
rle_blocks = 0; // reset RLE block counter
skip_flag = 0;
error = IV3_NOERR;
switch (mode) {
case 0: /*------------------ MODES 0 & 1 (4x4 block processing) --------------------*/
case 1:
case 3: /*------------------ MODES 3 & 4 (4x8 block processing) --------------------*/
case 4:
if (mode >= 3 && cell->mv_ptr) {
av_log(avctx, AV_LOG_ERROR, "Attempt to apply Mode 3/4 to an INTER cell!\n");
return -1;
}
zoom_fac = mode >= 3;
line_offset = (zoom_fac) ? row_offset : 0;
blk_row_offset = (row_offset << (2 + zoom_fac)) - (cell->width << 2);
DECODE_CELL_TEMPLATE(0, zoom_fac, SELECT_DELTA_TAB, APPLY_DELTA_4,
RLE_BLOCK_COPY, RLE_LINES_COPY);
break;
case 10: /*-------------------- MODE 10 (8x8 block processing) ---------------------*/
case 11: /*----------------- MODE 11 (4x8 INTER block processing) ------------------*/
delta_tab = delta[1];
if (mode == 10 && !cell->mv_ptr) { /* MODE 10 INTRA processing */
DECODE_CELL_TEMPLATE(1, 1, NO_ACTION, APPLY_DELTA_8,
RLE_BLOCK_COPY_8, RLE_LINES_COPY_M10);
} else { /* mode 10 and 11 INTER processing */
if (mode == 11 && !cell->mv_ptr) {
av_log(avctx, AV_LOG_ERROR, "Attempt to use Mode 11 for an INTRA cell!\n");
return -1;
}
zoom_fac = mode == 10;
DECODE_CELL_TEMPLATE(zoom_fac, 1, NO_ACTION, APPLY_DELTA_1011_INTER,
NO_ACTION, NO_ACTION);
}
break;
default:
av_log(avctx, AV_LOG_ERROR, "Unsupported coding mode: %d\n", mode);
return -1;
}//switch mode
fail:
switch (error) {
case IV3_BAD_RLE:
av_log(avctx, AV_LOG_ERROR, "Mode %d: RLE code %X is not allowed at the line %d\n",
mode, data_ptr[-1], line);
return -1;
case IV3_BAD_DATA:
av_log(avctx, AV_LOG_ERROR, "Mode %d: invalid VQ data\n", mode);
return -1;
case IV3_BAD_COUNTER:
av_log(avctx, AV_LOG_ERROR, "Mode %d: RLE-FB invalid counter: %d\n", mode, code);
return -1;
case IV3_UNSUPPORTED:
av_log(avctx, AV_LOG_ERROR, "Mode %d: unsupported RLE code: %X\n", mode, data_ptr[-1]);
return -1;
case IV3_OUT_OF_DATA:
av_log(avctx, AV_LOG_ERROR, "Mode %d: attempt to read past end of buffer\n", mode);
return -1;
}
return (data_ptr - data_start); /* report number of bytes consumed from the input buffer */
}
/**
* Binary tree codes.
*/
enum {
H_SPLIT = 0,
V_SPLIT = 1,
INTRA_NULL = 2,
INTER_DATA = 3
};
#define SPLIT_CELL(size, new_size) (new_size) = ((size) > 2) ? ((((size) + 2) >> 2) << 1) : 1
#define UPDATE_BITPOS(n) \
ctx->skip_bits += (n); \
ctx->need_resync = 1
#define RESYNC_BITSTREAM \
if (ctx->need_resync && !(get_bits_count(&ctx->gb) & 7)) { \
skip_bits_long(&ctx->gb, ctx->skip_bits); \
ctx->skip_bits = 0; \
ctx->need_resync = 0; \
}
#define CHECK_CELL \
if (curr_cell.xpos + curr_cell.width > (plane->width >> 2) || \
curr_cell.ypos + curr_cell.height > (plane->height >> 2)) { \
av_log(avctx, AV_LOG_ERROR, "Invalid cell: x=%d, y=%d, w=%d, h=%d\n", \
curr_cell.xpos, curr_cell.ypos, curr_cell.width, curr_cell.height); \
return -1; \
}
/**
* Parse plane's binary tree recursively.
*/
static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, Plane *plane,
int code, Cell *ref_cell, const int depth, const int strip_width)
{
Cell curr_cell;
int bytes_used;
if (depth <= 0) {
av_log(avctx, AV_LOG_ERROR, "Stack overflow (corrupted binary tree)!\n");
return -1; // unwind recursion
}
curr_cell = *ref_cell; // clone parent cell
if (code == H_SPLIT) {
SPLIT_CELL(ref_cell->height, curr_cell.height);
ref_cell->ypos += curr_cell.height;
ref_cell->height -= curr_cell.height;
} else if (code == V_SPLIT) {
if (curr_cell.width > strip_width) {
/* split strip */
curr_cell.width = (curr_cell.width <= (strip_width << 1) ? 1 : 2) * strip_width;
} else
SPLIT_CELL(ref_cell->width, curr_cell.width);
ref_cell->xpos += curr_cell.width;
ref_cell->width -= curr_cell.width;
}
while (1) { /* loop until return */
RESYNC_BITSTREAM;
switch (code = get_bits(&ctx->gb, 2)) {
case H_SPLIT:
case V_SPLIT:
if (parse_bintree(ctx, avctx, plane, code, &curr_cell, depth-1, strip_width))
return -1;
break;
case INTRA_NULL:
if (!curr_cell.tree) { /* MC tree INTRA code */
curr_cell.mv_ptr = 0; /* mark the current strip as INTRA */
curr_cell.tree = 1; /* enter the VQ tree */
} else { /* VQ tree NULL code */
RESYNC_BITSTREAM;
code = get_bits(&ctx->gb, 2);
if (code >= 2) {
av_log(avctx, AV_LOG_ERROR, "Invalid VQ_NULL code: %d\n", code);
return -1;
}
if (code == 1)
av_log(avctx, AV_LOG_ERROR, "SkipCell procedure not implemented yet!\n");
CHECK_CELL
copy_cell(ctx, plane, &curr_cell);
return 0;
}
break;
case INTER_DATA:
if (!curr_cell.tree) { /* MC tree INTER code */
/* get motion vector index and setup the pointer to the mv set */
if (!ctx->need_resync)
ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3];
curr_cell.mv_ptr = &ctx->mc_vectors[*(ctx->next_cell_data++) << 1];
curr_cell.tree = 1; /* enter the VQ tree */
UPDATE_BITPOS(8);
} else { /* VQ tree DATA code */
if (!ctx->need_resync)
ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3];
CHECK_CELL
bytes_used = decode_cell(ctx, avctx, plane, &curr_cell, ctx->next_cell_data, ctx->last_byte);
if (bytes_used < 0)
return -1;
UPDATE_BITPOS(bytes_used << 3);
ctx->next_cell_data += bytes_used;
return 0;
}
break;
}
}//while
return 0;
}
/**
* Decode a plane (Y, V or U)
*/
static int decode_plane(Indeo3DecodeContext *ctx, AVCodecContext *avctx, Plane *plane,
const uint8_t *data, int32_t data_size, int32_t strip_width)
{
Cell curr_cell;
int num_vectors;
/* each plane data starts with mc_vector_count field, */
/* an optional array of motion vectors followed by the vq data */
num_vectors = bytestream_get_le32(&data);
ctx->mc_vectors = num_vectors ? data : 0;
/* init the bitreader */
init_get_bits(&ctx->gb, &data[num_vectors * 2], data_size << 3);
ctx->skip_bits = 0;
ctx->need_resync = 0;
ctx->last_byte = data + data_size - 1;
/* initialize the 1st cell and set its dimensions to whole plane */
curr_cell.xpos = curr_cell.ypos = 0;
curr_cell.width = plane->width >> 2;
curr_cell.height = plane->height >> 2;
curr_cell.tree = 0; // we are in the MC tree now
curr_cell.mv_ptr = 0; // no motion vector = INTRA cell
return parse_bintree(ctx, avctx, plane, INTRA_NULL, &curr_cell, CELL_STACK_MAX, strip_width);
}
#define OS_HDR_ID MKBETAG('F', 'R', 'M', 'H')
/**
* Parse indeo3 frame headers
*/
static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
{
const uint8_t *buf_ptr = buf, *bs_hdr;
uint32_t frame_num, word2, check_sum, data_size;
uint32_t y_offset, u_offset, v_offset, starts[3], ends[3];
uint16_t height, width;
int i, j;
/* parse and check the OS header */
frame_num = bytestream_get_le32(&buf_ptr);
word2 = bytestream_get_le32(&buf_ptr);
check_sum = bytestream_get_le32(&buf_ptr);
data_size = bytestream_get_le32(&buf_ptr);
if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) {
av_log(avctx, AV_LOG_ERROR, "OS header checksum mismatch!\n");
return -1;
}
/* parse the bitstream header */
bs_hdr = buf_ptr;
if (bytestream_get_le16(&buf_ptr) != 32) {
av_log(avctx, AV_LOG_ERROR, "Unsupported decoder version!\n");
return -1;
}
ctx->frame_num = frame_num;
ctx->frame_flags = bytestream_get_le16(&buf_ptr);
ctx->data_size = (bytestream_get_le32(&buf_ptr) + 7) >> 3;
ctx->cb_offset = *buf_ptr++;
if (ctx->data_size == 16)
return 4;
if (ctx->data_size > buf_size)
ctx->data_size = buf_size;
buf_ptr += 3; // skip reserved byte and checksum
/* check frame dimensions */
height = bytestream_get_le16(&buf_ptr);
width = bytestream_get_le16(&buf_ptr);
if (av_image_check_size(width, height, 0, avctx))
return -1;
if (width != ctx->width || height != ctx->height) {
av_dlog(avctx, "Frame dimensions changed!\n");
ctx->width = width;
ctx->height = height;
free_frame_buffers(ctx);
allocate_frame_buffers(ctx, avctx);
avcodec_set_dimensions(avctx, width, height);
}
y_offset = bytestream_get_le32(&buf_ptr);
v_offset = bytestream_get_le32(&buf_ptr);
u_offset = bytestream_get_le32(&buf_ptr);
/* unfortunately there is no common order of planes in the buffer */
/* so we use that sorting algo for determining planes data sizes */
starts[0] = y_offset;
starts[1] = v_offset;
starts[2] = u_offset;
for (j = 0; j < 3; j++) {
ends[j] = ctx->data_size;
for (i = 2; i >= 0; i--)
if (starts[i] < ends[j] && starts[i] > starts[j])
ends[j] = starts[i];
}
ctx->y_data_size = ends[0] - starts[0];
ctx->v_data_size = ends[1] - starts[1];
ctx->u_data_size = ends[2] - starts[2];
if (FFMAX3(y_offset, v_offset, u_offset) >= ctx->data_size - 16 ||
FFMIN3(ctx->y_data_size, ctx->v_data_size, ctx->u_data_size) <= 0) {
av_log(avctx, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n");
return -1;
}
ctx->y_data_ptr = bs_hdr + y_offset;
ctx->v_data_ptr = bs_hdr + v_offset;
ctx->u_data_ptr = bs_hdr + u_offset;
ctx->alt_quant = buf_ptr + sizeof(uint32_t);
if (ctx->data_size == 16) {
av_log(avctx, AV_LOG_DEBUG, "Sync frame encountered!\n");
return 16;
}
if (ctx->frame_flags & BS_8BIT_PEL) {
av_log(avctx, AV_LOG_ERROR, "8bit pixel format unsupported!\n");
return -1;
}
if (ctx->frame_flags & BS_MV_X_HALF || ctx->frame_flags & BS_MV_Y_HALF) {
av_log(avctx, AV_LOG_ERROR, "Halfpel motion vectors unsupported!\n");
return -1;
}
return 0;
}
/**
* Convert and output the current plane.
* All pixel values will be upsampled by shifting right by one bit.
*
* @param plane [in] pointer to the descriptor of the plane being processed
* @param buf_sel [in] indicates which frame buffer the input data stored in
* @param dst [out] pointer to the buffer receiving converted pixels
* @param dst_pitch [in] pitch for moving to the next y line
*/
static void output_plane(const Plane *plane, int buf_sel, uint8_t *dst, int dst_pitch)
{
int x,y;
const uint32_t *src32;
const uint8_t *src = plane->pixels[buf_sel];
uint32_t pitch = plane->pitch, *dst32;
for (y = 0; y < plane->height; y++) {
src32 = (const uint32_t *)src;
dst32 = (uint32_t *)dst;
/* convert four pixels at once using softSIMD */
for (x = 0; x < plane->width >> 2; x++)
*dst32++ = (*src32++ & 0x7F7F7F7F) << 1;
for (x <<= 2; x < plane->width; x++)
dst[x] = src[x] << 1;
src += pitch;
dst += dst_pitch;
}
}
/**
* Indeo3 decoder initializations.
*/
static av_cold int decode_init(AVCodecContext *avctx)
{
Indeo3DecodeContext *ctx = avctx->priv_data;
ctx->avctx = avctx;
ctx->width = avctx->width;
ctx->height = avctx->height;
avctx->pix_fmt = PIX_FMT_YUV410P;
build_requant_tab();
dsputil_init(&ctx->dsp, avctx);
allocate_frame_buffers(ctx, avctx);
return 0;
}
/**
* Main decoder function.
*/
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
AVPacket *avpkt)
{
Indeo3DecodeContext *ctx = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
int res;
res = decode_frame_headers(ctx, avctx, buf, buf_size);
if (res < 0)
return -1;
/* skip sync(null) frames */
if (res) {
// we have processed 16 bytes but no data was decoded
*data_size = 0;
return buf_size;
}
/* skip droppable INTER frames if requested */
if (ctx->frame_flags & BS_NONREF &&
(avctx->skip_frame >= AVDISCARD_NONREF))
return 0;
/* skip INTER frames if requested */
if (!(ctx->frame_flags & BS_KEYFRAME) && avctx->skip_frame >= AVDISCARD_NONKEY)
return 0;
/* use BS_BUFFER flag for buffer switching */
ctx->buf_sel = (ctx->frame_flags >> BS_BUFFER) & 1;
/* decode luma plane */
if (decode_plane(ctx, avctx, ctx->planes, ctx->y_data_ptr, ctx->y_data_size, 40))
return -1;
/* decode chroma planes */
if (decode_plane(ctx, avctx, &ctx->planes[1], ctx->u_data_ptr, ctx->u_data_size, 10))
return -1;
if (decode_plane(ctx, avctx, &ctx->planes[2], ctx->v_data_ptr, ctx->v_data_size, 10))
return -1;
if (ctx->frame.data[0])
avctx->release_buffer(avctx, &ctx->frame);
ctx->frame.reference = 0;
if (avctx->get_buffer(avctx, &ctx->frame) < 0) {
av_log(ctx->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
output_plane(&ctx->planes[0], ctx->buf_sel, ctx->frame.data[0], ctx->frame.linesize[0]);
output_plane(&ctx->planes[1], ctx->buf_sel, ctx->frame.data[1], ctx->frame.linesize[1]);
output_plane(&ctx->planes[2], ctx->buf_sel, ctx->frame.data[2], ctx->frame.linesize[2]);
*data_size = sizeof(AVFrame);
*(AVFrame*)data = ctx->frame;
return buf_size;
}
/**
* Indeo3 free function.
*/
static av_cold int decode_close(AVCodecContext *avctx)
{
Indeo3DecodeContext *ctx = avctx->priv_data;
free_frame_buffers(avctx->priv_data);
if (ctx->frame.data[0])
avctx->release_buffer(avctx, &ctx->frame);
return 0;
}
AVCodec ff_indeo3_decoder = {
.name = "indeo3",
.type = AVMEDIA_TYPE_VIDEO,
.id = CODEC_ID_INDEO3,
.priv_data_size = sizeof(Indeo3DecodeContext),
.init = decode_init,
.close = decode_close,
.decode = decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"),
};
/*
* Indeo Video v3 compatible decoder
* Copyright (c) 2009 - 2011 Maxim Poliakovski
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_INDEO3DATA_H
#define AVCODEC_INDEO3DATA_H
#include <stdint.h>
/*
* Define compressed VQ tables.
*/
#define TAB_1_1 \
PD( 0, 0), E2( 2, 2), E4( -1, 3), E2( 4, 4), E4( 1, 5),\
E2( -4, 4), E4( -2, 6), E4( 4, 9), E2( 9, 9), E4( 1, 10),\
E4( -5, 8), E4( 9, 15), E4( -3, 12), E4( 4, 16), E2( 16, 16),\
E4( 0, 18), E2( -12, 12), E4( -9, 16), E4( 11, 27), E4( 19, 28),\
E4( -6, 22), E4( 4, 29), E2( 30, 30), E4( -2, 33), E4( -18, 23),\
E4( -15, 30), E4( 22, 46), E4( 13, 47), E4( 35, 49), E4( -11, 41),\
E4( 4, 51), E2( 54, 54), E2( -34, 34), E4( -29, 42), E4( -6, 60),\
E4( 27, 76), E4( 43, 77), E4( -24, 55), E4( 14, 79), E4( 63, 83),\
E4( -20, 74), E4( 2, 88), E2( 93, 93), E4( -52, 61), E4( 52, 120),\
E4( -45, 75), E4( 75, 125), E4( 33, 122), E4( -13, 103), E4( -40, 96),\
E4( -34, 127), E2( -89, 89), E4( -78, 105), E2( 12, 12), E2( 23, 23),\
E2( 42, 42), E2( 73, 73)
#define TAB_1_2 \
PD( 0, 0), E2( 3, 3), E4( -1, 4), E2( 7, 7), E4( 2, 8),\
E4( -2, 9), E2( -6, 6), E4( 6, 13), E2( 13, 13), E4( 1, 14),\
E4( -8, 12), E4( 14, 23), E4( -5, 18), E4( 6, 24), E2( 24, 24),\
E4( -1, 27), E2( -17, 17), E4( -13, 23), E4( 16, 40), E4( 28, 41),\
E4( -9, 33), E4( 6, 43), E2( 46, 46), E4( -4, 50), E4( -27, 34),\
E4( -22, 45), E4( 34, 69), E4( 19, 70), E4( 53, 73), E4( -17, 62),\
E4( 5, 77), E2( 82, 82), E2( -51, 51), E4( -43, 64), E4( -10, 90),\
E4( 41, 114), E4( 64, 116), E4( -37, 82), E4( 22, 119), E4( 95, 124),\
E4( -30, 111), E4( -78, 92), E4( -68, 113), E2( 18, 18), E2( 34, 34),\
E2( 63, 63), E2( 109, 109)
#define TAB_1_3 \
PD( 0, 0), E2( 4, 4), E4( -1, 5), E4( 3, 10), E2( 9, 9),\
E2( -7, 7), E4( -3, 12), E4( 8, 17), E2( 17, 17), E4( 1, 19),\
E4( -11, 16), E4( -6, 23), E4( 18, 31), E4( 8, 32), E2( 33, 33),\
E4( -1, 36), E2( -23, 23), E4( -17, 31), E4( 21, 54), E4( 37, 55),\
E4( -12, 44), E4( 8, 57), E2( 61, 61), E4( -5, 66), E4( -36, 45),\
E4( -29, 60), E4( 45, 92), E4( 25, 93), E4( 71, 97), E4( -22, 83),\
E4( 7, 102), E2( 109, 109), E2( -68, 68), E4( -57, 85), E4( -13, 120),\
E4( -49, 110), E4(-104, 123), E2( 24, 24), E2( 46, 46), E2( 84, 84)
#define TAB_1_4 \
PD( 0, 0), E2( 5, 5), E4( -2, 7), E2( 11, 11), E4( 3, 13),\
E2( -9, 9), E4( -4, 15), E4( 11, 22), E2( 21, 21), E4( 2, 24),\
E4( -14, 20), E4( 23, 38), E4( -8, 29), E4( 11, 39), E2( 41, 41),\
E4( -1, 45), E2( -29, 29), E4( -22, 39), E4( 27, 67), E4( 47, 69),\
E4( -15, 56), E4( 11, 71), E2( 76, 76), E4( -6, 83), E4( -45, 57),\
E4( -36, 75), E4( 56, 115), E4( 31, 117), E4( 88, 122), E4( -28, 104),\
E2( -85, 85), E4( -72, 106), E2( 30, 30), E2( 58, 58), E2( 105, 105)
#define TAB_1_5 \
PD( 0, 0), E2( 6, 6), E4( -2, 8), E2( 13, 13), E4( 4, 15),\
E2( -11, 11), E4( -5, 18), E4( 13, 26), E2( 26, 26), E4( 2, 29),\
E4( -16, 24), E4( 28, 46), E4( -9, 35), E4( 13, 47), E2( 49, 49),\
E4( -1, 54), E2( -35, 35), E4( -26, 47), E4( 32, 81), E4( 56, 83),\
E4( -18, 67), E4( 13, 86), E2( 91, 91), E4( -7, 99), E4( -54, 68),\
E4( -44, 90), E4( -33, 124), E2(-103, 103), E4( -86, 127), E2( 37, 37),\
E2( 69, 69)
#define TAB_1_6 \
PD( 0, 0), E2( 7, 7), E4( -3, 10), E2( 16, 16), E4( 5, 18),\
E2( -13, 13), E4( -6, 21), E4( 15, 30), E2( 30, 30), E4( 2, 34),\
E4( -19, 28), E4( 32, 54), E4( -11, 41), E4( 15, 55), E2( 57, 57),\
E4( -1, 63), E2( -40, 40), E4( -30, 55), E4( 37, 94), E4( 65, 96),\
E4( -21, 78), E4( 15, 100), E2( 106, 106), E4( -8, 116), E4( -63, 79),\
E4( -51, 105), E2(-120, 120), E2( 43, 43), E2( 80, 80)
#define TAB_1_7 \
PD( 0, 0), E2( 8, 8), E4( -3, 11), E2( 18, 18), E4( 5, 20),\
E2( -15, 15), E4( -7, 24), E4( 17, 35), E2( 34, 34), E4( 3, 38),\
E4( -22, 32), E4( 37, 61), E4( -13, 47), E4( 17, 63), E2( 65, 65),\
E4( -1, 72), E2( -46, 46), E4( -35, 63), E4( 43, 107), E4( 75, 110),\
E4( -24, 89), E4( 17, 114), E2( 121, 121), E4( -72, 91), E4( -58, 120),\
E2( 49, 49), E2( 92, 92)
#define TAB_1_8 \
PD( 0, 0), E2( 9, 9), E4( -3, 12), E2( 20, 20), E4( 6, 23),\
E2( -17, 17), E4( -7, 27), E4( 19, 39), E2( 39, 39), E4( 3, 43),\
E4( -24, 36), E4( 42, 69), E4( -14, 53), E4( 19, 71), E2( 73, 73),\
E4( -2, 80), E2( -52, 52), E4( -39, 70), E4( 48, 121), E4( 84, 124),\
E4( -27, 100), E4( -81, 102), E2( 55, 55), E2( 104, 104)
#define TAB_2_1 \
PD( 0, 0), E2( 2, 2), E4( 0, 2), E2( 4, 4), E4( 0, 4),\
E2( -4, 4), E4( -2, 6), E4( 4, 8), E2( 8, 8), E4( 0, 10),\
E4( -4, 8), E4( 8, 14), E4( -2, 12), E4( 4, 16), E2( 16, 16),\
E4( 0, 18), E2( -12, 12), E4( -8, 16), E4( 10, 26), E4( 18, 28),\
E4( -6, 22), E4( 4, 28), E2( 30, 30), E4( -2, 32), E4( -18, 22),\
E4( -14, 30), E4( 22, 46), E4( 12, 46), E4( 34, 48), E4( -10, 40),\
E4( 4, 50), E2( 54, 54), E2( -34, 34), E4( -28, 42), E4( -6, 60),\
E4( 26, 76), E4( 42, 76), E4( -24, 54), E4( 14, 78), E4( 62, 82),\
E4( -20, 74), E4( 2, 88), E2( 92, 92), E4( -52, 60), E4( 52, 118),\
E4( -44, 74), E4( 74, 118), E4( 32, 118), E4( -12, 102), E4( -40, 96),\
E4( -34, 118), E2( -88, 88), E4( -78, 104), E2( 12, 12), E2( 22, 22),\
E2( 42, 42), E2( 72, 72)
#define TAB_2_2 \
PD( 0, 0), E2( 3, 3), E4( 0, 3), E2( 6, 6), E4( 3, 9),\
E4( -3, 9), E2( -6, 6), E4( 6, 12), E2( 12, 12), E4( 0, 15),\
E4( -9, 12), E4( 15, 24), E4( -6, 18), E4( 6, 24), E2( 24, 24),\
E4( 0, 27), E2( -18, 18), E4( -12, 24), E4( 15, 39), E4( 27, 42),\
E4( -9, 33), E4( 6, 42), E2( 45, 45), E4( -3, 51), E4( -27, 33),\
E4( -21, 45), E4( 33, 69), E4( 18, 69), E4( 54, 72), E4( -18, 63),\
E4( 6, 78), E2( 81, 81), E2( -51, 51), E4( -42, 63), E4( -9, 90),\
E4( 42, 114), E4( 63, 117), E4( -36, 81), E4( 21, 120), E4( 96, 123),\
E4( -30, 111), E4( -78, 93), E4( -69, 114), E2( 18, 18), E2( 33, 33),\
E2( 63, 63), E2( 108, 108)
#define TAB_2_3 \
PD( 0, 0), E2( 4, 4), E4( 0, 4), E4( 4, 8), E2( 8, 8),\
E2( -8, 8), E4( -4, 12), E4( 8, 16), E2( 16, 16), E4( 0, 20),\
E4( -12, 16), E4( -4, 24), E4( 16, 32), E4( 8, 32), E2( 32, 32),\
E4( 0, 36), E2( -24, 24), E4( -16, 32), E4( 20, 52), E4( 36, 56),\
E4( -12, 44), E4( 8, 56), E2( 60, 60), E4( -4, 64), E4( -36, 44),\
E4( -28, 60), E4( 44, 92), E4( 24, 92), E4( 72, 96), E4( -20, 84),\
E4( 8, 100), E2( 108, 108), E2( -68, 68), E4( -56, 84), E4( -12, 120),\
E4( -48, 108), E4(-104, 124), E2( 24, 24), E2( 44, 44), E2( 84, 84)
#define TAB_2_4 \
PD( 0, 0), E2( 5, 5), E4( 0, 5), E2( 10, 10), E4( 5, 15),\
E2( -10, 10), E4( -5, 15), E4( 10, 20), E2( 20, 20), E4( 0, 25),\
E4( -15, 20), E4( 25, 40), E4( -10, 30), E4( 10, 40), E2( 40, 40),\
E4( 0, 45), E2( -30, 30), E4( -20, 40), E4( 25, 65), E4( 45, 70),\
E4( -15, 55), E4( 10, 70), E2( 75, 75), E4( -5, 85), E4( -45, 55),\
E4( -35, 75), E4( 55, 115), E4( 30, 115), E4( 90, 120), E4( -30, 105),\
E2( -85, 85), E4( -70, 105), E2( 30, 30), E2( 60, 60), E2( 105, 105)
#define TAB_2_5 \
PD( 0, 0), E2( 6, 6), E4( 0, 6), E2( 12, 12), E4( 6, 12),\
E2( -12, 12), E4( -6, 18), E4( 12, 24), E2( 24, 24), E4( 0, 30),\
E4( -18, 24), E4( 30, 48), E4( -6, 36), E4( 12, 48), E2( 48, 48),\
E4( 0, 54), E2( -36, 36), E4( -24, 48), E4( 30, 78), E4( 54, 84),\
E4( -18, 66), E4( 12, 84), E2( 90, 90), E4( -6, 96), E4( -54, 66),\
E4( -42, 90), E4( -30, 126), E2(-102, 102), E4( -84, 126), E2( 36, 36),\
E2( 66, 66)
#define TAB_2_6 \
PD( 0, 0), E2( 7, 7), E4( 0, 7), E2( 14, 14), E4( 7, 21),\
E2( -14, 14), E4( -7, 21), E4( 14, 28), E2( 28, 28), E4( 0, 35),\
E4( -21, 28), E4( 35, 56), E4( -14, 42), E4( 14, 56), E2( 56, 56),\
E4( 0, 63), E2( -42, 42), E4( -28, 56), E4( 35, 91), E4( 63, 98),\
E4( -21, 77), E4( 14, 98), E2( 105, 105), E4( -7, 119), E4( -63, 77),\
E4( -49, 105), E2(-119, 119), E2( 42, 42), E2( 77, 77)
#define TAB_2_7 \
PD( 0, 0), E2( 8, 8), E4( 0, 8), E2( 16, 16), E4( 8, 16),\
E2( -16, 16), E4( -8, 24), E4( 16, 32), E2( 32, 32), E4( 0, 40),\
E4( -24, 32), E4( 40, 64), E4( -16, 48), E4( 16, 64), E2( 64, 64),\
E4( 0, 72), E2( -48, 48), E4( -32, 64), E4( 40, 104), E4( 72, 112),\
E4( -24, 88), E4( 16, 112), E2( 120, 120), E4( -72, 88), E4( -56, 120),\
E2( 48, 48), E2( 88, 88)
#define TAB_2_8 \
PD( 0, 0), E2( 9, 9), E4( 0, 9), E2( 18, 18), E4( 9, 27),\
E2( -18, 18), E4( -9, 27), E4( 18, 36), E2( 36, 36), E4( 0, 45),\
E4( -27, 36), E4( 45, 72), E4( -18, 54), E4( 18, 72), E2( 72, 72),\
E4( 0, 81), E2( -54, 54), E4( -36, 72), E4( 45, 117), E4( 81, 126),\
E4( -27, 99), E4( -81, 99), E2( 54, 54), E2( 108, 108)
#define TAB_3_1 \
PD( 0, 0), E2( 2, 2), E4( 0, 3), E2( 6, 6), E4( 0, 7),\
E2( -5, 5), E2( 5, -5), E4( 6, 11), E4( 0, 8), E2( 11, 11),\
E4( 0, 12), E4( 12, 17), E2( 17, 17), E4( 6, 18), E4( -8, 11),\
E4( 0, 15), E4( 0, 20), E4( 18, 25), E4( 11, 25), E2( 25, 25),\
E2( -14, 14), E2( 14, -14), E4( 0, 26), E4( -11, 18), E4( -7, 22),\
E4( 26, 34), E4( 18, 34), E2( 34, 34), E4( 11, 35), E4( 0, 29),\
E4( -19, 22), E4( -15, 26), E4( 0, 37), E4( 27, 44), E4( 36, 44),\
E4( 18, 44), E4( -10, 33), E2( 45, 45)
#define TAB_3_2 \
PD( 0, 0), E4( 0, 2), E2( 2, 2), E2( 6, 6), E4( 0, 6),\
E2( -4, 4), E2( 10, -6), E2( 0, -12), PD( -6, -12), E2( 6, -12),\
PD( 6, 12), E2( -14, 0), E2( 12, 12), E2( 0, -18), E2( 14, -12),\
PD( -18, -6), E2( 18, -6), PD( 18, 6), PD( -10, -18), E2( 10, -18),\
PD( 10, 18), E2( -22, 0), E2( 0, -24), PD( -22, -12), E2( 22, -12),\
PD( 22, 12), PD( -8, -24), E2( 8, -24), PD( 8, 24), PD( -26, -6),\
E2( 26, -6), PD( 26, 6), E2( -28, 0), E2( 20, 20), E2( -14, -26),\
E2( -30, -12), E2( -10, -32), E2( -18, -32), E2( -26, -26), E2( -34, -20),\
E2( -38, -12), E2( -32, -32), PD( 32, 32), PD( -22, -40), E2( -34, -34)
#define TAB_3_3 \
PD( 0, 0), E4( 0, 2), E2( 4, 4), E2( 10, 10), E4( 0, 10),\
E2( -6, 6), E2( 14, -8), E2( -18, 0), E2( 10, -16), E2( 0, -24),\
PD( -24, -8), E2( 24, -8), PD( 24, 8), E2( 18, 18), E2( 20, -16),\
PD( -14, -26), E2( 14, -26), PD( 14, 26), E2( -30, 0), E2( 0, -34),\
PD( -34, -8), E2( 34, -8), PD( 34, 8), PD( -30, -18), E2( 30, -18),\
PD( 30, 18), PD( -10, -34), E2( 10, -34), PD( 10, 34), E2( -20, -34),\
E2( -40, 0), E2( 30, 30), E2( -40, -18), E2( 0, -44), E2( -16, -44),\
PD( -36, -36), E2( -36, -36), E2( -26, -44), E2( -46, -26), E2( -52, -18),\
PD( -20, -54), E2( -44, -44), PD( -32, -54), PD( -46, -46), E2( -46, -46)
#define TAB_3_4 \
PD( 0, 0), E4( 0, 4), E2( 4, 4), E2( 12, 12), E4( 0, 12),\
E2( -8, 8), E2( 8, -16), E2( 0, -24), PD( -24, -8), E2( 24, -8),\
PD( 24, 8), E2( 20, -16), E2( -28, 0), PD( -16, -24), E2( 16, -24),\
PD( 16, 24), E2( 0, -32), PD( -28, -16), E2( 28, -16), PD( 28, 16),\
PD( -8, -32), PD( 8, -32), PD( -32, -8), E2( 32, -8), PD( 32, 8),\
PD( -8, 32), PD( 8, 32), E2( 24, 24), E2( 24, -24), E2( -20, -32),\
E2( -40, 0), E2( -40, -16), PD( 0, -44), PD( 0, -44), E2( -44, 0),\
PD( 0, 44), PD( 0, 44), E2( -32, -32), E2( -16, -44), PD( -24, -44),\
E2( -44, -24), PD( 24, 44), E2( -48, -16), PD( -36, -36), E2( -36, -36),\
PD( 36, 36), PD( -20, -52), E2( 40, 40), PD( -32, -52)
#define TAB_3_5 \
PD( 0, 0), E2( 2, 2), E2( 6, 6), E2( 12, 12), E2( 20, 20),\
E2( 32, 32), E2( 46, 46)
/**
* Pack two delta values (a,b) into one 16bit word
* according with endianess of the host machine.
*/
#if HAVE_BIGENDIAN
#define PD(a,b) (((a) << 8) + (b))
#else
#define PD(a,b) (((b) << 8) + (a))
#endif
/**
* Expand a pair of delta values (a,b)
* into two/four delta entries.
*/
#define E2(a, b) PD(a, b), PD(-a, -b)
#define E4(a, b) PD(a, b), PD(-a, -b), PD(b, a), PD(-b, -a)
/*
* VQ tables for 4x4 block modes.
* Let the compiler decompress and build the tables for us.
*/
static const int16_t delta_tab_1_1[195] = { TAB_1_1 };
static const int16_t delta_tab_1_2[159] = { TAB_1_2 };
static const int16_t delta_tab_1_3[133] = { TAB_1_3 };
static const int16_t delta_tab_1_4[115] = { TAB_1_4 };
static const int16_t delta_tab_1_5[101] = { TAB_1_5 };
static const int16_t delta_tab_1_6[93] = { TAB_1_6 };
static const int16_t delta_tab_1_7[87] = { TAB_1_7 };
static const int16_t delta_tab_1_8[77] = { TAB_1_8 };
static const int16_t delta_tab_2_1[195] = { TAB_2_1 };
static const int16_t delta_tab_2_2[159] = { TAB_2_2 };
static const int16_t delta_tab_2_3[133] = { TAB_2_3 };
static const int16_t delta_tab_2_4[115] = { TAB_2_4 };
static const int16_t delta_tab_2_5[101] = { TAB_2_5 };
static const int16_t delta_tab_2_6[93] = { TAB_2_6 };
static const int16_t delta_tab_2_7[87] = { TAB_2_7 };
static const int16_t delta_tab_2_8[77] = { TAB_2_8 };
static const int16_t delta_tab_3_1[128] = { TAB_3_1 };
static const int16_t delta_tab_3_2[79] = { TAB_3_2 };
static const int16_t delta_tab_3_3[79] = { TAB_3_3 };
static const int16_t delta_tab_3_4[79] = { TAB_3_4 };
static const int16_t delta_tab_3_5[79] = { TAB_3_5 };
#undef PD
/**
* Pack four delta values (a,a,b,b) into one 32bit word
* according with endianess of the host machine.
*/
#if HAVE_BIGENDIAN
#define PD(a,b) (((a) << 24) + ((a) << 16) + ((b) << 8) + (b))
#else
#define PD(a,b) (((b) << 24) + ((b) << 16) + ((a) << 8) + (a))
#endif
/*
* VQ tables for 8x8 block modes.
* Those are based on the same delta tables by using
* each value twice: ABCD --> AABBCCDD.
*/
static const int32_t delta_tab_1_1_m10[195] = { TAB_1_1 };
static const int32_t delta_tab_1_2_m10[159] = { TAB_1_2 };
static const int32_t delta_tab_1_3_m10[133] = { TAB_1_3 };
static const int32_t delta_tab_1_4_m10[115] = { TAB_1_4 };
static const int32_t delta_tab_1_5_m10[101] = { TAB_1_5 };
static const int32_t delta_tab_1_6_m10[93] = { TAB_1_6 };
static const int32_t delta_tab_1_7_m10[87] = { TAB_1_7 };
static const int32_t delta_tab_1_8_m10[77] = { TAB_1_8 };
static const int32_t delta_tab_2_1_m10[195] = { TAB_2_1 };
static const int32_t delta_tab_2_2_m10[159] = { TAB_2_2 };
static const int32_t delta_tab_2_3_m10[133] = { TAB_2_3 };
static const int32_t delta_tab_2_4_m10[115] = { TAB_2_4 };
static const int32_t delta_tab_2_5_m10[101] = { TAB_2_5 };
static const int32_t delta_tab_2_6_m10[93] = { TAB_2_6 };
static const int32_t delta_tab_2_7_m10[87] = { TAB_2_7 };
static const int32_t delta_tab_2_8_m10[77] = { TAB_2_8 };
static const int32_t delta_tab_3_1_m10[128] = { TAB_3_1 };
static const int32_t delta_tab_3_2_m10[79] = { TAB_3_2 };
static const int32_t delta_tab_3_3_m10[79] = { TAB_3_3 };
static const int32_t delta_tab_3_4_m10[79] = { TAB_3_4 };
static const int32_t delta_tab_3_5_m10[79] = { TAB_3_5 };
typedef struct {
const int16_t *deltas; ///< delta tables for 4x4 block modes
const int32_t *deltas_m10; ///< delta tables for 8x8 block modes
uint8_t num_dyads; ///< number of two-pixel deltas
uint8_t quad_exp; ///< log2 of four-pixel deltas
} vqEntry;
static const vqEntry vq_tab[24] = {
/* set 1 */
{ delta_tab_1_1, delta_tab_1_1_m10, 195, 7 },
{ delta_tab_1_2, delta_tab_1_2_m10, 159, 9 },
{ delta_tab_1_3, delta_tab_1_3_m10, 133, 10 },
{ delta_tab_1_4, delta_tab_1_4_m10, 115, 11 },
{ delta_tab_1_5, delta_tab_1_5_m10, 101, 12 },
{ delta_tab_1_6, delta_tab_1_6_m10, 93, 12 },
{ delta_tab_1_7, delta_tab_1_7_m10, 87, 12 },
{ delta_tab_1_8, delta_tab_1_8_m10, 77, 13 },
/* set 2 */
{ delta_tab_2_1, delta_tab_2_1_m10, 195, 7 },
{ delta_tab_2_2, delta_tab_2_2_m10, 159, 9 },
{ delta_tab_2_3, delta_tab_2_3_m10, 133, 10 },
{ delta_tab_2_4, delta_tab_2_4_m10, 115, 11 },
{ delta_tab_2_5, delta_tab_2_5_m10, 101, 12 },
{ delta_tab_2_6, delta_tab_2_6_m10, 93, 12 },
{ delta_tab_2_7, delta_tab_2_7_m10, 87, 12 },
{ delta_tab_2_8, delta_tab_2_8_m10, 77, 13 },
/* set 3 */
{ delta_tab_3_1, delta_tab_3_1_m10, 128, 11 },
{ delta_tab_3_2, delta_tab_3_2_m10, 79, 13 },
{ delta_tab_3_3, delta_tab_3_3_m10, 79, 13 },
{ delta_tab_3_4, delta_tab_3_4_m10, 79, 13 },
{ delta_tab_3_5, delta_tab_3_5_m10, 79, 13 },
{ delta_tab_3_5, delta_tab_3_5_m10, 79, 13 },
{ delta_tab_3_5, delta_tab_3_5_m10, 79, 13 },
{ delta_tab_3_5, delta_tab_3_5_m10, 79, 13 }
};
#endif /* AVCODEC_INDEO3DATA_H */
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel