ffmpeg-devel
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
June 2022
- 87 participants
- 314 discussions
Signed-off-by: Paul B Mahol <onemda(a)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
4
7
[PATCH] swscale/x86/yuv_2_rgb: fix access to memory past the frame data in yuv to rgb conversion
by Vardan Margaryan 01 Jun '22
by Vardan Margaryan 01 Jun '22
01 Jun '22
Y, U, V data is loaded at the end of the current iteration for the next
iteration.
It results in memory access past the frame data on the last iteration
(that data is never used after the loading).
So load data at the start of the iteration, so that only useful data is
loaded.
Signed-off-by: Vardan Margaryan <v.t.margaryan(a)gmail.com>
---
libswscale/x86/yuv_2_rgb.asm | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/libswscale/x86/yuv_2_rgb.asm b/libswscale/x86/yuv_2_rgb.asm
index 2f0b4130df..f968b3a0a2 100644
--- a/libswscale/x86/yuv_2_rgb.asm
+++ b/libswscale/x86/yuv_2_rgb.asm
@@ -139,10 +139,10 @@ cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num,
parameters
VBROADCASTSD vr_coff, [pointer_c_ditherq + 4 * 8]
%endif
%endif
+.loop0:
movu m_y, [py_2indexq + 2 * indexq]
movh m_u, [pu_indexq + indexq]
movh m_v, [pv_indexq + indexq]
-.loop0:
pxor m4, m4
mova m7, m6
punpcklbw m0, m4
@@ -347,9 +347,6 @@ cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num,
parameters
%endif ; PACK RGB15/16
%endif ; PACK RGB15/16/32
-movu m_y, [py_2indexq + 2 * indexq + 8 * time_num]
-movh m_v, [pv_indexq + indexq + 4 * time_num]
-movh m_u, [pu_indexq + indexq + 4 * time_num]
add imageq, 8 * depth * time_num
add indexq, 4 * time_num
js .loop0
--
2.30.2
2
1
Signed-off-by: Paul B Mahol <onemda(a)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
1
0
01 Jun '22
In libavformat/isom.c there is a table of object type indications,
ff_mp4_obj_type. There are a few entries at the bottom that are
nonstandard. I was wondering where this table is used, and more
specifically, where the FLAC entry is used. I can find few references
to this table in the source code, and I can figure out whether the
entry for FLAC is used at all.
The reason why I'm asking this: I sent in a request to register FLAC
fourccs and object type indication with the MP4 registration authority
(MP4RA) and I got a reply (referring to the object type indication)
which contained the following:
> Since very few use the MPEG-4 Object System any more, one can be assigned, but only if asked for. We no longer do it automatically.
So now my question is: would there be a problem (for ffmpeg) when such
an object type is NOT requested for FLAC? Would there be a benefit to
registering?
Please advise. If possible, please add a short reasoning that I can
copy/rephrase to MP4RA on this matter.
Kind regards, Martijn van Beurden
1
0