* [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
@ 2022-05-24 13:36 Paul B Mahol
2022-05-25 18:17 ` Tomas Härdin
2022-05-28 10:39 ` Andreas Rheinhardt
0 siblings, 2 replies; 10+ messages in thread
From: Paul B Mahol @ 2022-05-24 13:36 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
configure | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/bink2.c | 479 +++++++++++++
libavcodec/bink2f.c | 1234 ++++++++++++++++++++++++++++++++
libavcodec/bink2g.c | 1479 +++++++++++++++++++++++++++++++++++++++
libavcodec/codec_desc.c | 7 +
libavcodec/codec_id.h | 1 +
libavformat/bink.c | 7 +-
9 files changed, 3206 insertions(+), 4 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 f115b21064..516c3a5db4 100755
--- a/configure
+++ b/configure
@@ -2782,6 +2782,7 @@ atrac3pal_decoder_select="mdct sinewin"
atrac9_decoder_select="mdct"
av1_decoder_select="cbs_av1"
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 38425d2f22..e6eb8c0854 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -252,6 +252,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 c47133aa18..3ae41827a2 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -66,6 +66,7 @@ extern const FFCodec ff_ayuv_decoder;
extern const FFCodec ff_bethsoftvid_decoder;
extern const FFCodec ff_bfi_decoder;
extern const FFCodec ff_bink_decoder;
+extern const FFCodec ff_bink2_decoder;
extern const FFCodec ff_bitpacked_decoder;
extern const FFCodec ff_bitpacked_encoder;
extern const FFCodec ff_bmp_encoder;
diff --git a/libavcodec/bink2.c b/libavcodec/bink2.c
new file mode 100644
index 0000000000..102d844c89
--- /dev/null
+++ b/libavcodec/bink2.c
@@ -0,0 +1,479 @@
+/*
+ * Bink video 2 decoder
+ * Copyright (c) 2014 Konstantin Shishkov
+ * Copyright (c) 2019 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/attributes.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "avcodec.h"
+#include "blockdsp.h"
+#include "codec_internal.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 uint8_t dq_patterns[8] = { 8, 0, 1, 0, 2, 0, 1, 0 };
+
+static const uint8_t bink2_next_skips[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
+};
+
+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
+};
+
+#include "bink2f.c"
+#include "bink2g.c"
+
+static void bink2_get_block_flags(GetBitContext *gb, int offset, int size, uint8_t *dst)
+{
+ int j, v = 0, flags_left, mode = 0, nv;
+ unsigned cache, flag = 0;
+
+ if (get_bits1(gb) == 0) {
+ for (j = 0; j < size >> 3; j++)
+ dst[j] = get_bits(gb, 8);
+ dst[j] = get_bitsz(gb, size & 7);
+
+ return;
+ }
+
+ flags_left = size;
+ while (flags_left > 0) {
+ cache = offset;
+ if (get_bits1(gb) == 0) {
+ if (mode == 3) {
+ flag ^= 1;
+ } else {
+ flag = get_bits1(gb);
+ }
+ mode = 2;
+ if (flags_left < 5) {
+ nv = get_bitsz(gb, flags_left - 1);
+ nv <<= (offset + 1) & 0x1f;
+ offset += flags_left;
+ flags_left = 0;
+ } else {
+ nv = get_bits(gb, 4) << ((offset + 1) & 0x1f);
+ offset += 5;
+ flags_left -= 5;
+ }
+ v |= flag << (cache & 0x1f) | nv;
+ if (offset >= 8) {
+ *dst++ = v & 0xff;
+ v >>= 8;
+ offset -= 8;
+ }
+ } else {
+ int temp, bits, nb_coded;
+
+ bits = flags_left < 4 ? 2 : flags_left < 16 ? 4 : 5;
+ nb_coded = bits + 1;
+ if (mode == 3) {
+ flag ^= 1;
+ } else {
+ nb_coded++;
+ flag = get_bits1(gb);
+ }
+ nb_coded = FFMIN(nb_coded, flags_left);
+ flags_left -= nb_coded;
+ if (flags_left > 0) {
+ temp = get_bits(gb, bits);
+ flags_left -= temp;
+ nb_coded += temp;
+ mode = temp == (1 << bits) - 1U ? 1 : 3;
+ }
+
+ temp = (flag << 0x1f) >> 0x1f & 0xff;
+ while (nb_coded > 8) {
+ v |= temp << (cache & 0x1f);
+ *dst++ = v & 0xff;
+ v >>= 8;
+ nb_coded -= 8;
+ }
+ if (nb_coded > 0) {
+ offset += nb_coded;
+ v |= ((1 << (nb_coded & 0x1f)) - 1U & temp) << (cache & 0x1f);
+ if (offset >= 8) {
+ *dst++ = v & 0xff;
+ v >>= 8;
+ offset -= 8;
+ }
+ }
+ }
+ }
+
+ if (offset != 0)
+ *dst = v;
+}
+
+static int bink2_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame, AVPacket *pkt)
+{
+ Bink2Context * const c = avctx->priv_data;
+ GetBitContext *gb = &c->gb;
+ uint8_t *dst[4];
+ uint8_t *src[4];
+ int stride[4];
+ int sstride[4];
+ uint32_t off = 0;
+ int is_kf = !!(pkt->flags & AV_PKT_FLAG_KEY);
+ int ret, w, h;
+ int height_a;
+
+ w = avctx->width;
+ h = avctx->height;
+ ret = ff_set_dimensions(avctx, FFALIGN(w, 32), FFALIGN(h, 32));
+ if (ret < 0)
+ return ret;
+ avctx->width = w;
+ avctx->height = h;
+
+ if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
+ return ret;
+
+ for (int i = 0; i < 4; i++) {
+ src[i] = c->last->data[i];
+ dst[i] = frame->data[i];
+ stride[i] = frame->linesize[i];
+ sstride[i] = c->last->linesize[i];
+ }
+
+ if (!is_kf && (!src[0] || !src[1] || !src[2]))
+ return AVERROR_INVALIDDATA;
+
+ c->frame_flags = AV_RL32(pkt->data);
+ ff_dlog(avctx, "frame flags %X\n", c->frame_flags);
+
+ if ((ret = init_get_bits8(gb, pkt->data, pkt->size)) < 0)
+ return ret;
+
+ height_a = (avctx->height + 31) & 0xFFFFFFE0;
+ if (c->version <= 'f') {
+ c->num_slices = 2;
+ c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
+ } else if (c->version == 'g') {
+ if (height_a < 128) {
+ c->num_slices = 1;
+ } else {
+ c->num_slices = 2;
+ c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
+ }
+ } else {
+ int start, end;
+
+ c->num_slices = kb2h_num_slices[c->flags & 3];
+ start = 0;
+ end = height_a + 32 * c->num_slices - 1;
+ for (int i = 0; i < c->num_slices - 1; i++) {
+ start += ((end - start) / (c->num_slices - i)) & 0xFFFFFFE0;
+ end -= 32;
+ c->slice_height[i] = start;
+ }
+ }
+ c->slice_height[c->num_slices - 1] = height_a;
+
+ skip_bits_long(gb, 32 + 32 * (c->num_slices - 1));
+
+ if (c->frame_flags & 0x10000) {
+ if (!(c->frame_flags & 0x8000))
+ bink2_get_block_flags(gb, 1, (((avctx->height + 15) & ~15) >> 3) - 1, c->row_cbp);
+ if (!(c->frame_flags & 0x4000))
+ bink2_get_block_flags(gb, 1, (((avctx->width + 15) & ~15) >> 3) - 1, c->col_cbp);
+ }
+
+ for (int i = 0; i < c->num_slices; i++) {
+ if (i == c->num_slices - 1)
+ off = pkt->size;
+ else
+ off = AV_RL32(pkt->data + 4 + i * 4);
+
+ if (c->version <= 'f')
+ ret = bink2f_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
+ else
+ ret = bink2g_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
+ if (ret < 0)
+ return ret;
+
+ align_get_bits(gb);
+ if (get_bits_left(gb) < 0)
+ av_log(avctx, AV_LOG_WARNING, "slice %d: overread\n", i);
+ if (8 * (off - (get_bits_count(gb) >> 3)) > 24)
+ av_log(avctx, AV_LOG_WARNING, "slice %d: underread %d\n", i, 8 * (off - (get_bits_count(gb) >> 3)));
+ skip_bits_long(gb, 8 * (off - (get_bits_count(gb) >> 3)));
+
+ dst[0] = frame->data[0] + c->slice_height[i] * stride[0];
+ dst[1] = frame->data[1] + c->slice_height[i]/2 * stride[1];
+ dst[2] = frame->data[2] + c->slice_height[i]/2 * stride[2];
+ dst[3] = frame->data[3] + c->slice_height[i] * stride[3];
+ }
+
+ frame->key_frame = is_kf;
+ frame->pict_type = is_kf ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+
+ av_frame_unref(c->last);
+ if ((ret = av_frame_ref(c->last, frame)) < 0)
+ return ret;
+
+ *got_frame = 1;
+
+ /* always report that the buffer was completely consumed */
+ return pkt->size;
+}
+
+#define INIT_VLC_STATIC_LE(vlc, nb_bits, nb_codes, \
+ bits, bits_wrap, bits_size, \
+ codes, codes_wrap, codes_size, \
+ symbols, symbols_wrap, symbols_size, \
+ static_size) \
+ do { \
+ static VLC_TYPE table[static_size][2]; \
+ (vlc)->table = table; \
+ (vlc)->table_allocated = static_size; \
+ ff_init_vlc_sparse(vlc, nb_bits, nb_codes, \
+ bits, bits_wrap, bits_size, \
+ codes, codes_wrap, codes_size, \
+ symbols, symbols_wrap, symbols_size, \
+ INIT_VLC_LE | INIT_VLC_USE_NEW_STATIC); \
+ } while (0)
+
+static av_cold int bink2_decode_init(AVCodecContext *avctx)
+{
+ Bink2Context * const c = avctx->priv_data;
+ int ret;
+
+ c->version = avctx->codec_tag >> 24;
+ if (avctx->extradata_size < 4) {
+ av_log(avctx, AV_LOG_ERROR, "Extradata missing or too short\n");
+ return AVERROR_INVALIDDATA;
+ }
+ c->flags = AV_RL32(avctx->extradata);
+ av_log(avctx, AV_LOG_DEBUG, "flags: 0x%X\n", c->flags);
+ c->has_alpha = c->flags & BINK_FLAG_ALPHA;
+ c->avctx = avctx;
+
+ c->last = av_frame_alloc();
+ if (!c->last)
+ return AVERROR(ENOMEM);
+
+ if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
+ return ret;
+
+ avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
+
+ ff_blockdsp_init(&c->dsp, avctx);
+
+ INIT_VLC_STATIC_LE(&bink2f_quant_vlc, 9, FF_ARRAY_ELEMS(bink2f_quant_codes),
+ bink2f_quant_bits, 1, 1, bink2f_quant_codes, 1, 1, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_val0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[0]),
+ bink2f_ac_val_bits[0], 1, 1, bink2f_ac_val_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_val1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[1]),
+ bink2f_ac_val_bits[1], 1, 1, bink2f_ac_val_codes[1], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[0]),
+ bink2f_ac_skip_bits[0], 1, 1, bink2f_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[1]),
+ bink2f_ac_skip_bits[1], 1, 1, bink2f_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
+
+ INIT_VLC_STATIC_LE(&bink2g_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[0]),
+ bink2g_ac_skip_bits[0], 1, 1, bink2g_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2g_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[1]),
+ bink2g_ac_skip_bits[1], 1, 1, bink2g_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2g_mv_vlc, 9, FF_ARRAY_ELEMS(bink2g_mv_bits),
+ bink2g_mv_bits, 1, 1, bink2g_mv_codes, 1, 1, NULL, 0, 0, 512);
+
+ c->current_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_q));
+ if (!c->current_q)
+ return AVERROR(ENOMEM);
+
+ c->prev_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_q));
+ if (!c->prev_q)
+ return AVERROR(ENOMEM);
+
+ c->current_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_dc));
+ if (!c->current_dc)
+ return AVERROR(ENOMEM);
+
+ c->prev_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_dc));
+ if (!c->prev_dc)
+ return AVERROR(ENOMEM);
+
+ c->current_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_idc));
+ if (!c->current_idc)
+ return AVERROR(ENOMEM);
+
+ c->prev_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_idc));
+ if (!c->prev_q)
+ return AVERROR(ENOMEM);
+
+ c->current_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_mv));
+ if (!c->current_mv)
+ return AVERROR(ENOMEM);
+
+ c->prev_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_mv));
+ if (!c->prev_mv)
+ return AVERROR(ENOMEM);
+
+ c->col_cbp = av_calloc((((avctx->width + 31) >> 3) + 7) >> 3, sizeof(*c->col_cbp));
+ if (!c->col_cbp)
+ return AVERROR(ENOMEM);
+
+ c->row_cbp = av_calloc((((avctx->height + 31) >> 3) + 7) >> 3, sizeof(*c->row_cbp));
+ if (!c->row_cbp)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+static void bink2_flush(AVCodecContext *avctx)
+{
+ Bink2Context *c = avctx->priv_data;
+
+ av_frame_unref(c->last);
+}
+
+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;
+}
+
+const FFCodec ff_bink2_decoder = {
+ .p.name = "binkvideo2",
+ .p.long_name = NULL_IF_CONFIG_SMALL("Bink video 2"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_BINKVIDEO2,
+ .priv_data_size = sizeof(Bink2Context),
+ .init = bink2_decode_init,
+ .close = bink2_decode_end,
+ FF_CODEC_DECODE_CB(bink2_decode_frame),
+ .flush = bink2_flush,
+ .p.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
+ FF_CODEC_CAP_INIT_CLEANUP,
+};
diff --git a/libavcodec/bink2f.c b/libavcodec/bink2f.c
new file mode 100644
index 0000000000..d5ed96fd9c
--- /dev/null
+++ b/libavcodec/bink2f.c
@@ -0,0 +1,1234 @@
+/*
+ * 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 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 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 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.f;
+
+ 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(lrintf(block[j] - 512.0f));
+ block += 8;
+ dst += stride;
+ }
+}
+
+static void bink2f_idct_add(uint8_t *dst, int stride,
+ float *block)
+{
+ block[0] += 512.f;
+
+ 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] + lrintf(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 (av_popcount(cbp & 0xF)) {
+ if (av_popcount(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 (av_popcount(cbplo & 0xF)) {
+ if (av_popcount(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] = {
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6,
+};
+
+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);
+ 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] + 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;
+ }
+ 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;
+
+ 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;
+ }
+
+ 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 = bink2_next_skips[skip];
+ skip = bink2f_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ 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);
+ 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, 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);
+ 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, 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]);
+ }
+ }
+}
+
+#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];
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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;
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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);
+ }
+}
+
+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;
+ }
+
+ 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);
+
+ 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;
+
+ 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..8e050148e6
--- /dev/null
+++ b/libavcodec/bink2g.c
@@ -0,0 +1,1479 @@
+/*
+ * 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 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,
+};
+
+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 uint8_t bink2g_skips[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 64, 0, 0, 0,
+};
+
+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 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 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;
+
+ 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;
+}
+
+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;
+ }
+ }
+
+ 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;
+
+ next = 0;
+ idx = 1;
+ while (idx < 64) {
+ next--;
+ if (next < 1) {
+ skip = get_vlc2(gb, skip_vlc->table, skip_vlc->bits, 1);
+ if (skip < 0)
+ return AVERROR_INVALIDDATA;
+ next = bink2_next_skips[skip];
+ skip = bink2g_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ 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;
+ block[i][scan[idx]] = ((val * qmat[q & 3][scan[idx]] * (1 << (q >> 2))) + 64) >> 7;
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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];
+
+ 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]);
+ }
+ }
+}
+
+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);
+
+ 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;
+ }
+ }
+
+ 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];
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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;
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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);
+ }
+}
+
+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 };
+
+ 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;
+ 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);
+ 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);
+ 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 e7f0f6a8d4..3bcf22e6e7 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1879,6 +1879,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
AV_CODEC_PROP_LOSSLESS,
.mime_types= MT("image/jxl"),
},
+ {
+ .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/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 8b317fa121..03234b7543 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -310,6 +310,7 @@ enum AVCodecID {
AV_CODEC_ID_GEM,
AV_CODEC_ID_VBN,
AV_CODEC_ID_JPEGXL,
+ 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/libavformat/bink.c b/libavformat/bink.c
index f4079dfb1d..abfc769a0b 100644
--- a/libavformat/bink.c
+++ b/libavformat/bink.c
@@ -72,7 +72,7 @@ static int probe(const AVProbeData *p)
b[3] == 'k')) ||
(b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */
(b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' ||
- b[3] == 'i' || b[3] == 'j' || b[3] == 'k'))) &&
+ b[3] == 'i' || b[3] == 'j' || b[3] == 'k' || b[3] == 'n'))) &&
AV_RL32(b+8) > 0 && // num_frames
AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
@@ -149,8 +149,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 ((ret = ff_get_extradata(s, vst->codecpar, pb, 4)) < 0)
@@ -169,7 +168,7 @@ static int read_header(AVFormatContext *s)
revision = ((vst->codecpar->codec_tag >> 24) % 0xFF);
if ((signature == AV_RL32("BIK") && (revision == 'k')) ||
- (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k')))
+ (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k') || revision == 'n'))
avio_skip(pb, 4); /* unknown new field */
if (bink->num_audio_tracks) {
--
2.36.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
2022-05-24 13:36 [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder Paul B Mahol
@ 2022-05-25 18:17 ` Tomas Härdin
2022-05-28 10:39 ` Andreas Rheinhardt
1 sibling, 0 replies; 10+ messages in thread
From: Tomas Härdin @ 2022-05-25 18:17 UTC (permalink / raw)
To: FFmpeg development discussions and patches
tis 2022-05-24 klockan 15:36 +0200 skrev Paul B Mahol:
>
> + c->current_q = av_malloc_array((avctx->width + 31) / 32,
> sizeof(*c->current_q));
> + if (!c->current_q)
> + return AVERROR(ENOMEM);
You can exploit BINK_MAX_WIDTH and BINK_MAX_HEIGHT to make the size of
these arrays constant, thus simplifying the code.
/Tomas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
2022-05-24 13:36 [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder Paul B Mahol
2022-05-25 18:17 ` Tomas Härdin
@ 2022-05-28 10:39 ` Andreas Rheinhardt
2022-06-01 8:09 ` Paul B Mahol
1 sibling, 1 reply; 10+ messages in thread
From: Andreas Rheinhardt @ 2022-05-28 10:39 UTC (permalink / raw)
To: ffmpeg-devel
Paul B Mahol:
> Signed-off-by: Paul B Mahol <onemda@gmail.com>
> ---
> configure | 1 +
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/bink2.c | 479 +++++++++++++
> libavcodec/bink2f.c | 1234 ++++++++++++++++++++++++++++++++
> libavcodec/bink2g.c | 1479 +++++++++++++++++++++++++++++++++++++++
The latter two files are not standalone files, but are included in
bink2.c. That means that bink2.d will contain bink2f.c and bink2g.c as
prerequisites for bink2.c. Yet if the code were to be changed so that
these files would no longer exist, then the build would fail if you have
an old bink2.d with bink2[fg]].c prerequisites, because make would not
know how to create these prerequisites.
To fix this, rename these files so that they are either templates or
headers.
> libavcodec/codec_desc.c | 7 +
> libavcodec/codec_id.h | 1 +
> libavformat/bink.c | 7 +-
> 9 files changed, 3206 insertions(+), 4 deletions(-)
> create mode 100644 libavcodec/bink2.c
> create mode 100644 libavcodec/bink2f.c
> create mode 100644 libavcodec/bink2g.c
>
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
2022-05-28 10:39 ` Andreas Rheinhardt
@ 2022-06-01 8:09 ` Paul B Mahol
2022-06-01 8:57 ` Andreas Rheinhardt
0 siblings, 1 reply; 10+ messages in thread
From: Paul B Mahol @ 2022-06-01 8:09 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Renamed to headers, will apply right now!
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
2022-06-01 8:09 ` Paul B Mahol
@ 2022-06-01 8:57 ` Andreas Rheinhardt
2022-06-01 9:04 ` Paul B Mahol
0 siblings, 1 reply; 10+ messages in thread
From: Andreas Rheinhardt @ 2022-06-01 8:57 UTC (permalink / raw)
To: ffmpeg-devel
Paul B Mahol:
> Renamed to headers, will apply right now!
In this case you will likely either add these headers to SKIPHEADERS or
add the necessary headers to them to make them standalone.
- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
2022-06-01 9:04 ` Paul B Mahol
@ 2022-06-01 9:03 ` Andreas Rheinhardt
2022-06-01 9:45 ` Anton Khirnov
1 sibling, 0 replies; 10+ messages in thread
From: Andreas Rheinhardt @ 2022-06-01 9:03 UTC (permalink / raw)
To: ffmpeg-devel
Paul B Mahol:
> On Wed, Jun 1, 2022 at 10:57 AM Andreas Rheinhardt <
> andreas.rheinhardt@outlook.com> wrote:
>
>> Paul B Mahol:
>>> Renamed to headers, will apply right now!
>>
>> In this case you will likely either add these headers to SKIPHEADERS or
>> add the necessary headers to them to make them standalone.
>>
>>
> Why? fate source test does not complain.
>
>
fate-source only checks for license headers, not for proper inclusions.
"make checkheaders" does the latter. It is not part of the standard fate
run.
- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
2022-06-01 8:57 ` Andreas Rheinhardt
@ 2022-06-01 9:04 ` Paul B Mahol
2022-06-01 9:03 ` Andreas Rheinhardt
2022-06-01 9:45 ` Anton Khirnov
0 siblings, 2 replies; 10+ messages in thread
From: Paul B Mahol @ 2022-06-01 9:04 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Wed, Jun 1, 2022 at 10:57 AM Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> wrote:
> Paul B Mahol:
> > Renamed to headers, will apply right now!
>
> In this case you will likely either add these headers to SKIPHEADERS or
> add the necessary headers to them to make them standalone.
>
>
Why? fate source test does not complain.
> - Andreas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
2022-06-01 9:04 ` Paul B Mahol
2022-06-01 9:03 ` Andreas Rheinhardt
@ 2022-06-01 9:45 ` Anton Khirnov
1 sibling, 0 replies; 10+ messages in thread
From: Anton Khirnov @ 2022-06-01 9:45 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Andreas Rheinhardt (2022-06-01 11:03:28)
> "make checkheaders" does the latter. It is not part of the standard fate
Any reason it isn't?
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
@ 2022-06-01 10:41 Paul B Mahol
0 siblings, 0 replies; 10+ messages in thread
From: Paul B Mahol @ 2022-06-01 10:41 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
configure | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/bink2.c | 381 ++++++++++
libavcodec/bink2.h | 135 ++++
libavcodec/bink2f.h | 1240 ++++++++++++++++++++++++++++++++
libavcodec/bink2g.h | 1486 +++++++++++++++++++++++++++++++++++++++
libavcodec/codec_desc.c | 7 +
libavcodec/codec_id.h | 1 +
libavformat/bink.c | 7 +-
10 files changed, 3256 insertions(+), 4 deletions(-)
create mode 100644 libavcodec/bink2.c
create mode 100644 libavcodec/bink2.h
create mode 100644 libavcodec/bink2f.h
create mode 100644 libavcodec/bink2g.h
diff --git a/configure b/configure
index 5a167613a4..f09c2eeac8 100755
--- a/configure
+++ b/configure
@@ -2782,6 +2782,7 @@ atrac3pal_decoder_select="mdct sinewin"
atrac9_decoder_select="mdct"
av1_decoder_select="cbs_av1"
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 38425d2f22..e6eb8c0854 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -252,6 +252,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 c47133aa18..3ae41827a2 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -66,6 +66,7 @@ extern const FFCodec ff_ayuv_decoder;
extern const FFCodec ff_bethsoftvid_decoder;
extern const FFCodec ff_bfi_decoder;
extern const FFCodec ff_bink_decoder;
+extern const FFCodec ff_bink2_decoder;
extern const FFCodec ff_bitpacked_decoder;
extern const FFCodec ff_bitpacked_encoder;
extern const FFCodec ff_bmp_encoder;
diff --git a/libavcodec/bink2.c b/libavcodec/bink2.c
new file mode 100644
index 0000000000..e815a7bd25
--- /dev/null
+++ b/libavcodec/bink2.c
@@ -0,0 +1,381 @@
+/*
+ * Bink video 2 decoder
+ * Copyright (c) 2014 Konstantin Shishkov
+ * Copyright (c) 2019 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/attributes.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "avcodec.h"
+#include "blockdsp.h"
+#include "codec_internal.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"
+#include "bink2.h"
+
+#include "bink2f.h"
+#include "bink2g.h"
+
+static void bink2_get_block_flags(GetBitContext *gb, int offset, int size, uint8_t *dst)
+{
+ int j, v = 0, flags_left, mode = 0, nv;
+ unsigned cache, flag = 0;
+
+ if (get_bits1(gb) == 0) {
+ for (j = 0; j < size >> 3; j++)
+ dst[j] = get_bits(gb, 8);
+ dst[j] = get_bitsz(gb, size & 7);
+
+ return;
+ }
+
+ flags_left = size;
+ while (flags_left > 0) {
+ cache = offset;
+ if (get_bits1(gb) == 0) {
+ if (mode == 3) {
+ flag ^= 1;
+ } else {
+ flag = get_bits1(gb);
+ }
+ mode = 2;
+ if (flags_left < 5) {
+ nv = get_bitsz(gb, flags_left - 1);
+ nv <<= (offset + 1) & 0x1f;
+ offset += flags_left;
+ flags_left = 0;
+ } else {
+ nv = get_bits(gb, 4) << ((offset + 1) & 0x1f);
+ offset += 5;
+ flags_left -= 5;
+ }
+ v |= flag << (cache & 0x1f) | nv;
+ if (offset >= 8) {
+ *dst++ = v & 0xff;
+ v >>= 8;
+ offset -= 8;
+ }
+ } else {
+ int temp, bits, nb_coded;
+
+ bits = flags_left < 4 ? 2 : flags_left < 16 ? 4 : 5;
+ nb_coded = bits + 1;
+ if (mode == 3) {
+ flag ^= 1;
+ } else {
+ nb_coded++;
+ flag = get_bits1(gb);
+ }
+ nb_coded = FFMIN(nb_coded, flags_left);
+ flags_left -= nb_coded;
+ if (flags_left > 0) {
+ temp = get_bits(gb, bits);
+ flags_left -= temp;
+ nb_coded += temp;
+ mode = temp == (1 << bits) - 1U ? 1 : 3;
+ }
+
+ temp = (flag << 0x1f) >> 0x1f & 0xff;
+ while (nb_coded > 8) {
+ v |= temp << (cache & 0x1f);
+ *dst++ = v & 0xff;
+ v >>= 8;
+ nb_coded -= 8;
+ }
+ if (nb_coded > 0) {
+ offset += nb_coded;
+ v |= ((1 << (nb_coded & 0x1f)) - 1U & temp) << (cache & 0x1f);
+ if (offset >= 8) {
+ *dst++ = v & 0xff;
+ v >>= 8;
+ offset -= 8;
+ }
+ }
+ }
+ }
+
+ if (offset != 0)
+ *dst = v;
+}
+
+static int bink2_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame, AVPacket *pkt)
+{
+ Bink2Context * const c = avctx->priv_data;
+ GetBitContext *gb = &c->gb;
+ uint8_t *dst[4];
+ uint8_t *src[4];
+ int stride[4];
+ int sstride[4];
+ uint32_t off = 0;
+ int is_kf = !!(pkt->flags & AV_PKT_FLAG_KEY);
+ int ret, w, h;
+ int height_a;
+
+ w = avctx->width;
+ h = avctx->height;
+ ret = ff_set_dimensions(avctx, FFALIGN(w, 32), FFALIGN(h, 32));
+ if (ret < 0)
+ return ret;
+ avctx->width = w;
+ avctx->height = h;
+
+ if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
+ return ret;
+
+ for (int i = 0; i < 4; i++) {
+ src[i] = c->last->data[i];
+ dst[i] = frame->data[i];
+ stride[i] = frame->linesize[i];
+ sstride[i] = c->last->linesize[i];
+ }
+
+ if (!is_kf && (!src[0] || !src[1] || !src[2]))
+ return AVERROR_INVALIDDATA;
+
+ c->frame_flags = AV_RL32(pkt->data);
+ ff_dlog(avctx, "frame flags %X\n", c->frame_flags);
+
+ if ((ret = init_get_bits8(gb, pkt->data, pkt->size)) < 0)
+ return ret;
+
+ height_a = (avctx->height + 31) & 0xFFFFFFE0;
+ if (c->version <= 'f') {
+ c->num_slices = 2;
+ c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
+ } else if (c->version == 'g') {
+ if (height_a < 128) {
+ c->num_slices = 1;
+ } else {
+ c->num_slices = 2;
+ c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
+ }
+ } else {
+ int start, end;
+
+ c->num_slices = kb2h_num_slices[c->flags & 3];
+ start = 0;
+ end = height_a + 32 * c->num_slices - 1;
+ for (int i = 0; i < c->num_slices - 1; i++) {
+ start += ((end - start) / (c->num_slices - i)) & 0xFFFFFFE0;
+ end -= 32;
+ c->slice_height[i] = start;
+ }
+ }
+ c->slice_height[c->num_slices - 1] = height_a;
+
+ skip_bits_long(gb, 32 + 32 * (c->num_slices - 1));
+
+ if (c->frame_flags & 0x10000) {
+ if (!(c->frame_flags & 0x8000))
+ bink2_get_block_flags(gb, 1, (((avctx->height + 15) & ~15) >> 3) - 1, c->row_cbp);
+ if (!(c->frame_flags & 0x4000))
+ bink2_get_block_flags(gb, 1, (((avctx->width + 15) & ~15) >> 3) - 1, c->col_cbp);
+ }
+
+ for (int i = 0; i < c->num_slices; i++) {
+ if (i == c->num_slices - 1)
+ off = pkt->size;
+ else
+ off = AV_RL32(pkt->data + 4 + i * 4);
+
+ if (c->version <= 'f')
+ ret = bink2f_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
+ else
+ ret = bink2g_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
+ if (ret < 0)
+ return ret;
+
+ align_get_bits(gb);
+ if (get_bits_left(gb) < 0)
+ av_log(avctx, AV_LOG_WARNING, "slice %d: overread\n", i);
+ if (8 * (off - (get_bits_count(gb) >> 3)) > 24)
+ av_log(avctx, AV_LOG_WARNING, "slice %d: underread %d\n", i, 8 * (off - (get_bits_count(gb) >> 3)));
+ skip_bits_long(gb, 8 * (off - (get_bits_count(gb) >> 3)));
+
+ dst[0] = frame->data[0] + c->slice_height[i] * stride[0];
+ dst[1] = frame->data[1] + c->slice_height[i]/2 * stride[1];
+ dst[2] = frame->data[2] + c->slice_height[i]/2 * stride[2];
+ dst[3] = frame->data[3] + c->slice_height[i] * stride[3];
+ }
+
+ frame->key_frame = is_kf;
+ frame->pict_type = is_kf ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+
+ av_frame_unref(c->last);
+ if ((ret = av_frame_ref(c->last, frame)) < 0)
+ return ret;
+
+ *got_frame = 1;
+
+ /* always report that the buffer was completely consumed */
+ return pkt->size;
+}
+
+#define INIT_VLC_STATIC_LE(vlc, nb_bits, nb_codes, \
+ bits, bits_wrap, bits_size, \
+ codes, codes_wrap, codes_size, \
+ symbols, symbols_wrap, symbols_size, \
+ static_size) \
+ do { \
+ static VLC_TYPE table[static_size][2]; \
+ (vlc)->table = table; \
+ (vlc)->table_allocated = static_size; \
+ ff_init_vlc_sparse(vlc, nb_bits, nb_codes, \
+ bits, bits_wrap, bits_size, \
+ codes, codes_wrap, codes_size, \
+ symbols, symbols_wrap, symbols_size, \
+ INIT_VLC_LE | INIT_VLC_USE_NEW_STATIC); \
+ } while (0)
+
+static av_cold int bink2_decode_init(AVCodecContext *avctx)
+{
+ Bink2Context * const c = avctx->priv_data;
+ int ret;
+
+ c->version = avctx->codec_tag >> 24;
+ if (avctx->extradata_size < 4) {
+ av_log(avctx, AV_LOG_ERROR, "Extradata missing or too short\n");
+ return AVERROR_INVALIDDATA;
+ }
+ c->flags = AV_RL32(avctx->extradata);
+ av_log(avctx, AV_LOG_DEBUG, "flags: 0x%X\n", c->flags);
+ c->has_alpha = c->flags & BINK_FLAG_ALPHA;
+ c->avctx = avctx;
+
+ c->last = av_frame_alloc();
+ if (!c->last)
+ return AVERROR(ENOMEM);
+
+ if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
+ return ret;
+
+ avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
+
+ ff_blockdsp_init(&c->dsp, avctx);
+
+ INIT_VLC_STATIC_LE(&bink2f_quant_vlc, 9, FF_ARRAY_ELEMS(bink2f_quant_codes),
+ bink2f_quant_bits, 1, 1, bink2f_quant_codes, 1, 1, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_val0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[0]),
+ bink2f_ac_val_bits[0], 1, 1, bink2f_ac_val_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_val1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[1]),
+ bink2f_ac_val_bits[1], 1, 1, bink2f_ac_val_codes[1], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[0]),
+ bink2f_ac_skip_bits[0], 1, 1, bink2f_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[1]),
+ bink2f_ac_skip_bits[1], 1, 1, bink2f_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
+
+ INIT_VLC_STATIC_LE(&bink2g_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[0]),
+ bink2g_ac_skip_bits[0], 1, 1, bink2g_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2g_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[1]),
+ bink2g_ac_skip_bits[1], 1, 1, bink2g_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2g_mv_vlc, 9, FF_ARRAY_ELEMS(bink2g_mv_bits),
+ bink2g_mv_bits, 1, 1, bink2g_mv_codes, 1, 1, NULL, 0, 0, 512);
+
+ c->current_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_q));
+ if (!c->current_q)
+ return AVERROR(ENOMEM);
+
+ c->prev_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_q));
+ if (!c->prev_q)
+ return AVERROR(ENOMEM);
+
+ c->current_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_dc));
+ if (!c->current_dc)
+ return AVERROR(ENOMEM);
+
+ c->prev_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_dc));
+ if (!c->prev_dc)
+ return AVERROR(ENOMEM);
+
+ c->current_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_idc));
+ if (!c->current_idc)
+ return AVERROR(ENOMEM);
+
+ c->prev_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_idc));
+ if (!c->prev_q)
+ return AVERROR(ENOMEM);
+
+ c->current_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_mv));
+ if (!c->current_mv)
+ return AVERROR(ENOMEM);
+
+ c->prev_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_mv));
+ if (!c->prev_mv)
+ return AVERROR(ENOMEM);
+
+ c->col_cbp = av_calloc((((avctx->width + 31) >> 3) + 7) >> 3, sizeof(*c->col_cbp));
+ if (!c->col_cbp)
+ return AVERROR(ENOMEM);
+
+ c->row_cbp = av_calloc((((avctx->height + 31) >> 3) + 7) >> 3, sizeof(*c->row_cbp));
+ if (!c->row_cbp)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+static void bink2_flush(AVCodecContext *avctx)
+{
+ Bink2Context *c = avctx->priv_data;
+
+ av_frame_unref(c->last);
+}
+
+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;
+}
+
+const FFCodec ff_bink2_decoder = {
+ .p.name = "binkvideo2",
+ .p.long_name = NULL_IF_CONFIG_SMALL("Bink video 2"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_BINKVIDEO2,
+ .priv_data_size = sizeof(Bink2Context),
+ .init = bink2_decode_init,
+ .close = bink2_decode_end,
+ FF_CODEC_DECODE_CB(bink2_decode_frame),
+ .flush = bink2_flush,
+ .p.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
+ FF_CODEC_CAP_INIT_CLEANUP,
+};
diff --git a/libavcodec/bink2.h b/libavcodec/bink2.h
new file mode 100644
index 0000000000..501cb0781e
--- /dev/null
+++ b/libavcodec/bink2.h
@@ -0,0 +1,135 @@
+/*
+ * 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
+ */
+
+#ifndef AVCODEC_BINK2_H
+#define AVCODEC_BINK2_H
+
+#include <stdint.h>
+#include "avcodec.h"
+#include "blockdsp.h"
+#include "copy_block.h"
+#include "unary.h"
+#include "get_bits.h"
+
+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 uint8_t dq_patterns[8] = { 8, 0, 1, 0, 2, 0, 1, 0 };
+
+static const uint8_t bink2_next_skips[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
+};
+
+#define NUM_AC_SKIPS 14
+#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)))
+#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)
+
+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
+};
+
+#endif /* AVCODEC_BINK2_H */
diff --git a/libavcodec/bink2f.h b/libavcodec/bink2f.h
new file mode 100644
index 0000000000..1358e5cfc2
--- /dev/null
+++ b/libavcodec/bink2f.h
@@ -0,0 +1,1240 @@
+/*
+ * 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
+ */
+
+#ifndef AVCODEC_BINK2F_H
+#define AVCODEC_BINK2F_H
+
+#include <stdint.h>
+#include "avcodec.h"
+#include "get_bits.h"
+#include "bink2.h"
+
+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 },
+};
+
+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 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 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.f;
+
+ 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(lrintf(block[j] - 512.0f));
+ block += 8;
+ dst += stride;
+ }
+}
+
+static void bink2f_idct_add(uint8_t *dst, int stride,
+ float *block)
+{
+ block[0] += 512.f;
+
+ 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] + lrintf(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 (av_popcount(cbp & 0xF)) {
+ if (av_popcount(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 (av_popcount(cbplo & 0xF)) {
+ if (av_popcount(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] = {
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6,
+};
+
+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);
+ 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] + 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;
+ }
+ 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;
+
+ 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;
+ }
+
+ 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 = bink2_next_skips[skip];
+ skip = bink2f_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ 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);
+ 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, 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);
+ 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, 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]);
+ }
+ }
+}
+
+#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];
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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 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;
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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);
+ }
+}
+
+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;
+ }
+
+ 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);
+
+ 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;
+
+ 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;
+}
+
+#endif /* AVCODEC_BINK2F_H */
diff --git a/libavcodec/bink2g.h b/libavcodec/bink2g.h
new file mode 100644
index 0000000000..c1d80a4d15
--- /dev/null
+++ b/libavcodec/bink2g.h
@@ -0,0 +1,1486 @@
+/*
+ * 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
+ */
+
+#ifndef AVCODEC_BINK2G_H
+#define AVCODEC_BINK2G_H
+
+#include <stdint.h>
+#include "avcodec.h"
+#include "get_bits.h"
+#include "bink2.h"
+
+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,
+};
+
+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 uint8_t bink2g_skips[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 64, 0, 0, 0,
+};
+
+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 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 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;
+
+ 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;
+}
+
+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 + 0x1FF) >> 10;
+ }
+ }
+
+ 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;
+
+ next = 0;
+ idx = 1;
+ while (idx < 64) {
+ next--;
+ if (next < 1) {
+ skip = get_vlc2(gb, skip_vlc->table, skip_vlc->bits, 1);
+ if (skip < 0)
+ return AVERROR_INVALIDDATA;
+ next = bink2_next_skips[skip];
+ skip = bink2g_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ 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;
+ block[i][scan[idx]] = ((val * qmat[q & 3][scan[idx]] * (1 << (q >> 2))) + 64) >> 7;
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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];
+
+ 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]);
+ }
+ }
+}
+
+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);
+
+ 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;
+ }
+ }
+
+ 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];
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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;
+}
+
+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;
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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);
+ }
+}
+
+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 };
+
+ 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;
+ 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);
+ 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);
+ 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;
+}
+
+#endif /* AVCODEC_BINK2G_H */
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index e7f0f6a8d4..3bcf22e6e7 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1879,6 +1879,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
AV_CODEC_PROP_LOSSLESS,
.mime_types= MT("image/jxl"),
},
+ {
+ .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/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 8b317fa121..03234b7543 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -310,6 +310,7 @@ enum AVCodecID {
AV_CODEC_ID_GEM,
AV_CODEC_ID_VBN,
AV_CODEC_ID_JPEGXL,
+ 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/libavformat/bink.c b/libavformat/bink.c
index f4079dfb1d..abfc769a0b 100644
--- a/libavformat/bink.c
+++ b/libavformat/bink.c
@@ -72,7 +72,7 @@ static int probe(const AVProbeData *p)
b[3] == 'k')) ||
(b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */
(b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' ||
- b[3] == 'i' || b[3] == 'j' || b[3] == 'k'))) &&
+ b[3] == 'i' || b[3] == 'j' || b[3] == 'k' || b[3] == 'n'))) &&
AV_RL32(b+8) > 0 && // num_frames
AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
@@ -149,8 +149,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 ((ret = ff_get_extradata(s, vst->codecpar, pb, 4)) < 0)
@@ -169,7 +168,7 @@ static int read_header(AVFormatContext *s)
revision = ((vst->codecpar->codec_tag >> 24) % 0xFF);
if ((signature == AV_RL32("BIK") && (revision == 'k')) ||
- (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k')))
+ (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k') || revision == 'n'))
avio_skip(pb, 4); /* unknown new field */
if (bink->num_audio_tracks) {
--
2.36.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
* [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder
@ 2022-06-01 8:20 Paul B Mahol
0 siblings, 0 replies; 10+ messages in thread
From: Paul B Mahol @ 2022-06-01 8:20 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
configure | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/bink2.c | 481 +++++++++++++
libavcodec/bink2f.h | 1236 ++++++++++++++++++++++++++++++++
libavcodec/bink2g.h | 1481 +++++++++++++++++++++++++++++++++++++++
libavcodec/codec_desc.c | 7 +
libavcodec/codec_id.h | 1 +
libavformat/bink.c | 7 +-
9 files changed, 3212 insertions(+), 4 deletions(-)
create mode 100644 libavcodec/bink2.c
create mode 100644 libavcodec/bink2f.h
create mode 100644 libavcodec/bink2g.h
diff --git a/configure b/configure
index 5a167613a4..f09c2eeac8 100755
--- a/configure
+++ b/configure
@@ -2782,6 +2782,7 @@ atrac3pal_decoder_select="mdct sinewin"
atrac9_decoder_select="mdct"
av1_decoder_select="cbs_av1"
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 38425d2f22..e6eb8c0854 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -252,6 +252,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 c47133aa18..3ae41827a2 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -66,6 +66,7 @@ extern const FFCodec ff_ayuv_decoder;
extern const FFCodec ff_bethsoftvid_decoder;
extern const FFCodec ff_bfi_decoder;
extern const FFCodec ff_bink_decoder;
+extern const FFCodec ff_bink2_decoder;
extern const FFCodec ff_bitpacked_decoder;
extern const FFCodec ff_bitpacked_encoder;
extern const FFCodec ff_bmp_encoder;
diff --git a/libavcodec/bink2.c b/libavcodec/bink2.c
new file mode 100644
index 0000000000..8524ac57c2
--- /dev/null
+++ b/libavcodec/bink2.c
@@ -0,0 +1,481 @@
+/*
+ * Bink video 2 decoder
+ * Copyright (c) 2014 Konstantin Shishkov
+ * Copyright (c) 2019 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/attributes.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "avcodec.h"
+#include "blockdsp.h"
+#include "codec_internal.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)))
+#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 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 uint8_t dq_patterns[8] = { 8, 0, 1, 0, 2, 0, 1, 0 };
+
+static const uint8_t bink2_next_skips[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
+};
+
+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
+};
+
+#include "bink2f.h"
+#include "bink2g.h"
+
+static void bink2_get_block_flags(GetBitContext *gb, int offset, int size, uint8_t *dst)
+{
+ int j, v = 0, flags_left, mode = 0, nv;
+ unsigned cache, flag = 0;
+
+ if (get_bits1(gb) == 0) {
+ for (j = 0; j < size >> 3; j++)
+ dst[j] = get_bits(gb, 8);
+ dst[j] = get_bitsz(gb, size & 7);
+
+ return;
+ }
+
+ flags_left = size;
+ while (flags_left > 0) {
+ cache = offset;
+ if (get_bits1(gb) == 0) {
+ if (mode == 3) {
+ flag ^= 1;
+ } else {
+ flag = get_bits1(gb);
+ }
+ mode = 2;
+ if (flags_left < 5) {
+ nv = get_bitsz(gb, flags_left - 1);
+ nv <<= (offset + 1) & 0x1f;
+ offset += flags_left;
+ flags_left = 0;
+ } else {
+ nv = get_bits(gb, 4) << ((offset + 1) & 0x1f);
+ offset += 5;
+ flags_left -= 5;
+ }
+ v |= flag << (cache & 0x1f) | nv;
+ if (offset >= 8) {
+ *dst++ = v & 0xff;
+ v >>= 8;
+ offset -= 8;
+ }
+ } else {
+ int temp, bits, nb_coded;
+
+ bits = flags_left < 4 ? 2 : flags_left < 16 ? 4 : 5;
+ nb_coded = bits + 1;
+ if (mode == 3) {
+ flag ^= 1;
+ } else {
+ nb_coded++;
+ flag = get_bits1(gb);
+ }
+ nb_coded = FFMIN(nb_coded, flags_left);
+ flags_left -= nb_coded;
+ if (flags_left > 0) {
+ temp = get_bits(gb, bits);
+ flags_left -= temp;
+ nb_coded += temp;
+ mode = temp == (1 << bits) - 1U ? 1 : 3;
+ }
+
+ temp = (flag << 0x1f) >> 0x1f & 0xff;
+ while (nb_coded > 8) {
+ v |= temp << (cache & 0x1f);
+ *dst++ = v & 0xff;
+ v >>= 8;
+ nb_coded -= 8;
+ }
+ if (nb_coded > 0) {
+ offset += nb_coded;
+ v |= ((1 << (nb_coded & 0x1f)) - 1U & temp) << (cache & 0x1f);
+ if (offset >= 8) {
+ *dst++ = v & 0xff;
+ v >>= 8;
+ offset -= 8;
+ }
+ }
+ }
+ }
+
+ if (offset != 0)
+ *dst = v;
+}
+
+static int bink2_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame, AVPacket *pkt)
+{
+ Bink2Context * const c = avctx->priv_data;
+ GetBitContext *gb = &c->gb;
+ uint8_t *dst[4];
+ uint8_t *src[4];
+ int stride[4];
+ int sstride[4];
+ uint32_t off = 0;
+ int is_kf = !!(pkt->flags & AV_PKT_FLAG_KEY);
+ int ret, w, h;
+ int height_a;
+
+ w = avctx->width;
+ h = avctx->height;
+ ret = ff_set_dimensions(avctx, FFALIGN(w, 32), FFALIGN(h, 32));
+ if (ret < 0)
+ return ret;
+ avctx->width = w;
+ avctx->height = h;
+
+ if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
+ return ret;
+
+ for (int i = 0; i < 4; i++) {
+ src[i] = c->last->data[i];
+ dst[i] = frame->data[i];
+ stride[i] = frame->linesize[i];
+ sstride[i] = c->last->linesize[i];
+ }
+
+ if (!is_kf && (!src[0] || !src[1] || !src[2]))
+ return AVERROR_INVALIDDATA;
+
+ c->frame_flags = AV_RL32(pkt->data);
+ ff_dlog(avctx, "frame flags %X\n", c->frame_flags);
+
+ if ((ret = init_get_bits8(gb, pkt->data, pkt->size)) < 0)
+ return ret;
+
+ height_a = (avctx->height + 31) & 0xFFFFFFE0;
+ if (c->version <= 'f') {
+ c->num_slices = 2;
+ c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
+ } else if (c->version == 'g') {
+ if (height_a < 128) {
+ c->num_slices = 1;
+ } else {
+ c->num_slices = 2;
+ c->slice_height[0] = (avctx->height / 2 + 16) & 0xFFFFFFE0;
+ }
+ } else {
+ int start, end;
+
+ c->num_slices = kb2h_num_slices[c->flags & 3];
+ start = 0;
+ end = height_a + 32 * c->num_slices - 1;
+ for (int i = 0; i < c->num_slices - 1; i++) {
+ start += ((end - start) / (c->num_slices - i)) & 0xFFFFFFE0;
+ end -= 32;
+ c->slice_height[i] = start;
+ }
+ }
+ c->slice_height[c->num_slices - 1] = height_a;
+
+ skip_bits_long(gb, 32 + 32 * (c->num_slices - 1));
+
+ if (c->frame_flags & 0x10000) {
+ if (!(c->frame_flags & 0x8000))
+ bink2_get_block_flags(gb, 1, (((avctx->height + 15) & ~15) >> 3) - 1, c->row_cbp);
+ if (!(c->frame_flags & 0x4000))
+ bink2_get_block_flags(gb, 1, (((avctx->width + 15) & ~15) >> 3) - 1, c->col_cbp);
+ }
+
+ for (int i = 0; i < c->num_slices; i++) {
+ if (i == c->num_slices - 1)
+ off = pkt->size;
+ else
+ off = AV_RL32(pkt->data + 4 + i * 4);
+
+ if (c->version <= 'f')
+ ret = bink2f_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
+ else
+ ret = bink2g_decode_slice(c, dst, stride, src, sstride, is_kf, i ? c->slice_height[i-1] : 0, c->slice_height[i]);
+ if (ret < 0)
+ return ret;
+
+ align_get_bits(gb);
+ if (get_bits_left(gb) < 0)
+ av_log(avctx, AV_LOG_WARNING, "slice %d: overread\n", i);
+ if (8 * (off - (get_bits_count(gb) >> 3)) > 24)
+ av_log(avctx, AV_LOG_WARNING, "slice %d: underread %d\n", i, 8 * (off - (get_bits_count(gb) >> 3)));
+ skip_bits_long(gb, 8 * (off - (get_bits_count(gb) >> 3)));
+
+ dst[0] = frame->data[0] + c->slice_height[i] * stride[0];
+ dst[1] = frame->data[1] + c->slice_height[i]/2 * stride[1];
+ dst[2] = frame->data[2] + c->slice_height[i]/2 * stride[2];
+ dst[3] = frame->data[3] + c->slice_height[i] * stride[3];
+ }
+
+ frame->key_frame = is_kf;
+ frame->pict_type = is_kf ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+
+ av_frame_unref(c->last);
+ if ((ret = av_frame_ref(c->last, frame)) < 0)
+ return ret;
+
+ *got_frame = 1;
+
+ /* always report that the buffer was completely consumed */
+ return pkt->size;
+}
+
+#define INIT_VLC_STATIC_LE(vlc, nb_bits, nb_codes, \
+ bits, bits_wrap, bits_size, \
+ codes, codes_wrap, codes_size, \
+ symbols, symbols_wrap, symbols_size, \
+ static_size) \
+ do { \
+ static VLC_TYPE table[static_size][2]; \
+ (vlc)->table = table; \
+ (vlc)->table_allocated = static_size; \
+ ff_init_vlc_sparse(vlc, nb_bits, nb_codes, \
+ bits, bits_wrap, bits_size, \
+ codes, codes_wrap, codes_size, \
+ symbols, symbols_wrap, symbols_size, \
+ INIT_VLC_LE | INIT_VLC_USE_NEW_STATIC); \
+ } while (0)
+
+static av_cold int bink2_decode_init(AVCodecContext *avctx)
+{
+ Bink2Context * const c = avctx->priv_data;
+ int ret;
+
+ c->version = avctx->codec_tag >> 24;
+ if (avctx->extradata_size < 4) {
+ av_log(avctx, AV_LOG_ERROR, "Extradata missing or too short\n");
+ return AVERROR_INVALIDDATA;
+ }
+ c->flags = AV_RL32(avctx->extradata);
+ av_log(avctx, AV_LOG_DEBUG, "flags: 0x%X\n", c->flags);
+ c->has_alpha = c->flags & BINK_FLAG_ALPHA;
+ c->avctx = avctx;
+
+ c->last = av_frame_alloc();
+ if (!c->last)
+ return AVERROR(ENOMEM);
+
+ if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
+ return ret;
+
+ avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
+
+ ff_blockdsp_init(&c->dsp, avctx);
+
+ INIT_VLC_STATIC_LE(&bink2f_quant_vlc, 9, FF_ARRAY_ELEMS(bink2f_quant_codes),
+ bink2f_quant_bits, 1, 1, bink2f_quant_codes, 1, 1, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_val0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[0]),
+ bink2f_ac_val_bits[0], 1, 1, bink2f_ac_val_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_val1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_val_bits[1]),
+ bink2f_ac_val_bits[1], 1, 1, bink2f_ac_val_codes[1], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[0]),
+ bink2f_ac_skip_bits[0], 1, 1, bink2f_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2f_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2f_ac_skip_bits[1]),
+ bink2f_ac_skip_bits[1], 1, 1, bink2f_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
+
+ INIT_VLC_STATIC_LE(&bink2g_ac_skip0_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[0]),
+ bink2g_ac_skip_bits[0], 1, 1, bink2g_ac_skip_codes[0], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2g_ac_skip1_vlc, 9, FF_ARRAY_ELEMS(bink2g_ac_skip_bits[1]),
+ bink2g_ac_skip_bits[1], 1, 1, bink2g_ac_skip_codes[1], 2, 2, NULL, 0, 0, 512);
+ INIT_VLC_STATIC_LE(&bink2g_mv_vlc, 9, FF_ARRAY_ELEMS(bink2g_mv_bits),
+ bink2g_mv_bits, 1, 1, bink2g_mv_codes, 1, 1, NULL, 0, 0, 512);
+
+ c->current_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_q));
+ if (!c->current_q)
+ return AVERROR(ENOMEM);
+
+ c->prev_q = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_q));
+ if (!c->prev_q)
+ return AVERROR(ENOMEM);
+
+ c->current_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_dc));
+ if (!c->current_dc)
+ return AVERROR(ENOMEM);
+
+ c->prev_dc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_dc));
+ if (!c->prev_dc)
+ return AVERROR(ENOMEM);
+
+ c->current_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_idc));
+ if (!c->current_idc)
+ return AVERROR(ENOMEM);
+
+ c->prev_idc = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_idc));
+ if (!c->prev_q)
+ return AVERROR(ENOMEM);
+
+ c->current_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->current_mv));
+ if (!c->current_mv)
+ return AVERROR(ENOMEM);
+
+ c->prev_mv = av_malloc_array((avctx->width + 31) / 32, sizeof(*c->prev_mv));
+ if (!c->prev_mv)
+ return AVERROR(ENOMEM);
+
+ c->col_cbp = av_calloc((((avctx->width + 31) >> 3) + 7) >> 3, sizeof(*c->col_cbp));
+ if (!c->col_cbp)
+ return AVERROR(ENOMEM);
+
+ c->row_cbp = av_calloc((((avctx->height + 31) >> 3) + 7) >> 3, sizeof(*c->row_cbp));
+ if (!c->row_cbp)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+static void bink2_flush(AVCodecContext *avctx)
+{
+ Bink2Context *c = avctx->priv_data;
+
+ av_frame_unref(c->last);
+}
+
+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;
+}
+
+const FFCodec ff_bink2_decoder = {
+ .p.name = "binkvideo2",
+ .p.long_name = NULL_IF_CONFIG_SMALL("Bink video 2"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_BINKVIDEO2,
+ .priv_data_size = sizeof(Bink2Context),
+ .init = bink2_decode_init,
+ .close = bink2_decode_end,
+ FF_CODEC_DECODE_CB(bink2_decode_frame),
+ .flush = bink2_flush,
+ .p.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
+ FF_CODEC_CAP_INIT_CLEANUP,
+};
diff --git a/libavcodec/bink2f.h b/libavcodec/bink2f.h
new file mode 100644
index 0000000000..1e32239af9
--- /dev/null
+++ b/libavcodec/bink2f.h
@@ -0,0 +1,1236 @@
+/*
+ * 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
+ */
+
+#ifndef AVCODEC_BINK2F_H
+#define AVCODEC_BINK2F_H
+
+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 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 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.f;
+
+ 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(lrintf(block[j] - 512.0f));
+ block += 8;
+ dst += stride;
+ }
+}
+
+static void bink2f_idct_add(uint8_t *dst, int stride,
+ float *block)
+{
+ block[0] += 512.f;
+
+ 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] + lrintf(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 (av_popcount(cbp & 0xF)) {
+ if (av_popcount(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 (av_popcount(cbplo & 0xF)) {
+ if (av_popcount(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] = {
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6,
+};
+
+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);
+ 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] + 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;
+ }
+ 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;
+
+ 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;
+ }
+
+ 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 = bink2_next_skips[skip];
+ skip = bink2f_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ 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);
+ 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, 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);
+ 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, 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]);
+ }
+ }
+}
+
+#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];
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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 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;
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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);
+ }
+}
+
+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;
+ }
+
+ 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);
+
+ 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;
+
+ 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;
+}
+
+#endif /* AVCODEC_BINK2F_H */
diff --git a/libavcodec/bink2g.h b/libavcodec/bink2g.h
new file mode 100644
index 0000000000..bf1dce688c
--- /dev/null
+++ b/libavcodec/bink2g.h
@@ -0,0 +1,1481 @@
+/*
+ * 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
+ */
+
+#ifndef AVCODEC_BINK2G_H
+#define AVCODEC_BINK2G_H
+
+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,
+};
+
+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 uint8_t bink2g_skips[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 64, 0, 0, 0,
+};
+
+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 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 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;
+
+ 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;
+}
+
+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 + 0x1FF) >> 10;
+ }
+ }
+
+ 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;
+
+ next = 0;
+ idx = 1;
+ while (idx < 64) {
+ next--;
+ if (next < 1) {
+ skip = get_vlc2(gb, skip_vlc->table, skip_vlc->bits, 1);
+ if (skip < 0)
+ return AVERROR_INVALIDDATA;
+ next = bink2_next_skips[skip];
+ skip = bink2g_skips[skip];
+ if (skip == 11)
+ skip = get_bits(gb, 6);
+ 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;
+ block[i][scan[idx]] = ((val * qmat[q & 3][scan[idx]] * (1 << (q >> 2))) + 64) >> 7;
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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];
+
+ 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]);
+ }
+ }
+}
+
+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);
+
+ 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;
+ }
+ }
+
+ 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];
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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;
+}
+
+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;
+
+ if (mv_x < 0 || mv_x >= width ||
+ mv_y < 0 || mv_y >= height)
+ return;
+
+ msrc = src + mv_x + mv_y * sstride;
+
+ 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);
+ }
+}
+
+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 };
+
+ 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;
+ 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);
+ 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);
+ 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;
+}
+
+#endif /* AVCODEC_BINK2G_H */
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index e7f0f6a8d4..3bcf22e6e7 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1879,6 +1879,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
AV_CODEC_PROP_LOSSLESS,
.mime_types= MT("image/jxl"),
},
+ {
+ .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/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 8b317fa121..03234b7543 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -310,6 +310,7 @@ enum AVCodecID {
AV_CODEC_ID_GEM,
AV_CODEC_ID_VBN,
AV_CODEC_ID_JPEGXL,
+ 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/libavformat/bink.c b/libavformat/bink.c
index f4079dfb1d..abfc769a0b 100644
--- a/libavformat/bink.c
+++ b/libavformat/bink.c
@@ -72,7 +72,7 @@ static int probe(const AVProbeData *p)
b[3] == 'k')) ||
(b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */
(b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' ||
- b[3] == 'i' || b[3] == 'j' || b[3] == 'k'))) &&
+ b[3] == 'i' || b[3] == 'j' || b[3] == 'k' || b[3] == 'n'))) &&
AV_RL32(b+8) > 0 && // num_frames
AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
@@ -149,8 +149,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 ((ret = ff_get_extradata(s, vst->codecpar, pb, 4)) < 0)
@@ -169,7 +168,7 @@ static int read_header(AVFormatContext *s)
revision = ((vst->codecpar->codec_tag >> 24) % 0xFF);
if ((signature == AV_RL32("BIK") && (revision == 'k')) ||
- (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k')))
+ (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k') || revision == 'n'))
avio_skip(pb, 4); /* unknown new field */
if (bink->num_audio_tracks) {
--
2.36.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-06-01 10:38 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-24 13:36 [FFmpeg-devel] [PATCH] avcodec: add bink2 video decoder Paul B Mahol
2022-05-25 18:17 ` Tomas Härdin
2022-05-28 10:39 ` Andreas Rheinhardt
2022-06-01 8:09 ` Paul B Mahol
2022-06-01 8:57 ` Andreas Rheinhardt
2022-06-01 9:04 ` Paul B Mahol
2022-06-01 9:03 ` Andreas Rheinhardt
2022-06-01 9:45 ` Anton Khirnov
2022-06-01 8:20 Paul B Mahol
2022-06-01 10:41 Paul B Mahol
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git