1433 lines · 47.9 KB · C
RawDownload
/* * Bink video decoder * Copyright (c) 2009 Konstantin Shishkov * Copyright (C) 2011 Peter Ross <pross@xvid.org> * * This file is part of FFmpeg. * * FFmpeg 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. * * FFmpeg 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/attributes.h"#include "libavutil/emms.h"#include "libavutil/imgutils.h"#include "libavutil/mem.h"#include "libavutil/mem_internal.h"#include "libavutil/thread.h" #define BITSTREAM_READER_LE#include "avcodec.h"#include "binkdata.h"#include "binkdsp.h"#include "blockdsp.h"#include "codec_internal.h"#include "decode.h"#include "get_bits.h"#include "hpeldsp.h" #define BINK_FLAG_ALPHA 0x00100000#define BINK_FLAG_GRAY  0x00020000 static VLC bink_trees[16]; /** * IDs for different data types used in old version of Bink video codec */enum OldSources {    BINKB_SRC_BLOCK_TYPES = 0, ///< 8x8 block types    BINKB_SRC_COLORS,          ///< pixel values used for different block types    BINKB_SRC_PATTERN,         ///< 8-bit values for 2-colour pattern fill    BINKB_SRC_X_OFF,           ///< X components of motion value    BINKB_SRC_Y_OFF,           ///< Y components of motion value    BINKB_SRC_INTRA_DC,        ///< DC values for intrablocks with DCT    BINKB_SRC_INTER_DC,        ///< DC values for interblocks with DCT    BINKB_SRC_INTRA_Q,         ///< quantizer values for intrablocks with DCT    BINKB_SRC_INTER_Q,         ///< quantizer values for interblocks with DCT    BINKB_SRC_INTER_COEFS,     ///< number of coefficients for residue blocks     BINKB_NB_SRC}; static const uint8_t binkb_bundle_sizes[BINKB_NB_SRC] = {    4, 8, 8, 5, 5, 11, 11, 4, 4, 7}; static const uint8_t binkb_bundle_signed[BINKB_NB_SRC] = {    0, 0, 0, 1, 1, 0, 1, 0, 0, 0}; static int32_t binkb_intra_quant[16][64];static int32_t binkb_inter_quant[16][64]; /** * IDs for different data types used in Bink video codec */enum Sources {    BINK_SRC_BLOCK_TYPES = 0, ///< 8x8 block types    BINK_SRC_SUB_BLOCK_TYPES, ///< 16x16 block types (a subset of 8x8 block types)    BINK_SRC_COLORS,          ///< pixel values used for different block types    BINK_SRC_PATTERN,         ///< 8-bit values for 2-colour pattern fill    BINK_SRC_X_OFF,           ///< X components of motion value    BINK_SRC_Y_OFF,           ///< Y components of motion value    BINK_SRC_INTRA_DC,        ///< DC values for intrablocks with DCT    BINK_SRC_INTER_DC,        ///< DC values for interblocks with DCT    BINK_SRC_RUN,             ///< run lengths for special fill block     BINK_NB_SRC}; /** * data needed to decode 4-bit Huffman-coded value */typedef struct Tree {    int     vlc_num;  ///< tree number (in bink_trees[])    uint8_t syms[16]; ///< leaf value to symbol mapping} Tree; #define GET_HUFF(gb, tree)  (tree).syms[get_vlc2(gb, bink_trees[(tree).vlc_num].table,\                                                 bink_trees[(tree).vlc_num].bits, 1)] /** * data structure used for decoding single Bink data type */typedef struct Bundle {    int     len;       ///< length of number of entries to decode (in bits)    Tree    tree;      ///< Huffman tree-related data    uint8_t *data;     ///< buffer for decoded symbols    uint8_t *data_end; ///< buffer end    uint8_t *cur_dec;  ///< pointer to the not yet decoded part of the buffer    uint8_t *cur_ptr;  ///< pointer to the data that is not read from buffer yet} Bundle; /* * Decoder context */typedef struct BinkContext {    AVCodecContext *avctx;    BlockDSPContext bdsp;    op_pixels_func put_pixels_tab;    BinkDSPContext binkdsp;    AVFrame        *last;    int            version;              ///< internal Bink file version    int            has_alpha;    int            swap_planes;    unsigned       frame_num;     Bundle         bundle[BINKB_NB_SRC]; ///< bundles for decoding all data types    Tree           col_high[16];         ///< trees for decoding high nibble in "colours" data type    int            col_lastval;          ///< value of last decoded high nibble in "colours" data type} BinkContext; /** * Bink video block types */enum BlockTypes {    SKIP_BLOCK = 0, ///< skipped block    SCALED_BLOCK,   ///< block has size 16x16    MOTION_BLOCK,   ///< block is copied from previous frame with some offset    RUN_BLOCK,      ///< block is composed from runs of colours with custom scan order    RESIDUE_BLOCK,  ///< motion block with some difference added    INTRA_BLOCK,    ///< intra DCT block    FILL_BLOCK,     ///< block is filled with single colour    INTER_BLOCK,    ///< motion block with DCT applied to the difference    PATTERN_BLOCK,  ///< block is filled with two colours following custom pattern    RAW_BLOCK,      ///< uncoded 8x8 block}; /** * Initialize length in all bundles. * * @param c     decoder context * @param width plane width * @param bw    plane width in 8x8 blocks */static void init_lengths(BinkContext *c, int width, int bw){    width = FFALIGN(width, 8);     c->bundle[BINK_SRC_BLOCK_TYPES].len = av_log2((width >> 3) + 511) + 1;     c->bundle[BINK_SRC_SUB_BLOCK_TYPES].len = av_log2((width >> 4) + 511) + 1;     c->bundle[BINK_SRC_COLORS].len = av_log2(bw*64 + 511) + 1;     c->bundle[BINK_SRC_INTRA_DC].len =    c->bundle[BINK_SRC_INTER_DC].len =    c->bundle[BINK_SRC_X_OFF].len =    c->bundle[BINK_SRC_Y_OFF].len = av_log2((width >> 3) + 511) + 1;     c->bundle[BINK_SRC_PATTERN].len = av_log2((bw << 3) + 511) + 1;     c->bundle[BINK_SRC_RUN].len = av_log2(bw*48 + 511) + 1;} /** * Allocate memory for bundles. * * @param c decoder context */static av_cold int init_bundles(BinkContext *c){    int bw, bh, blocks;    uint8_t *tmp;    int i;     bw = (c->avctx->width  + 7) >> 3;    bh = (c->avctx->height + 7) >> 3;    blocks = bw * bh;     tmp = av_calloc(blocks, 64 * BINKB_NB_SRC);    if (!tmp)        return AVERROR(ENOMEM);    for (i = 0; i < BINKB_NB_SRC; i++) {        c->bundle[i].data     = tmp;        tmp                  += blocks * 64;        c->bundle[i].data_end = tmp;    }     return 0;} /** * Free memory used by bundles. * * @param c decoder context */static av_cold void free_bundles(BinkContext *c){    av_freep(&c->bundle[0].data);} /** * Merge two consequent lists of equal size depending on bits read. * * @param gb   context for reading bits * @param dst  buffer where merged list will be written to * @param src  pointer to the head of the first list (the second lists starts at src+size) * @param size input lists size */static void merge(GetBitContext *gb, uint8_t *dst, uint8_t *src, int size){    uint8_t *src2 = src + size;    int size2 = size;     do {        if (!get_bits1(gb)) {            *dst++ = *src++;            size--;        } else {            *dst++ = *src2++;            size2--;        }    } while (size && size2);     while (size--)        *dst++ = *src++;    while (size2--)        *dst++ = *src2++;} /** * Read information about Huffman tree used to decode data. * * @param gb   context for reading bits * @param tree pointer for storing tree data */static int read_tree(GetBitContext *gb, Tree *tree){    uint8_t tmp1[16] = { 0 }, tmp2[16], *in = tmp1, *out = tmp2;    int i, t, len;     if (get_bits_left(gb) < 4)        return AVERROR_INVALIDDATA;     tree->vlc_num = get_bits(gb, 4);    if (!tree->vlc_num) {        for (i = 0; i < 16; i++)            tree->syms[i] = i;        return 0;    }    if (get_bits1(gb)) {        len = get_bits(gb, 3);        for (i = 0; i <= len; i++) {            tree->syms[i] = get_bits(gb, 4);            tmp1[tree->syms[i]] = 1;        }        for (i = 0; i < 16 && len < 16 - 1; i++)            if (!tmp1[i])                tree->syms[++len] = i;    } else {        len = get_bits(gb, 2);        for (i = 0; i < 16; i++)            in[i] = i;        for (i = 0; i <= len; i++) {            int size = 1 << i;            for (t = 0; t < 16; t += size << 1)                merge(gb, out + t, in + t, size);            FFSWAP(uint8_t*, in, out);        }        memcpy(tree->syms, in, 16);    }    return 0;} /** * Prepare bundle for decoding data. * * @param gb          context for reading bits * @param c           decoder context * @param bundle_num  number of the bundle to initialize */static int read_bundle(GetBitContext *gb, BinkContext *c, int bundle_num){    int i;     if (bundle_num == BINK_SRC_COLORS) {        for (i = 0; i < 16; i++) {            int ret = read_tree(gb, &c->col_high[i]);            if (ret < 0)                return ret;        }        c->col_lastval = 0;    }    if (bundle_num != BINK_SRC_INTRA_DC && bundle_num != BINK_SRC_INTER_DC) {        int ret = read_tree(gb, &c->bundle[bundle_num].tree);        if (ret < 0)            return ret;    }    c->bundle[bundle_num].cur_dec =    c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data;     return 0;} /** * common check before starting decoding bundle data * * @param gb context for reading bits * @param b  bundle * @param t  variable where number of elements to decode will be stored */#define CHECK_READ_VAL(gb, b, t) \    if (!b->cur_dec || (b->cur_dec > b->cur_ptr)) \        return 0; \    t = get_bits(gb, b->len); \    if (!t) { \        b->cur_dec = NULL; \        return 0; \    } \ static int read_runs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b){    int t, v;    const uint8_t *dec_end;     CHECK_READ_VAL(gb, b, t);    dec_end = b->cur_dec + t;    if (dec_end > b->data_end) {        av_log(avctx, AV_LOG_ERROR, "Run value went out of bounds\n");        return AVERROR_INVALIDDATA;    }    if (get_bits_left(gb) < 1)        return AVERROR_INVALIDDATA;    if (get_bits1(gb)) {        v = get_bits(gb, 4);        memset(b->cur_dec, v, t);        b->cur_dec += t;    } else {        while (b->cur_dec < dec_end)            *b->cur_dec++ = GET_HUFF(gb, b->tree);    }    return 0;} static int read_motion_values(AVCodecContext *avctx, GetBitContext *gb, Bundle *b){    int t, sign, v;    const uint8_t *dec_end;     CHECK_READ_VAL(gb, b, t);    dec_end = b->cur_dec + t;    if (dec_end > b->data_end) {        av_log(avctx, AV_LOG_ERROR, "Too many motion values\n");        return AVERROR_INVALIDDATA;    }    if (get_bits_left(gb) < 1)        return AVERROR_INVALIDDATA;    if (get_bits1(gb)) {        v = get_bits(gb, 4);        if (v) {            sign = -get_bits1(gb);            v = (v ^ sign) - sign;        }        memset(b->cur_dec, v, t);        b->cur_dec += t;    } else {        while (b->cur_dec < dec_end) {            v = GET_HUFF(gb, b->tree);            if (v) {                sign = -get_bits1(gb);                v = (v ^ sign) - sign;            }            *b->cur_dec++ = v;        }    }    return 0;} static const uint8_t bink_rlelens[4] = { 4, 8, 12, 32 }; static int read_block_types(AVCodecContext *avctx, GetBitContext *gb, Bundle *b){    BinkContext * const c = avctx->priv_data;    int t, v;    int last = 0;    const uint8_t *dec_end;     CHECK_READ_VAL(gb, b, t);    if (c->version == 'k') {        t ^= 0xBBu;        if (t == 0) {            b->cur_dec = NULL;            return 0;        }    }    dec_end = b->cur_dec + t;    if (dec_end > b->data_end) {        av_log(avctx, AV_LOG_ERROR, "Too many block type values\n");        return AVERROR_INVALIDDATA;    }    if (get_bits_left(gb) < 1)        return AVERROR_INVALIDDATA;    if (get_bits1(gb)) {        v = get_bits(gb, 4);        memset(b->cur_dec, v, t);        b->cur_dec += t;    } else {        while (b->cur_dec < dec_end) {            v = GET_HUFF(gb, b->tree);            if (v < 12) {                last = v;                *b->cur_dec++ = v;            } else {                int run = bink_rlelens[v - 12];                 if (dec_end - b->cur_dec < run)                    return AVERROR_INVALIDDATA;                memset(b->cur_dec, last, run);                b->cur_dec += run;            }        }    }    return 0;} static int read_patterns(AVCodecContext *avctx, GetBitContext *gb, Bundle *b){    int t, v;    const uint8_t *dec_end;     CHECK_READ_VAL(gb, b, t);    dec_end = b->cur_dec + t;    if (dec_end > b->data_end) {        av_log(avctx, AV_LOG_ERROR, "Too many pattern values\n");        return AVERROR_INVALIDDATA;    }    while (b->cur_dec < dec_end) {        if (get_bits_left(gb) < 2)            return AVERROR_INVALIDDATA;        v  = GET_HUFF(gb, b->tree);        v |= GET_HUFF(gb, b->tree) << 4;        *b->cur_dec++ = v;    }     return 0;} static int read_colors(GetBitContext *gb, Bundle *b, BinkContext *c){    int t, sign, v;    const uint8_t *dec_end;     CHECK_READ_VAL(gb, b, t);    dec_end = b->cur_dec + t;    if (dec_end > b->data_end) {        av_log(c->avctx, AV_LOG_ERROR, "Too many color values\n");        return AVERROR_INVALIDDATA;    }    if (get_bits_left(gb) < 1)        return AVERROR_INVALIDDATA;    if (get_bits1(gb)) {        c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]);        v = GET_HUFF(gb, b->tree);        v = (c->col_lastval << 4) | v;        if (c->version < 'i') {            sign = ((int8_t) v) >> 7;            v = ((v & 0x7F) ^ sign) - sign;            v += 0x80;        }        memset(b->cur_dec, v, t);        b->cur_dec += t;    } else {        while (b->cur_dec < dec_end) {            if (get_bits_left(gb) < 2)                return AVERROR_INVALIDDATA;            c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]);            v = GET_HUFF(gb, b->tree);            v = (c->col_lastval << 4) | v;            if (c->version < 'i') {                sign = ((int8_t) v) >> 7;                v = ((v & 0x7F) ^ sign) - sign;                v += 0x80;            }            *b->cur_dec++ = v;        }    }    return 0;} 

Lines 1–500 of 1433.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t