[FFmpeg-devel] [PATCH 2/2] avcodec: add bink2 video decoder
Paul B Mahol
onemda at gmail.com
Wed Mar 27 22:21:47 EET 2019
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"
+#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 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];
+ }
+
+ 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,
+};
diff --git a/libavcodec/bink2f.c b/libavcodec/bink2f.c
new file mode 100644
index 0000000000..487c53038d
--- /dev/null
+++ b/libavcodec/bink2f.c
@@ -0,0 +1,1139 @@
+/*
+ * 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
+ */
+
+static inline void bink2f_idct_1d(float *blk, int step)
+{
+ float t00 = blk[2 * step] + blk[6 * step];
+ float t01 = (blk[2 * step] - blk[6 * step]) * 1.4142135f - t00;
+ float t02 = blk[0 * step] + blk[4 * step];
+ float t03 = blk[0 * step] - blk[4 * step];
+ float t04 = blk[3 * step] + blk[5 * step];
+ float t05 = blk[3 * step] - blk[5 * step];
+ float t06 = blk[1 * step] + blk[7 * step];
+ float t07 = blk[1 * step] - blk[7 * step];
+ float t08 = t02 + t00;
+ float t09 = t02 - t00;
+ float t10 = t03 + t01;
+ float t11 = t03 - t01;
+ float t12 = t06 + t04;
+ float t13 = (t06 - t04) * 1.4142135f;
+ float t14 = (t07 - t05) * 1.847759f;
+ float t15 = t05 * 2.613126f + t14 - t12;
+ float t16 = t13 - t15;
+ float t17 = t07 * 1.0823922f - t14 + t16;
+
+ blk[0*step] = t08 + t12;
+ blk[1*step] = t10 + t15;
+ blk[2*step] = t11 + t16;
+ blk[3*step] = t09 - t17;
+ blk[4*step] = t09 + t17;
+ blk[5*step] = t11 - t16;
+ blk[6*step] = t10 - t15;
+ blk[7*step] = t08 - t12;
+}
+
+static void bink2f_idct_put(uint8_t *dst, int stride, float *block)
+{
+ block[0] += 512.5f;
+
+ for (int i = 0; i < 8; i++)
+ bink2f_idct_1d(block + i, 8);
+ for (int i = 0; i < 8; i++) {
+ bink2f_idct_1d(block, 1);
+ for (int j = 0; j < 8; j++)
+ dst[j] = av_clip_uint8(block[j] - 512.0f);
+ block += 8;
+ dst += stride;
+ }
+}
+
+static void bink2f_idct_add(uint8_t *dst, int stride,
+ float *block)
+{
+ block[0] += 512.5f;
+
+ for (int i = 0; i < 8; i++)
+ bink2f_idct_1d(block + i, 8);
+ for (int i = 0; i < 8; i++) {
+ bink2f_idct_1d(block, 1);
+ for (int j = 0; j < 8; j++)
+ dst[j] = av_clip_uint8(dst[j] + block[j] - 512.0f);
+ block += 8;
+ dst += stride;
+ }
+}
+
+static int bink2f_decode_delta_q(GetBitContext *gb)
+{
+ int dq = get_vlc2(gb, bink2f_quant_vlc.table, bink2f_quant_vlc.bits, 1);
+
+ if (dq < 0)
+ return AVERROR_INVALIDDATA;
+ if (dq && get_bits1(gb))
+ dq = -dq;
+
+ return dq;
+}
+
+static unsigned bink2f_decode_cbp_luma(GetBitContext *gb, unsigned prev_cbp)
+{
+ unsigned cbp, cbp4, cbplo, cbphi;
+
+ if (get_bits1(gb)) {
+ if (get_bits1(gb))
+ return prev_cbp;
+ cbplo = prev_cbp & 0xFFFF;
+ } else {
+ cbplo = 0;
+ cbp4 = (prev_cbp >> 4) & 0xF;
+ for (int i = 0; i < 4; i++) {
+ if (!get_bits1(gb))
+ cbp4 = get_bits(gb, 4);
+ cbplo |= cbp4 << (i * 4);
+ }
+ }
+ cbphi = 0;
+ cbp = cbplo;
+ cbp4 = prev_cbp >> 20 & 0xF;
+ for (int i = 0; i < 4; i++) {
+ if (ones_count[cbp & 0xF]) {
+ if (ones_count[cbp & 0xF] == 1) {
+ cbp4 = 0;
+ for (int j = 1; j < 16; j <<= 1) {
+ if ((j & cbp) && get_bits1(gb))
+ cbp4 |= j;
+ }
+ } else if (!get_bits1(gb)) {
+ cbp4 = 0;
+ for (int j = 1; j < 16; j <<= 1) {
+ if ((j & cbp) && get_bits1(gb))
+ cbp4 |= j;
+ }
+ }
+ } else {
+ cbp4 = 0;
+ }
+ cbp4 &= cbp;
+ cbphi = (cbphi >> 4) | (cbp4 << 0x1c);
+ cbp >>= 4;
+ }
+ return cbphi | cbplo;
+}
+
+static unsigned bink2f_decode_cbp_chroma(GetBitContext *gb, unsigned prev_cbp)
+{
+ unsigned cbplo, cbphi;
+
+ if (get_bits1(gb)) {
+ if (get_bits1(gb))
+ return prev_cbp;
+ cbplo = prev_cbp & 0xF;
+ } else {
+ cbplo = get_bits(gb, 4);
+ }
+
+ cbphi = 0;
+ if (ones_count[cbplo & 0xF]) {
+ if (ones_count[cbplo & 0xF] != 1) {
+ cbphi = (prev_cbp >> 16) & cbplo;
+ if (get_bits1(gb))
+ return cbplo | (cbphi << 16);
+ }
+ cbphi = 0;
+ for (int j = 1; j < 16; j <<= 1) {
+ if ((j & cbplo) && get_bits1(gb))
+ cbphi |= j;
+ }
+ }
+ return cbplo | (cbphi << 16);
+}
+
+static const uint8_t q_dc_bits[16] = {
+ 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7
+};
+
+static void bink2f_predict_dc(Bink2Context *c,
+ int is_luma, float mindc, float maxdc,
+ int flags, float tdc[16])
+{
+ float *LTdc = c->prev_dc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
+ float *Tdc = c->prev_dc[c->mb_pos].dc[c->comp];
+ float *Ldc = c->current_dc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
+
+ if (is_luma && (flags & 0x20) && (flags & 0x80)) {
+ dc[0] = av_clipf((mindc < 0 ? 0 : 1024.f) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clipf(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clipf(dc[4] + tdc[5], mindc, maxdc);
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clipf(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clipf(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (is_luma && (flags & 0x80)) {
+ dc[0] = av_clipf(DC_MPRED2(Ldc[5], Ldc[7]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clipf(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clipf(dc[4] + tdc[5], mindc, maxdc);
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clipf(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clipf(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (is_luma && (flags & 0x20)) {
+ dc[0] = av_clipf(DC_MPRED2(Tdc[10], Tdc[11]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clipf(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clipf(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clipf(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clipf(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (is_luma) {
+ dc[0] = av_clipf(DC_MPRED(LTdc[15], Ldc[5], Tdc[10]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clipf(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clipf(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clipf(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clipf(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (!is_luma && (flags & 0x20) && (flags & 0x80)) {
+ dc[0] = av_clipf((mindc < 0 ? 0 : 1024.f) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ } else if (!is_luma && (flags & 0x80)) {
+ dc[0] = av_clipf(DC_MPRED2(Ldc[1], Ldc[3]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ } else if (!is_luma && (flags & 0x20)) {
+ dc[0] = av_clipf(DC_MPRED2(Tdc[2], Tdc[3]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ } else if (!is_luma) {
+ dc[0] = av_clipf(DC_MPRED(LTdc[3], Ldc[1], Tdc[2]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clipf(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clipf(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ }
+}
+
+static void bink2f_decode_dc(Bink2Context *c, GetBitContext *gb, float *dc,
+ int is_luma, int q, int mindc, int maxdc,
+ int flags)
+{
+ const int num_dc = is_luma ? 16 : 4;
+ float tdc[16] = { 0 };
+ int dc_bits;
+
+ dc_bits = get_bits(gb, 3);
+ if (dc_bits == 7)
+ dc_bits += get_bits(gb, 2);
+ //ff_dlog(NULL, " DC bits %d @ %d\n", dc_bits, get_bits_count(gb));
+ if (!dc_bits) {
+ memset(dc, 0, sizeof(*dc) * num_dc);
+ } else {
+ for (int j = 0; j < num_dc; j += 4) {
+ for (int i = 0; i < 4; i++)
+ tdc[i + j] = get_bits(gb, dc_bits);
+
+ for (int i = 0; i < 4; i++)
+ if (tdc[i + j] && get_bits1(gb))
+ tdc[i + j] = -tdc[i + j];
+ }
+ }
+
+ if ((flags & 0x20) && (flags & 0x80) && mindc >= 0) {
+ int bits = (q_dc_bits[q] - 1) + dc_bits;
+
+ if (bits < 10) {
+ int dc_val = get_bits(gb, 10 - bits);
+
+ if (dc_val) {
+ dc_val <<= dc_bits;
+ if (get_bits1(gb))
+ dc_val = -dc_val;
+ }
+ //ff_dlog(NULL, " start DC %d (%d bits) @ %d\n", dc_val, dc_bits, get_bits_count(gb));
+ tdc[0] += dc_val;
+ }
+ }
+
+ for (int i = 0; i < num_dc; i++)
+ tdc[i] *= bink2f_dc_quant[q];
+
+ bink2f_predict_dc(c, is_luma, mindc, maxdc, flags, tdc);
+}
+
+static int bink2f_decode_ac(GetBitContext *gb, const uint8_t *scan,
+ float block[4][64], unsigned cbp,
+ float q, const float qmat[64])
+{
+ int idx, next, val, skip;
+ VLC *val_vlc, *skip_vlc;
+
+ for (int i = 0; i < 4; i++, cbp >>= 1) {
+ memset(block[i], 0, sizeof(**block) * 64);
+
+ if (!(cbp & 1))
+ continue;
+
+ //ff_dlog(NULL, " blk %d\n", i);
+ if (cbp & 0x10000) {
+ val_vlc = &bink2f_ac_val1_vlc;
+ skip_vlc = &bink2f_ac_skip1_vlc;
+ } else {
+ val_vlc = &bink2f_ac_val0_vlc;
+ skip_vlc = &bink2f_ac_skip0_vlc;
+ }
+
+ next = 0;
+ idx = 1;
+ while (idx < 64) {
+ val = get_vlc2(gb, val_vlc->table, val_vlc->bits, 1);
+ if (val < 0)
+ return AVERROR_INVALIDDATA;
+ if (val) {
+ if (val >= 4) {
+ val -= 3;
+ val = get_bits(gb, val) + (1 << val) + 2;
+ }
+ if (get_bits1(gb))
+ val = -val;
+ }
+
+ ff_dlog(NULL, " AC level = %d @ %d\n", val, get_bits_count(gb));
+ block[i][scan[idx]] = val * q * qmat[scan[idx]];
+ if (idx > 62)
+ break;
+ idx++;
+ next--;
+ if (next < 1) {
+ skip = get_vlc2(gb, skip_vlc->table, skip_vlc->bits, 1);
+ if (skip < 0)
+ return AVERROR_INVALIDDATA;
+ next = bink2f_next_skips[skip];
+ skip = bink2f_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ ff_dlog(NULL, " AC skip = %d @ %d\n", skip, get_bits_count(gb));
+ idx += skip;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int bink2f_decode_intra_luma(Bink2Context *c,
+ float block[4][64],
+ unsigned *prev_cbp, int *prev_q,
+ uint8_t *dst, int stride,
+ int flags)
+{
+ GetBitContext *gb = &c->gb;
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
+ int q, dq, ret;
+ unsigned cbp;
+
+ *prev_cbp = cbp = bink2f_decode_cbp_luma(gb, *prev_cbp);
+ //ff_dlog(NULL, " Y CBP %X @ %d\n", cbp, get_bits_count(gb));
+ dq = bink2f_decode_delta_q(gb);
+ q = *prev_q + dq;
+ //ff_dlog(NULL, " Y q %d @ %d\n", q, get_bits_count(gb));
+ if (q < 0 || q >= 16)
+ return AVERROR_INVALIDDATA;
+ *prev_q = q;
+
+ bink2f_decode_dc(c, gb, dc, 1, q, 0, 2047, flags);
+
+ for (int i = 0; i < 4; i++) {
+ ret = bink2f_decode_ac(gb, bink2f_luma_scan, block, cbp >> (4 * i),
+ bink2f_ac_quant[q], bink2f_luma_intra_qmat);
+ if (ret < 0)
+ return ret;
+
+ for (int j = 0; j < 4; j++) {
+ block[j][0] = dc[i * 4 + j] * 0.125f;
+ bink2f_idct_put(dst + (luma_repos[i*4+j]&3) * 8 +
+ (luma_repos[i*4+j]>>2) * 8 * stride, stride, block[j]);
+ }
+ }
+
+ return 0;
+}
+
+static int bink2f_decode_intra_chroma(Bink2Context *c,
+ float block[4][64],
+ unsigned *prev_cbp, int *prev_q,
+ uint8_t *dst, int stride,
+ int flags)
+{
+ GetBitContext *gb = &c->gb;
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
+ int q, dq, ret;
+ unsigned cbp;
+
+ *prev_cbp = cbp = bink2f_decode_cbp_chroma(gb, *prev_cbp);
+ //ff_dlog(NULL, " C CBP %X @ %d\n", cbp, get_bits_count(gb));
+ dq = bink2f_decode_delta_q(gb);
+ q = *prev_q + dq;
+ //ff_dlog(NULL, " C q %d @ %d\n", q, get_bits_count(gb));
+ if (q < 0 || q >= 16)
+ return AVERROR_INVALIDDATA;
+ *prev_q = q;
+
+ bink2f_decode_dc(c, gb, dc, 0, q, 0, 2047, flags);
+
+ ret = bink2f_decode_ac(gb, bink2f_chroma_scan, block, cbp,
+ bink2f_ac_quant[q], bink2f_chroma_qmat);
+ if (ret < 0)
+ return ret;
+
+ for (int j = 0; j < 4; j++) {
+ block[j][0] = dc[j] * 0.125f;
+ bink2f_idct_put(dst + (j & 1) * 8 + (j >> 1) * 8 * stride, stride, block[j]);
+ }
+
+ return 0;
+}
+
+static int bink2f_decode_inter_luma(Bink2Context *c,
+ float block[4][64],
+ unsigned *prev_cbp, int *prev_q,
+ uint8_t *dst, int stride,
+ int flags)
+{
+ GetBitContext *gb = &c->gb;
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
+ unsigned cbp;
+ int q, dq;
+
+ *prev_cbp = cbp = bink2f_decode_cbp_luma(gb, *prev_cbp);
+ dq = bink2f_decode_delta_q(gb);
+ q = *prev_q + dq;
+ if (q < 0 || q >= 16)
+ return AVERROR_INVALIDDATA;
+ *prev_q = q;
+
+ bink2f_decode_dc(c, gb, dc, 1, q, -1023, 1023, 0xA8);
+
+ for (int i = 0; i < 4; i++) {
+ bink2f_decode_ac(gb, bink2f_luma_scan, block, cbp >> (i * 4),
+ bink2f_ac_quant[q], bink2f_luma_inter_qmat);
+ for (int j = 0; j < 4; j++) {
+ block[j][0] = dc[i * 4 + j] * 0.125f;
+ bink2f_idct_add(dst + (luma_repos[i*4+j]&3) * 8 +
+ (luma_repos[i*4+j]>>2) * 8 * stride, stride,
+ block[j]);
+ }
+ }
+
+ return 0;
+}
+
+static int bink2f_decode_inter_chroma(Bink2Context *c,
+ float block[4][64],
+ unsigned *prev_cbp, int *prev_q,
+ uint8_t *dst, int stride,
+ int flags)
+{
+ GetBitContext *gb = &c->gb;
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
+ unsigned cbp;
+ int q, dq;
+
+ *prev_cbp = cbp = bink2f_decode_cbp_chroma(gb, *prev_cbp);
+ dq = bink2f_decode_delta_q(gb);
+ q = *prev_q + dq;
+ if (q < 0 || q >= 16)
+ return AVERROR_INVALIDDATA;
+ *prev_q = q;
+
+ bink2f_decode_dc(c, gb, dc, 0, q, -1023, 1023, 0xA8);
+
+ bink2f_decode_ac(gb, bink2f_chroma_scan, block, cbp,
+ bink2f_ac_quant[q], bink2f_chroma_qmat);
+
+ for (int i = 0; i < 4; i++) {
+ block[i][0] = dc[i] * 0.125f;
+ bink2f_idct_add(dst + (i & 1) * 8 + (i >> 1) * 8 * stride, stride,
+ block[i]);
+ }
+
+ return 0;
+}
+
+static void bink2f_predict_mv(Bink2Context *c, int x, int y, int flags, MVectors mv)
+{
+ MVectors *c_mv = &c->current_mv[c->mb_pos].mv;
+ MVectors *l_mv = &c->current_mv[FFMAX(c->mb_pos - 1, 0)].mv;
+ MVectors *lt_mv = &c->prev_mv[FFMAX(c->mb_pos - 1, 0)].mv;
+ MVectors *t_mv = &c->prev_mv[c->mb_pos].mv;
+
+ if (!(flags & 0x80)) {
+ if (flags & 0x20) {
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(t_mv->v[0][0], t_mv->v[2][0], t_mv->v[3][0]);
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(t_mv->v[0][1], t_mv->v[2][1], t_mv->v[3][1]);
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred(t_mv->v[2][0], t_mv->v[3][0], c_mv->v[0][0]);
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred(t_mv->v[2][1], t_mv->v[3][1], c_mv->v[0][1]);
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred(t_mv->v[2][0], c_mv->v[0][0], c_mv->v[1][0]);
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred(t_mv->v[2][1], c_mv->v[0][1], c_mv->v[1][1]);
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
+ } else {
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(lt_mv->v[3][0], t_mv->v[2][0], l_mv->v[1][0]);
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(lt_mv->v[3][1], t_mv->v[2][1], l_mv->v[1][1]);
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred( t_mv->v[2][0], t_mv->v[3][0], c_mv->v[0][0]);
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred( t_mv->v[2][1], t_mv->v[3][1], c_mv->v[0][1]);
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred( t_mv->v[2][0], c_mv->v[0][0], c_mv->v[1][0]);
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred( t_mv->v[2][1], c_mv->v[0][1], c_mv->v[1][1]);
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred( c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred( c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
+ }
+ } else {
+ if (flags & 0x20) {
+ c_mv->v[0][0] = mv.v[0][0];
+ c_mv->v[0][1] = mv.v[0][1];
+ c_mv->v[1][0] = mv.v[1][0];
+ c_mv->v[1][1] = mv.v[1][1];
+ c_mv->v[2][0] = mv.v[2][0];
+ c_mv->v[2][1] = mv.v[2][1];
+ c_mv->v[3][0] = mv.v[3][0];
+ c_mv->v[3][1] = mv.v[3][1];
+ } else {
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(l_mv->v[0][0], l_mv->v[1][0], l_mv->v[3][0]);
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(l_mv->v[0][1], l_mv->v[1][1], l_mv->v[3][1]);
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred(l_mv->v[1][0], l_mv->v[3][0], c_mv->v[0][0]);
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred(l_mv->v[1][1], l_mv->v[3][1], c_mv->v[0][1]);
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred(l_mv->v[1][0], c_mv->v[0][0], c_mv->v[2][0]);
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred(l_mv->v[1][1], c_mv->v[0][1], c_mv->v[2][1]);
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
+ }
+ }
+
+ for (int i = 0; i < 4; i++)
+ ff_dlog(NULL, "pred MV %dx%d %d: %dx%d\n", x, y, i, c_mv->v[i][0], c_mv->v[i][1]);
+}
+
+#define CH1FILTER(src) ((6*(src)[0] + 2*(src)[1] + 4) >> 3)
+#define CH2FILTER(src) (( (src)[0] + (src)[1] + 1) >> 1)
+#define CH3FILTER(src) ((2*(src)[0] + 6*(src)[1] + 4) >> 3)
+
+#define CV1FILTER(src, i) ((6*(src)[0] + 2*(src)[i] + 4) >> 3)
+#define CV2FILTER(src, i) (( (src)[0] + (src)[i] + 1) >> 1)
+#define CV3FILTER(src, i) ((2*(src)[0] + 6*(src)[i] + 4) >> 3)
+
+static void bink2f_c_mc(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height,
+ int mv_x, int mv_y,
+ int mode)
+{
+ uint8_t *msrc;
+ uint8_t temp[8*9];
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ //ff_dlog(NULL, "CHROMA %d: %dx%d | %dx%d\n", mode, x, y, mv_x, mv_y);
+ switch (mode) {
+ case 0:
+ copy_block8(dst, msrc, stride, sstride, 8);
+ break;
+ case 1:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CH1FILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ break;
+ case 2:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CH2FILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ break;
+ case 3:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CH3FILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ break;
+ case 4:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i*stride] = av_clip_uint8(CV1FILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ break;
+ case 5:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 6:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 7:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 8:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i*stride] = av_clip_uint8(CV2FILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ break;
+ case 9:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 10:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 11:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 12:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i*stride] = av_clip_uint8(CV3FILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ break;
+ case 13:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 14:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 15:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ }
+}
+
+#define LHFILTER(src) ((((src)[0]+(src)[1])*19 >> 1)-((src)[-1]+(src)[2 ])*2+(((src)[-2 ]+(src)[3 ])>>1)+8>>4)
+#define LVFILTER(src, i) ((((src)[0]+(src)[i])*19 >> 1)-((src)[-i]+(src)[2*i])*2+(((src)[-2*i]+(src)[3*i])>>1)+8>>4)
+
+static void bink2f_y_mc(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height,
+ int mv_x, int mv_y, int mode)
+{
+ uint8_t *msrc;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ //ff_dlog(NULL, "LUMA %d: %dx%d | %dx%d\n", mode, x, y, mv_x, mv_y);
+ if (mode == 0) {
+ copy_block16(dst, msrc, stride, sstride, 16);
+ } else if (mode == 1) {
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 16; i++)
+ dst[i] = av_clip_uint8(LHFILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ } else if (mode == 2) {
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 16; i++)
+ dst[i*stride] = av_clip_uint8(LVFILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ } else if (mode == 3) {
+ uint8_t temp[21 * 16];
+
+ msrc -= 2 * sstride;
+ for (int i = 0; i < 21; i++) {
+ for (int j = 0; j < 16; j++)
+ temp[i*16+j] = av_clip_uint8(LHFILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 16; i++)
+ dst[i] = av_clip_uint8(LVFILTER(temp+(j+2)*16+i, 16));
+ dst += stride;
+ }
+ }
+}
+
+static int bink2f_mcompensate_chroma(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height)
+{
+ MVectors *mv = &c->current_mv[c->mb_pos].mv;
+ int mv_x, mv_y, mode;
+
+ mv_x = (mv->v[0][0] >> 2) + x;
+ mv_y = (mv->v[0][1] >> 2) + y;
+ mode = mv->v[0][0] & 3;
+ mode |= (mv->v[0][1] & 3) << 2;
+ bink2f_c_mc(c, x, y, dst + x, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[1][0] >> 2) + x + 8;
+ mv_y = (mv->v[1][1] >> 2) + y;
+ mode = mv->v[1][0] & 3;
+ mode |= (mv->v[1][1] & 3) << 2;
+ bink2f_c_mc(c, x, y, dst + x + 8, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[2][0] >> 2) + x;
+ mv_y = (mv->v[2][1] >> 2) + y + 8;
+ mode = mv->v[2][0] & 3;
+ mode |= (mv->v[2][1] & 3) << 2;
+ bink2f_c_mc(c, x, y, dst + x + 8 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[3][0] >> 2) + x + 8;
+ mv_y = (mv->v[3][1] >> 2) + y + 8;
+ mode = mv->v[3][0] & 3;
+ mode |= (mv->v[3][1] & 3) << 2;
+ bink2f_c_mc(c, x, y, dst + x + 8 + 8 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ return 0;
+}
+
+static float bink2f_average_block(uint8_t *src, int stride)
+{
+ int sum = 0;
+
+ for (int i = 0; i < 8; i++) {
+ int avg_a = (src[i+0*stride] + src[i+1*stride] + 1) >> 1;
+ int avg_b = (src[i+2*stride] + src[i+3*stride] + 1) >> 1;
+ int avg_c = (src[i+4*stride] + src[i+5*stride] + 1) >> 1;
+ int avg_d = (src[i+6*stride] + src[i+7*stride] + 1) >> 1;
+ int avg_e = (avg_a + avg_b + 1) >> 1;
+ int avg_f = (avg_c + avg_d + 1) >> 1;
+ int avg_g = (avg_e + avg_f + 1) >> 1;
+ sum += avg_g;
+ }
+
+ return sum;
+}
+
+static void bink2f_average_chroma(Bink2Context *c, int x, int y,
+ uint8_t *src, int stride,
+ float *dc)
+{
+ for (int i = 0; i < 4; i++) {
+ int X = i & 1;
+ int Y = i >> 1;
+ dc[i] = bink2f_average_block(src + x + X * 8 + (y + Y * 8) * stride, stride);
+ }
+}
+
+static void bink2f_average_luma(Bink2Context *c, int x, int y,
+ uint8_t *src, int stride,
+ float *dc)
+{
+ for (int i = 0; i < 16; i++) {
+ int I = luma_repos[i];
+ int X = I & 3;
+ int Y = I >> 2;
+ dc[i] = bink2f_average_block(src + x + X * 8 + (y + Y * 8) * stride, stride);
+ ff_dlog(NULL, " DC avg %d:%f\n", i, dc[i]);
+ }
+}
+
+static int bink2f_mcompensate_luma(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height)
+{
+ MVectors *mv = &c->current_mv[c->mb_pos].mv;
+ int mv_x, mv_y, mode;
+
+ mv_x = (mv->v[0][0] >> 1) + x;
+ mv_y = (mv->v[0][1] >> 1) + y;
+ mode = mv->v[0][0] & 1;
+ mode |= (mv->v[0][1] & 1) << 1;
+ bink2f_y_mc(c, x, y, dst + x, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[1][0] >> 1) + x + 16;
+ mv_y = (mv->v[1][1] >> 1) + y;
+ mode = mv->v[1][0] & 1;
+ mode |= (mv->v[1][1] & 1) << 1;
+ bink2f_y_mc(c, x, y, dst + x + 16, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[2][0] >> 1) + x;
+ mv_y = (mv->v[2][1] >> 1) + y + 16;
+ mode = mv->v[2][0] & 1;
+ mode |= (mv->v[2][1] & 1) << 1;
+ bink2f_y_mc(c, x, y, dst + x + 16 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[3][0] >> 1) + x + 16;
+ mv_y = (mv->v[3][1] >> 1) + y + 16;
+ mode = mv->v[3][0] & 1;
+ mode |= (mv->v[3][1] & 1) << 1;
+ bink2f_y_mc(c, x, y, dst + x + 16 + 16 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ return 0;
+}
+
+static int bink2f_decode_mv(Bink2Context *c, GetBitContext *gb, int x, int y,
+ int flags, MVectors *mv)
+{
+ for (int i = 0; i < 2; i++) {
+ int val = 0, bits = get_bits(gb, 3);
+
+ if (bits == 7)
+ bits += get_bits(gb, 2);
+ if (bits) {
+ for (int j = 0; j < 4; j++)
+ mv->v[j][i] = get_bits(gb, bits);
+ for (int j = 0; j < 4; j++)
+ if (mv->v[j][i] && get_bits1(gb))
+ mv->v[j][i] = -mv->v[j][i];
+ }
+
+ if ((flags & 0x80) && (flags & 0x20)) {
+ val = get_bits(gb, 5) * 16;
+ if (val && get_bits1(gb))
+ val = -val;
+ }
+
+ mv->v[0][i] += val;
+ mv->v[1][i] += val;
+ mv->v[2][i] += val;
+ mv->v[3][i] += val;
+ //ff_dlog(NULL, "MV val %d\n", val);
+ }
+
+ //for (int i = 0; i < 4; i++)
+ //ff_dlog(NULL, "MV %dx%d %d: %dx%d\n", x, y, i, mv->v[i][0], mv->v[i][1]);
+
+ return 0;
+}
+
+static int bink2f_decode_slice(Bink2Context *c,
+ uint8_t *dst[4], int stride[4],
+ uint8_t *src[4], int sstride[4],
+ int is_kf, int start, int end)
+{
+ GetBitContext *gb = &c->gb;
+ int w = c->avctx->width;
+ int h = c->avctx->height;
+ int flags, ret = 0;
+
+ memset(c->prev_mv, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->prev_mv));
+
+ for (int y = start; y < end; y += 32) {
+ unsigned y_cbp_intra = 0, u_cbp_intra = 0, v_cbp_intra = 0, a_cbp_intra = 0;
+ unsigned y_cbp_inter = 0, u_cbp_inter = 0, v_cbp_inter = 0, a_cbp_inter = 0;
+ int y_intra_q = 8, u_intra_q = 8, v_intra_q = 8, a_intra_q = 8;
+ int y_inter_q = 8, u_inter_q = 8, v_inter_q = 8, a_inter_q = 8;
+
+ memset(c->current_mv, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->current_mv));
+
+ for (int x = 0; x < c->avctx->width; x += 32) {
+ MVectors mv = { 0 };
+ int type = is_kf ? INTRA_BLOCK : get_bits(gb, 2);
+
+ ff_dlog(NULL, " MB %d,%d\n", x/32, y/32);
+
+ c->mb_pos = x / 32;
+ c->current_dc[c->mb_pos].block_type = type;
+ flags = 0;
+ if (y == start)
+ flags |= 0x80;
+ if (!x)
+ flags |= 0x20;
+ if (x == 32)
+ flags |= 0x200;
+ if (x + 32 >= c->avctx->width)
+ flags |= 0x40;
+
+ ff_dlog(NULL, " MB type %d @ %d\n", type, get_bits_count(gb));
+ switch (type) {
+ case INTRA_BLOCK:
+ if (!(flags & 0xA0) && c->prev_dc[c->mb_pos - 1].block_type != INTRA_BLOCK) {
+ bink2f_average_luma (c, x -32, -32, dst[0], stride[0], c->prev_dc[c->mb_pos - 1].dc[0]);
+ bink2f_average_chroma(c, x/2-16, -16, dst[2], stride[2], c->prev_dc[c->mb_pos - 1].dc[1]);
+ bink2f_average_chroma(c, x/2-16, -16, dst[1], stride[1], c->prev_dc[c->mb_pos - 1].dc[2]);
+ }
+ if (!(flags & 0x20) && c->current_dc[c->mb_pos - 1].block_type != INTRA_BLOCK) {
+ bink2f_average_luma (c, x -32, 0, dst[0], stride[0], c->current_dc[c->mb_pos - 1].dc[0]);
+ bink2f_average_chroma(c, x/2-16, 0, dst[2], stride[2], c->current_dc[c->mb_pos - 1].dc[1]);
+ bink2f_average_chroma(c, x/2-16, 0, dst[1], stride[1], c->current_dc[c->mb_pos - 1].dc[2]);
+ }
+ if ((flags & 0x20) && !(flags & 0x80) && c->prev_dc[c->mb_pos + 1].block_type != INTRA_BLOCK) {
+ bink2f_average_luma (c, x +32, -32, dst[0], stride[0], c->prev_dc[c->mb_pos + 1].dc[0]);
+ bink2f_average_chroma(c, x/2+16, -16, dst[2], stride[2], c->prev_dc[c->mb_pos + 1].dc[1]);
+ bink2f_average_chroma(c, x/2+16, -16, dst[1], stride[1], c->prev_dc[c->mb_pos + 1].dc[2]);
+ }
+ if (!(flags & 0x80) && c->prev_dc[c->mb_pos].block_type != INTRA_BLOCK) {
+ bink2f_average_luma (c, x, -32, dst[0], stride[0], c->prev_dc[c->mb_pos].dc[0]);
+ bink2f_average_chroma(c, x/2, -16, dst[2], stride[2], c->prev_dc[c->mb_pos].dc[1]);
+ bink2f_average_chroma(c, x/2, -16, dst[1], stride[1], c->prev_dc[c->mb_pos].dc[2]);
+ }
+
+ bink2f_predict_mv(c, x, y, flags, mv);
+ c->comp = 0;
+ ret = bink2f_decode_intra_luma(c, c->block, &y_cbp_intra, &y_intra_q,
+ dst[0] + x, stride[0], flags);
+ if (ret < 0)
+ goto fail;
+ c->comp = 1;
+ ret = bink2f_decode_intra_chroma(c, c->block, &u_cbp_intra, &u_intra_q,
+ dst[2] + x/2, stride[2], flags);
+ if (ret < 0)
+ goto fail;
+ c->comp = 2;
+ ret = bink2f_decode_intra_chroma(c, c->block, &v_cbp_intra, &v_intra_q,
+ dst[1] + x/2, stride[1], flags);
+ if (ret < 0)
+ goto fail;
+ if (c->has_alpha) {
+ c->comp = 3;
+ ret = bink2f_decode_intra_luma(c, c->block, &a_cbp_intra, &a_intra_q,
+ dst[3] + x, stride[3], flags);
+ if (ret < 0)
+ goto fail;
+ }
+ break;
+ case SKIP_BLOCK:
+ copy_block16(dst[0] + x, src[0] + x + sstride[0] * y,
+ stride[0], sstride[0], 32);
+ copy_block16(dst[0] + x + 16, src[0] + x + 16 + sstride[0] * y,
+ stride[0], sstride[0], 32);
+ copy_block16(dst[1] + (x/2), src[1] + (x/2) + sstride[1] * (y/2),
+ stride[1], sstride[1], 16);
+ copy_block16(dst[2] + (x/2), src[2] + (x/2) + sstride[2] * (y/2),
+ stride[2], sstride[2], 16);
+ if (c->has_alpha) {
+ copy_block16(dst[3] + x, src[3] + x + sstride[3] * y,
+ stride[3], sstride[3], 32);
+ copy_block16(dst[3] + x + 16, src[3] + x + 16 + sstride[3] * y,
+ stride[3], sstride[3], 32);
+ }
+ break;
+ case MOTION_BLOCK:
+ bink2f_decode_mv(c, gb, x, y, flags, &mv);
+ bink2f_predict_mv(c, x, y, flags, mv);
+ c->comp = 0;
+ ret = bink2f_mcompensate_luma(c, x, y,
+ dst[0], stride[0],
+ src[0], sstride[0],
+ w, h);
+ if (ret < 0)
+ goto fail;
+ c->comp = 1;
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
+ dst[2], stride[2],
+ src[2], sstride[2],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ c->comp = 2;
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
+ dst[1], stride[1],
+ src[1], sstride[1],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ break;
+ case RESIDUE_BLOCK:
+ bink2f_decode_mv(c, gb, x, y, flags, &mv);
+ bink2f_predict_mv(c, x, y, flags, mv);
+ ret = bink2f_mcompensate_luma(c, x, y,
+ dst[0], stride[0],
+ src[0], sstride[0],
+ w, h);
+ if (ret < 0)
+ goto fail;
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
+ dst[2], stride[2],
+ src[2], sstride[2],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
+ dst[1], stride[1],
+ src[1], sstride[1],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ c->comp = 0;
+ ret = bink2f_decode_inter_luma(c, c->block, &y_cbp_inter, &y_inter_q,
+ dst[0] + x, stride[0], flags);
+ if (ret < 0)
+ goto fail;
+ c->comp = 1;
+ ret = bink2f_decode_inter_chroma(c, c->block, &u_cbp_inter, &u_inter_q,
+ dst[2] + x/2, stride[2], flags);
+ if (ret < 0)
+ goto fail;
+ c->comp = 2;
+ ret = bink2f_decode_inter_chroma(c, c->block, &v_cbp_inter, &v_inter_q,
+ dst[1] + x/2, stride[1], flags);
+ if (ret < 0)
+ goto fail;
+ if (c->has_alpha) {
+ c->comp = 3;
+ ret = bink2f_decode_inter_luma(c, c->block, &a_cbp_inter, &a_inter_q,
+ dst[3] + x, stride[3], flags);
+ if (ret < 0)
+ goto fail;
+ }
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ dst[0] += stride[0] * 32;
+ dst[1] += stride[1] * 16;
+ dst[2] += stride[2] * 16;
+ dst[3] += stride[3] * 32;
+
+ FFSWAP(MVPredict *, c->current_mv, c->prev_mv);
+ FFSWAP(DCPredict *, c->current_dc, c->prev_dc);
+ }
+fail:
+ emms_c();
+
+ return ret;
+}
diff --git a/libavcodec/bink2g.c b/libavcodec/bink2g.c
new file mode 100644
index 0000000000..3f8d14e6eb
--- /dev/null
+++ b/libavcodec/bink2g.c
@@ -0,0 +1,1342 @@
+/*
+ * 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
+ */
+
+static inline void bink2g_idct_1d(int16_t *blk, int step, int shift)
+{
+#define idct_mul_a(val) ((val) + ((val) >> 2))
+#define idct_mul_b(val) ((val) >> 1)
+#define idct_mul_c(val) ((val) - ((val) >> 2) - ((val) >> 4))
+#define idct_mul_d(val) ((val) + ((val) >> 2) - ((val) >> 4))
+#define idct_mul_e(val) ((val) >> 2)
+ int tmp00 = blk[3*step] + blk[5*step];
+ int tmp01 = blk[3*step] - blk[5*step];
+ int tmp02 = idct_mul_a(blk[2*step]) + idct_mul_b(blk[6*step]);
+ int tmp03 = idct_mul_b(blk[2*step]) - idct_mul_a(blk[6*step]);
+ int tmp0 = (blk[0*step] + blk[4*step]) + tmp02;
+ int tmp1 = (blk[0*step] + blk[4*step]) - tmp02;
+ int tmp2 = blk[0*step] - blk[4*step];
+ int tmp3 = blk[1*step] + tmp00;
+ int tmp4 = blk[1*step] - tmp00;
+ int tmp5 = tmp01 + blk[7*step];
+ int tmp6 = tmp01 - blk[7*step];
+ int tmp7 = tmp4 + idct_mul_c(tmp6);
+ int tmp8 = idct_mul_c(tmp4) - tmp6;
+ int tmp9 = idct_mul_d(tmp3) + idct_mul_e(tmp5);
+ int tmp10 = idct_mul_e(tmp3) - idct_mul_d(tmp5);
+ int tmp11 = tmp2 + tmp03;
+ int tmp12 = tmp2 - tmp03;
+
+ blk[0*step] = (tmp0 + tmp9) >> shift;
+ blk[1*step] = (tmp11 + tmp7) >> shift;
+ blk[2*step] = (tmp12 + tmp8) >> shift;
+ blk[3*step] = (tmp1 + tmp10) >> shift;
+ blk[4*step] = (tmp1 - tmp10) >> shift;
+ blk[5*step] = (tmp12 - tmp8) >> shift;
+ blk[6*step] = (tmp11 - tmp7) >> shift;
+ blk[7*step] = (tmp0 - tmp9) >> shift;
+}
+
+static void bink2g_idct_put(uint8_t *dst, int stride, int16_t *block)
+{
+ for (int i = 0; i < 8; i++)
+ bink2g_idct_1d(block + i, 8, 0);
+ for (int i = 0; i < 8; i++)
+ bink2g_idct_1d(block + i * 8, 1, 6);
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++)
+ dst[j] = av_clip_uint8(block[j * 8 + i]);
+ dst += stride;
+ }
+}
+
+static void bink2g_idct_add(uint8_t *dst, int stride, int16_t *block)
+{
+ for (int i = 0; i < 8; i++)
+ bink2g_idct_1d(block + i, 8, 0);
+ for (int i = 0; i < 8; i++)
+ bink2g_idct_1d(block + i * 8, 1, 6);
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++)
+ dst[j] = av_clip_uint8(dst[j] + block[j * 8 + i]);
+ dst += stride;
+ }
+}
+
+static int bink2g_get_type(GetBitContext *gb, int *lru)
+{
+ int val;
+
+ ff_dlog(NULL, " type show %X @ %d\n", show_bits(gb, 4), get_bits_count(gb));
+ switch (get_unary(gb, 1, 3)) {
+ case 0:
+ val = lru[0];
+ break;
+ case 1:
+ val = lru[1];
+ FFSWAP(int, lru[0], lru[1]);
+ break;
+ case 2:
+ val = lru[3];
+ FFSWAP(int, lru[2], lru[3]);
+ break;
+ case 3:
+ val = lru[2];
+ FFSWAP(int, lru[1], lru[2]);
+ break;
+ }
+
+ return val;
+}
+
+static int bink2g_decode_dq(GetBitContext *gb)
+{
+ int dq = get_unary(gb, 1, 4);
+
+ if (dq == 3)
+ dq += get_bits1(gb);
+ else if (dq == 4)
+ dq += get_bits(gb, 5) + 1;
+ if (dq && get_bits1(gb))
+ dq = -dq;
+
+ return dq;
+}
+
+typedef uint8_t byte;
+typedef int8_t sbyte;
+typedef unsigned uint;
+
+static void bink2g_get_cbp_flags(GetBitContext *gb, int offset, int size, uint8_t *dst)
+{
+ unsigned flag;
+ int i, j;
+ byte bVar4;
+ sbyte sVar5;
+ byte bVar6;
+ int iVar7;
+ int uVar8;
+ int uVar9;
+ int local_20;
+ int local_1c;
+ int v;
+ int temp;
+
+ v = 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);
+ } else {
+ flag = 0;
+ local_1c = 0;
+ i = size;
+ if (size <= 0)
+ return;
+ do {
+ bVar4 = (byte)offset;
+ if (get_bits1(gb) == 0) {
+ if (local_1c == 3) {
+ flag ^= 1;
+ } else {
+ flag = get_bits1(gb);
+ }
+ local_1c = 2;
+ temp = i - 1;
+ bVar6 = (byte)(offset + 1);
+ if (temp < 4) {
+ uVar8 = get_bitsz(gb, temp);
+ uVar8 <<= bVar6 & 0x1f;
+ i = 0;
+ offset = offset + 1 + temp;
+ } else {
+ uVar8 = (get_bits(gb, 4)) << (bVar6 & 0x1f);
+ offset += 5;
+ i -= 5;
+ }
+ v = v | flag << (bVar4 & 0x1f) | uVar8;
+ if (7 < offset) {
+ *dst = v;
+ dst++;
+ v >>= 8;
+ offset -= 8;
+ }
+ } else {
+ uVar9 = 5;
+ if (i < 4) {
+ uVar9 = 2;
+ } else {
+ if (i < 0x10)
+ uVar9 = 4;
+ }
+ local_20 = uVar9 + 1;
+ if (local_1c == 3) {
+ flag ^= 1;
+ }
+ else {
+ local_20 = uVar9 + 2;
+ flag = get_bits1(gb);
+ }
+ if (i < local_20) {
+ local_20 = i;
+ }
+ i -= local_20;
+ if (i > 0) {
+ sVar5 = (sbyte)uVar9;
+ temp = get_bits(gb, sVar5);
+ i -= temp;
+ local_20 += temp;
+ local_1c = 3;
+ if (temp == (1 << sVar5) - 1U) {
+ local_1c = 1;
+ }
+ }
+ temp = (int)(flag << 0x1f) >> 0x1f & 0xff;
+ if (8 < local_20) {
+ iVar7 = (local_20 - 9 >> 3) + 1;
+ do {
+ v |= temp << (bVar4 & 0x1f);
+ *dst = v;
+ dst++;
+ v >>= 8;
+ local_20 -= 8;
+ iVar7 += -1;
+ } while (iVar7 != 0);
+ }
+ if (local_20 > 0) {
+ offset += local_20;
+ v |= ((1 << ((byte)local_20 & 0x1f)) - 1U & temp) << (bVar4 & 0x1f);
+ if (7 < offset) {
+ *dst = v;
+ dst++;
+ v >>= 8;
+ offset -= 8;
+ }
+ }
+ }
+ } while (i > 0);
+
+ if (offset != 0)
+ *dst = v;
+ }
+}
+
+static unsigned bink2g_decode_cbp_luma(Bink2Context *c,
+ GetBitContext *gb, unsigned prev_cbp)
+{
+ unsigned ones = 0, cbp, mask;
+
+ for (int i = 0; i < 16; i++) {
+ if (prev_cbp & (1 << i))
+ ones += 1;
+ }
+
+ cbp = 0;
+ mask = 0;
+ if (ones > 7) {
+ ones = 16 - ones;
+ mask = 0xFFFF;
+ }
+
+ if (get_bits1(gb) == 0) {
+ if (ones < 4) {
+ for (int j = 0; j < 16; j += 4)
+ if (!get_bits1(gb))
+ cbp |= get_bits(gb, 4) << j;
+ } else {
+ cbp = get_bits(gb, 16);
+ }
+ }
+
+ cbp ^= mask;
+ if (!(c->frame_flags & 0x40000) || cbp) {
+ if (get_bits1(gb))
+ cbp = cbp | cbp << 16;
+ }
+
+ return cbp;
+}
+
+static unsigned bink2g_decode_cbp_chroma(GetBitContext *gb, unsigned prev_cbp)
+{
+ unsigned cbp;
+
+ cbp = prev_cbp & 0xF0000 | bink2g_chroma_cbp_pat[prev_cbp & 0xF];
+ if (get_bits1(gb) == 0) {
+ cbp = get_bits(gb, 4);
+ if (get_bits1(gb))
+ cbp |= cbp << 16;
+ }
+
+ return cbp;
+}
+
+static void bink2g_predict_dc(Bink2Context *c,
+ int is_luma, int mindc, int maxdc,
+ int flags, int tdc[16])
+{
+ int *LTdc = c->prev_idc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
+ int *Tdc = c->prev_idc[c->mb_pos].dc[c->comp];
+ int *Ldc = c->current_idc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
+ int *dc = c->current_idc[c->mb_pos].dc[c->comp];
+
+ if (is_luma && (flags & 0x20) && (flags & 0x80)) {
+ dc[0] = av_clip((mindc < 0 ? 0 : 1024) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clip(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clip(dc[4] + tdc[5], mindc, maxdc);
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clip(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clip(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (is_luma && (flags & 0x80)) {
+ dc[0] = av_clip(DC_MPRED2(Ldc[5], Ldc[7]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clip(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clip(dc[4] + tdc[5], mindc, maxdc);
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clip(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clip(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (is_luma && (flags & 0x20)) {
+ dc[0] = av_clip(DC_MPRED2(Tdc[10], Tdc[11]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clip(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clip(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clip(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clip(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (is_luma) {
+ dc[0] = av_clip(DC_MPRED(LTdc[15], Ldc[5], Tdc[10]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ dc[4] = av_clip(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
+ dc[5] = av_clip(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
+ dc[8] = av_clip(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
+ dc[10] = av_clip(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
+ } else if (!is_luma && (flags & 0x20) && (flags & 0x80)) {
+ dc[0] = av_clip((mindc < 0 ? 0 : 1024) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ } else if (!is_luma && (flags & 0x80)) {
+ dc[0] = av_clip(DC_MPRED2(Ldc[1], Ldc[3]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ } else if (!is_luma && (flags & 0x20)) {
+ dc[0] = av_clip(DC_MPRED2(Tdc[2], Tdc[3]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ } else if (!is_luma) {
+ dc[0] = av_clip(DC_MPRED(LTdc[3], Ldc[1], Tdc[2]) + tdc[0], mindc, maxdc);
+ dc[1] = av_clip(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
+ dc[2] = av_clip(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
+ }
+}
+
+static void bink2g_decode_dc(Bink2Context *c, GetBitContext *gb, int *dc,
+ int is_luma, int q, int mindc, int maxdc,
+ int flags)
+{
+ const int num_dc = is_luma ? 16 : 4;
+ int tdc[16];
+ int pat;
+
+ q = FFMAX(q, 8);
+ pat = bink2g_dc_pat[q];
+
+ memset(tdc, 0, sizeof(tdc));
+
+ if (get_bits1(gb)) {
+ for (int i = 0; i < num_dc; i++) {
+ int cnt = get_unary(gb, 0, 12);
+
+ if (cnt > 3)
+ cnt = (1 << (cnt - 3)) + get_bits(gb, cnt - 3) + 2;
+ if (cnt && get_bits1(gb))
+ cnt = -cnt;
+ tdc[i] = (cnt * pat + 0x200) >> 10;
+ //ff_dlog(NULL, " dc = %d @ %d\n", cnt, get_bits_count(gb));
+ //ff_dlog(NULL, " tdc = %d @ %d\n", tdc[i], get_bits_count(gb));
+ }
+ }
+
+ bink2g_predict_dc(c, is_luma, mindc, maxdc, flags, tdc);
+}
+
+static int bink2g_decode_ac(GetBitContext *gb, const uint8_t scan[64],
+ int16_t block[4][64], unsigned cbp,
+ int q, const uint16_t qmat[4][64])
+{
+ int idx, next, val, skip;
+ VLC *skip_vlc;
+
+ for (int i = 0; i < 4; i++)
+ memset(block[i], 0, sizeof(int16_t) * 64);
+
+ if ((cbp & 0xf) == 0)
+ return 0;
+
+ skip_vlc = &bink2g_ac_skip0_vlc;
+ if (cbp & 0xffff0000)
+ skip_vlc = &bink2g_ac_skip1_vlc;
+
+ for (int i = 0; i < 4; i++, cbp >>= 1) {
+ if (!(cbp & 1))
+ continue;
+
+ //ff_dlog(NULL, " block %d\n", i);
+ next = 0;
+ idx = 1;
+ while (idx < 64) {
+ next--;
+ if (next < 1) {
+ skip = get_vlc2(gb, skip_vlc->table, skip_vlc->bits, 1);
+ //ff_dlog(NULL, " AC skip sym %d @ %d\n", skip, get_bits_count(gb));
+ if (skip < 0)
+ return AVERROR_INVALIDDATA;
+ next = bink2_next_skips[skip];
+ skip = bink2g_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ //ff_dlog(NULL, " AC skip = %d + %d\n", skip, idx);
+ idx += skip;
+ if (idx >= 64)
+ break;
+ }
+
+ val = get_unary(gb, 0, 12) + 1;
+ if (val > 3)
+ val = get_bits(gb, val - 3) + (1 << (val - 3)) + 2;
+ if (get_bits1(gb))
+ val = -val;
+ //ff_dlog(NULL, " AC val = %d @ %d\n", val, get_bits_count(gb));
+ block[i][scan[idx]] = ((val * qmat[q & 3][scan[idx]] * (1 << (q >> 2))) + 64) >> 7;
+ //ff_dlog(NULL, " AC val = %d @ %d\n", block[i][scan[idx]], get_bits_count(gb));
+ idx++;
+ }
+ }
+
+ return 0;
+}
+
+static int bink2g_decode_intra_luma(Bink2Context *c,
+ GetBitContext *gb, int16_t block[4][64],
+ unsigned *prev_cbp, int q,
+ BlockDSPContext *dsp, uint8_t *dst, int stride,
+ int flags)
+{
+ int *dc = c->current_idc[c->mb_pos].dc[c->comp];
+ unsigned cbp;
+ int ret;
+
+ *prev_cbp = cbp = bink2g_decode_cbp_luma(c, gb, *prev_cbp);
+ ff_dlog(NULL, " intra Y CBP %X @ %d\n", cbp, get_bits_count(gb));
+
+ bink2g_decode_dc(c, gb, dc, 1, q, 0, 2047, flags);
+
+ for (int i = 0; i < 4; i++) {
+ ret = bink2g_decode_ac(gb, bink2g_scan, block, cbp >> (4*i),
+ q, bink2g_luma_intra_qmat);
+ if (ret < 0)
+ return ret;
+
+ for (int j = 0; j < 4; j++) {
+ block[j][0] = dc[i * 4 + j] * 8 + 32;
+ bink2g_idct_put(dst + (luma_repos[i * 4 + j] & 3) * 8 +
+ (luma_repos[i * 4 + j] >> 2) * 8 * stride, stride, block[j]);
+ }
+ }
+
+ return 0;
+}
+
+static int bink2g_decode_intra_chroma(Bink2Context *c,
+ GetBitContext *gb, int16_t block[4][64],
+ unsigned *prev_cbp, int q,
+ BlockDSPContext *dsp, uint8_t *dst, int stride,
+ int flags)
+{
+ int *dc = c->current_idc[c->mb_pos].dc[c->comp];
+ unsigned cbp;
+ int ret;
+
+ *prev_cbp = cbp = bink2g_decode_cbp_chroma(gb, *prev_cbp);
+ ff_dlog(NULL, " intra C CBP %X @ %d\n", cbp, get_bits_count(gb));
+
+ bink2g_decode_dc(c, gb, dc, 0, q, 0, 2047, flags);
+
+ ret = bink2g_decode_ac(gb, bink2g_scan, block, cbp,
+ q, bink2g_chroma_intra_qmat);
+ if (ret < 0)
+ return ret;
+
+ for (int j = 0; j < 4; j++) {
+ block[j][0] = dc[j] * 8 + 32;
+ bink2g_idct_put(dst + (j & 1) * 8 +
+ (j >> 1) * 8 * stride, stride, block[j]);
+ }
+
+ return 0;
+}
+
+static int bink2g_decode_inter_luma(Bink2Context *c,
+ GetBitContext *gb, int16_t block[4][64],
+ unsigned *prev_cbp, int q,
+ BlockDSPContext *dsp, uint8_t *dst, int stride,
+ int flags)
+{
+ int *dc = c->current_idc[c->mb_pos].dc[c->comp];
+ unsigned cbp;
+ int ret;
+
+ *prev_cbp = cbp = bink2g_decode_cbp_luma(c, gb, *prev_cbp);
+ ff_dlog(NULL, " inter Y CBP %X @ %d\n", cbp, get_bits_count(gb));
+
+ bink2g_decode_dc(c, gb, dc, 1, q, -1023, 1023, 0xA8);
+
+ for (int i = 0; i < 4; i++) {
+ ret = bink2g_decode_ac(gb, bink2g_scan, block, cbp >> (4 * i),
+ q, bink2g_inter_qmat);
+ if (ret < 0)
+ return ret;
+
+ for (int j = 0; j < 4; j++) {
+ block[j][0] = dc[i * 4 + j] * 8 + 32;
+ bink2g_idct_add(dst + (luma_repos[i * 4 + j] & 3) * 8 +
+ (luma_repos[i * 4 + j] >> 2) * 8 * stride,
+ stride, block[j]);
+ }
+ }
+
+ return 0;
+}
+
+static int bink2g_decode_inter_chroma(Bink2Context *c,
+ GetBitContext *gb, int16_t block[4][64],
+ unsigned *prev_cbp, int q,
+ BlockDSPContext *dsp, uint8_t *dst, int stride,
+ int flags)
+{
+ int *dc = c->current_idc[c->mb_pos].dc[c->comp];
+ unsigned cbp;
+ int ret;
+
+ *prev_cbp = cbp = bink2g_decode_cbp_chroma(gb, *prev_cbp);
+ ff_dlog(NULL, " inter C CBP %X @ %d\n", cbp, get_bits_count(gb));
+
+ bink2g_decode_dc(c, gb, dc, 0, q, -1023, 1023, 0xA8);
+
+ ret = bink2g_decode_ac(gb, bink2g_scan, block, cbp,
+ q, bink2g_inter_qmat);
+ if (ret < 0)
+ return ret;
+
+ for (int j = 0; j < 4; j++) {
+ block[j][0] = dc[j] * 8 + 32;
+ bink2g_idct_add(dst + (j & 1) * 8 +
+ (j >> 1) * 8 * stride, stride, block[j]);
+ }
+
+ return 0;
+}
+
+static void bink2g_predict_mv(Bink2Context *c, int x, int y, int flags, MVectors mv)
+{
+ MVectors *c_mv = &c->current_mv[c->mb_pos].mv;
+ MVectors *l_mv = &c->current_mv[FFMAX(c->mb_pos - 1, 0)].mv;
+ MVectors *lt_mv = &c->prev_mv[FFMAX(c->mb_pos - 1, 0)].mv;
+ MVectors *t_mv = &c->prev_mv[c->mb_pos].mv;
+
+ if (mv.nb_vectors == 1) {
+ if (flags & 0x80) {
+ if (!(flags & 0x20)) {
+ mv.v[0][0] += mid_pred(l_mv->v[0][0], l_mv->v[1][0], l_mv->v[3][0]);
+ mv.v[0][1] += mid_pred(l_mv->v[0][1], l_mv->v[1][1], l_mv->v[3][1]);
+ }
+ } else {
+ if (!(flags & 0x20)) {
+ mv.v[0][0] += mid_pred(lt_mv->v[3][0], t_mv->v[2][0], l_mv->v[1][0]);
+ mv.v[0][1] += mid_pred(lt_mv->v[3][1], t_mv->v[2][1], l_mv->v[1][1]);
+ } else {
+ mv.v[0][0] += mid_pred(t_mv->v[0][0], t_mv->v[2][0], t_mv->v[3][0]);
+ mv.v[0][1] += mid_pred(t_mv->v[0][1], t_mv->v[2][1], t_mv->v[3][1]);
+ }
+ }
+
+ c_mv->v[0][0] = mv.v[0][0];
+ c_mv->v[0][1] = mv.v[0][1];
+ c_mv->v[1][0] = mv.v[0][0];
+ c_mv->v[1][1] = mv.v[0][1];
+ c_mv->v[2][0] = mv.v[0][0];
+ c_mv->v[2][1] = mv.v[0][1];
+ c_mv->v[3][0] = mv.v[0][0];
+ c_mv->v[3][1] = mv.v[0][1];
+
+ ff_dlog(NULL, " predicted MVs:");
+ for (int i = 0; i < 4; i++)
+ ff_dlog(NULL, " %d,%d", c_mv->v[i][0], c_mv->v[i][1]);
+ ff_dlog(NULL, "\n");
+ return;
+ }
+
+ if (!(flags & 0x80)) {
+ if (flags & 0x20) {
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(t_mv->v[0][0], t_mv->v[2][0], t_mv->v[3][0]);
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(t_mv->v[0][1], t_mv->v[2][1], t_mv->v[3][1]);
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred(t_mv->v[2][0], t_mv->v[3][0], c_mv->v[0][0]);
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred(t_mv->v[2][1], t_mv->v[3][1], c_mv->v[0][1]);
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred(t_mv->v[2][0], c_mv->v[0][0], c_mv->v[1][0]);
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred(t_mv->v[2][1], c_mv->v[0][1], c_mv->v[1][1]);
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
+ } else {
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(t_mv->v[2][0], lt_mv->v[3][0], l_mv->v[1][0]);
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(t_mv->v[2][1], lt_mv->v[3][1], l_mv->v[1][1]);
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred(t_mv->v[2][0], t_mv->v[3][0], c_mv->v[0][0]);
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred(t_mv->v[2][1], t_mv->v[3][1], c_mv->v[0][1]);
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred(l_mv->v[1][0], l_mv->v[3][0], c_mv->v[0][0]);
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred(l_mv->v[1][1], l_mv->v[3][1], c_mv->v[0][1]);
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
+ }
+ } else {
+ if (flags & 0x20) {
+ c_mv->v[0][0] = mv.v[0][0];
+ c_mv->v[0][1] = mv.v[0][1];
+ c_mv->v[1][0] = mv.v[1][0] + mv.v[0][0];
+ c_mv->v[1][1] = mv.v[1][1] + mv.v[0][1];
+ c_mv->v[2][0] = mv.v[2][0] + mv.v[0][0];
+ c_mv->v[2][1] = mv.v[2][1] + mv.v[0][1];
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
+ } else {
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(l_mv->v[0][0], l_mv->v[1][0], l_mv->v[3][0]);
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(l_mv->v[0][1], l_mv->v[1][1], l_mv->v[3][1]);
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred(l_mv->v[1][0], l_mv->v[3][0], c_mv->v[0][0]);
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred(l_mv->v[1][1], l_mv->v[3][1], c_mv->v[0][1]);
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred(l_mv->v[1][0], c_mv->v[0][0], c_mv->v[2][0]);
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred(l_mv->v[1][1], c_mv->v[0][1], c_mv->v[2][1]);
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
+ }
+ }
+
+ ff_dlog(NULL, " predicted MVs:");
+ for (int i = 0; i < 4; i++)
+ ff_dlog(NULL, " %d,%d", c_mv->v[i][0], c_mv->v[i][1]);
+ ff_dlog(NULL, "\n");
+}
+
+static int bink2g_decode_mv(Bink2Context *c, GetBitContext *gb, int x, int y,
+ MVectors *mv)
+{
+ int num_mvs = get_bits1(gb) ? 1 : 4;
+
+ mv->nb_vectors = num_mvs;
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < num_mvs; j++) {
+ int val = get_vlc2(gb, bink2g_mv_vlc.table, bink2g_mv_vlc.bits, 1);
+
+ ff_dlog(NULL, " MV val = %d @ %d\n", val, get_bits_count(gb));
+ if (val < 0)
+ return AVERROR_INVALIDDATA;
+ if (val >= 8 && val != 15)
+ val = val - 15;
+ if (val == 15) {
+ int bits = get_unary(gb, 1, 12) + 4;
+ val = get_bits(gb, bits) + (1 << bits) - 1;
+ if (val & 1)
+ val = (-(val >> 1) - 1);
+ else
+ val = val >> 1;
+ }
+ mv->v[j][i] = val;
+ ff_dlog(NULL, " MV [%d,%d] = %d @ %d\n", j, i, val, get_bits_count(gb));
+ }
+ }
+
+ return 0;
+}
+
+static void update_intra_q(Bink2Context *c, int8_t *intra_q, int dq, int flags)
+{
+ if (flags & 0x20 && flags & 0x80)
+ *intra_q = 16 + dq;
+ else if (flags & 0x80)
+ *intra_q = c->current_q[c->mb_pos - 1].intra_q + dq;
+ else if (flags & 0x20)
+ *intra_q = c->prev_q[c->mb_pos].intra_q + dq;
+ else
+ *intra_q = mid_pred(c->prev_q[c->mb_pos].intra_q,
+ c->current_q[c->mb_pos - 1].intra_q,
+ c->prev_q[c->mb_pos - 1].intra_q) + dq;
+}
+
+static void update_inter_q(Bink2Context *c, int8_t *inter_q, int dq, int flags)
+{
+ if (flags & 0x20 && flags & 0x80)
+ *inter_q = 16 + dq;
+ else if (flags & 0x80)
+ *inter_q = c->current_q[c->mb_pos - 1].inter_q + dq;
+ else if (flags & 0x20)
+ *inter_q = c->prev_q[c->mb_pos].inter_q + dq;
+ else
+ *inter_q = mid_pred(c->prev_q[c->mb_pos].inter_q,
+ c->current_q[c->mb_pos - 1].inter_q,
+ c->prev_q[c->mb_pos - 1].inter_q) + dq;
+}
+
+#define CH1FILTER(src) ((6*(src)[0] + 2*(src)[1] + 4) >> 3)
+#define CH2FILTER(src) (( (src)[0] + (src)[1] + 1) >> 1)
+#define CH3FILTER(src) ((2*(src)[0] + 6*(src)[1] + 4) >> 3)
+
+#define CV1FILTER(src, i) ((6*(src)[0] + 2*(src)[i] + 4) >> 3)
+#define CV2FILTER(src, i) (( (src)[0] + (src)[i] + 1) >> 1)
+#define CV3FILTER(src, i) ((2*(src)[0] + 6*(src)[i] + 4) >> 3)
+
+static void bink2g_c_mc(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height,
+ int mv_x, int mv_y,
+ int mode)
+{
+ uint8_t *msrc;
+ uint8_t temp[8*9];
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ //ff_dlog(NULL, "CHROMA %d: %dx%d | %dx%d\n", mode, x, y, mv_x, mv_y);
+ switch (mode) {
+ case 0:
+ copy_block8(dst, msrc, stride, sstride, 8);
+ break;
+ case 1:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CH1FILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ break;
+ case 2:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CH2FILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ break;
+ case 3:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CH3FILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ break;
+ case 4:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i*stride] = av_clip_uint8(CV1FILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ break;
+ case 5:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 6:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 7:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 8:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i*stride] = av_clip_uint8(CV2FILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ break;
+ case 9:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 10:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 11:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 12:
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i*stride] = av_clip_uint8(CV3FILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ break;
+ case 13:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 14:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ case 15:
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 8; j++)
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 8; j++) {
+ for (int i = 0; i < 8; i++)
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
+ dst += stride;
+ }
+ break;
+ }
+}
+
+static int bink2g_mcompensate_chroma(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height)
+{
+ MVectors *mv = &c->current_mv[c->mb_pos].mv;
+ int mv_x, mv_y, mode;
+
+ mv_x = (mv->v[0][0] >> 2) + x;
+ mv_y = (mv->v[0][1] >> 2) + y;
+ mode = mv->v[0][0] & 3;
+ mode |= (mv->v[0][1] & 3) << 2;
+ bink2g_c_mc(c, x, y, dst + x, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[1][0] >> 2) + x + 8;
+ mv_y = (mv->v[1][1] >> 2) + y;
+ mode = mv->v[1][0] & 3;
+ mode |= (mv->v[1][1] & 3) << 2;
+ bink2g_c_mc(c, x, y, dst + x + 8, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[2][0] >> 2) + x;
+ mv_y = (mv->v[2][1] >> 2) + y + 8;
+ mode = mv->v[2][0] & 3;
+ mode |= (mv->v[2][1] & 3) << 2;
+ bink2g_c_mc(c, x, y, dst + x + 8 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[3][0] >> 2) + x + 8;
+ mv_y = (mv->v[3][1] >> 2) + y + 8;
+ mode = mv->v[3][0] & 3;
+ mode |= (mv->v[3][1] & 3) << 2;
+ bink2g_c_mc(c, x, y, dst + x + 8 + 8 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ return 0;
+}
+
+#define LHFILTER(src) ((((src)[0]+(src)[1])*19 >> 1)-((src)[-1]+(src)[2 ])*2+(((src)[-2 ]+(src)[3 ])>>1)+8>>4)
+#define LVFILTER(src, i) ((((src)[0]+(src)[i])*19 >> 1)-((src)[-i]+(src)[2*i])*2+(((src)[-2*i]+(src)[3*i])>>1)+8>>4)
+
+static void bink2g_y_mc(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height,
+ int mv_x, int mv_y, int mode)
+{
+ uint8_t *msrc;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ //ff_dlog(NULL, "LUMA %d: %dx%d | %dx%d\n", mode, x, y, mv_x, mv_y);
+ if (mode == 0) {
+ copy_block16(dst, msrc, stride, sstride, 16);
+ } else if (mode == 1) {
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 16; i++)
+ dst[i] = av_clip_uint8(LHFILTER(msrc + i));
+ dst += stride;
+ msrc += sstride;
+ }
+ } else if (mode == 2) {
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 16; i++)
+ dst[i*stride] = av_clip_uint8(LVFILTER(msrc + i*sstride, sstride));
+ dst += 1;
+ msrc += 1;
+ }
+ } else if (mode == 3) {
+ uint8_t temp[21 * 16];
+
+ msrc -= 2 * sstride;
+ for (int i = 0; i < 21; i++) {
+ for (int j = 0; j < 16; j++)
+ temp[i*16+j] = av_clip_uint8(LHFILTER(msrc + j));
+ msrc += sstride;
+ }
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 16; i++)
+ dst[i] = av_clip_uint8(LVFILTER(temp+(j+2)*16+i, 16));
+ dst += stride;
+ }
+ }
+}
+
+static int bink2g_mcompensate_luma(Bink2Context *c, int x, int y,
+ uint8_t *dst, int stride,
+ uint8_t *src, int sstride,
+ int width, int height)
+{
+ MVectors *mv = &c->current_mv[c->mb_pos].mv;
+ int mv_x, mv_y, mode;
+
+ mv_x = (mv->v[0][0] >> 1) + x;
+ mv_y = (mv->v[0][1] >> 1) + y;
+ mode = mv->v[0][0] & 1;
+ mode |= (mv->v[0][1] & 1) << 1;
+ bink2g_y_mc(c, x, y, dst + x, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[1][0] >> 1) + x + 16;
+ mv_y = (mv->v[1][1] >> 1) + y;
+ mode = mv->v[1][0] & 1;
+ mode |= (mv->v[1][1] & 1) << 1;
+ bink2g_y_mc(c, x, y, dst + x + 16, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[2][0] >> 1) + x;
+ mv_y = (mv->v[2][1] >> 1) + y + 16;
+ mode = mv->v[2][0] & 1;
+ mode |= (mv->v[2][1] & 1) << 1;
+ bink2g_y_mc(c, x, y, dst + x + 16 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ mv_x = (mv->v[3][0] >> 1) + x + 16;
+ mv_y = (mv->v[3][1] >> 1) + y + 16;
+ mode = mv->v[3][0] & 1;
+ mode |= (mv->v[3][1] & 1) << 1;
+ bink2g_y_mc(c, x, y, dst + x + 16 + 16 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
+
+ return 0;
+}
+
+static int bink2g_average_block(uint8_t *src, int stride)
+{
+ int sum = 0;
+
+ for (int i = 0; i < 8; i++) {
+ int avg_a = (src[i+0*stride] + src[i+1*stride] + 1) >> 1;
+ int avg_b = (src[i+2*stride] + src[i+3*stride] + 1) >> 1;
+ int avg_c = (src[i+4*stride] + src[i+5*stride] + 1) >> 1;
+ int avg_d = (src[i+6*stride] + src[i+7*stride] + 1) >> 1;
+ int avg_e = (avg_a + avg_b + 1) >> 1;
+ int avg_f = (avg_c + avg_d + 1) >> 1;
+ int avg_g = (avg_e + avg_f + 1) >> 1;
+ sum += avg_g;
+ }
+
+ return sum;
+}
+
+static void bink2g_average_chroma(Bink2Context *c, int x, int y,
+ uint8_t *src, int stride,
+ int *dc)
+{
+ for (int i = 0; i < 4; i++) {
+ int X = i & 1;
+ int Y = i >> 1;
+ dc[i] = bink2g_average_block(src + x + X * 8 + (y + Y * 8) * stride, stride);
+ }
+}
+
+static void bink2g_average_luma(Bink2Context *c, int x, int y,
+ uint8_t *src, int stride,
+ int *dc)
+{
+ for (int i = 0; i < 16; i++) {
+ int I = luma_repos[i];
+ int X = I & 3;
+ int Y = I >> 2;
+ dc[i] = bink2g_average_block(src + x + X * 8 + (y + Y * 8) * stride, stride);
+ //ff_dlog(NULL, " DC avg %d:%d\n", i, dc[i]);
+ }
+}
+
+static int bink2g_decode_slice(Bink2Context *c,
+ uint8_t *dst[4], int stride[4],
+ uint8_t *src[4], int sstride[4],
+ int is_kf, int start, int end)
+{
+ GetBitContext *gb = &c->gb;
+ int w = c->avctx->width;
+ int h = c->avctx->height;
+ int ret = 0, dq, flags;
+
+ memset(c->prev_q, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->prev_q));
+ memset(c->prev_mv, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->prev_mv));
+
+ for (int y = start; y < end; y += 32) {
+ int types_lru[4] = { MOTION_BLOCK, RESIDUE_BLOCK, SKIP_BLOCK, INTRA_BLOCK };
+ unsigned y_cbp_intra = 0, u_cbp_intra = 0, v_cbp_intra = 0, a_cbp_intra = 0;
+ unsigned y_cbp_inter = 0, u_cbp_inter = 0, v_cbp_inter = 0, a_cbp_inter = 0;
+
+ memset(c->current_q, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->current_q));
+ memset(c->current_mv, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->current_mv));
+
+ for (int x = 0; x < c->avctx->width; x += 32) {
+ int type = is_kf ? INTRA_BLOCK : bink2g_get_type(gb, types_lru);
+ int8_t *intra_q = &c->current_q[x / 32].intra_q;
+ int8_t *inter_q = &c->current_q[x / 32].inter_q;
+ MVectors mv = { 0 };
+
+ if (!is_kf)
+ ff_dlog(NULL, " lru %d %d %d %d @ %d\n",
+ types_lru[0], types_lru[1], types_lru[2], types_lru[3],
+ get_bits_count(gb));
+ ff_dlog(NULL, " MB %d,%d @ %d\n", x/32, y/32, get_bits_count(gb));
+
+ c->mb_pos = x / 32;
+ c->current_idc[c->mb_pos].block_type = type;
+ flags = 0;
+ if (y == start)
+ flags |= 0x80;
+ if (!x)
+ flags |= 0x20;
+ if (x == 32)
+ flags |= 0x200;
+ if (x + 32 >= c->avctx->width)
+ flags |= 0x40;
+ ff_dlog(NULL, " MB type %d @ %d\n", type, get_bits_count(gb));
+ switch (type) {
+ case INTRA_BLOCK:
+ if (!(flags & 0xA0) && c->prev_idc[c->mb_pos - 1].block_type != INTRA_BLOCK) {
+ bink2g_average_luma (c, x -32, -32, dst[0], stride[0], c->prev_idc[c->mb_pos - 1].dc[0]);
+ bink2g_average_chroma(c, x/2-16, -16, dst[2], stride[2], c->prev_idc[c->mb_pos - 1].dc[1]);
+ bink2g_average_chroma(c, x/2-16, -16, dst[1], stride[1], c->prev_idc[c->mb_pos - 1].dc[2]);
+ if (c->has_alpha)
+ bink2g_average_luma(c, x-32, -32, dst[3], stride[3], c->prev_idc[c->mb_pos - 1].dc[3]);
+ }
+ if (!(flags & 0x20) && c->current_idc[c->mb_pos - 1].block_type != INTRA_BLOCK) {
+ bink2g_average_luma (c, x -32, 0, dst[0], stride[0], c->current_idc[c->mb_pos - 1].dc[0]);
+ bink2g_average_chroma(c, x/2-16, 0, dst[2], stride[2], c->current_idc[c->mb_pos - 1].dc[1]);
+ bink2g_average_chroma(c, x/2-16, 0, dst[1], stride[1], c->current_idc[c->mb_pos - 1].dc[2]);
+ if (c->has_alpha)
+ bink2g_average_luma(c, x-32, 0, dst[3], stride[3], c->current_idc[c->mb_pos - 1].dc[3]);
+ }
+ if ((flags & 0x20) && !(flags & 0x80) && c->prev_idc[c->mb_pos + 1].block_type != INTRA_BLOCK) {
+ bink2g_average_luma (c, x +32, -32, dst[0], stride[0], c->prev_idc[c->mb_pos + 1].dc[0]);
+ bink2g_average_chroma(c, x/2+16, -16, dst[2], stride[2], c->prev_idc[c->mb_pos + 1].dc[1]);
+ bink2g_average_chroma(c, x/2+16, -16, dst[1], stride[1], c->prev_idc[c->mb_pos + 1].dc[2]);
+ if (c->has_alpha)
+ bink2g_average_luma(c, x+32, -32, dst[3], stride[3], c->prev_idc[c->mb_pos + 1].dc[3]);
+ }
+ if (!(flags & 0x80) && c->prev_idc[c->mb_pos].block_type != INTRA_BLOCK) {
+ bink2g_average_luma (c, x, -32, dst[0], stride[0], c->prev_idc[c->mb_pos].dc[0]);
+ bink2g_average_chroma(c, x/2, -16, dst[2], stride[2], c->prev_idc[c->mb_pos].dc[1]);
+ bink2g_average_chroma(c, x/2, -16, dst[1], stride[1], c->prev_idc[c->mb_pos].dc[2]);
+ if (c->has_alpha)
+ bink2g_average_luma(c, x, -32, dst[3], stride[3], c->prev_idc[c->mb_pos].dc[3]);
+ }
+
+ bink2g_predict_mv(c, x, y, flags, mv);
+ update_inter_q(c, inter_q, 0, flags);
+ dq = bink2g_decode_dq(gb);
+ update_intra_q(c, intra_q, dq, flags);
+ ff_dlog(NULL, " MB quant %d @ %d\n", *intra_q, get_bits_count(gb));
+ if (*intra_q < 0 || *intra_q >= 37) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ c->comp = 0;
+ ret = bink2g_decode_intra_luma(c, gb, c->iblock, &y_cbp_intra, *intra_q, &c->dsp,
+ dst[0] + x, stride[0], flags);
+ if (ret < 0)
+ goto fail;
+ c->comp = 1;
+ ret = bink2g_decode_intra_chroma(c, gb, c->iblock, &u_cbp_intra, *intra_q, &c->dsp,
+ dst[2] + x/2, stride[2], flags);
+ if (ret < 0)
+ goto fail;
+ c->comp = 2;
+ ret = bink2g_decode_intra_chroma(c, gb, c->iblock, &v_cbp_intra, *intra_q, &c->dsp,
+ dst[1] + x/2, stride[1], flags);
+ if (ret < 0)
+ goto fail;
+ if (c->has_alpha) {
+ c->comp = 3;
+ ret = bink2g_decode_intra_luma(c, gb, c->iblock, &a_cbp_intra, *intra_q, &c->dsp,
+ dst[3] + x, stride[3], flags);
+ if (ret < 0)
+ goto fail;
+ }
+ break;
+ case SKIP_BLOCK:
+ update_inter_q(c, inter_q, 0, flags);
+ update_intra_q(c, intra_q, 0, flags);
+ copy_block16(dst[0] + x, src[0] + x + sstride[0] * y,
+ stride[0], sstride[0], 32);
+ copy_block16(dst[0] + x + 16, src[0] + x + 16 + sstride[0] * y,
+ stride[0], sstride[0], 32);
+ copy_block16(dst[1] + (x/2), src[1] + (x/2) + sstride[1] * (y/2),
+ stride[1], sstride[1], 16);
+ copy_block16(dst[2] + (x/2), src[2] + (x/2) + sstride[2] * (y/2),
+ stride[2], sstride[2], 16);
+ if (c->has_alpha) {
+ copy_block16(dst[3] + x, src[3] + x + sstride[3] * y,
+ stride[3], sstride[3], 32);
+ copy_block16(dst[3] + x + 16, src[3] + x + 16 + sstride[3] * y,
+ stride[3], sstride[3], 32);
+ }
+ break;
+ case MOTION_BLOCK:
+ update_intra_q(c, intra_q, 0, flags);
+ update_inter_q(c, inter_q, 0, flags);
+ ret = bink2g_decode_mv(c, gb, x, y, &mv);
+ if (ret < 0)
+ goto fail;
+ bink2g_predict_mv(c, x, y, flags, mv);
+ c->comp = 0;
+ ret = bink2g_mcompensate_luma(c, x, y,
+ dst[0], stride[0],
+ src[0], sstride[0],
+ w, h);
+ if (ret < 0)
+ goto fail;
+ c->comp = 1;
+ ret = bink2g_mcompensate_chroma(c, x/2, y/2,
+ dst[2], stride[2],
+ src[2], sstride[2],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ c->comp = 2;
+ ret = bink2g_mcompensate_chroma(c, x/2, y/2,
+ dst[1], stride[1],
+ src[1], sstride[1],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ if (c->has_alpha) {
+ c->comp = 3;
+ ret = bink2g_mcompensate_luma(c, x, y,
+ dst[3], stride[3],
+ src[3], sstride[3],
+ w, h);
+ if (ret < 0)
+ goto fail;
+ }
+ break;
+ case RESIDUE_BLOCK:
+ update_intra_q(c, intra_q, 0, flags);
+ ret = bink2g_decode_mv(c, gb, x, y, &mv);
+ if (ret < 0)
+ goto fail;
+ bink2g_predict_mv(c, x, y, flags, mv);
+ dq = bink2g_decode_dq(gb);
+ update_inter_q(c, inter_q, dq, flags);
+ ff_dlog(NULL, " MB quant %d @ %d\n", *inter_q, get_bits_count(gb));
+ if (*inter_q < 0 || *inter_q >= 37) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ c->comp = 0;
+ ret = bink2g_mcompensate_luma(c, x, y,
+ dst[0], stride[0],
+ src[0], sstride[0],
+ w, h);
+ if (ret < 0)
+ goto fail;
+ c->comp = 1;
+ ret = bink2g_mcompensate_chroma(c, x/2, y/2,
+ dst[2], stride[2],
+ src[2], sstride[2],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ c->comp = 2;
+ ret = bink2g_mcompensate_chroma(c, x/2, y/2,
+ dst[1], stride[1],
+ src[1], sstride[1],
+ w/2, h/2);
+ if (ret < 0)
+ goto fail;
+ if (c->has_alpha) {
+ c->comp = 3;
+ ret = bink2g_mcompensate_luma(c, x, y,
+ dst[3], stride[3],
+ src[3], sstride[3],
+ w, h);
+ if (ret < 0)
+ goto fail;
+ }
+ c->comp = 0;
+ ret = bink2g_decode_inter_luma(c, gb, c->iblock, &y_cbp_inter, *inter_q, &c->dsp,
+ dst[0] + x, stride[0], flags);
+ if (ret < 0)
+ goto fail;
+ if (get_bits1(gb)) {
+ c->comp = 1;
+ ret = bink2g_decode_inter_chroma(c, gb, c->iblock, &u_cbp_inter, *inter_q, &c->dsp,
+ dst[2] + x/2, stride[2], flags);
+ if (ret < 0)
+ goto fail;
+ c->comp = 2;
+ ret = bink2g_decode_inter_chroma(c, gb, c->iblock, &v_cbp_inter, *inter_q, &c->dsp,
+ dst[1] + x/2, stride[1], flags);
+ if (ret < 0)
+ goto fail;
+ } else {
+ u_cbp_inter = 0;
+ v_cbp_inter = 0;
+ }
+ if (c->has_alpha) {
+ c->comp = 3;
+ ret = bink2g_decode_inter_luma(c, gb, c->iblock, &a_cbp_inter, *inter_q, &c->dsp,
+ dst[3] + x, stride[3], flags);
+ if (ret < 0)
+ goto fail;
+ }
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ dst[0] += stride[0] * 32;
+ dst[1] += stride[1] * 16;
+ dst[2] += stride[2] * 16;
+ dst[3] += stride[3] * 32;
+
+ FFSWAP(MVPredict *, c->current_mv, c->prev_mv);
+ FFSWAP(QuantPredict *, c->current_q, c->prev_q);
+ FFSWAP(DCIPredict *, c->current_idc, c->prev_idc);
+ }
+fail:
+ emms_c();
+
+ return ret;
+}
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index a3de8e1c2b..0e8df1a56e 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1705,6 +1705,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("Gryphon's Anim Compressor"),
.props = AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_BINKVIDEO2,
+ .type = AVMEDIA_TYPE_VIDEO,
+ .name = "binkvideo2",
+ .long_name = NULL_IF_CONFIG_SMALL("Bink video 2"),
+ .props = AV_CODEC_PROP_LOSSY,
+ },
/* various PCM "codecs" */
{
diff --git a/libavformat/bink.c b/libavformat/bink.c
index 44eb04362e..29e59c7276 100644
--- a/libavformat/bink.c
+++ b/libavformat/bink.c
@@ -148,8 +148,7 @@ static int read_header(AVFormatContext *s)
vst->codecpar->codec_id = AV_CODEC_ID_BINKVIDEO;
if ((vst->codecpar->codec_tag & 0xFFFFFF) == MKTAG('K', 'B', '2', 0)) {
- av_log(s, AV_LOG_WARNING, "Bink 2 video is not implemented\n");
- vst->codecpar->codec_id = AV_CODEC_ID_NONE;
+ vst->codecpar->codec_id = AV_CODEC_ID_BINKVIDEO2;
}
if (ff_get_extradata(s, vst->codecpar, pb, 4) < 0)
--
2.17.1
More information about the ffmpeg-devel
mailing list