[FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
Vittorio Giovara
vittorio.giovara at gmail.com
Fri Mar 20 19:15:45 EET 2020
On Fri, Mar 20, 2020 at 9:31 AM Paul B Mahol <onemda at gmail.com> wrote:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> configure | 1 +
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/avcodec.h | 1 +
> libavcodec/bink2.c | 869 ++++++++++++++++++++++++++++
> libavcodec/bink2f.c | 1125 ++++++++++++++++++++++++++++++++++++
> libavcodec/bink2g.c | 1197 +++++++++++++++++++++++++++++++++++++++
> libavcodec/codec_desc.c | 7 +
> libavformat/bink.c | 3 +-
> 9 files changed, 3203 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 18f2841765..1d89d49b41 100755
> --- a/configure
> +++ b/configure
> @@ -2678,6 +2678,7 @@ atrac3pal_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 c1c9a44f2b..a79b4c6524 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -230,6 +230,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 b3184af954..d032547a9d 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -60,6 +60,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 78c483c25c..e8b20fa527 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -463,6 +463,7 @@ enum AVCodecID {
> AV_CODEC_ID_MVDV,
> AV_CODEC_ID_MVHA,
> AV_CODEC_ID_CDTOONS,
> + 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..0ebce7feeb
> --- /dev/null
> +++ b/libavcodec/bink2.c
> @@ -0,0 +1,869 @@
> +/*
> + * 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
> + */
> +
> +#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"
> +#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,
> +};
> +
> +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 void bink2_get_block_flags(GetBitContext *gb, int offset, int
> size, uint8_t *dst)
> +{
> + int j, v = 0, flags_left, mode = 0, nv;
> + unsigned cache, flag = 0;
> +
> + if (get_bits1(gb) == 0) {
> + for (j = 0; j < size >> 3; j++)
> + dst[j] = get_bits(gb, 8);
> + dst[j] = get_bitsz(gb, size & 7);
> +
> + return;
> + }
> +
> + flags_left = size;
> + while (flags_left > 0) {
> + cache = offset;
> + if (get_bits1(gb) == 0) {
> + if (mode == 3) {
> + flag ^= 1;
> + } else {
> + flag = get_bits1(gb);
> + }
> + mode = 2;
> + if (flags_left < 5) {
> + nv = get_bitsz(gb, flags_left - 1);
> + nv <<= (offset + 1) & 0x1f;
> + offset += flags_left;
> + flags_left = 0;
> + } else {
> + nv = get_bits(gb, 4) << ((offset + 1) & 0x1f);
> + offset += 5;
> + flags_left -= 5;
> + }
> + v |= flag << (cache & 0x1f) | nv;
> + if (offset >= 8) {
> + *dst++ = v & 0xff;
> + v >>= 8;
> + offset -= 8;
> + }
> + } else {
> + int temp, bits, nb_coded;
> +
> + bits = flags_left < 4 ? 2 : flags_left < 16 ? 4 : 5;
> + nb_coded = bits + 1;
> + if (mode == 3) {
> + flag ^= 1;
> + } else {
> + nb_coded++;
> + flag = get_bits1(gb);
> + }
> + nb_coded = FFMIN(nb_coded, flags_left);
> + flags_left -= nb_coded;
> + if (flags_left > 0) {
> + temp = get_bits(gb, bits);
> + flags_left -= temp;
> + nb_coded += temp;
> + mode = temp == (1 << bits) - 1U ? 1 : 3;
> + }
> +
> + temp = (flag << 0x1f) >> 0x1f & 0xff;
> + while (nb_coded > 8) {
> + v |= temp << (cache & 0x1f);
> + *dst++ = v & 0xff;
> + v >>= 8;
> + nb_coded -= 8;
> + }
> + if (nb_coded > 0) {
> + offset += nb_coded;
> + v |= ((1 << (nb_coded & 0x1f)) - 1U & temp) << (cache &
> 0x1f);
> + if (offset >= 8) {
> + *dst++ = v & 0xff;
> + v >>= 8;
> + offset -= 8;
> + }
> + }
> + }
> + }
> +
> + if (offset != 0)
> + *dst = v;
> +}
> +
> +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;
> +
> + 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];
> + }
> +
> + if (!is_kf && (!src[0] || !src[1] || !src[2]))
> + return AVERROR_INVALIDDATA;
> +
> + c->frame_flags = AV_RL32(pkt->data);
> + ff_dlog(avctx, "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))
> + bink2_get_block_flags(gb, 1, (((avctx->height + 15) & ~15) >>
> 3) - 1, c->row_cbp);
> + if (!(c->frame_flags & 0x4000))
> + bink2_get_block_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 (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,
> +};
>
could be wrong, but the decode_end seems to clean memory correctly, so you
could add the internal capabilitiy that cleans memory on init error.
--
Vittorio
More information about the ffmpeg-devel
mailing list