[FFmpeg-devel] [PATCH 2/2] avcodec: add bink2 video decoder

James Almer jamrial at gmail.com
Sun Apr 7 04:43:04 EEST 2019


On 3/27/2019 5:21 PM, Paul B Mahol wrote:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> Missing deblocking.
> ---
>  configure               |    1 +
>  libavcodec/Makefile     |    1 +
>  libavcodec/allcodecs.c  |    1 +
>  libavcodec/avcodec.h    |    1 +
>  libavcodec/bink2.c      |  787 +++++++++++++++++++++++
>  libavcodec/bink2f.c     | 1139 +++++++++++++++++++++++++++++++++
>  libavcodec/bink2g.c     | 1342 +++++++++++++++++++++++++++++++++++++++
>  libavcodec/codec_desc.c |    7 +
>  libavformat/bink.c      |    3 +-
>  9 files changed, 3280 insertions(+), 2 deletions(-)
>  create mode 100644 libavcodec/bink2.c
>  create mode 100644 libavcodec/bink2f.c
>  create mode 100644 libavcodec/bink2g.c
> 
> diff --git a/configure b/configure
> index 331393f8d5..2fdb7e589c 100755
> --- a/configure
> +++ b/configure
> @@ -2643,6 +2643,7 @@ atrac3p_decoder_select="mdct sinewin"
>  atrac9_decoder_select="mdct"
>  avrn_decoder_select="exif jpegtables"
>  bink_decoder_select="blockdsp hpeldsp"
> +bink2_decoder_select="blockdsp"
>  binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs"
>  binkaudio_rdft_decoder_select="mdct rdft sinewin wma_freqs"
>  cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp"
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 15c43a8a6a..d02240febc 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -228,6 +228,7 @@ OBJS-$(CONFIG_AYUV_ENCODER)            += v408enc.o
>  OBJS-$(CONFIG_BETHSOFTVID_DECODER)     += bethsoftvideo.o
>  OBJS-$(CONFIG_BFI_DECODER)             += bfi.o
>  OBJS-$(CONFIG_BINK_DECODER)            += bink.o binkdsp.o
> +OBJS-$(CONFIG_BINK2_DECODER)           += bink2.o
>  OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER)   += binkaudio.o
>  OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER)  += binkaudio.o
>  OBJS-$(CONFIG_BINTEXT_DECODER)         += bintext.o cga_data.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index b26aeca239..3a9ddb7b37 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -59,6 +59,7 @@ extern AVCodec ff_ayuv_decoder;
>  extern AVCodec ff_bethsoftvid_decoder;
>  extern AVCodec ff_bfi_decoder;
>  extern AVCodec ff_bink_decoder;
> +extern AVCodec ff_bink2_decoder;
>  extern AVCodec ff_bitpacked_decoder;
>  extern AVCodec ff_bmp_encoder;
>  extern AVCodec ff_bmp_decoder;
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 0ce22ec4fa..6b881ac351 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -454,6 +454,7 @@ enum AVCodecID {
>      AV_CODEC_ID_RASC,
>      AV_CODEC_ID_HYMT,
>      AV_CODEC_ID_ARBC,
> +    AV_CODEC_ID_BINKVIDEO2,
>  
>      /* various PCM "codecs" */
>      AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
> diff --git a/libavcodec/bink2.c b/libavcodec/bink2.c
> new file mode 100644
> index 0000000000..5513710bae
> --- /dev/null
> +++ b/libavcodec/bink2.c
> @@ -0,0 +1,787 @@
> +/*
> + * Bink video 2 decoder
> + * Copyright (c) 2014 Konstantin Shishkov
> + * Copyright (c) 2019 Paul B Mahol
> + *
> + * 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
> + */
> +
> +#define CACHED_BITSTREAM_READER 1
> +#define DEBUG 1
> +#define ASSERT_LEVEL 3
> +#include "libavutil/avassert.h"
> +#include "libavutil/attributes.h"
> +#include "libavutil/imgutils.h"
> +#include "libavutil/internal.h"
> +#include "avcodec.h"
> +#include "blockdsp.h"
> +#include "copy_block.h"
> +#include "idctdsp.h"

Unused?

> +#include "internal.h"
> +#include "mathops.h"
> +
> +#define BITSTREAM_READER_LE
> +#include "get_bits.h"
> +#include "unary.h"
> +
> +#define BINK_FLAG_ALPHA 0x00100000
> +#define DC_MPRED(A, B, C) FFMIN(FFMAX((C) + (B) - (A), FFMIN3(A, B, C)), FFMAX3(A, B, C))
> +#define DC_MPRED2(A, B) FFMIN(FFMAX((A), (B)), FFMAX(FFMIN((A), (B)), 2 * (A) - (B)))
> +
> +static VLC bink2f_quant_vlc;
> +static VLC bink2f_ac_val0_vlc;
> +static VLC bink2f_ac_val1_vlc;
> +static VLC bink2f_ac_skip0_vlc;
> +static VLC bink2f_ac_skip1_vlc;
> +static VLC bink2g_ac_skip0_vlc;
> +static VLC bink2g_ac_skip1_vlc;
> +static VLC bink2g_mv_vlc;
> +
> +static const uint8_t kb2h_num_slices[] = {
> +    2, 3, 4, 8,
> +};
> +
> +static const uint8_t luma_repos[] = {
> +    0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15,
> +};
> +
> +static const uint16_t bink2g_luma_intra_qmat[4][64] = {
> +    {
> +     1024,   1432,   1506,   1181,
> +     1843,   2025,   5271,   8592,
> +     1313,   1669,   1630,   1672,
> +     2625,   3442,   8023,  12794,
> +     1076,   1755,   1808,   1950,
> +     3980,   4875,   8813,  11909,
> +     1350,   1868,   2127,   2016,
> +     4725,   4450,   7712,   9637,
> +     2458,   3103,   4303,   4303,
> +     6963,   6835,  11079,  13365,
> +     3375,   5704,   5052,   6049,
> +     9198,   7232,  10725,   9834,
> +     5486,   7521,   7797,   7091,
> +    11079,  10016,  13559,  12912,
> +     7279,   7649,   7020,   6097,
> +     9189,   9047,  12661,  13768,
> +    },
> +    {
> +     1218,   1703,   1791,   1405,
> +     2192,   2408,   6268,  10218,
> +     1561,   1985,   1938,   1988,
> +     3122,   4093,   9541,  15215,
> +     1279,   2087,   2150,   2319,
> +     4733,   5798,  10481,  14162,
> +     1606,   2222,   2530,   2398,
> +     5619,   5292,   9171,  11460,
> +     2923,   3690,   5117,   5118,
> +     8281,   8128,  13176,  15894,
> +     4014,   6783,   6008,   7194,
> +    10938,   8600,  12755,  11694,
> +     6524,   8944,   9272,   8433,
> +    13176,  11911,  16125,  15354,
> +     8657,   9096,   8348,   7250,
> +    10927,  10759,  15056,  16373,
> +    },
> +    {
> +     1448,   2025,   2130,   1671,
> +     2607,   2864,   7454,  12151,
> +     1856,   2360,   2305,   2364,
> +     3713,   4867,  11346,  18094,
> +     1521,   2482,   2557,   2758,
> +     5628,   6894,  12464,  16841,
> +     1909,   2642,   3008,   2852,
> +     6683,   6293,  10906,  13629,
> +     3476,   4388,   6085,   6086,
> +     9847,   9666,  15668,  18901,
> +     4773,   8066,   7145,   8555,
> +    13007,  10227,  15168,  13907,
> +     7758,  10637,  11026,  10028,
> +    15668,  14165,  19175,  18259,
> +    10294,  10817,   9927,   8622,
> +    12995,  12794,  17905,  19470,
> +    },
> +    {
> +     1722,   2408,   2533,   1987,
> +     3100,   3406,   8864,  14450,
> +     2208,   2807,   2741,   2811,
> +     4415,   5788,  13493,  21517,
> +     1809,   2951,   3041,   3280,
> +     6693,   8199,  14822,  20028,
> +     2271,   3142,   3578,   3391,
> +     7947,   7484,  12969,  16207,
> +     4133,   5218,   7236,   7238,
> +    11711,  11495,  18633,  22478,
> +     5677,   9592,   8497,  10174,
> +    15469,  12162,  18038,  16538,
> +     9226,  12649,  13112,  11926,
> +    18633,  16845,  22804,  21715,
> +    12242,  12864,  11806,  10254,
> +    15454,  15215,  21293,  23155,
> +    },
> +};
> +
> +static const uint16_t bink2g_chroma_intra_qmat[4][64] = {
> +    {
> +     1024,   1193,   1434,   2203,
> +     5632,   4641,   5916,   6563,
> +     1193,   1622,   1811,   3606,
> +     6563,   5408,   6894,   7649,
> +     1434,   1811,   3515,   4875,
> +     5916,   4875,   6215,   6894,
> +     2203,   3606,   4875,   3824,
> +     4641,   3824,   4875,   5408,
> +     5632,   6563,   5916,   4641,
> +     5632,   4641,   5916,   6563,
> +     4641,   5408,   4875,   3824,
> +     4641,   3824,   4875,   5408,
> +     5916,   6894,   6215,   4875,
> +     5916,   4875,   6215,   6894,
> +     6563,   7649,   6894,   5408,
> +     6563,   5408,   6894,   7649,
> +    },
> +    {
> +     1218,   1419,   1706,   2620,
> +     6698,   5519,   7035,   7805,
> +     1419,   1929,   2153,   4288,
> +     7805,   6432,   8199,   9096,
> +     1706,   2153,   4180,   5798,
> +     7035,   5798,   7390,   8199,
> +     2620,   4288,   5798,   4548,
> +     5519,   4548,   5798,   6432,
> +     6698,   7805,   7035,   5519,
> +     6698,   5519,   7035,   7805,
> +     5519,   6432,   5798,   4548,
> +     5519,   4548,   5798,   6432,
> +     7035,   8199,   7390,   5798,
> +     7035,   5798,   7390,   8199,
> +     7805,   9096,   8199,   6432,
> +     7805,   6432,   8199,   9096,
> +    },
> +    {
> +     1448,   1688,   2028,   3116,
> +     7965,   6563,   8367,   9282,
> +     1688,   2294,   2561,   5099,
> +     9282,   7649,   9750,  10817,
> +     2028,   2561,   4971,   6894,
> +     8367,   6894,   8789,   9750,
> +     3116,   5099,   6894,   5408,
> +     6563,   5408,   6894,   7649,
> +     7965,   9282,   8367,   6563,
> +     7965,   6563,   8367,   9282,
> +     6563,   7649,   6894,   5408,
> +     6563,   5408,   6894,   7649,
> +     8367,   9750,   8789,   6894,
> +     8367,   6894,   8789,   9750,
> +     9282,  10817,   9750,   7649,
> +     9282,   7649,   9750,  10817,
> +    },
> +    {
> +     1722,   2007,   2412,   3706,
> +     9472,   7805,   9950,  11038,
> +     2007,   2729,   3045,   6064,
> +    11038,   9096,  11595,  12864,
> +     2412,   3045,   5912,   8199,
> +     9950,   8199,  10452,  11595,
> +     3706,   6064,   8199,   6432,
> +     7805,   6432,   8199,   9096,
> +     9472,  11038,   9950,   7805,
> +     9472,   7805,   9950,  11038,
> +     7805,   9096,   8199,   6432,
> +     7805,   6432,   8199,   9096,
> +     9950,  11595,  10452,   8199,
> +     9950,   8199,  10452,  11595,
> +    11038,  12864,  11595,   9096,
> +    11038,   9096,  11595,  12864,
> +    },
> +};
> +
> +
> +static const uint16_t bink2g_inter_qmat[4][64] = {
> +    {
> +     1024,   1193,   1076,    844,
> +     1052,    914,   1225,   1492,
> +     1193,   1391,   1254,    983,
> +     1227,   1065,   1463,   1816,
> +     1076,   1254,   1161,    936,
> +     1195,   1034,   1444,   1741,
> +      844,    983,    936,    811,
> +     1055,    927,   1305,   1584,
> +     1052,   1227,   1195,   1055,
> +     1451,   1336,   1912,   2354,
> +      914,   1065,   1034,    927,
> +     1336,   1313,   1945,   2486,
> +     1225,   1463,   1444,   1305,
> +     1912,   1945,   3044,   4039,
> +     1492,   1816,   1741,   1584,
> +     2354,   2486,   4039,   5679,
> +    },
> +    {
> +     1218,   1419,   1279,   1003,
> +     1252,   1087,   1457,   1774,
> +     1419,   1654,   1491,   1169,
> +     1459,   1267,   1739,   2159,
> +     1279,   1491,   1381,   1113,
> +     1421,   1230,   1717,   2070,
> +     1003,   1169,   1113,    965,
> +     1254,   1103,   1552,   1884,
> +     1252,   1459,   1421,   1254,
> +     1725,   1589,   2274,   2799,
> +     1087,   1267,   1230,   1103,
> +     1589,   1562,   2313,   2956,
> +     1457,   1739,   1717,   1552,
> +     2274,   2313,   3620,   4803,
> +     1774,   2159,   2070,   1884,
> +     2799,   2956,   4803,   6753,
> +    },
> +    {
> +     1448,   1688,   1521,   1193,
> +     1488,   1293,   1732,   2110,
> +     1688,   1967,   1773,   1391,
> +     1735,   1507,   2068,   2568,
> +     1521,   1773,   1642,   1323,
> +     1690,   1462,   2042,   2462,
> +     1193,   1391,   1323,   1147,
> +     1492,   1311,   1845,   2241,
> +     1488,   1735,   1690,   1492,
> +     2052,   1889,   2704,   3328,
> +     1293,   1507,   1462,   1311,
> +     1889,   1857,   2751,   3515,
> +     1732,   2068,   2042,   1845,
> +     2704,   2751,   4306,   5712,
> +     2110,   2568,   2462,   2241,
> +     3328,   3515,   5712,   8031,
> +    },
> +    {
> +     1722,   2007,   1809,   1419,
> +     1770,   1537,   2060,   2509,
> +     2007,   2339,   2108,   1654,
> +     2063,   1792,   2460,   3054,
> +     1809,   2108,   1953,   1574,
> +     2010,   1739,   2428,   2928,
> +     1419,   1654,   1574,   1364,
> +     1774,   1559,   2195,   2664,
> +     1770,   2063,   2010,   1774,
> +     2440,   2247,   3216,   3958,
> +     1537,   1792,   1739,   1559,
> +     2247,   2209,   3271,   4181,
> +     2060,   2460,   2428,   2195,
> +     3216,   3271,   5120,   6793,
> +     2509,   3054,   2928,   2664,
> +     3958,   4181,   6793,   9550,
> +    },
> +};
> +
> +static uint8_t bink2g_chroma_cbp_pat[16] = {
> +    0x00, 0x00, 0x00, 0x0F,
> +    0x00, 0x0F, 0x0F, 0x0F,
> +    0x00, 0x0F, 0x0F, 0x0F,
> +    0x0F, 0x0F, 0x0F, 0x0F,
> +};
> +
> +static const int32_t bink2g_dc_pat[] = {
> +    1024, 1218, 1448, 1722, 2048,
> +    2435, 2896, 3444, 4096, 4871,
> +    5793, 6889, 8192, 9742, 11585, 13777, 16384,
> +    19484, 23170,  27555, 32768, 38968, 46341,
> +    55109, 65536, 77936, 92682, 110218, 131072,
> +    155872, 185364, 220436, 262144, 311744,
> +    370728, 440872, 524288,
> +};
> +
> +static const uint8_t dq_patterns[8] = { 8, 0, 1, 0, 2, 0, 1, 0 };
> +
> +static const uint8_t bink2f_quant_codes[16] = {
> +    0x01, 0x02, 0x04, 0x08, 0x10, 0x30, 0x50, 0x70,
> +    0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0,
> +};
> +
> +static const uint8_t bink2f_quant_bits[16] = {
> +    1, 2, 3, 4, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
> +};
> +
> +static const uint16_t bink2f_ac_val_codes[2][13] = {
> +    {
> +        0x04, 0x01, 0x02, 0x00, 0x08, 0x18, 0xF8, 0x178, 0x138,
> +        0x38, 0x1B8, 0x78, 0xB8
> +    },
> +    {
> +        0x0A, 0x01, 0x04, 0x08, 0x06, 0x00, 0x02, 0x1A, 0x2A,
> +        0x16A, 0x1EA, 0x6A, 0xEA
> +    },
> +};
> +
> +static const uint8_t bink2f_ac_val_bits[2][13] = {
> +    { 3, 1, 2, 4, 5, 6, 8, 9, 9, 9, 9, 9, 9 },
> +    { 6, 1, 3, 4, 3, 4, 4, 5, 7, 9, 9, 9, 9 },
> +};
> +
> +#define NUM_AC_SKIPS 14
> +static const uint16_t bink2f_ac_skip_codes[2][NUM_AC_SKIPS] = {
> +    {
> +        0x00, 0x01, 0x0D, 0x15, 0x45, 0x85, 0xA5, 0x165,
> +        0x65, 0x1E5, 0xE5, 0x25, 0x03, 0x05
> +    },
> +    {
> +        0x00, 0x01, 0x03, 0x07, 0x1F, 0x1B, 0x0F, 0x2F,
> +        0x5B, 0xDB, 0x1DB, 0x3B, 0x05, 0x0B
> +    }
> +};
> +
> +static const uint8_t bink2f_ac_skip_bits[2][NUM_AC_SKIPS] = {
> +    { 1, 3, 4, 5, 7, 8, 8, 9, 9, 9, 9, 8, 2, 8 },
> +    { 1, 3, 4, 4, 5, 7, 6, 6, 8, 9, 9, 6, 3, 5 }
> +};
> +
> +static const uint8_t bink2f_skips[] = {
> +    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 62, 0, 0, 0,
> +};
> +
> +static const uint8_t bink2g_skips[] = {
> +    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 64, 0, 0, 0,
> +};
> +
> +static const uint8_t bink2f_next_skips[] = {
> +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
> +};
> +
> +static const uint8_t bink2_next_skips[] = {
> +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
> +};
> +
> +static const uint16_t bink2g_ac_skip_codes[2][NUM_AC_SKIPS] = {
> +    {
> +        0x01, 0x00, 0x004, 0x02C, 0x06C, 0x0C, 0x4C,
> +        0xAC, 0xEC, 0x12C, 0x16C, 0x1AC, 0x02, 0x1C,
> +    },
> +    {
> +        0x01, 0x04, 0x00, 0x08, 0x02, 0x32, 0x0A,
> +        0x12, 0x3A, 0x7A, 0xFA, 0x72, 0x06, 0x1A,
> +    },
> +};
> +
> +static const uint8_t bink2g_ac_skip_bits[2][NUM_AC_SKIPS] = {
> +    { 1, 3, 4, 9, 9, 7, 7, 9, 8, 9, 9, 9, 2, 5 },
> +    { 1, 3, 4, 4, 5, 7, 5, 6, 7, 8, 8, 7, 3, 6 },
> +};
> +
> +static const uint8_t bink2g_mv_codes[] = {
> +    0x01, 0x06, 0x0C, 0x1C, 0x18, 0x38, 0x58, 0x78,
> +    0x68, 0x48, 0x28, 0x08, 0x14, 0x04, 0x02, 0x00,
> +};
> +
> +static const uint8_t bink2g_mv_bits[] = {
> +    1, 3, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 3, 4,
> +};
> +
> +static const float bink2f_dc_quant[16] = {
> +    4, 4, 4, 4, 4, 6, 7, 8, 10, 12, 16, 24, 32, 48, 64, 128
> +};
> +
> +static const float bink2f_ac_quant[16] = {
> +    1.0, 2.0, 2.5, 3.0, 3.5, 4.0, 6.0, 7.0, 8.0, 12.0, 16.0, 24.0, 32.0, 48.0, 64.0, 128.0
> +};
> +
> +static const float bink2f_luma_intra_qmat[64] = {
> +    0.125,    0.190718, 0.16332,  0.235175, 0.3,      0.392847, 0.345013, 0.210373,
> +    0.208056, 0.288582, 0.317145, 0.387359, 0.450788, 0.790098, 0.562995, 0.263095,
> +    0.228649, 0.294491, 0.341421, 0.460907, 0.653281, 0.731424, 0.60988,  0.252336,
> +    0.205778, 0.346585, 0.422498, 0.501223, 0.749621, 1.004719, 0.636379, 0.251428,
> +    0.225,    0.381436, 0.604285, 0.823113, 0.85,     1.070509, 0.69679,  0.265553,
> +    0.235708, 0.476783, 0.70576,  0.739104, 0.795516, 0.802512, 0.600616, 0.249289,
> +    0.331483, 0.600528, 0.689429, 0.692062, 0.69679,  0.643138, 0.43934,  0.188511,
> +    0.248309, 0.440086, 0.42807,  0.397419, 0.386259, 0.270966, 0.192244, 0.094199,
> +};
> +
> +static const float bink2f_luma_inter_qmat[64] = {
> +    0.125,    0.17338,  0.16332,  0.146984, 0.128475, 0.106393, 0.077046, 0.043109,
> +    0.17338,  0.240485, 0.226532, 0.203873, 0.1782,   0.147571, 0.109474, 0.062454,
> +    0.16332,  0.226532, 0.219321, 0.202722, 0.181465, 0.149711, 0.112943, 0.062584,
> +    0.146984, 0.203873, 0.202722, 0.201647, 0.183731, 0.153976, 0.11711,  0.065335,
> +    0.128475, 0.1782,   0.181465, 0.183731, 0.177088, 0.155499, 0.120267, 0.068016,
> +    0.106393, 0.147571, 0.149711, 0.153976, 0.155499, 0.145756, 0.116636, 0.068495,
> +    0.077046, 0.109474, 0.112943, 0.11711,  0.120267, 0.116636, 0.098646, 0.060141,
> +    0.043109, 0.062454, 0.062584, 0.065335, 0.068016, 0.068495, 0.060141, 0.038853,
> +};
> +
> +static const float bink2f_chroma_qmat[64] = {
> +    0.125,      0.17338,    0.217761,   0.383793,   0.6875,     0.54016501, 0.37207201, 0.18968099,
> +    0.17338,    0.28056601, 0.32721299, 0.74753499, 0.95358998, 0.74923098, 0.51607901, 0.26309499,
> +    0.217761,   0.32721299, 0.66387498, 1.056244,   0.89826202, 0.70576,    0.48613599, 0.24783,
> +    0.383793,   0.74753499, 1.056244,   0.95059502, 0.80841398, 0.635167,   0.437511,   0.223041,
> +    0.6875,     0.95358998, 0.89826202, 0.80841398, 0.6875,     0.54016501, 0.37207201, 0.18968099,
> +    0.54016501, 0.74923098, 0.70576,    0.635167,   0.54016501, 0.42440501, 0.292335,   0.149031,
> +    0.37207201, 0.51607901, 0.48613599, 0.437511,   0.37207201, 0.292335,   0.201364,   0.102655,
> +    0.18968099, 0.26309499, 0.24783,    0.223041,   0.18968099, 0.149031,   0.102655,   0.052333001
> +};
> +
> +static const uint8_t bink2f_luma_scan[64] = {
> +     0,  2,  1,  8,  9, 17, 10, 16,
> +    24,  3, 18, 25, 32, 11, 33, 26,
> +     4, 40, 19, 12, 27, 41, 34,  5,
> +    20, 48,  6, 28, 15, 42, 23, 35,
> +    21, 13, 14,  7, 31, 43, 49, 36,
> +    22, 56, 39, 50, 30, 44, 29, 51,
> +    57, 47, 58, 59, 63, 61, 55, 38,
> +    52, 62, 45, 37, 60, 46, 54, 53
> +};
> +
> +static const uint8_t bink2f_chroma_scan[64] = {
> +     0,  1,  8,  2,  9, 16, 10, 17,
> +     3, 24, 11, 18, 25, 13, 14,  4,
> +    15,  5,  6,  7, 12, 19, 20, 21,
> +    22, 23, 26, 27, 28, 29, 30, 31,
> +    32, 33, 34, 35, 36, 37, 38, 39,
> +    40, 41, 42, 43, 44, 45, 46, 47,
> +    48, 49, 50, 51, 52, 53, 54, 55,
> +    56, 57, 58, 59, 60, 61, 62, 63
> +};
> +
> +static const uint8_t bink2g_scan[64] = {
> +     0,   8,   1,   2,  9,  16,  24,  17,
> +    10,   3,   4,  11, 18,  25,  32,  40,
> +    33,  26,  19,  12,  5,   6,  13,  20,
> +    27,  34,  41,  48, 56,  49,  42,  35,
> +    28,  21,  14,   7, 15,  22,  29,  36,
> +    43,  50,  57,  58, 51,  44,  37,  30,
> +    23,  31,  38,  45, 52,  59,  60,  53,
> +    46,  39,  47,  54, 61,  62,  55,  63,
> +};

All these tables could be in a separate file.

> +
> +typedef struct QuantPredict {
> +    int8_t intra_q;
> +    int8_t inter_q;
> +} QuantPredict;
> +
> +typedef struct DCPredict {
> +    float dc[4][16];
> +    int   block_type;
> +} DCPredict;
> +
> +typedef struct DCIPredict {
> +    int dc[4][16];
> +    int block_type;
> +} DCIPredict;
> +
> +typedef struct MVectors {
> +    int v[4][2];
> +    int nb_vectors;
> +} MVectors;
> +
> +typedef struct MVPredict {
> +    MVectors mv;
> +} MVPredict;
> +
> +/*
> + * Decoder context
> + */
> +typedef struct Bink2Context {
> +    AVCodecContext  *avctx;
> +    GetBitContext   gb;
> +    BlockDSPContext dsp;
> +    AVFrame         *last;
> +    int             version;              ///< internal Bink file version
> +    int             has_alpha;
> +
> +    DECLARE_ALIGNED(16, float, block[4][64]);
> +    DECLARE_ALIGNED(16, int16_t, iblock[4][64]);
> +
> +    QuantPredict    *current_q;
> +    QuantPredict    *prev_q;
> +
> +    DCPredict       *current_dc;
> +    DCPredict       *prev_dc;
> +
> +    DCIPredict      *current_idc;
> +    DCIPredict      *prev_idc;
> +
> +    MVPredict       *current_mv;
> +    MVPredict       *prev_mv;
> +
> +    uint8_t         *col_cbp;
> +    uint8_t         *row_cbp;
> +
> +    int             num_slices;
> +    int             slice_height[4];
> +
> +    int             comp;
> +    int             mb_pos;
> +    unsigned        flags;
> +    unsigned        frame_flags;
> +} Bink2Context;
> +
> +/**
> + * Bink2 video block types
> + */
> +enum BlockTypes {
> +    INTRA_BLOCK = 0, ///< intra DCT block
> +    SKIP_BLOCK,      ///< skipped block
> +    MOTION_BLOCK,    ///< block is copied from previous frame with some offset
> +    RESIDUE_BLOCK,   ///< motion block with some difference added
> +};
> +
> +static const uint8_t ones_count[16] = {
> +    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
> +};
> +
> +#include "bink2f.c"
> +#include "bink2g.c"
> +
> +static int bink2_decode_frame(AVCodecContext *avctx, void *data,
> +                              int *got_frame, AVPacket *pkt)
> +{
> +    Bink2Context * const c = avctx->priv_data;
> +    GetBitContext *gb = &c->gb;
> +    AVFrame *frame = data;
> +    uint8_t *dst[4];
> +    uint8_t *src[4];
> +    int stride[4];
> +    int sstride[4];
> +    uint32_t off = 0;
> +    int is_kf = !!(pkt->flags & AV_PKT_FLAG_KEY);
> +    int ret, w, h;
> +    int height_a;
> +
> +    w = avctx->width;
> +    h = avctx->height;
> +    ret = ff_set_dimensions(avctx, FFALIGN(w, 32), FFALIGN(h, 32));
> +    if (ret < 0)
> +        return ret;
> +    avctx->width  = w;
> +    avctx->height = h;

Why doing this on every frame? The result will always be the same.

> +
> +    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
> +        return ret;
> +
> +    for (int i = 0; i < 4; i++) {
> +        src[i]     = c->last->data[i];
> +        dst[i]     = frame->data[i];
> +        stride[i]  = frame->linesize[i];
> +        sstride[i] = c->last->linesize[i];
> +    }
> +
> +    c->frame_flags = AV_RL32(pkt->data);
> +    ff_dlog(NULL, "frame flags %X\n", c->frame_flags);
> +
> +    if ((ret = init_get_bits8(gb, pkt->data, pkt->size)) < 0)
> +        return ret;
> +
> +    height_a = (avctx->height + 31) & 0xFFFFFFE0;
> +    if (c->version <= 'f') {
> +        c->num_slices = 2;
> +        c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
> +    } else if (c->version == 'g') {
> +        if (height_a < 128) {
> +            c->num_slices = 1;
> +        } else {
> +            c->num_slices = 2;
> +            c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
> +        }
> +    } else {
> +        int start, end;
> +
> +        c->num_slices = kb2h_num_slices[c->flags & 3];
> +        start = 0;
> +        end = height_a + 32 * c->num_slices - 1;
> +        for (int i = 0; i < c->num_slices - 1; i++) {
> +            start += ((end - start) / (c->num_slices - i)) & 0xFFFFFFE0;
> +            end -= 32;
> +            c->slice_height[i] = start;
> +        }
> +    }
> +    c->slice_height[c->num_slices - 1] = height_a;
> +
> +    skip_bits_long(gb, 32 + 32 * (c->num_slices - 1));
> +
> +    if (c->frame_flags & 0x10000) {
> +        if (!(c->frame_flags & 0x8000))
> +            bink2g_get_cbp_flags(gb, 1, (((avctx->height + 15) & ~15) >> 3) - 1, c->row_cbp);
> +        if (!(c->frame_flags & 0x4000))
> +            bink2g_get_cbp_flags(gb, 1, (((avctx->width + 15) & ~15) >> 3) - 1, c->col_cbp);
> +    }
> +
> +    for (int i = 0; i < c->num_slices; i++) {
> +        if (i == c->num_slices - 1)
> +            off = pkt->size;
> +        else
> +            off = AV_RL32(pkt->data + 4 + i * 4);
> +
> +        if (c->version <= 'f')
> +            ret = bink2f_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
> +        else
> +            ret = bink2g_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
> +        if (0 && ret < 0)
> +            return ret;
> +
> +        align_get_bits(gb);
> +        if (get_bits_left(gb) < 0)
> +            av_log(avctx, AV_LOG_WARNING, "slice %d: overread\n", i);
> +        if (8 * (off - (get_bits_count(gb) >> 3)) > 24)
> +            av_log(avctx, AV_LOG_WARNING, "slice %d: underread %d\n", i, 8 * (off - (get_bits_count(gb) >> 3)));
> +        skip_bits_long(gb, 8 * (off - (get_bits_count(gb) >> 3)));
> +
> +        dst[0] = frame->data[0] + c->slice_height[i]   * stride[0];
> +        dst[1] = frame->data[1] + c->slice_height[i]/2 * stride[1];
> +        dst[2] = frame->data[2] + c->slice_height[i]/2 * stride[2];
> +        dst[3] = frame->data[3] + c->slice_height[i]   * stride[3];
> +    }
> +
> +    frame->key_frame = is_kf;
> +    frame->pict_type = is_kf ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
> +
> +    av_frame_unref(c->last);
> +    if ((ret = av_frame_ref(c->last, frame)) < 0)
> +        return ret;
> +
> +    *got_frame = 1;
> +
> +    /* always report that the buffer was completely consumed */
> +    return pkt->size;
> +}
> +
> +#define INIT_VLC_STATIC_LE(vlc, nb_bits, nb_codes,                 \
> +                           bits, bits_wrap, bits_size,             \
> +                           codes, codes_wrap, codes_size,          \
> +                           symbols, symbols_wrap, symbols_size,    \
> +                           static_size)                            \
> +    do {                                                           \
> +        static VLC_TYPE table[static_size][2];                     \
> +        (vlc)->table           = table;                            \
> +        (vlc)->table_allocated = static_size;                      \
> +        ff_init_vlc_sparse(vlc, nb_bits, nb_codes,                 \
> +                           bits, bits_wrap, bits_size,             \
> +                           codes, codes_wrap, codes_size,          \
> +                           symbols, symbols_wrap, symbols_size,    \
> +                           INIT_VLC_LE | INIT_VLC_USE_NEW_STATIC); \
> +    } while (0)
> +
> +static av_cold int bink2_decode_init(AVCodecContext *avctx)
> +{
> +    Bink2Context * const c = avctx->priv_data;
> +    int ret;
> +
> +    c->version = avctx->codec_tag >> 24;
> +    if (avctx->extradata_size < 4) {
> +        av_log(avctx, AV_LOG_ERROR, "Extradata missing or too short\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    c->flags = AV_RL32(avctx->extradata);
> +    av_log(avctx, AV_LOG_DEBUG, "flags: 0x%X\n", c->flags);
> +    c->has_alpha = c->flags & BINK_FLAG_ALPHA;
> +    c->avctx = avctx;
> +
> +    c->last = av_frame_alloc();
> +    if (!c->last)
> +        return AVERROR(ENOMEM);
> +
> +    if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
> +        return ret;
> +
> +    avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
> +
> +    ff_blockdsp_init(&c->dsp, avctx);
> +
> +    INIT_VLC_STATIC_LE(&bink2f_quant_vlc, 9, FF_ARRAY_ELEMS(bink2f_quant_codes),
> +                       bink2f_quant_bits, 1, 1, bink2f_quant_codes, 1, 1, NULL, 0, 0, 512);
> +    INIT_VLC_STATIC_LE(&bink2f_ac_val0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[0]),
> +                       bink2f_ac_val_bits[0], 1, 1, bink2f_ac_val_codes[0], 2, 2, NULL, 0, 0, 512);
> +    INIT_VLC_STATIC_LE(&bink2f_ac_val1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[1]),
> +                       bink2f_ac_val_bits[1], 1, 1, bink2f_ac_val_codes[1], 2, 2, NULL, 0, 0, 512);
> +    INIT_VLC_STATIC_LE(&bink2f_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[0]),
> +                       bink2f_ac_skip_bits[0], 1, 1, bink2f_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
> +    INIT_VLC_STATIC_LE(&bink2f_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[1]),
> +                       bink2f_ac_skip_bits[1], 1, 1, bink2f_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
> +
> +    INIT_VLC_STATIC_LE(&bink2g_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[0]),
> +                       bink2g_ac_skip_bits[0], 1, 1, bink2g_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
> +    INIT_VLC_STATIC_LE(&bink2g_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[1]),
> +                       bink2g_ac_skip_bits[1], 1, 1, bink2g_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
> +    INIT_VLC_STATIC_LE(&bink2g_mv_vlc, 9, FF_ARRAY_ELEMS(bink2g_mv_bits),
> +                       bink2g_mv_bits, 1, 1, bink2g_mv_codes, 1, 1, NULL, 0, 0, 512);
> +
> +    c->current_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_q));
> +    if (!c->current_q)
> +        return AVERROR(ENOMEM);
> +
> +    c->prev_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_q));
> +    if (!c->prev_q)
> +        return AVERROR(ENOMEM);
> +
> +    c->current_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_dc));
> +    if (!c->current_dc)
> +        return AVERROR(ENOMEM);
> +
> +    c->prev_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_dc));
> +    if (!c->prev_dc)
> +        return AVERROR(ENOMEM);
> +
> +    c->current_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_idc));
> +    if (!c->current_idc)
> +        return AVERROR(ENOMEM);
> +
> +    c->prev_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_idc));
> +    if (!c->prev_q)
> +        return AVERROR(ENOMEM);
> +
> +    c->current_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_mv));
> +    if (!c->current_mv)
> +        return AVERROR(ENOMEM);
> +
> +    c->prev_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_mv));
> +    if (!c->prev_mv)
> +        return AVERROR(ENOMEM);
> +
> +    c->col_cbp = av_calloc((((avctx->width + 31) >> 3) + 7) >> 3, sizeof(*c->col_cbp));
> +    if (!c->col_cbp)
> +        return AVERROR(ENOMEM);
> +
> +    c->row_cbp = av_calloc((((avctx->height + 31) >> 3) + 7) >> 3, sizeof(*c->row_cbp));
> +    if (!c->row_cbp)
> +        return AVERROR(ENOMEM);
> +
> +    return 0;
> +}
> +
> +static av_cold int bink2_decode_end(AVCodecContext *avctx)
> +{
> +    Bink2Context * const c = avctx->priv_data;
> +
> +    av_frame_free(&c->last);
> +    av_freep(&c->current_q);
> +    av_freep(&c->prev_q);
> +    av_freep(&c->current_dc);
> +    av_freep(&c->prev_dc);
> +    av_freep(&c->current_idc);
> +    av_freep(&c->prev_idc);
> +    av_freep(&c->current_mv);
> +    av_freep(&c->prev_mv);
> +    av_freep(&c->col_cbp);
> +    av_freep(&c->row_cbp);
> +
> +    return 0;
> +}
> +
> +AVCodec ff_bink2_decoder = {
> +    .name           = "binkvideo2",
> +    .long_name      = NULL_IF_CONFIG_SMALL("Bink video 2"),
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_BINKVIDEO2,
> +    .priv_data_size = sizeof(Bink2Context),
> +    .init           = bink2_decode_init,
> +    .close          = bink2_decode_end,
> +    .decode         = bink2_decode_frame,
> +    .capabilities   = AV_CODEC_CAP_DR1,

Missing FF_CODEC_CAP_INIT_CLEANUP, and a flush function to unref c->last
and do any other potentially required cleaning.


More information about the ffmpeg-devel mailing list