mirror of
https://github.com/sharpemu/ffmpeg-core.git
synced 2026-10-08 16:22:43 -07:00
3866 lines
149 KiB
Diff
3866 lines
149 KiB
Diff
diff --git a/configure b/configure
|
|
index 98b582a5d5..89ac08f611 100755
|
|
--- a/configure
|
|
+++ b/configure
|
|
@@ -2919,6 +2919,7 @@ atrac3p_decoder_select="sinewin"
|
|
atrac3pal_decoder_select="sinewin"
|
|
av1_decoder_select="atsc_a53 cbs_av1 dovi_rpudec"
|
|
bink_decoder_select="blockdsp hpeldsp"
|
|
+bink2_decoder_select="blockdsp"
|
|
binkaudio_dct_decoder_select="wma_freqs"
|
|
binkaudio_rdft_decoder_select="wma_freqs"
|
|
cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp"
|
|
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
|
|
index 153a9e3881..ebff3c239a 100644
|
|
--- a/libavcodec/Makefile
|
|
+++ b/libavcodec/Makefile
|
|
@@ -277,6 +277,7 @@ OBJS-$(CONFIG_AVUI_ENCODER) += avuienc.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 aa0fc47647..0b806a1458 100644
|
|
--- a/libavcodec/allcodecs.c
|
|
+++ b/libavcodec/allcodecs.c
|
|
@@ -63,6 +63,7 @@ extern const FFCodec ff_avui_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..6519efa335
|
|
--- /dev/null
|
|
+++ b/libavcodec/bink2.c
|
|
@@ -0,0 +1,480 @@
|
|
+/*
|
|
+ * 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/emms.h"
|
|
+#include "libavutil/imgutils.h"
|
|
+#include "libavutil/internal.h"
|
|
+#include "libavutil/mem.h"
|
|
+#include "avcodec.h"
|
|
+#include "blockdsp.h"
|
|
+#include "codec_internal.h"
|
|
+#include "copy_block.h"
|
|
+#include "decode.h"
|
|
+#include "idctdsp.h"
|
|
+#include "internal.h"
|
|
+#include "mathops.h"
|
|
+
|
|
+#define BITSTREAM_READER_LE
|
|
+#include "get_bits.h"
|
|
+#include "unary.h"
|
|
+#include "bink2.h"
|
|
+
|
|
+#include "bink2f.h"
|
|
+#include "bink2g.h"
|
|
+
|
|
+static void bink2_get_block_flags(GetBitContext *gb, int offset, int size, uint8_t *dst)
|
|
+{
|
|
+ int flags_left, mode = 0;
|
|
+ unsigned flag = 0;
|
|
+
|
|
+ if (get_bits1(gb) == 0) {
|
|
+ for (int i = 0; i < size; i++, offset++) {
|
|
+ const unsigned value = get_bits1(gb);
|
|
+
|
|
+ dst[offset >> 3] |= value << (offset & 7);
|
|
+ }
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ flags_left = size;
|
|
+ while (flags_left > 0) {
|
|
+ if (get_bits1(gb) == 0) {
|
|
+ int count;
|
|
+
|
|
+ if (mode == 3) {
|
|
+ flag ^= 1;
|
|
+ } else {
|
|
+ flag = get_bits1(gb);
|
|
+ }
|
|
+
|
|
+ dst[offset >> 3] |= flag << (offset & 7);
|
|
+ offset++;
|
|
+ flags_left--;
|
|
+
|
|
+ count = FFMIN(flags_left, 4);
|
|
+ for (int i = 0; i < count; i++, offset++, flags_left--) {
|
|
+ const unsigned value = get_bits1(gb);
|
|
+
|
|
+ dst[offset >> 3] |= value << (offset & 7);
|
|
+ }
|
|
+ mode = 2;
|
|
+ } else {
|
|
+ int bits, run;
|
|
+
|
|
+ bits = flags_left < 4 ? 2 : flags_left < 16 ? 4 : 5;
|
|
+ if (mode == 3) {
|
|
+ flag ^= 1;
|
|
+ run = bits + 1;
|
|
+ } else {
|
|
+ flag = get_bits1(gb);
|
|
+ run = bits + 2;
|
|
+ }
|
|
+
|
|
+ run = FFMIN(run, flags_left);
|
|
+ if (run != flags_left) {
|
|
+ const unsigned extra = get_bits(gb, bits);
|
|
+
|
|
+ run += extra;
|
|
+ mode = extra == (1U << bits) - 1 ? 1 : 3;
|
|
+ }
|
|
+
|
|
+ for (int i = 0; i < run; i++, offset++)
|
|
+ dst[offset >> 3] |= flag << (offset & 7);
|
|
+ flags_left -= run;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+typedef struct Bink2ThreadData {
|
|
+ AVFrame *frame;
|
|
+ int is_kf;
|
|
+ int slice_end[BINK2_MAX_SLICES];
|
|
+} Bink2ThreadData;
|
|
+
|
|
+static int bink2_decode_slice(AVCodecContext *avctx, void *arg,
|
|
+ int jobnr, int threadnr)
|
|
+{
|
|
+ Bink2Context *parent = avctx->priv_data;
|
|
+ Bink2ThreadData *td = arg;
|
|
+ Bink2Context *c = parent->slice_ctx[jobnr];
|
|
+ GetBitContext *gb = &c->gb;
|
|
+ AVFrame *frame = td->frame;
|
|
+ uint8_t *dst[4];
|
|
+ uint8_t *src[4];
|
|
+ int stride[4];
|
|
+ int sstride[4];
|
|
+ const int start = jobnr ? parent->slice_height[jobnr - 1] : 0;
|
|
+ const int end = parent->slice_height[jobnr];
|
|
+ int bits_left, ret;
|
|
+
|
|
+ (void)threadnr;
|
|
+
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ src[i] = parent->last->data[i];
|
|
+ dst[i] = frame->data[i];
|
|
+ stride[i] = frame->linesize[i];
|
|
+ sstride[i] = parent->last->linesize[i];
|
|
+ }
|
|
+
|
|
+ dst[0] += start * stride[0];
|
|
+ dst[1] += start / 2 * stride[1];
|
|
+ dst[2] += start / 2 * stride[2];
|
|
+ if (c->has_alpha)
|
|
+ dst[3] += start * stride[3];
|
|
+
|
|
+ if (c->version <= 'f' || !(c->frame_flags & 0x2000))
|
|
+ ret = bink2f_decode_slice(c, dst, stride, src, sstride,
|
|
+ td->is_kf, start, end);
|
|
+ else
|
|
+ ret = bink2g_decode_slice(c, dst, stride, src, sstride,
|
|
+ td->is_kf, start, end);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ align_get_bits(gb);
|
|
+ bits_left = 8 * td->slice_end[jobnr] - get_bits_count(gb);
|
|
+ if (bits_left < 0)
|
|
+ av_log(avctx, AV_LOG_WARNING, "slice %d: overread\n", jobnr);
|
|
+ else if (bits_left > 24)
|
|
+ av_log(avctx, AV_LOG_WARNING, "slice %d: underread %d\n",
|
|
+ jobnr, bits_left);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int bink2_decode_frame(AVCodecContext *avctx, AVFrame *frame,
|
|
+ int *got_frame, AVPacket *pkt)
|
|
+{
|
|
+ Bink2Context * const c = avctx->priv_data;
|
|
+ GetBitContext *gb = &c->gb;
|
|
+ Bink2ThreadData td = { .frame = frame };
|
|
+ int thread_ret[BINK2_MAX_SLICES] = { 0 };
|
|
+ int is_kf = !!(pkt->flags & AV_PKT_FLAG_KEY);
|
|
+ int first_slice_bit, ret, w, h;
|
|
+ int height_a;
|
|
+
|
|
+ if (pkt->size < 4)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+
|
|
+ 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;
|
|
+
|
|
+ if (!is_kf && (!c->last->data[0] ||
|
|
+ !c->last->data[1] ||
|
|
+ !c->last->data[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;
|
|
+
|
|
+ if (pkt->size < 4 + 4 * (c->num_slices - 1))
|
|
+ return AVERROR_INVALIDDATA;
|
|
+
|
|
+ skip_bits_long(gb, 32 + 32 * (c->num_slices - 1));
|
|
+
|
|
+ memset(c->row_cbp, 0,
|
|
+ ((((avctx->height + 31) >> 3) + 7) >> 3) * sizeof(*c->row_cbp));
|
|
+ memset(c->col_cbp, 0,
|
|
+ ((((avctx->width + 31) >> 3) + 7) >> 3) * sizeof(*c->col_cbp));
|
|
+
|
|
+ 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 + 31) & ~31) >> 3) - 1, c->col_cbp);
|
|
+ }
|
|
+
|
|
+ if (get_bits_left(gb) < 0)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+
|
|
+ td.is_kf = is_kf;
|
|
+ first_slice_bit = get_bits_count(gb);
|
|
+ for (int i = 0; i < c->num_slices; i++) {
|
|
+ Bink2Context *sc = c->slice_ctx[i];
|
|
+ const int start = i ? td.slice_end[i - 1] : 0;
|
|
+ const int start_bit = i ? 8 * start : first_slice_bit;
|
|
+
|
|
+ td.slice_end[i] = i == c->num_slices - 1 ?
|
|
+ pkt->size : AV_RL32(pkt->data + 4 + 4 * i);
|
|
+ if (td.slice_end[i] < start ||
|
|
+ td.slice_end[i] > pkt->size ||
|
|
+ 8 * td.slice_end[i] < start_bit)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+
|
|
+ sc->frame_flags = c->frame_flags;
|
|
+ if (i) {
|
|
+ if ((ret = init_get_bits8(&sc->gb, pkt->data, pkt->size)) < 0)
|
|
+ return ret;
|
|
+ skip_bits_long(&sc->gb, start_bit);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((ret = avctx->execute2(avctx, bink2_decode_slice, &td,
|
|
+ thread_ret, c->num_slices)) < 0)
|
|
+ return ret;
|
|
+ for (int i = 0; i < c->num_slices; i++)
|
|
+ if (thread_ret[i] < 0)
|
|
+ return thread_ret[i];
|
|
+
|
|
+ if (c->version > 'f' && (c->frame_flags & 0x2000)) {
|
|
+ bink2g_postprocess_frame(c, frame->data, frame->linesize);
|
|
+ }
|
|
+
|
|
+ if (is_kf)
|
|
+ frame->flags |= AV_FRAME_FLAG_KEY;
|
|
+ else
|
|
+ frame->flags &= ~AV_FRAME_FLAG_KEY;
|
|
+ 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;
|
|
+
|
|
+ frame->colorspace = avctx->colorspace;
|
|
+ frame->color_range = avctx->color_range;
|
|
+
|
|
+ *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 VLCElem table[static_size]; \
|
|
+ (vlc)->table = table; \
|
|
+ (vlc)->table_allocated = static_size; \
|
|
+ ff_vlc_init_sparse(vlc, nb_bits, nb_codes, \
|
|
+ bits, bits_wrap, bits_size, \
|
|
+ codes, codes_wrap, codes_size, \
|
|
+ symbols, symbols_wrap, symbols_size, \
|
|
+ VLC_INIT_LE | VLC_INIT_USE_STATIC); \
|
|
+ } while (0)
|
|
+
|
|
+static int bink2_alloc_slice_state(Bink2Context *c, int width)
|
|
+{
|
|
+ const int mb_width = (width + 31) / 32;
|
|
+
|
|
+ c->current_q = av_malloc_array(mb_width, sizeof(*c->current_q));
|
|
+ c->prev_q = av_malloc_array(mb_width, sizeof(*c->prev_q));
|
|
+ c->current_dc = av_malloc_array(mb_width, sizeof(*c->current_dc));
|
|
+ c->prev_dc = av_malloc_array(mb_width, sizeof(*c->prev_dc));
|
|
+ c->current_idc = av_malloc_array(mb_width, sizeof(*c->current_idc));
|
|
+ c->prev_idc = av_malloc_array(mb_width, sizeof(*c->prev_idc));
|
|
+ c->current_mv = av_malloc_array(mb_width, sizeof(*c->current_mv));
|
|
+ c->prev_mv = av_malloc_array(mb_width, sizeof(*c->prev_mv));
|
|
+
|
|
+ if (!c->current_q || !c->prev_q ||
|
|
+ !c->current_dc || !c->prev_dc ||
|
|
+ !c->current_idc || !c->prev_idc ||
|
|
+ !c->current_mv || !c->prev_mv)
|
|
+ return AVERROR(ENOMEM);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void bink2_free_slice_state(Bink2Context *c)
|
|
+{
|
|
+ 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);
|
|
+}
|
|
+
|
|
+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->slice_ctx[0] = c;
|
|
+
|
|
+ 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;
|
|
+ avctx->colorspace = AVCOL_SPC_SMPTE170M;
|
|
+ avctx->color_range = c->flags & BINK_FLAG_YCRCB_NEW ?
|
|
+ AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
|
|
+
|
|
+ ff_blockdsp_init(&c->dsp);
|
|
+
|
|
+ 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);
|
|
+
|
|
+ if ((ret = bink2_alloc_slice_state(c, avctx->width)) < 0)
|
|
+ return ret;
|
|
+
|
|
+ {
|
|
+ const size_t mb_count = (size_t)((avctx->width + 31) >> 5) *
|
|
+ ((avctx->height + 31) >> 5);
|
|
+
|
|
+ c->frame_idc = av_malloc_array(mb_count, sizeof(*c->frame_idc));
|
|
+ c->frame_mv = av_malloc_array(mb_count, sizeof(*c->frame_mv));
|
|
+ if (!c->frame_idc || !c->frame_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);
|
|
+
|
|
+ for (int i = 1; i < BINK2_MAX_SLICES; i++) {
|
|
+ Bink2Context *sc = av_mallocz(sizeof(*sc));
|
|
+
|
|
+ if (!sc)
|
|
+ return AVERROR(ENOMEM);
|
|
+ c->slice_ctx[i] = sc;
|
|
+ sc->avctx = avctx;
|
|
+ sc->version = c->version;
|
|
+ sc->has_alpha = c->has_alpha;
|
|
+ sc->flags = c->flags;
|
|
+ sc->dsp = c->dsp;
|
|
+ sc->col_cbp = c->col_cbp;
|
|
+ sc->row_cbp = c->row_cbp;
|
|
+ sc->frame_idc = c->frame_idc;
|
|
+ sc->frame_mv = c->frame_mv;
|
|
+ if ((ret = bink2_alloc_slice_state(sc, avctx->width)) < 0)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ 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);
|
|
+ for (int i = 1; i < BINK2_MAX_SLICES; i++) {
|
|
+ if (c->slice_ctx[i]) {
|
|
+ bink2_free_slice_state(c->slice_ctx[i]);
|
|
+ av_freep(&c->slice_ctx[i]);
|
|
+ }
|
|
+ }
|
|
+ bink2_free_slice_state(c);
|
|
+ av_freep(&c->frame_idc);
|
|
+ av_freep(&c->frame_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 | AV_CODEC_CAP_SLICE_THREADS,
|
|
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
|
+};
|
|
diff --git a/libavcodec/bink2.h b/libavcodec/bink2.h
|
|
new file mode 100644
|
|
index 0000000000..67d7603370
|
|
--- /dev/null
|
|
+++ b/libavcodec/bink2.h
|
|
@@ -0,0 +1,147 @@
|
|
+/*
|
|
+ * Bink video 2 decoder
|
|
+ * Copyright (c) 2014 Konstantin Shishkov
|
|
+ * Copyright (c) 2019 Paul B Mahol
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#ifndef AVCODEC_BINK2_H
|
|
+#define AVCODEC_BINK2_H
|
|
+
|
|
+#include <stdint.h>
|
|
+#include "libavutil/mem_internal.h"
|
|
+#include "avcodec.h"
|
|
+#include "blockdsp.h"
|
|
+#include "copy_block.h"
|
|
+#include "unary.h"
|
|
+#include "get_bits.h"
|
|
+
|
|
+static VLC bink2f_quant_vlc;
|
|
+static VLC bink2f_ac_val0_vlc;
|
|
+static VLC bink2f_ac_val1_vlc;
|
|
+static VLC bink2f_ac_skip0_vlc;
|
|
+static VLC bink2f_ac_skip1_vlc;
|
|
+static VLC bink2g_ac_skip0_vlc;
|
|
+static VLC bink2g_ac_skip1_vlc;
|
|
+static VLC bink2g_mv_vlc;
|
|
+
|
|
+static const uint8_t kb2h_num_slices[] = {
|
|
+ 2, 3, 4, 8,
|
|
+};
|
|
+
|
|
+static const uint8_t luma_repos[] = {
|
|
+ 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15,
|
|
+};
|
|
+
|
|
+static const uint8_t dq_patterns[8] = { 8, 0, 1, 0, 2, 0, 1, 0 };
|
|
+
|
|
+static const uint8_t bink2_next_skips[] = {
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
|
|
+};
|
|
+
|
|
+#define NUM_AC_SKIPS 14
|
|
+#define BINK2_MAX_SLICES 8
|
|
+#define BINK_FLAG_YCRCB_NEW 0x00000010
|
|
+#define BINK_FLAG_ALPHA 0x00100000
|
|
+#define DC_MPRED(A, B, C) FFMIN(FFMAX((C) + (B) - (A), FFMIN3(A, B, C)), FFMAX3(A, B, C))
|
|
+#define DC_MPRED2(A, B) FFMIN(FFMAX((A), (B)), FFMAX(FFMIN((A), (B)), 2 * (A) - (B)))
|
|
+#define LHFILTER(src) (((((src)[0]+(src)[1])*19 >> 1)-((src)[-1]+(src)[2 ])*2+(((src)[-2 ]+(src)[3 ])>>1)+8)>>4)
|
|
+#define LVFILTER(src, i) (((((src)[0]+(src)[i])*19 >> 1)-((src)[-i]+(src)[2*i])*2+(((src)[-2*i]+(src)[3*i])>>1)+8)>>4)
|
|
+
|
|
+typedef struct QuantPredict {
|
|
+ int8_t intra_q;
|
|
+ int8_t inter_q;
|
|
+} QuantPredict;
|
|
+
|
|
+typedef struct DCPredict {
|
|
+ float dc[4][16];
|
|
+ int block_type;
|
|
+} DCPredict;
|
|
+
|
|
+typedef struct DCIPredict {
|
|
+ int dc[4][16];
|
|
+ uint16_t state[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;
|
|
+
|
|
+ /* Modern Bink2 reconstruction and filtering need the neighbouring rows
|
|
+ * even when those rows belong to different bitstream slices. Slice jobs
|
|
+ * write disjoint rows here; the parent context post-processes the complete
|
|
+ * frame after every slice has finished. */
|
|
+ DCIPredict *frame_idc;
|
|
+ MVPredict *frame_mv;
|
|
+
|
|
+ uint8_t *col_cbp;
|
|
+ uint8_t *row_cbp;
|
|
+
|
|
+ int num_slices;
|
|
+ int slice_height[BINK2_MAX_SLICES];
|
|
+ struct Bink2Context *slice_ctx[BINK2_MAX_SLICES];
|
|
+
|
|
+ int comp;
|
|
+ int mb_pos;
|
|
+ unsigned flags;
|
|
+ unsigned frame_flags;
|
|
+} Bink2Context;
|
|
+
|
|
+/**
|
|
+ * Bink2 video block types
|
|
+ */
|
|
+enum BlockTypes {
|
|
+ INTRA_BLOCK = 0, ///< intra DCT block
|
|
+ SKIP_BLOCK, ///< skipped block
|
|
+ MOTION_BLOCK, ///< block is copied from previous frame with some offset
|
|
+ RESIDUE_BLOCK, ///< motion block with some difference added
|
|
+};
|
|
+
|
|
+#endif /* AVCODEC_BINK2_H */
|
|
diff --git a/libavcodec/bink2f.h b/libavcodec/bink2f.h
|
|
new file mode 100644
|
|
index 0000000000..4fa42d0b71
|
|
--- /dev/null
|
|
+++ b/libavcodec/bink2f.h
|
|
@@ -0,0 +1,1241 @@
|
|
+/*
|
|
+ * Bink video 2 decoder
|
|
+ * Copyright (c) 2014 Konstantin Shishkov
|
|
+ * Copyright (c) 2019 Paul B Mahol
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#ifndef AVCODEC_BINK2F_H
|
|
+#define AVCODEC_BINK2F_H
|
|
+
|
|
+#include <stdint.h>
|
|
+#include "avcodec.h"
|
|
+#include "get_bits.h"
|
|
+#include "bink2.h"
|
|
+
|
|
+static const uint8_t bink2f_quant_codes[16] = {
|
|
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x30, 0x50, 0x70,
|
|
+ 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0,
|
|
+};
|
|
+
|
|
+static const uint8_t bink2f_quant_bits[16] = {
|
|
+ 1, 2, 3, 4, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
|
|
+};
|
|
+
|
|
+static const uint16_t bink2f_ac_val_codes[2][13] = {
|
|
+ {
|
|
+ 0x04, 0x01, 0x02, 0x00, 0x08, 0x18, 0xF8, 0x178, 0x138,
|
|
+ 0x38, 0x1B8, 0x78, 0xB8
|
|
+ },
|
|
+ {
|
|
+ 0x0A, 0x01, 0x04, 0x08, 0x06, 0x00, 0x02, 0x1A, 0x2A,
|
|
+ 0x16A, 0x1EA, 0x6A, 0xEA
|
|
+ },
|
|
+};
|
|
+
|
|
+static const uint8_t bink2f_ac_val_bits[2][13] = {
|
|
+ { 3, 1, 2, 4, 5, 6, 8, 9, 9, 9, 9, 9, 9 },
|
|
+ { 6, 1, 3, 4, 3, 4, 4, 5, 7, 9, 9, 9, 9 },
|
|
+};
|
|
+
|
|
+static const uint16_t bink2f_ac_skip_codes[2][NUM_AC_SKIPS] = {
|
|
+ {
|
|
+ 0x00, 0x01, 0x0D, 0x15, 0x45, 0x85, 0xA5, 0x165,
|
|
+ 0x65, 0x1E5, 0xE5, 0x25, 0x03, 0x05
|
|
+ },
|
|
+ {
|
|
+ 0x00, 0x01, 0x03, 0x07, 0x1F, 0x1B, 0x0F, 0x2F,
|
|
+ 0x5B, 0xDB, 0x1DB, 0x3B, 0x05, 0x0B
|
|
+ }
|
|
+};
|
|
+
|
|
+static const uint8_t bink2f_ac_skip_bits[2][NUM_AC_SKIPS] = {
|
|
+ { 1, 3, 4, 5, 7, 8, 8, 9, 9, 9, 9, 8, 2, 8 },
|
|
+ { 1, 3, 4, 4, 5, 7, 6, 6, 8, 9, 9, 6, 3, 5 }
|
|
+};
|
|
+
|
|
+static const uint8_t bink2f_skips[] = {
|
|
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 62, 0, 0, 0,
|
|
+};
|
|
+
|
|
+static const float bink2f_dc_quant[16] = {
|
|
+ 4, 4, 4, 4, 4, 6, 7, 8, 10, 12, 16, 24, 32, 48, 64, 128
|
|
+};
|
|
+
|
|
+static const float bink2f_ac_quant[16] = {
|
|
+ 1.0, 2.0, 2.5, 3.0, 3.5, 4.0, 6.0, 7.0, 8.0, 12.0, 16.0, 24.0, 32.0, 48.0, 64.0, 128.0
|
|
+};
|
|
+
|
|
+static const float bink2f_luma_intra_qmat[64] = {
|
|
+ 0.125, 0.190718, 0.16332, 0.235175, 0.3, 0.392847, 0.345013, 0.210373,
|
|
+ 0.208056, 0.288582, 0.317145, 0.387359, 0.450788, 0.790098, 0.562995, 0.263095,
|
|
+ 0.228649, 0.294491, 0.341421, 0.460907, 0.653281, 0.731424, 0.60988, 0.252336,
|
|
+ 0.205778, 0.346585, 0.422498, 0.501223, 0.749621, 1.004719, 0.636379, 0.251428,
|
|
+ 0.225, 0.381436, 0.604285, 0.823113, 0.85, 1.070509, 0.69679, 0.265553,
|
|
+ 0.235708, 0.476783, 0.70576, 0.739104, 0.795516, 0.802512, 0.600616, 0.249289,
|
|
+ 0.331483, 0.600528, 0.689429, 0.692062, 0.69679, 0.643138, 0.43934, 0.188511,
|
|
+ 0.248309, 0.440086, 0.42807, 0.397419, 0.386259, 0.270966, 0.192244, 0.094199,
|
|
+};
|
|
+
|
|
+static const float bink2f_luma_inter_qmat[64] = {
|
|
+ 0.125, 0.17338, 0.16332, 0.146984, 0.128475, 0.106393, 0.077046, 0.043109,
|
|
+ 0.17338, 0.240485, 0.226532, 0.203873, 0.1782, 0.147571, 0.109474, 0.062454,
|
|
+ 0.16332, 0.226532, 0.219321, 0.202722, 0.181465, 0.149711, 0.112943, 0.062584,
|
|
+ 0.146984, 0.203873, 0.202722, 0.201647, 0.183731, 0.153976, 0.11711, 0.065335,
|
|
+ 0.128475, 0.1782, 0.181465, 0.183731, 0.177088, 0.155499, 0.120267, 0.068016,
|
|
+ 0.106393, 0.147571, 0.149711, 0.153976, 0.155499, 0.145756, 0.116636, 0.068495,
|
|
+ 0.077046, 0.109474, 0.112943, 0.11711, 0.120267, 0.116636, 0.098646, 0.060141,
|
|
+ 0.043109, 0.062454, 0.062584, 0.065335, 0.068016, 0.068495, 0.060141, 0.038853,
|
|
+};
|
|
+
|
|
+static const float bink2f_chroma_qmat[64] = {
|
|
+ 0.125, 0.17338, 0.217761, 0.383793, 0.6875, 0.54016501, 0.37207201, 0.18968099,
|
|
+ 0.17338, 0.28056601, 0.32721299, 0.74753499, 0.95358998, 0.74923098, 0.51607901, 0.26309499,
|
|
+ 0.217761, 0.32721299, 0.66387498, 1.056244, 0.89826202, 0.70576, 0.48613599, 0.24783,
|
|
+ 0.383793, 0.74753499, 1.056244, 0.95059502, 0.80841398, 0.635167, 0.437511, 0.223041,
|
|
+ 0.6875, 0.95358998, 0.89826202, 0.80841398, 0.6875, 0.54016501, 0.37207201, 0.18968099,
|
|
+ 0.54016501, 0.74923098, 0.70576, 0.635167, 0.54016501, 0.42440501, 0.292335, 0.149031,
|
|
+ 0.37207201, 0.51607901, 0.48613599, 0.437511, 0.37207201, 0.292335, 0.201364, 0.102655,
|
|
+ 0.18968099, 0.26309499, 0.24783, 0.223041, 0.18968099, 0.149031, 0.102655, 0.052333001
|
|
+};
|
|
+
|
|
+static const uint8_t bink2f_luma_scan[64] = {
|
|
+ 0, 2, 1, 8, 9, 17, 10, 16,
|
|
+ 24, 3, 18, 25, 32, 11, 33, 26,
|
|
+ 4, 40, 19, 12, 27, 41, 34, 5,
|
|
+ 20, 48, 6, 28, 15, 42, 23, 35,
|
|
+ 21, 13, 14, 7, 31, 43, 49, 36,
|
|
+ 22, 56, 39, 50, 30, 44, 29, 51,
|
|
+ 57, 47, 58, 59, 63, 61, 55, 38,
|
|
+ 52, 62, 45, 37, 60, 46, 54, 53
|
|
+};
|
|
+
|
|
+static const uint8_t bink2f_chroma_scan[64] = {
|
|
+ 0, 1, 8, 2, 9, 16, 10, 17,
|
|
+ 3, 24, 11, 18, 25, 13, 14, 4,
|
|
+ 15, 5, 6, 7, 12, 19, 20, 21,
|
|
+ 22, 23, 26, 27, 28, 29, 30, 31,
|
|
+ 32, 33, 34, 35, 36, 37, 38, 39,
|
|
+ 40, 41, 42, 43, 44, 45, 46, 47,
|
|
+ 48, 49, 50, 51, 52, 53, 54, 55,
|
|
+ 56, 57, 58, 59, 60, 61, 62, 63
|
|
+};
|
|
+
|
|
+static inline void bink2f_idct_1d(float *blk, int step)
|
|
+{
|
|
+ float t00 = blk[2 * step] + blk[6 * step];
|
|
+ float t01 = (blk[2 * step] - blk[6 * step]) * 1.4142135f - t00;
|
|
+ float t02 = blk[0 * step] + blk[4 * step];
|
|
+ float t03 = blk[0 * step] - blk[4 * step];
|
|
+ float t04 = blk[3 * step] + blk[5 * step];
|
|
+ float t05 = blk[3 * step] - blk[5 * step];
|
|
+ float t06 = blk[1 * step] + blk[7 * step];
|
|
+ float t07 = blk[1 * step] - blk[7 * step];
|
|
+ float t08 = t02 + t00;
|
|
+ float t09 = t02 - t00;
|
|
+ float t10 = t03 + t01;
|
|
+ float t11 = t03 - t01;
|
|
+ float t12 = t06 + t04;
|
|
+ float t13 = (t06 - t04) * 1.4142135f;
|
|
+ float t14 = (t07 - t05) * 1.847759f;
|
|
+ float t15 = t05 * 2.613126f + t14 - t12;
|
|
+ float t16 = t13 - t15;
|
|
+ float t17 = t07 * 1.0823922f - t14 + t16;
|
|
+
|
|
+ blk[0*step] = t08 + t12;
|
|
+ blk[1*step] = t10 + t15;
|
|
+ blk[2*step] = t11 + t16;
|
|
+ blk[3*step] = t09 - t17;
|
|
+ blk[4*step] = t09 + t17;
|
|
+ blk[5*step] = t11 - t16;
|
|
+ blk[6*step] = t10 - t15;
|
|
+ blk[7*step] = t08 - t12;
|
|
+}
|
|
+
|
|
+static void bink2f_idct_put(uint8_t *dst, int stride, float *block)
|
|
+{
|
|
+ block[0] += 512.f;
|
|
+
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ bink2f_idct_1d(block + i, 8);
|
|
+ for (int i = 0; i < 8; i++) {
|
|
+ bink2f_idct_1d(block, 1);
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ dst[j] = av_clip_uint8(lrintf(block[j] - 512.0f));
|
|
+ block += 8;
|
|
+ dst += stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2f_idct_add(uint8_t *dst, int stride,
|
|
+ float *block)
|
|
+{
|
|
+ block[0] += 512.f;
|
|
+
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ bink2f_idct_1d(block + i, 8);
|
|
+ for (int i = 0; i < 8; i++) {
|
|
+ bink2f_idct_1d(block, 1);
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ dst[j] = av_clip_uint8(dst[j] + lrintf(block[j] - 512.0f));
|
|
+ block += 8;
|
|
+ dst += stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int bink2f_decode_delta_q(GetBitContext *gb)
|
|
+{
|
|
+ int dq = get_vlc2(gb, bink2f_quant_vlc.table, bink2f_quant_vlc.bits, 1);
|
|
+
|
|
+ if (dq < 0)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ if (dq && get_bits1(gb))
|
|
+ dq = -dq;
|
|
+
|
|
+ return dq;
|
|
+}
|
|
+
|
|
+static unsigned bink2f_decode_cbp_luma(GetBitContext *gb, unsigned prev_cbp)
|
|
+{
|
|
+ unsigned cbp, cbp4, cbplo, cbphi;
|
|
+
|
|
+ if (get_bits1(gb)) {
|
|
+ if (get_bits1(gb))
|
|
+ return prev_cbp;
|
|
+ cbplo = prev_cbp & 0xFFFF;
|
|
+ } else {
|
|
+ cbplo = 0;
|
|
+ cbp4 = (prev_cbp >> 4) & 0xF;
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ if (!get_bits1(gb))
|
|
+ cbp4 = get_bits(gb, 4);
|
|
+ cbplo |= cbp4 << (i * 4);
|
|
+ }
|
|
+ }
|
|
+ cbphi = 0;
|
|
+ cbp = cbplo;
|
|
+ cbp4 = prev_cbp >> 20 & 0xF;
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ if (av_popcount(cbp & 0xF)) {
|
|
+ if (av_popcount(cbp & 0xF) == 1) {
|
|
+ cbp4 = 0;
|
|
+ for (int j = 1; j < 16; j <<= 1) {
|
|
+ if ((j & cbp) && get_bits1(gb))
|
|
+ cbp4 |= j;
|
|
+ }
|
|
+ } else if (!get_bits1(gb)) {
|
|
+ cbp4 = 0;
|
|
+ for (int j = 1; j < 16; j <<= 1) {
|
|
+ if ((j & cbp) && get_bits1(gb))
|
|
+ cbp4 |= j;
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ cbp4 = 0;
|
|
+ }
|
|
+ cbp4 &= cbp;
|
|
+ cbphi = (cbphi >> 4) | (cbp4 << 0x1c);
|
|
+ cbp >>= 4;
|
|
+ }
|
|
+ return cbphi | cbplo;
|
|
+}
|
|
+
|
|
+static unsigned bink2f_decode_cbp_chroma(GetBitContext *gb, unsigned prev_cbp)
|
|
+{
|
|
+ unsigned cbplo, cbphi;
|
|
+
|
|
+ if (get_bits1(gb)) {
|
|
+ if (get_bits1(gb))
|
|
+ return prev_cbp;
|
|
+ cbplo = prev_cbp & 0xF;
|
|
+ } else {
|
|
+ cbplo = get_bits(gb, 4);
|
|
+ }
|
|
+
|
|
+ cbphi = 0;
|
|
+ if (av_popcount(cbplo & 0xF)) {
|
|
+ if (av_popcount(cbplo & 0xF) != 1) {
|
|
+ cbphi = (prev_cbp >> 16) & cbplo;
|
|
+ if (get_bits1(gb))
|
|
+ return cbplo | (cbphi << 16);
|
|
+ }
|
|
+ cbphi = 0;
|
|
+ for (int j = 1; j < 16; j <<= 1) {
|
|
+ if ((j & cbplo) && get_bits1(gb))
|
|
+ cbphi |= j;
|
|
+ }
|
|
+ }
|
|
+ return cbplo | (cbphi << 16);
|
|
+}
|
|
+
|
|
+static const uint8_t q_dc_bits[16] = {
|
|
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6,
|
|
+};
|
|
+
|
|
+static void bink2f_predict_dc(Bink2Context *c,
|
|
+ int is_luma, float mindc, float maxdc,
|
|
+ int flags, float tdc[16])
|
|
+{
|
|
+ float *LTdc = c->prev_dc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
|
|
+ float *Tdc = c->prev_dc[c->mb_pos].dc[c->comp];
|
|
+ float *Ldc = c->current_dc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
|
|
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
|
|
+
|
|
+ if (is_luma && (flags & 0x20) && (flags & 0x80)) {
|
|
+ dc[0] = av_clipf((mindc < 0 ? 0 : 1024.f) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clipf(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clipf(dc[4] + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clipf(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clipf(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (is_luma && (flags & 0x80)) {
|
|
+ dc[0] = av_clipf(DC_MPRED2(Ldc[5], Ldc[7]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clipf(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clipf(dc[4] + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clipf(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clipf(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (is_luma && (flags & 0x20)) {
|
|
+ dc[0] = av_clipf(DC_MPRED2(Tdc[10], Tdc[11]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clipf(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clipf(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clipf(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clipf(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (is_luma) {
|
|
+ dc[0] = av_clipf(DC_MPRED(LTdc[15], Ldc[5], Tdc[10]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clipf(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clipf(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clipf(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clipf(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clipf(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clipf(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clipf(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clipf(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clipf(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clipf(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clipf(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clipf(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (!is_luma && (flags & 0x20) && (flags & 0x80)) {
|
|
+ dc[0] = av_clipf((mindc < 0 ? 0 : 1024.f) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ } else if (!is_luma && (flags & 0x80)) {
|
|
+ dc[0] = av_clipf(DC_MPRED2(Ldc[1], Ldc[3]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ } else if (!is_luma && (flags & 0x20)) {
|
|
+ dc[0] = av_clipf(DC_MPRED2(Tdc[2], Tdc[3]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ } else if (!is_luma) {
|
|
+ dc[0] = av_clipf(DC_MPRED(LTdc[3], Ldc[1], Tdc[2]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clipf(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clipf(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clipf(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2f_decode_dc(Bink2Context *c, GetBitContext *gb, float *dc,
|
|
+ int is_luma, int q, int mindc, int maxdc,
|
|
+ int flags)
|
|
+{
|
|
+ const int num_dc = is_luma ? 16 : 4;
|
|
+ float tdc[16] = { 0 };
|
|
+ int dc_bits;
|
|
+
|
|
+ dc_bits = get_bits(gb, 3);
|
|
+ if (dc_bits == 7)
|
|
+ dc_bits += get_bits(gb, 2);
|
|
+ if (!dc_bits) {
|
|
+ memset(dc, 0, sizeof(*dc) * num_dc);
|
|
+ } else {
|
|
+ for (int j = 0; j < num_dc; j += 4) {
|
|
+ for (int i = 0; i < 4; i++)
|
|
+ tdc[i + j] = get_bits(gb, dc_bits);
|
|
+
|
|
+ for (int i = 0; i < 4; i++)
|
|
+ if (tdc[i + j] && get_bits1(gb))
|
|
+ tdc[i + j] = -tdc[i + j];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((flags & 0x20) && (flags & 0x80) && mindc >= 0) {
|
|
+ int bits = q_dc_bits[q] + dc_bits;
|
|
+
|
|
+ if (bits < 10) {
|
|
+ int dc_val = get_bits(gb, 10 - bits);
|
|
+
|
|
+ if (dc_val) {
|
|
+ dc_val <<= dc_bits;
|
|
+ if (get_bits1(gb))
|
|
+ dc_val = -dc_val;
|
|
+ }
|
|
+ tdc[0] += dc_val;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (int i = 0; i < num_dc; i++)
|
|
+ tdc[i] *= bink2f_dc_quant[q];
|
|
+
|
|
+ bink2f_predict_dc(c, is_luma, mindc, maxdc, flags, tdc);
|
|
+}
|
|
+
|
|
+static int bink2f_decode_ac(GetBitContext *gb, const uint8_t *scan,
|
|
+ float block[4][64], unsigned cbp,
|
|
+ float q, const float qmat[64])
|
|
+{
|
|
+ int idx, next, val, skip;
|
|
+ VLC *val_vlc, *skip_vlc;
|
|
+
|
|
+ for (int i = 0; i < 4; i++, cbp >>= 1) {
|
|
+ memset(block[i], 0, sizeof(**block) * 64);
|
|
+
|
|
+ if (!(cbp & 1))
|
|
+ continue;
|
|
+
|
|
+ if (cbp & 0x10000) {
|
|
+ val_vlc = &bink2f_ac_val1_vlc;
|
|
+ skip_vlc = &bink2f_ac_skip1_vlc;
|
|
+ } else {
|
|
+ val_vlc = &bink2f_ac_val0_vlc;
|
|
+ skip_vlc = &bink2f_ac_skip0_vlc;
|
|
+ }
|
|
+
|
|
+ next = 0;
|
|
+ idx = 1;
|
|
+ while (idx < 64) {
|
|
+ val = get_vlc2(gb, val_vlc->table, val_vlc->bits, 1);
|
|
+ if (val < 0)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ if (val) {
|
|
+ if (val >= 4) {
|
|
+ val -= 3;
|
|
+ val = get_bits(gb, val) + (1 << val) + 2;
|
|
+ }
|
|
+ if (get_bits1(gb))
|
|
+ val = -val;
|
|
+ }
|
|
+
|
|
+ block[i][scan[idx]] = val * q * qmat[scan[idx]];
|
|
+ if (idx > 62)
|
|
+ break;
|
|
+ idx++;
|
|
+ next--;
|
|
+ if (next < 1) {
|
|
+ skip = get_vlc2(gb, skip_vlc->table, skip_vlc->bits, 1);
|
|
+ if (skip < 0)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ next = bink2_next_skips[skip];
|
|
+ skip = bink2f_skips[skip];
|
|
+ if (skip == 11)
|
|
+ skip = get_bits(gb, 6);
|
|
+ idx += skip;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int bink2f_decode_intra_luma(Bink2Context *c,
|
|
+ float block[4][64],
|
|
+ unsigned *prev_cbp, int *prev_q,
|
|
+ uint8_t *dst, int stride,
|
|
+ int flags)
|
|
+{
|
|
+ GetBitContext *gb = &c->gb;
|
|
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
|
|
+ int q, dq, ret;
|
|
+ unsigned cbp;
|
|
+
|
|
+ *prev_cbp = cbp = bink2f_decode_cbp_luma(gb, *prev_cbp);
|
|
+ dq = bink2f_decode_delta_q(gb);
|
|
+ q = *prev_q + dq;
|
|
+ if (q < 0 || q >= 16)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ *prev_q = q;
|
|
+
|
|
+ bink2f_decode_dc(c, gb, dc, 1, q, 0, 2047, flags);
|
|
+
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ ret = bink2f_decode_ac(gb, bink2f_luma_scan, block, cbp >> (4 * i),
|
|
+ bink2f_ac_quant[q], bink2f_luma_intra_qmat);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ for (int j = 0; j < 4; j++) {
|
|
+ block[j][0] = dc[i * 4 + j] * 0.125f;
|
|
+ bink2f_idct_put(dst + (luma_repos[i*4+j]&3) * 8 +
|
|
+ (luma_repos[i*4+j]>>2) * 8 * stride, stride, block[j]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int bink2f_decode_intra_chroma(Bink2Context *c,
|
|
+ float block[4][64],
|
|
+ unsigned *prev_cbp, int *prev_q,
|
|
+ uint8_t *dst, int stride,
|
|
+ int flags)
|
|
+{
|
|
+ GetBitContext *gb = &c->gb;
|
|
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
|
|
+ int q, dq, ret;
|
|
+ unsigned cbp;
|
|
+
|
|
+ *prev_cbp = cbp = bink2f_decode_cbp_chroma(gb, *prev_cbp);
|
|
+ dq = bink2f_decode_delta_q(gb);
|
|
+ q = *prev_q + dq;
|
|
+ if (q < 0 || q >= 16)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ *prev_q = q;
|
|
+
|
|
+ bink2f_decode_dc(c, gb, dc, 0, q, 0, 2047, flags);
|
|
+
|
|
+ ret = bink2f_decode_ac(gb, bink2f_chroma_scan, block, cbp,
|
|
+ bink2f_ac_quant[q], bink2f_chroma_qmat);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ for (int j = 0; j < 4; j++) {
|
|
+ block[j][0] = dc[j] * 0.125f;
|
|
+ bink2f_idct_put(dst + (j & 1) * 8 + (j >> 1) * 8 * stride, stride, block[j]);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int bink2f_decode_inter_luma(Bink2Context *c,
|
|
+ float block[4][64],
|
|
+ unsigned *prev_cbp, int *prev_q,
|
|
+ uint8_t *dst, int stride,
|
|
+ int flags)
|
|
+{
|
|
+ GetBitContext *gb = &c->gb;
|
|
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
|
|
+ unsigned cbp;
|
|
+ int q, dq;
|
|
+
|
|
+ *prev_cbp = cbp = bink2f_decode_cbp_luma(gb, *prev_cbp);
|
|
+ dq = bink2f_decode_delta_q(gb);
|
|
+ q = *prev_q + dq;
|
|
+ if (q < 0 || q >= 16)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ *prev_q = q;
|
|
+
|
|
+ bink2f_decode_dc(c, gb, dc, 1, q, -1023, 1023, 0xA8);
|
|
+
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ bink2f_decode_ac(gb, bink2f_luma_scan, block, cbp >> (i * 4),
|
|
+ bink2f_ac_quant[q], bink2f_luma_inter_qmat);
|
|
+ for (int j = 0; j < 4; j++) {
|
|
+ block[j][0] = dc[i * 4 + j] * 0.125f;
|
|
+ bink2f_idct_add(dst + (luma_repos[i*4+j]&3) * 8 +
|
|
+ (luma_repos[i*4+j]>>2) * 8 * stride, stride,
|
|
+ block[j]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int bink2f_decode_inter_chroma(Bink2Context *c,
|
|
+ float block[4][64],
|
|
+ unsigned *prev_cbp, int *prev_q,
|
|
+ uint8_t *dst, int stride,
|
|
+ int flags)
|
|
+{
|
|
+ GetBitContext *gb = &c->gb;
|
|
+ float *dc = c->current_dc[c->mb_pos].dc[c->comp];
|
|
+ unsigned cbp;
|
|
+ int q, dq;
|
|
+
|
|
+ *prev_cbp = cbp = bink2f_decode_cbp_chroma(gb, *prev_cbp);
|
|
+ dq = bink2f_decode_delta_q(gb);
|
|
+ q = *prev_q + dq;
|
|
+ if (q < 0 || q >= 16)
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ *prev_q = q;
|
|
+
|
|
+ bink2f_decode_dc(c, gb, dc, 0, q, -1023, 1023, 0xA8);
|
|
+
|
|
+ bink2f_decode_ac(gb, bink2f_chroma_scan, block, cbp,
|
|
+ bink2f_ac_quant[q], bink2f_chroma_qmat);
|
|
+
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ block[i][0] = dc[i] * 0.125f;
|
|
+ bink2f_idct_add(dst + (i & 1) * 8 + (i >> 1) * 8 * stride, stride,
|
|
+ block[i]);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void bink2f_predict_mv(Bink2Context *c, int x, int y, int flags, MVectors mv)
|
|
+{
|
|
+ MVectors *c_mv = &c->current_mv[c->mb_pos].mv;
|
|
+ MVectors *l_mv = &c->current_mv[FFMAX(c->mb_pos - 1, 0)].mv;
|
|
+ MVectors *lt_mv = &c->prev_mv[FFMAX(c->mb_pos - 1, 0)].mv;
|
|
+ MVectors *t_mv = &c->prev_mv[c->mb_pos].mv;
|
|
+
|
|
+ if (!(flags & 0x80)) {
|
|
+ if (flags & 0x20) {
|
|
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(t_mv->v[0][0], t_mv->v[2][0], t_mv->v[3][0]);
|
|
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(t_mv->v[0][1], t_mv->v[2][1], t_mv->v[3][1]);
|
|
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred(t_mv->v[2][0], t_mv->v[3][0], c_mv->v[0][0]);
|
|
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred(t_mv->v[2][1], t_mv->v[3][1], c_mv->v[0][1]);
|
|
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred(t_mv->v[2][0], c_mv->v[0][0], c_mv->v[1][0]);
|
|
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred(t_mv->v[2][1], c_mv->v[0][1], c_mv->v[1][1]);
|
|
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
|
|
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
|
|
+ } else {
|
|
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(lt_mv->v[3][0], t_mv->v[2][0], l_mv->v[1][0]);
|
|
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(lt_mv->v[3][1], t_mv->v[2][1], l_mv->v[1][1]);
|
|
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred( t_mv->v[2][0], t_mv->v[3][0], c_mv->v[0][0]);
|
|
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred( t_mv->v[2][1], t_mv->v[3][1], c_mv->v[0][1]);
|
|
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred( t_mv->v[2][0], c_mv->v[0][0], c_mv->v[1][0]);
|
|
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred( t_mv->v[2][1], c_mv->v[0][1], c_mv->v[1][1]);
|
|
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred( c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
|
|
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred( c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
|
|
+ }
|
|
+ } else {
|
|
+ if (flags & 0x20) {
|
|
+ c_mv->v[0][0] = mv.v[0][0];
|
|
+ c_mv->v[0][1] = mv.v[0][1];
|
|
+ c_mv->v[1][0] = mv.v[1][0];
|
|
+ c_mv->v[1][1] = mv.v[1][1];
|
|
+ c_mv->v[2][0] = mv.v[2][0];
|
|
+ c_mv->v[2][1] = mv.v[2][1];
|
|
+ c_mv->v[3][0] = mv.v[3][0];
|
|
+ c_mv->v[3][1] = mv.v[3][1];
|
|
+ } else {
|
|
+ c_mv->v[0][0] = mv.v[0][0] + mid_pred(l_mv->v[0][0], l_mv->v[1][0], l_mv->v[3][0]);
|
|
+ c_mv->v[0][1] = mv.v[0][1] + mid_pred(l_mv->v[0][1], l_mv->v[1][1], l_mv->v[3][1]);
|
|
+ c_mv->v[2][0] = mv.v[2][0] + mid_pred(l_mv->v[1][0], l_mv->v[3][0], c_mv->v[0][0]);
|
|
+ c_mv->v[2][1] = mv.v[2][1] + mid_pred(l_mv->v[1][1], l_mv->v[3][1], c_mv->v[0][1]);
|
|
+ c_mv->v[1][0] = mv.v[1][0] + mid_pred(l_mv->v[1][0], c_mv->v[0][0], c_mv->v[2][0]);
|
|
+ c_mv->v[1][1] = mv.v[1][1] + mid_pred(l_mv->v[1][1], c_mv->v[0][1], c_mv->v[2][1]);
|
|
+ c_mv->v[3][0] = mv.v[3][0] + mid_pred(c_mv->v[0][0], c_mv->v[1][0], c_mv->v[2][0]);
|
|
+ c_mv->v[3][1] = mv.v[3][1] + mid_pred(c_mv->v[0][1], c_mv->v[1][1], c_mv->v[2][1]);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+#define CH1FILTER(src) ((6*(src)[0] + 2*(src)[1] + 4) >> 3)
|
|
+#define CH2FILTER(src) (( (src)[0] + (src)[1] + 1) >> 1)
|
|
+#define CH3FILTER(src) ((2*(src)[0] + 6*(src)[1] + 4) >> 3)
|
|
+
|
|
+#define CV1FILTER(src, i) ((6*(src)[0] + 2*(src)[i] + 4) >> 3)
|
|
+#define CV2FILTER(src, i) (( (src)[0] + (src)[i] + 1) >> 1)
|
|
+#define CV3FILTER(src, i) ((2*(src)[0] + 6*(src)[i] + 4) >> 3)
|
|
+
|
|
+static void bink2f_c_mc(Bink2Context *c, int x, int y,
|
|
+ uint8_t *dst, int stride,
|
|
+ uint8_t *src, int sstride,
|
|
+ int width, int height,
|
|
+ int mv_x, int mv_y,
|
|
+ int mode)
|
|
+{
|
|
+ uint8_t *msrc;
|
|
+ uint8_t temp[8*9];
|
|
+
|
|
+ if (mv_x < 0 || mv_x >= width ||
|
|
+ mv_y < 0 || mv_y >= height)
|
|
+ return;
|
|
+
|
|
+ msrc = src + mv_x + mv_y * sstride;
|
|
+
|
|
+ switch (mode) {
|
|
+ case 0:
|
|
+ copy_block8(dst, msrc, stride, sstride, 8);
|
|
+ break;
|
|
+ case 1:
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CH1FILTER(msrc + i));
|
|
+ dst += stride;
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ break;
|
|
+ case 2:
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CH2FILTER(msrc + i));
|
|
+ dst += stride;
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ break;
|
|
+ case 3:
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CH3FILTER(msrc + i));
|
|
+ dst += stride;
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ break;
|
|
+ case 4:
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i*stride] = av_clip_uint8(CV1FILTER(msrc + i*sstride, sstride));
|
|
+ dst += 1;
|
|
+ msrc += 1;
|
|
+ }
|
|
+ break;
|
|
+ case 5:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 6:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 7:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV1FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 8:
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i*stride] = av_clip_uint8(CV2FILTER(msrc + i*sstride, sstride));
|
|
+ dst += 1;
|
|
+ msrc += 1;
|
|
+ }
|
|
+ break;
|
|
+ case 9:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 10:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 11:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV2FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 12:
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i*stride] = av_clip_uint8(CV3FILTER(msrc + i*sstride, sstride));
|
|
+ dst += 1;
|
|
+ msrc += 1;
|
|
+ }
|
|
+ break;
|
|
+ case 13:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH1FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 14:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH2FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ case 15:
|
|
+ for (int i = 0; i < 9; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ temp[i*8+j] = av_clip_uint8(CH3FILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 8; j++) {
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ dst[i] = av_clip_uint8(CV3FILTER(temp+j*8+i, 8));
|
|
+ dst += stride;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2f_y_mc(Bink2Context *c, int x, int y,
|
|
+ uint8_t *dst, int stride,
|
|
+ uint8_t *src, int sstride,
|
|
+ int width, int height,
|
|
+ int mv_x, int mv_y, int mode)
|
|
+{
|
|
+ uint8_t *msrc;
|
|
+
|
|
+ if (mv_x < 0 || mv_x >= width ||
|
|
+ mv_y < 0 || mv_y >= height)
|
|
+ return;
|
|
+
|
|
+ msrc = src + mv_x + mv_y * sstride;
|
|
+
|
|
+ if (mode == 0) {
|
|
+ copy_block16(dst, msrc, stride, sstride, 16);
|
|
+ } else if (mode == 1) {
|
|
+ for (int j = 0; j < 16; j++) {
|
|
+ for (int i = 0; i < 16; i++)
|
|
+ dst[i] = av_clip_uint8(LHFILTER(msrc + i));
|
|
+ dst += stride;
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ } else if (mode == 2) {
|
|
+ for (int j = 0; j < 16; j++) {
|
|
+ for (int i = 0; i < 16; i++)
|
|
+ dst[i*stride] = av_clip_uint8(LVFILTER(msrc + i*sstride, sstride));
|
|
+ dst += 1;
|
|
+ msrc += 1;
|
|
+ }
|
|
+ } else if (mode == 3) {
|
|
+ uint8_t temp[21 * 16];
|
|
+
|
|
+ msrc -= 2 * sstride;
|
|
+ for (int i = 0; i < 21; i++) {
|
|
+ for (int j = 0; j < 16; j++)
|
|
+ temp[i*16+j] = av_clip_uint8(LHFILTER(msrc + j));
|
|
+ msrc += sstride;
|
|
+ }
|
|
+ for (int j = 0; j < 16; j++) {
|
|
+ for (int i = 0; i < 16; i++)
|
|
+ dst[i] = av_clip_uint8(LVFILTER(temp+(j+2)*16+i, 16));
|
|
+ dst += stride;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static int bink2f_mcompensate_chroma(Bink2Context *c, int x, int y,
|
|
+ uint8_t *dst, int stride,
|
|
+ uint8_t *src, int sstride,
|
|
+ int width, int height)
|
|
+{
|
|
+ MVectors *mv = &c->current_mv[c->mb_pos].mv;
|
|
+ int mv_x, mv_y, mode;
|
|
+
|
|
+ mv_x = (mv->v[0][0] >> 2) + x;
|
|
+ mv_y = (mv->v[0][1] >> 2) + y;
|
|
+ mode = mv->v[0][0] & 3;
|
|
+ mode |= (mv->v[0][1] & 3) << 2;
|
|
+ bink2f_c_mc(c, x, y, dst + x, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ mv_x = (mv->v[1][0] >> 2) + x + 8;
|
|
+ mv_y = (mv->v[1][1] >> 2) + y;
|
|
+ mode = mv->v[1][0] & 3;
|
|
+ mode |= (mv->v[1][1] & 3) << 2;
|
|
+ bink2f_c_mc(c, x, y, dst + x + 8, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ mv_x = (mv->v[2][0] >> 2) + x;
|
|
+ mv_y = (mv->v[2][1] >> 2) + y + 8;
|
|
+ mode = mv->v[2][0] & 3;
|
|
+ mode |= (mv->v[2][1] & 3) << 2;
|
|
+ bink2f_c_mc(c, x, y, dst + x + 8 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ mv_x = (mv->v[3][0] >> 2) + x + 8;
|
|
+ mv_y = (mv->v[3][1] >> 2) + y + 8;
|
|
+ mode = mv->v[3][0] & 3;
|
|
+ mode |= (mv->v[3][1] & 3) << 2;
|
|
+ bink2f_c_mc(c, x, y, dst + x + 8 + 8 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static float bink2f_average_block(uint8_t *src, int stride)
|
|
+{
|
|
+ int sum = 0;
|
|
+
|
|
+ for (int i = 0; i < 8; i++) {
|
|
+ int avg_a = (src[i+0*stride] + src[i+1*stride] + 1) >> 1;
|
|
+ int avg_b = (src[i+2*stride] + src[i+3*stride] + 1) >> 1;
|
|
+ int avg_c = (src[i+4*stride] + src[i+5*stride] + 1) >> 1;
|
|
+ int avg_d = (src[i+6*stride] + src[i+7*stride] + 1) >> 1;
|
|
+ int avg_e = (avg_a + avg_b + 1) >> 1;
|
|
+ int avg_f = (avg_c + avg_d + 1) >> 1;
|
|
+ int avg_g = (avg_e + avg_f + 1) >> 1;
|
|
+ sum += avg_g;
|
|
+ }
|
|
+
|
|
+ return sum;
|
|
+}
|
|
+
|
|
+static void bink2f_average_chroma(Bink2Context *c, int x, int y,
|
|
+ uint8_t *src, int stride,
|
|
+ float *dc)
|
|
+{
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ int X = i & 1;
|
|
+ int Y = i >> 1;
|
|
+ dc[i] = bink2f_average_block(src + x + X * 8 + (y + Y * 8) * stride, stride);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2f_average_luma(Bink2Context *c, int x, int y,
|
|
+ uint8_t *src, int stride,
|
|
+ float *dc)
|
|
+{
|
|
+ for (int i = 0; i < 16; i++) {
|
|
+ int I = luma_repos[i];
|
|
+ int X = I & 3;
|
|
+ int Y = I >> 2;
|
|
+ dc[i] = bink2f_average_block(src + x + X * 8 + (y + Y * 8) * stride, stride);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int bink2f_mcompensate_luma(Bink2Context *c, int x, int y,
|
|
+ uint8_t *dst, int stride,
|
|
+ uint8_t *src, int sstride,
|
|
+ int width, int height)
|
|
+{
|
|
+ MVectors *mv = &c->current_mv[c->mb_pos].mv;
|
|
+ int mv_x, mv_y, mode;
|
|
+
|
|
+ mv_x = (mv->v[0][0] >> 1) + x;
|
|
+ mv_y = (mv->v[0][1] >> 1) + y;
|
|
+ mode = mv->v[0][0] & 1;
|
|
+ mode |= (mv->v[0][1] & 1) << 1;
|
|
+ bink2f_y_mc(c, x, y, dst + x, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ mv_x = (mv->v[1][0] >> 1) + x + 16;
|
|
+ mv_y = (mv->v[1][1] >> 1) + y;
|
|
+ mode = mv->v[1][0] & 1;
|
|
+ mode |= (mv->v[1][1] & 1) << 1;
|
|
+ bink2f_y_mc(c, x, y, dst + x + 16, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ mv_x = (mv->v[2][0] >> 1) + x;
|
|
+ mv_y = (mv->v[2][1] >> 1) + y + 16;
|
|
+ mode = mv->v[2][0] & 1;
|
|
+ mode |= (mv->v[2][1] & 1) << 1;
|
|
+ bink2f_y_mc(c, x, y, dst + x + 16 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ mv_x = (mv->v[3][0] >> 1) + x + 16;
|
|
+ mv_y = (mv->v[3][1] >> 1) + y + 16;
|
|
+ mode = mv->v[3][0] & 1;
|
|
+ mode |= (mv->v[3][1] & 1) << 1;
|
|
+ bink2f_y_mc(c, x, y, dst + x + 16 + 16 * stride, stride, src, sstride, width, height, mv_x, mv_y, mode);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int bink2f_decode_mv(Bink2Context *c, GetBitContext *gb, int x, int y,
|
|
+ int flags, MVectors *mv)
|
|
+{
|
|
+ for (int i = 0; i < 2; i++) {
|
|
+ int val = 0, bits = get_bits(gb, 3);
|
|
+
|
|
+ if (bits == 7)
|
|
+ bits += get_bits(gb, 2);
|
|
+ if (bits) {
|
|
+ for (int j = 0; j < 4; j++)
|
|
+ mv->v[j][i] = get_bits(gb, bits);
|
|
+ for (int j = 0; j < 4; j++)
|
|
+ if (mv->v[j][i] && get_bits1(gb))
|
|
+ mv->v[j][i] = -mv->v[j][i];
|
|
+ }
|
|
+
|
|
+ if ((flags & 0x80) && (flags & 0x20)) {
|
|
+ val = get_bits(gb, 5) * 16;
|
|
+ if (val && get_bits1(gb))
|
|
+ val = -val;
|
|
+ }
|
|
+
|
|
+ mv->v[0][i] += val;
|
|
+ mv->v[1][i] += val;
|
|
+ mv->v[2][i] += val;
|
|
+ mv->v[3][i] += val;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int bink2f_decode_slice(Bink2Context *c,
|
|
+ uint8_t *dst[4], int stride[4],
|
|
+ uint8_t *src[4], int sstride[4],
|
|
+ int is_kf, int start, int end)
|
|
+{
|
|
+ GetBitContext *gb = &c->gb;
|
|
+ int w = c->avctx->width;
|
|
+ int h = c->avctx->height;
|
|
+ int flags, ret = 0;
|
|
+
|
|
+ memset(c->prev_mv, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->prev_mv));
|
|
+
|
|
+ for (int y = start; y < end; y += 32) {
|
|
+ unsigned y_cbp_intra = 0, u_cbp_intra = 0, v_cbp_intra = 0, a_cbp_intra = 0;
|
|
+ unsigned y_cbp_inter = 0, u_cbp_inter = 0, v_cbp_inter = 0, a_cbp_inter = 0;
|
|
+ int y_intra_q = 8, u_intra_q = 8, v_intra_q = 8, a_intra_q = 8;
|
|
+ int y_inter_q = 8, u_inter_q = 8, v_inter_q = 8, a_inter_q = 8;
|
|
+
|
|
+ memset(c->current_mv, 0, ((c->avctx->width + 31) / 32) * sizeof(*c->current_mv));
|
|
+
|
|
+ for (int x = 0; x < c->avctx->width; x += 32) {
|
|
+ MVectors mv = { 0 };
|
|
+ int type = is_kf ? INTRA_BLOCK : get_bits(gb, 2);
|
|
+
|
|
+ c->mb_pos = x / 32;
|
|
+ c->current_dc[c->mb_pos].block_type = type;
|
|
+ flags = 0;
|
|
+ if (y == start)
|
|
+ flags |= 0x80;
|
|
+ if (!x)
|
|
+ flags |= 0x20;
|
|
+ if (x == 32)
|
|
+ flags |= 0x200;
|
|
+ if (x + 32 >= c->avctx->width)
|
|
+ flags |= 0x40;
|
|
+
|
|
+ switch (type) {
|
|
+ case INTRA_BLOCK:
|
|
+ if (!(flags & 0xA0) && c->prev_dc[c->mb_pos - 1].block_type != INTRA_BLOCK) {
|
|
+ bink2f_average_luma (c, x -32, -32, dst[0], stride[0], c->prev_dc[c->mb_pos - 1].dc[0]);
|
|
+ bink2f_average_chroma(c, x/2-16, -16, dst[2], stride[2], c->prev_dc[c->mb_pos - 1].dc[1]);
|
|
+ bink2f_average_chroma(c, x/2-16, -16, dst[1], stride[1], c->prev_dc[c->mb_pos - 1].dc[2]);
|
|
+ }
|
|
+ if (!(flags & 0x20) && c->current_dc[c->mb_pos - 1].block_type != INTRA_BLOCK) {
|
|
+ bink2f_average_luma (c, x -32, 0, dst[0], stride[0], c->current_dc[c->mb_pos - 1].dc[0]);
|
|
+ bink2f_average_chroma(c, x/2-16, 0, dst[2], stride[2], c->current_dc[c->mb_pos - 1].dc[1]);
|
|
+ bink2f_average_chroma(c, x/2-16, 0, dst[1], stride[1], c->current_dc[c->mb_pos - 1].dc[2]);
|
|
+ }
|
|
+ if ((flags & 0x20) && !(flags & 0x80) && c->prev_dc[c->mb_pos + 1].block_type != INTRA_BLOCK) {
|
|
+ bink2f_average_luma (c, x +32, -32, dst[0], stride[0], c->prev_dc[c->mb_pos + 1].dc[0]);
|
|
+ bink2f_average_chroma(c, x/2+16, -16, dst[2], stride[2], c->prev_dc[c->mb_pos + 1].dc[1]);
|
|
+ bink2f_average_chroma(c, x/2+16, -16, dst[1], stride[1], c->prev_dc[c->mb_pos + 1].dc[2]);
|
|
+ }
|
|
+ if (!(flags & 0x80) && c->prev_dc[c->mb_pos].block_type != INTRA_BLOCK) {
|
|
+ bink2f_average_luma (c, x, -32, dst[0], stride[0], c->prev_dc[c->mb_pos].dc[0]);
|
|
+ bink2f_average_chroma(c, x/2, -16, dst[2], stride[2], c->prev_dc[c->mb_pos].dc[1]);
|
|
+ bink2f_average_chroma(c, x/2, -16, dst[1], stride[1], c->prev_dc[c->mb_pos].dc[2]);
|
|
+ }
|
|
+
|
|
+ bink2f_predict_mv(c, x, y, flags, mv);
|
|
+ c->comp = 0;
|
|
+ ret = bink2f_decode_intra_luma(c, c->block, &y_cbp_intra, &y_intra_q,
|
|
+ dst[0] + x, stride[0], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ c->comp = 1;
|
|
+ ret = bink2f_decode_intra_chroma(c, c->block, &u_cbp_intra, &u_intra_q,
|
|
+ dst[2] + x/2, stride[2], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ c->comp = 2;
|
|
+ ret = bink2f_decode_intra_chroma(c, c->block, &v_cbp_intra, &v_intra_q,
|
|
+ dst[1] + x/2, stride[1], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ if (c->has_alpha) {
|
|
+ c->comp = 3;
|
|
+ ret = bink2f_decode_intra_luma(c, c->block, &a_cbp_intra, &a_intra_q,
|
|
+ dst[3] + x, stride[3], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ }
|
|
+ break;
|
|
+ case SKIP_BLOCK:
|
|
+ copy_block16(dst[0] + x, src[0] + x + sstride[0] * y,
|
|
+ stride[0], sstride[0], 32);
|
|
+ copy_block16(dst[0] + x + 16, src[0] + x + 16 + sstride[0] * y,
|
|
+ stride[0], sstride[0], 32);
|
|
+ copy_block16(dst[1] + (x/2), src[1] + (x/2) + sstride[1] * (y/2),
|
|
+ stride[1], sstride[1], 16);
|
|
+ copy_block16(dst[2] + (x/2), src[2] + (x/2) + sstride[2] * (y/2),
|
|
+ stride[2], sstride[2], 16);
|
|
+ if (c->has_alpha) {
|
|
+ copy_block16(dst[3] + x, src[3] + x + sstride[3] * y,
|
|
+ stride[3], sstride[3], 32);
|
|
+ copy_block16(dst[3] + x + 16, src[3] + x + 16 + sstride[3] * y,
|
|
+ stride[3], sstride[3], 32);
|
|
+ }
|
|
+ break;
|
|
+ case MOTION_BLOCK:
|
|
+ bink2f_decode_mv(c, gb, x, y, flags, &mv);
|
|
+ bink2f_predict_mv(c, x, y, flags, mv);
|
|
+ c->comp = 0;
|
|
+ ret = bink2f_mcompensate_luma(c, x, y,
|
|
+ dst[0], stride[0],
|
|
+ src[0], sstride[0],
|
|
+ w, h);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ c->comp = 1;
|
|
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
|
|
+ dst[2], stride[2],
|
|
+ src[2], sstride[2],
|
|
+ w/2, h/2);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ c->comp = 2;
|
|
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
|
|
+ dst[1], stride[1],
|
|
+ src[1], sstride[1],
|
|
+ w/2, h/2);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ break;
|
|
+ case RESIDUE_BLOCK:
|
|
+ bink2f_decode_mv(c, gb, x, y, flags, &mv);
|
|
+ bink2f_predict_mv(c, x, y, flags, mv);
|
|
+ ret = bink2f_mcompensate_luma(c, x, y,
|
|
+ dst[0], stride[0],
|
|
+ src[0], sstride[0],
|
|
+ w, h);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
|
|
+ dst[2], stride[2],
|
|
+ src[2], sstride[2],
|
|
+ w/2, h/2);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ ret = bink2f_mcompensate_chroma(c, x/2, y/2,
|
|
+ dst[1], stride[1],
|
|
+ src[1], sstride[1],
|
|
+ w/2, h/2);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ c->comp = 0;
|
|
+ ret = bink2f_decode_inter_luma(c, c->block, &y_cbp_inter, &y_inter_q,
|
|
+ dst[0] + x, stride[0], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ c->comp = 1;
|
|
+ ret = bink2f_decode_inter_chroma(c, c->block, &u_cbp_inter, &u_inter_q,
|
|
+ dst[2] + x/2, stride[2], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ c->comp = 2;
|
|
+ ret = bink2f_decode_inter_chroma(c, c->block, &v_cbp_inter, &v_inter_q,
|
|
+ dst[1] + x/2, stride[1], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ if (c->has_alpha) {
|
|
+ c->comp = 3;
|
|
+ ret = bink2f_decode_inter_luma(c, c->block, &a_cbp_inter, &a_inter_q,
|
|
+ dst[3] + x, stride[3], flags);
|
|
+ if (ret < 0)
|
|
+ goto fail;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ return AVERROR_INVALIDDATA;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ dst[0] += stride[0] * 32;
|
|
+ dst[1] += stride[1] * 16;
|
|
+ dst[2] += stride[2] * 16;
|
|
+ if (c->has_alpha)
|
|
+ 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..be50146e4f
|
|
--- /dev/null
|
|
+++ b/libavcodec/bink2g.h
|
|
@@ -0,0 +1,1870 @@
|
|
+/*
|
|
+ * Bink video 2 decoder
|
|
+ * Copyright (c) 2014 Konstantin Shishkov
|
|
+ * Copyright (c) 2019 Paul B Mahol
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#ifndef AVCODEC_BINK2G_H
|
|
+#define AVCODEC_BINK2G_H
|
|
+
|
|
+#include <stdint.h>
|
|
+#include "avcodec.h"
|
|
+#include "get_bits.h"
|
|
+#include "bink2.h"
|
|
+
|
|
+static const uint8_t bink2g_scan[64] = {
|
|
+ 0, 8, 1, 2, 9, 16, 24, 17,
|
|
+ 10, 3, 4, 11, 18, 25, 32, 40,
|
|
+ 33, 26, 19, 12, 5, 6, 13, 20,
|
|
+ 27, 34, 41, 48, 56, 49, 42, 35,
|
|
+ 28, 21, 14, 7, 15, 22, 29, 36,
|
|
+ 43, 50, 57, 58, 51, 44, 37, 30,
|
|
+ 23, 31, 38, 45, 52, 59, 60, 53,
|
|
+ 46, 39, 47, 54, 61, 62, 55, 63,
|
|
+};
|
|
+
|
|
+static const uint16_t bink2g_ac_skip_codes[2][NUM_AC_SKIPS] = {
|
|
+ {
|
|
+ 0x01, 0x00, 0x004, 0x02C, 0x06C, 0x0C, 0x4C,
|
|
+ 0xAC, 0xEC, 0x12C, 0x16C, 0x1AC, 0x02, 0x1C,
|
|
+ },
|
|
+ {
|
|
+ 0x01, 0x04, 0x00, 0x08, 0x02, 0x32, 0x0A,
|
|
+ 0x12, 0x3A, 0x7A, 0xFA, 0x72, 0x06, 0x1A,
|
|
+ },
|
|
+};
|
|
+
|
|
+static const uint8_t bink2g_ac_skip_bits[2][NUM_AC_SKIPS] = {
|
|
+ { 1, 3, 4, 9, 9, 7, 7, 9, 8, 9, 9, 9, 2, 5 },
|
|
+ { 1, 3, 4, 4, 5, 7, 5, 6, 7, 8, 8, 7, 3, 6 },
|
|
+};
|
|
+
|
|
+static const uint8_t bink2g_mv_codes[] = {
|
|
+ 0x01, 0x06, 0x0C, 0x1C, 0x18, 0x38, 0x58, 0x78,
|
|
+ 0x68, 0x48, 0x28, 0x08, 0x14, 0x04, 0x02, 0x00,
|
|
+};
|
|
+
|
|
+static const uint8_t bink2g_mv_bits[] = {
|
|
+ 1, 3, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 3, 4,
|
|
+};
|
|
+
|
|
+static const uint8_t bink2g_skips[] = {
|
|
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 64, 0, 0, 0,
|
|
+};
|
|
+
|
|
+static uint8_t bink2g_chroma_cbp_pat[16] = {
|
|
+ 0x00, 0x00, 0x00, 0x0F,
|
|
+ 0x00, 0x0F, 0x0F, 0x0F,
|
|
+ 0x00, 0x0F, 0x0F, 0x0F,
|
|
+ 0x0F, 0x0F, 0x0F, 0x0F,
|
|
+};
|
|
+
|
|
+static const int32_t bink2g_dc_pat[] = {
|
|
+ 1024, 1218, 1448, 1722, 2048,
|
|
+ 2435, 2896, 3444, 4096, 4871,
|
|
+ 5793, 6889, 8192, 9742, 11585, 13777, 16384,
|
|
+ 19484, 23170, 27555, 32768, 38968, 46341,
|
|
+ 55109, 65536, 77936, 92682, 110218, 131072,
|
|
+ 155872, 185364, 220436, 262144, 311744,
|
|
+ 370728, 440872, 524288,
|
|
+};
|
|
+
|
|
+static const uint16_t bink2g_luma_intra_qmat[4][64] = {
|
|
+ {
|
|
+ 1024, 1432, 1506, 1181,
|
|
+ 1843, 2025, 5271, 8592,
|
|
+ 1313, 1669, 1630, 1672,
|
|
+ 2625, 3442, 8023, 12794,
|
|
+ 1076, 1755, 1808, 1950,
|
|
+ 3980, 4875, 8813, 11909,
|
|
+ 1350, 1868, 2127, 2016,
|
|
+ 4725, 4450, 7712, 9637,
|
|
+ 2458, 3103, 4303, 4303,
|
|
+ 6963, 6835, 11079, 13365,
|
|
+ 3375, 5704, 5052, 6049,
|
|
+ 9198, 7232, 10725, 9834,
|
|
+ 5486, 7521, 7797, 7091,
|
|
+ 11079, 10016, 13559, 12912,
|
|
+ 7279, 7649, 7020, 6097,
|
|
+ 9189, 9047, 12661, 13768,
|
|
+ },
|
|
+ {
|
|
+ 1218, 1703, 1791, 1405,
|
|
+ 2192, 2408, 6268, 10218,
|
|
+ 1561, 1985, 1938, 1988,
|
|
+ 3122, 4093, 9541, 15215,
|
|
+ 1279, 2087, 2150, 2319,
|
|
+ 4733, 5798, 10481, 14162,
|
|
+ 1606, 2222, 2530, 2398,
|
|
+ 5619, 5292, 9171, 11460,
|
|
+ 2923, 3690, 5117, 5118,
|
|
+ 8281, 8128, 13176, 15894,
|
|
+ 4014, 6783, 6008, 7194,
|
|
+ 10938, 8600, 12755, 11694,
|
|
+ 6524, 8944, 9272, 8433,
|
|
+ 13176, 11911, 16125, 15354,
|
|
+ 8657, 9096, 8348, 7250,
|
|
+ 10927, 10759, 15056, 16373,
|
|
+ },
|
|
+ {
|
|
+ 1448, 2025, 2130, 1671,
|
|
+ 2607, 2864, 7454, 12151,
|
|
+ 1856, 2360, 2305, 2364,
|
|
+ 3713, 4867, 11346, 18094,
|
|
+ 1521, 2482, 2557, 2758,
|
|
+ 5628, 6894, 12464, 16841,
|
|
+ 1909, 2642, 3008, 2852,
|
|
+ 6683, 6293, 10906, 13629,
|
|
+ 3476, 4388, 6085, 6086,
|
|
+ 9847, 9666, 15668, 18901,
|
|
+ 4773, 8066, 7145, 8555,
|
|
+ 13007, 10227, 15168, 13907,
|
|
+ 7758, 10637, 11026, 10028,
|
|
+ 15668, 14165, 19175, 18259,
|
|
+ 10294, 10817, 9927, 8622,
|
|
+ 12995, 12794, 17905, 19470,
|
|
+ },
|
|
+ {
|
|
+ 1722, 2408, 2533, 1987,
|
|
+ 3100, 3406, 8864, 14450,
|
|
+ 2208, 2807, 2741, 2811,
|
|
+ 4415, 5788, 13493, 21517,
|
|
+ 1809, 2951, 3041, 3280,
|
|
+ 6693, 8199, 14822, 20028,
|
|
+ 2271, 3142, 3578, 3391,
|
|
+ 7947, 7484, 12969, 16207,
|
|
+ 4133, 5218, 7236, 7238,
|
|
+ 11711, 11495, 18633, 22478,
|
|
+ 5677, 9592, 8497, 10174,
|
|
+ 15469, 12162, 18038, 16538,
|
|
+ 9226, 12649, 13112, 11926,
|
|
+ 18633, 16845, 22804, 21715,
|
|
+ 12242, 12864, 11806, 10254,
|
|
+ 15454, 15215, 21293, 23155,
|
|
+ },
|
|
+};
|
|
+
|
|
+static const uint16_t bink2g_chroma_intra_qmat[4][64] = {
|
|
+ {
|
|
+ 1024, 1193, 1434, 2203,
|
|
+ 5632, 4641, 5916, 6563,
|
|
+ 1193, 1622, 1811, 3606,
|
|
+ 6563, 5408, 6894, 7649,
|
|
+ 1434, 1811, 3515, 4875,
|
|
+ 5916, 4875, 6215, 6894,
|
|
+ 2203, 3606, 4875, 3824,
|
|
+ 4641, 3824, 4875, 5408,
|
|
+ 5632, 6563, 5916, 4641,
|
|
+ 5632, 4641, 5916, 6563,
|
|
+ 4641, 5408, 4875, 3824,
|
|
+ 4641, 3824, 4875, 5408,
|
|
+ 5916, 6894, 6215, 4875,
|
|
+ 5916, 4875, 6215, 6894,
|
|
+ 6563, 7649, 6894, 5408,
|
|
+ 6563, 5408, 6894, 7649,
|
|
+ },
|
|
+ {
|
|
+ 1218, 1419, 1706, 2620,
|
|
+ 6698, 5519, 7035, 7805,
|
|
+ 1419, 1929, 2153, 4288,
|
|
+ 7805, 6432, 8199, 9096,
|
|
+ 1706, 2153, 4180, 5798,
|
|
+ 7035, 5798, 7390, 8199,
|
|
+ 2620, 4288, 5798, 4548,
|
|
+ 5519, 4548, 5798, 6432,
|
|
+ 6698, 7805, 7035, 5519,
|
|
+ 6698, 5519, 7035, 7805,
|
|
+ 5519, 6432, 5798, 4548,
|
|
+ 5519, 4548, 5798, 6432,
|
|
+ 7035, 8199, 7390, 5798,
|
|
+ 7035, 5798, 7390, 8199,
|
|
+ 7805, 9096, 8199, 6432,
|
|
+ 7805, 6432, 8199, 9096,
|
|
+ },
|
|
+ {
|
|
+ 1448, 1688, 2028, 3116,
|
|
+ 7965, 6563, 8367, 9282,
|
|
+ 1688, 2294, 2561, 5099,
|
|
+ 9282, 7649, 9750, 10817,
|
|
+ 2028, 2561, 4971, 6894,
|
|
+ 8367, 6894, 8789, 9750,
|
|
+ 3116, 5099, 6894, 5408,
|
|
+ 6563, 5408, 6894, 7649,
|
|
+ 7965, 9282, 8367, 6563,
|
|
+ 7965, 6563, 8367, 9282,
|
|
+ 6563, 7649, 6894, 5408,
|
|
+ 6563, 5408, 6894, 7649,
|
|
+ 8367, 9750, 8789, 6894,
|
|
+ 8367, 6894, 8789, 9750,
|
|
+ 9282, 10817, 9750, 7649,
|
|
+ 9282, 7649, 9750, 10817,
|
|
+ },
|
|
+ {
|
|
+ 1722, 2007, 2412, 3706,
|
|
+ 9472, 7805, 9950, 11038,
|
|
+ 2007, 2729, 3045, 6064,
|
|
+ 11038, 9096, 11595, 12864,
|
|
+ 2412, 3045, 5912, 8199,
|
|
+ 9950, 8199, 10452, 11595,
|
|
+ 3706, 6064, 8199, 6432,
|
|
+ 7805, 6432, 8199, 9096,
|
|
+ 9472, 11038, 9950, 7805,
|
|
+ 9472, 7805, 9950, 11038,
|
|
+ 7805, 9096, 8199, 6432,
|
|
+ 7805, 6432, 8199, 9096,
|
|
+ 9950, 11595, 10452, 8199,
|
|
+ 9950, 8199, 10452, 11595,
|
|
+ 11038, 12864, 11595, 9096,
|
|
+ 11038, 9096, 11595, 12864,
|
|
+ },
|
|
+};
|
|
+
|
|
+static const uint16_t bink2g_inter_qmat[4][64] = {
|
|
+ {
|
|
+ 1024, 1193, 1076, 844,
|
|
+ 1052, 914, 1225, 1492,
|
|
+ 1193, 1391, 1254, 983,
|
|
+ 1227, 1065, 1463, 1816,
|
|
+ 1076, 1254, 1161, 936,
|
|
+ 1195, 1034, 1444, 1741,
|
|
+ 844, 983, 936, 811,
|
|
+ 1055, 927, 1305, 1584,
|
|
+ 1052, 1227, 1195, 1055,
|
|
+ 1451, 1336, 1912, 2354,
|
|
+ 914, 1065, 1034, 927,
|
|
+ 1336, 1313, 1945, 2486,
|
|
+ 1225, 1463, 1444, 1305,
|
|
+ 1912, 1945, 3044, 4039,
|
|
+ 1492, 1816, 1741, 1584,
|
|
+ 2354, 2486, 4039, 5679,
|
|
+ },
|
|
+ {
|
|
+ 1218, 1419, 1279, 1003,
|
|
+ 1252, 1087, 1457, 1774,
|
|
+ 1419, 1654, 1491, 1169,
|
|
+ 1459, 1267, 1739, 2159,
|
|
+ 1279, 1491, 1381, 1113,
|
|
+ 1421, 1230, 1717, 2070,
|
|
+ 1003, 1169, 1113, 965,
|
|
+ 1254, 1103, 1552, 1884,
|
|
+ 1252, 1459, 1421, 1254,
|
|
+ 1725, 1589, 2274, 2799,
|
|
+ 1087, 1267, 1230, 1103,
|
|
+ 1589, 1562, 2313, 2956,
|
|
+ 1457, 1739, 1717, 1552,
|
|
+ 2274, 2313, 3620, 4803,
|
|
+ 1774, 2159, 2070, 1884,
|
|
+ 2799, 2956, 4803, 6753,
|
|
+ },
|
|
+ {
|
|
+ 1448, 1688, 1521, 1193,
|
|
+ 1488, 1293, 1732, 2110,
|
|
+ 1688, 1967, 1773, 1391,
|
|
+ 1735, 1507, 2068, 2568,
|
|
+ 1521, 1773, 1642, 1323,
|
|
+ 1690, 1462, 2042, 2462,
|
|
+ 1193, 1391, 1323, 1147,
|
|
+ 1492, 1311, 1845, 2241,
|
|
+ 1488, 1735, 1690, 1492,
|
|
+ 2052, 1889, 2704, 3328,
|
|
+ 1293, 1507, 1462, 1311,
|
|
+ 1889, 1857, 2751, 3515,
|
|
+ 1732, 2068, 2042, 1845,
|
|
+ 2704, 2751, 4306, 5712,
|
|
+ 2110, 2568, 2462, 2241,
|
|
+ 3328, 3515, 5712, 8031,
|
|
+ },
|
|
+ {
|
|
+ 1722, 2007, 1809, 1419,
|
|
+ 1770, 1537, 2060, 2509,
|
|
+ 2007, 2339, 2108, 1654,
|
|
+ 2063, 1792, 2460, 3054,
|
|
+ 1809, 2108, 1953, 1574,
|
|
+ 2010, 1739, 2428, 2928,
|
|
+ 1419, 1654, 1574, 1364,
|
|
+ 1774, 1559, 2195, 2664,
|
|
+ 1770, 2063, 2010, 1774,
|
|
+ 2440, 2247, 3216, 3958,
|
|
+ 1537, 1792, 1739, 1559,
|
|
+ 2247, 2209, 3271, 4181,
|
|
+ 2060, 2460, 2428, 2195,
|
|
+ 3216, 3271, 5120, 6793,
|
|
+ 2509, 3054, 2928, 2664,
|
|
+ 3958, 4181, 6793, 9550,
|
|
+ },
|
|
+};
|
|
+
|
|
+static inline void bink2g_idct_1d(int16_t *blk, int step, int shift)
|
|
+{
|
|
+#define idct_mul_a(val) ((val) + ((val) >> 2))
|
|
+#define idct_mul_b(val) ((val) >> 1)
|
|
+#define idct_mul_c(val) ((val) - ((val) >> 2) - ((val) >> 4))
|
|
+#define idct_mul_d(val) ((val) + ((val) >> 2) - ((val) >> 4))
|
|
+#define idct_mul_e(val) ((val) >> 2)
|
|
+ int tmp00 = blk[3*step] + blk[5*step];
|
|
+ int tmp01 = blk[3*step] - blk[5*step];
|
|
+ int tmp02 = idct_mul_a(blk[2*step]) + idct_mul_b(blk[6*step]);
|
|
+ int tmp03 = idct_mul_b(blk[2*step]) - idct_mul_a(blk[6*step]);
|
|
+ int tmp0 = (blk[0*step] + blk[4*step]) + tmp02;
|
|
+ int tmp1 = (blk[0*step] + blk[4*step]) - tmp02;
|
|
+ int tmp2 = blk[0*step] - blk[4*step];
|
|
+ int tmp3 = blk[1*step] + tmp00;
|
|
+ int tmp4 = blk[1*step] - tmp00;
|
|
+ int tmp5 = tmp01 + blk[7*step];
|
|
+ int tmp6 = tmp01 - blk[7*step];
|
|
+ int tmp7 = tmp4 + idct_mul_c(tmp6);
|
|
+ int tmp8 = idct_mul_c(tmp4) - tmp6;
|
|
+ int tmp9 = idct_mul_d(tmp3) + idct_mul_e(tmp5);
|
|
+ int tmp10 = idct_mul_e(tmp3) - idct_mul_d(tmp5);
|
|
+ int tmp11 = tmp2 + tmp03;
|
|
+ int tmp12 = tmp2 - tmp03;
|
|
+
|
|
+ blk[0*step] = (tmp0 + tmp9) >> shift;
|
|
+ blk[1*step] = (tmp11 + tmp7) >> shift;
|
|
+ blk[2*step] = (tmp12 + tmp8) >> shift;
|
|
+ blk[3*step] = (tmp1 + tmp10) >> shift;
|
|
+ blk[4*step] = (tmp1 - tmp10) >> shift;
|
|
+ blk[5*step] = (tmp12 - tmp8) >> shift;
|
|
+ blk[6*step] = (tmp11 - tmp7) >> shift;
|
|
+ blk[7*step] = (tmp0 - tmp9) >> shift;
|
|
+}
|
|
+
|
|
+static void bink2g_idct_put(uint8_t *dst, int stride, int16_t *block)
|
|
+{
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ bink2g_idct_1d(block + i, 8, 0);
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ bink2g_idct_1d(block + i * 8, 1, 6);
|
|
+ for (int i = 0; i < 8; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ dst[j] = av_clip_uint8(block[j * 8 + i]);
|
|
+ dst += stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_idct_add(uint8_t *dst, int stride, int16_t *block)
|
|
+{
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ bink2g_idct_1d(block + i, 8, 0);
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ bink2g_idct_1d(block + i * 8, 1, 6);
|
|
+ for (int i = 0; i < 8; i++) {
|
|
+ for (int j = 0; j < 8; j++)
|
|
+ dst[j] = av_clip_uint8(dst[j] + block[j * 8 + i]);
|
|
+ dst += stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int bink2g_get_type(GetBitContext *gb, int *lru)
|
|
+{
|
|
+ int val;
|
|
+
|
|
+ switch (get_unary(gb, 1, 3)) {
|
|
+ case 0:
|
|
+ val = lru[0];
|
|
+ break;
|
|
+ case 1:
|
|
+ val = lru[1];
|
|
+ FFSWAP(int, lru[0], lru[1]);
|
|
+ break;
|
|
+ case 2:
|
|
+ val = lru[3];
|
|
+ FFSWAP(int, lru[2], lru[3]);
|
|
+ break;
|
|
+ case 3:
|
|
+ val = lru[2];
|
|
+ FFSWAP(int, lru[1], lru[2]);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+static int bink2g_decode_dq(GetBitContext *gb)
|
|
+{
|
|
+ int dq = get_unary(gb, 1, 4);
|
|
+
|
|
+ if (dq == 3)
|
|
+ dq += get_bits1(gb);
|
|
+ else if (dq == 4)
|
|
+ dq += get_bits(gb, 5) + 1;
|
|
+ if (dq && get_bits1(gb))
|
|
+ dq = -dq;
|
|
+
|
|
+ return dq;
|
|
+}
|
|
+
|
|
+static unsigned bink2g_decode_cbp_luma(Bink2Context *c,
|
|
+ GetBitContext *gb, unsigned prev_cbp)
|
|
+{
|
|
+ unsigned ones = 0, cbp, mask;
|
|
+
|
|
+ for (int i = 0; i < 16; i++) {
|
|
+ if (prev_cbp & (1 << i))
|
|
+ ones += 1;
|
|
+ }
|
|
+
|
|
+ cbp = 0;
|
|
+ mask = 0;
|
|
+ if (ones > 7) {
|
|
+ ones = 16 - ones;
|
|
+ mask = 0xFFFF;
|
|
+ }
|
|
+
|
|
+ if (get_bits1(gb) == 0) {
|
|
+ if (ones < 4) {
|
|
+ for (int j = 0; j < 16; j += 4)
|
|
+ if (!get_bits1(gb))
|
|
+ cbp |= get_bits(gb, 4) << j;
|
|
+ } else {
|
|
+ cbp = get_bits(gb, 16);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cbp ^= mask;
|
|
+ if (!(c->frame_flags & 0x40000) || cbp) {
|
|
+ if (get_bits1(gb))
|
|
+ cbp = cbp | cbp << 16;
|
|
+ }
|
|
+
|
|
+ return cbp;
|
|
+}
|
|
+
|
|
+static unsigned bink2g_decode_cbp_chroma(GetBitContext *gb, unsigned prev_cbp)
|
|
+{
|
|
+ unsigned cbp;
|
|
+
|
|
+ cbp = prev_cbp & 0xF0000 | bink2g_chroma_cbp_pat[prev_cbp & 0xF];
|
|
+ if (get_bits1(gb) == 0) {
|
|
+ cbp = get_bits(gb, 4);
|
|
+ if (get_bits1(gb))
|
|
+ cbp |= cbp << 16;
|
|
+ }
|
|
+
|
|
+ return cbp;
|
|
+}
|
|
+
|
|
+static void bink2g_predict_dc(Bink2Context *c,
|
|
+ int is_luma, int mindc, int maxdc,
|
|
+ int flags, int tdc[16])
|
|
+{
|
|
+ int *LTdc = c->prev_idc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
|
|
+ int *Tdc = c->prev_idc[c->mb_pos].dc[c->comp];
|
|
+ int *Ldc = c->current_idc[FFMAX(c->mb_pos - 1, 0)].dc[c->comp];
|
|
+ int *dc = c->current_idc[c->mb_pos].dc[c->comp];
|
|
+
|
|
+ if (is_luma && (flags & 0x20) && (flags & 0x80)) {
|
|
+ dc[0] = av_clip((mindc < 0 ? 0 : 1024) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clip(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clip(dc[4] + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clip(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clip(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (is_luma && (flags & 0x80)) {
|
|
+ dc[0] = av_clip(DC_MPRED2(Ldc[5], Ldc[7]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clip(DC_MPRED2(dc[1], dc[3]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clip(dc[4] + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clip(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clip(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (is_luma && (flags & 0x20)) {
|
|
+ dc[0] = av_clip(DC_MPRED2(Tdc[10], Tdc[11]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clip(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clip(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clip(DC_MPRED2(dc[2], dc[3]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clip(DC_MPRED2(dc[8], dc[9]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (is_luma) {
|
|
+ dc[0] = av_clip(DC_MPRED(LTdc[15], Ldc[5], Tdc[10]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(DC_MPRED(Tdc[10], dc[0], Tdc[11]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED(Ldc[5], Ldc[7], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ dc[4] = av_clip(DC_MPRED(Tdc[11], dc[1], Tdc[14]) + tdc[4], mindc, maxdc);
|
|
+ dc[5] = av_clip(DC_MPRED(Tdc[14], dc[4], Tdc[15]) + tdc[5], mindc, maxdc);
|
|
+ dc[6] = av_clip(DC_MPRED(dc[1], dc[3], dc[4]) + tdc[6], mindc, maxdc);
|
|
+ dc[7] = av_clip(DC_MPRED(dc[4], dc[6], dc[5]) + tdc[7], mindc, maxdc);
|
|
+ dc[8] = av_clip(DC_MPRED(Ldc[7], Ldc[13], dc[2]) + tdc[8], mindc, maxdc);
|
|
+ dc[9] = av_clip(DC_MPRED(dc[2], dc[8], dc[3]) + tdc[9], mindc, maxdc);
|
|
+ dc[10] = av_clip(DC_MPRED(Ldc[13], Ldc[15], dc[8]) + tdc[10], mindc, maxdc);
|
|
+ dc[11] = av_clip(DC_MPRED(dc[8], dc[10], dc[9]) + tdc[11], mindc, maxdc);
|
|
+ dc[12] = av_clip(DC_MPRED(dc[3], dc[9], dc[6]) + tdc[12], mindc, maxdc);
|
|
+ dc[13] = av_clip(DC_MPRED(dc[6], dc[12], dc[7]) + tdc[13], mindc, maxdc);
|
|
+ dc[14] = av_clip(DC_MPRED(dc[9], dc[11], dc[12]) + tdc[14], mindc, maxdc);
|
|
+ dc[15] = av_clip(DC_MPRED(dc[12], dc[14], dc[13]) + tdc[15], mindc, maxdc);
|
|
+ } else if (!is_luma && (flags & 0x20) && (flags & 0x80)) {
|
|
+ dc[0] = av_clip((mindc < 0 ? 0 : 1024) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ } else if (!is_luma && (flags & 0x80)) {
|
|
+ dc[0] = av_clip(DC_MPRED2(Ldc[1], Ldc[3]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(dc[0] + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ } else if (!is_luma && (flags & 0x20)) {
|
|
+ dc[0] = av_clip(DC_MPRED2(Tdc[2], Tdc[3]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED2(dc[0], dc[1]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ } else if (!is_luma) {
|
|
+ dc[0] = av_clip(DC_MPRED(LTdc[3], Ldc[1], Tdc[2]) + tdc[0], mindc, maxdc);
|
|
+ dc[1] = av_clip(DC_MPRED(Tdc[2], dc[0], Tdc[3]) + tdc[1], mindc, maxdc);
|
|
+ dc[2] = av_clip(DC_MPRED(Ldc[1], Ldc[3], dc[0]) + tdc[2], mindc, maxdc);
|
|
+ dc[3] = av_clip(DC_MPRED(dc[0], dc[2], dc[1]) + tdc[3], mindc, maxdc);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_decode_dc(Bink2Context *c, GetBitContext *gb, int *dc,
|
|
+ int is_luma, int q, int mindc, int maxdc,
|
|
+ int flags)
|
|
+{
|
|
+ const int num_dc = is_luma ? 16 : 4;
|
|
+ int tdc[16];
|
|
+ int pat;
|
|
+
|
|
+ q = FFMAX(q, 8);
|
|
+ pat = bink2g_dc_pat[q];
|
|
+
|
|
+ memset(tdc, 0, sizeof(tdc));
|
|
+
|
|
+ if (get_bits1(gb)) {
|
|
+ for (int i = 0; i < num_dc; i++) {
|
|
+ int cnt = get_unary(gb, 0, 12);
|
|
+
|
|
+ if (cnt > 3)
|
|
+ cnt = (1 << (cnt - 3)) + get_bits(gb, cnt - 3) + 2;
|
|
+ if (cnt && get_bits1(gb))
|
|
+ cnt = -cnt;
|
|
+ tdc[i] = (cnt * pat + 0x1FF) >> 10;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ bink2g_predict_dc(c, is_luma, mindc, maxdc, flags, tdc);
|
|
+}
|
|
+
|
|
+static int bink2g_decode_ac(GetBitContext *gb, const uint8_t scan[64],
|
|
+ int16_t block[4][64], unsigned cbp,
|
|
+ int q, const uint16_t qmat[4][64],
|
|
+ uint8_t ac_count[4])
|
|
+{
|
|
+ int idx, next, val, skip;
|
|
+ VLC *skip_vlc;
|
|
+
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ memset(block[i], 0, sizeof(int16_t) * 64);
|
|
+ ac_count[i] = 0;
|
|
+ }
|
|
+
|
|
+ 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;
|
|
+ ac_count[i]++;
|
|
+ idx++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline uint16_t bink2g_block_state(int dc, unsigned ac_count, int intra)
|
|
+{
|
|
+ const unsigned strength = (ac_count < 8) + (ac_count < 4) + !ac_count;
|
|
+
|
|
+ return (dc & 0x1FFF) | (strength << 13) | (intra ? 0x8000 : 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];
|
|
+ uint16_t *state = c->current_idc[c->mb_pos].state[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++) {
|
|
+ uint8_t ac_count[4];
|
|
+
|
|
+ ret = bink2g_decode_ac(gb, bink2g_scan, block, cbp >> (4*i),
|
|
+ q, bink2g_luma_intra_qmat, ac_count);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ for (int j = 0; j < 4; j++) {
|
|
+ const int block_index = i * 4 + j;
|
|
+ const int raster_index = luma_repos[block_index];
|
|
+
|
|
+ state[raster_index] = bink2g_block_state(dc[block_index], ac_count[j], 1);
|
|
+ block[j][0] = dc[block_index] * 8 + 32;
|
|
+ bink2g_idct_put(dst + (raster_index & 3) * 8 +
|
|
+ (raster_index >> 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];
|
|
+ uint16_t *state = c->current_idc[c->mb_pos].state[c->comp];
|
|
+ uint8_t ac_count[4];
|
|
+ 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, ac_count);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ for (int j = 0; j < 4; j++) {
|
|
+ state[j] = bink2g_block_state(dc[j], ac_count[j], 1);
|
|
+ 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];
|
|
+ uint16_t *state = c->current_idc[c->mb_pos].state[c->comp];
|
|
+ const int maxdc = c->frame_flags & 0x40000 ? 2047 : 1023;
|
|
+ unsigned cbp;
|
|
+ int ret;
|
|
+
|
|
+ *prev_cbp = cbp = bink2g_decode_cbp_luma(c, gb, *prev_cbp);
|
|
+
|
|
+ bink2g_decode_dc(c, gb, dc, 1, q, -maxdc, maxdc, 0xA8);
|
|
+
|
|
+ for (int i = 0; i < 4; i++) {
|
|
+ uint8_t ac_count[4];
|
|
+
|
|
+ ret = bink2g_decode_ac(gb, bink2g_scan, block, cbp >> (4 * i),
|
|
+ q, bink2g_inter_qmat, ac_count);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ for (int j = 0; j < 4; j++) {
|
|
+ const int block_index = i * 4 + j;
|
|
+ const int raster_index = luma_repos[block_index];
|
|
+
|
|
+ state[raster_index] = bink2g_block_state(dc[block_index], ac_count[j], 0);
|
|
+ block[j][0] = dc[block_index] * 8 + 32;
|
|
+ bink2g_idct_add(dst + (raster_index & 3) * 8 +
|
|
+ (raster_index >> 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];
|
|
+ uint16_t *state = c->current_idc[c->mb_pos].state[c->comp];
|
|
+ uint8_t ac_count[4];
|
|
+ const int maxdc = c->frame_flags & 0x40000 ? 2047 : 1023;
|
|
+ unsigned cbp;
|
|
+ int ret;
|
|
+
|
|
+ *prev_cbp = cbp = bink2g_decode_cbp_chroma(gb, *prev_cbp);
|
|
+
|
|
+ bink2g_decode_dc(c, gb, dc, 0, q, -maxdc, maxdc, 0xA8);
|
|
+
|
|
+ ret = bink2g_decode_ac(gb, bink2g_scan, block, cbp,
|
|
+ q, bink2g_inter_qmat, ac_count);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ for (int j = 0; j < 4; j++) {
|
|
+ state[j] = bink2g_block_state(dc[j], ac_count[j], 0);
|
|
+ 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 {
|
|
+ const int left_v1 = mv.nb_vectors == 0 ? 3 : 1;
|
|
+
|
|
+ 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[left_v1][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[left_v1][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;
|
|
+}
|
|
+
|
|
+static const uint8_t bink2g_chroma_weights[4][2] = {
|
|
+ { 1, 0 },
|
|
+ { 3, 1 },
|
|
+ { 1, 1 },
|
|
+ { 1, 3 },
|
|
+};
|
|
+
|
|
+static const uint8_t bink2g_chroma_shifts[4] = { 0, 2, 1, 2 };
|
|
+
|
|
+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)
|
|
+{
|
|
+ const uint8_t *msrc;
|
|
+ int hphase, vphase, shift, rounding;
|
|
+
|
|
+ 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_block8(dst, msrc, stride, sstride, 8);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ hphase = mode & 3;
|
|
+ vphase = mode >> 2;
|
|
+ shift = bink2g_chroma_shifts[hphase] + bink2g_chroma_shifts[vphase];
|
|
+ rounding = 1 << (shift - 1);
|
|
+
|
|
+ for (int y = 0; y < 8; y++) {
|
|
+ const uint8_t *top = msrc + y * sstride;
|
|
+ const uint8_t *bottom = top + (vphase != 0) * sstride;
|
|
+
|
|
+ for (int x = 0; x < 8; x++) {
|
|
+ const int top_value = bink2g_chroma_weights[hphase][0] * top[x] +
|
|
+ bink2g_chroma_weights[hphase][1] * top[x + (hphase != 0)];
|
|
+ const int bottom_value = bink2g_chroma_weights[hphase][0] * bottom[x] +
|
|
+ bink2g_chroma_weights[hphase][1] * bottom[x + (hphase != 0)];
|
|
+ const int value = bink2g_chroma_weights[vphase][0] * top_value +
|
|
+ bink2g_chroma_weights[vphase][1] * bottom_value;
|
|
+
|
|
+ dst[x] = (value + rounding) >> shift;
|
|
+ }
|
|
+ dst += stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_filter_vertical_edge(uint8_t *p, int stride,
|
|
+ unsigned left, unsigned right)
|
|
+{
|
|
+ const unsigned index = left | (right << 2);
|
|
+
|
|
+ if (!index || index == 15)
|
|
+ return;
|
|
+
|
|
+ for (int y = 0; y < 8; y++, p += stride) {
|
|
+ const int b = p[-1];
|
|
+ const int c = p[0];
|
|
+ const int delta = c - b;
|
|
+ const int outer = (2 * delta + 8) >> 4;
|
|
+ const int inner = (4 * delta + 8) >> 4;
|
|
+
|
|
+ if (left >= 2)
|
|
+ p[-2] = av_clip_uint8(p[-2] + outer);
|
|
+ if (left >= 1)
|
|
+ p[-1] = av_clip_uint8(b + inner);
|
|
+ if (right >= 1)
|
|
+ p[0] = av_clip_uint8(c - inner);
|
|
+ if (right >= 2)
|
|
+ p[1] = av_clip_uint8(p[1] - outer);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_filter_horizontal_edge(uint8_t *p, int stride,
|
|
+ unsigned top, unsigned bottom)
|
|
+{
|
|
+ const unsigned index = top | (bottom << 2);
|
|
+
|
|
+ if (!index || index == 15)
|
|
+ return;
|
|
+
|
|
+ for (int x = 0; x < 8; x++, p++) {
|
|
+ const int b = p[-stride];
|
|
+ const int c = p[0];
|
|
+ const int delta = c - b;
|
|
+ const int outer = (2 * delta + 8) >> 4;
|
|
+ const int inner = (4 * delta + 8) >> 4;
|
|
+
|
|
+ if (top >= 2)
|
|
+ p[-2 * stride] = av_clip_uint8(p[-2 * stride] + outer);
|
|
+ if (top >= 1)
|
|
+ p[-stride] = av_clip_uint8(b + inner);
|
|
+ if (bottom >= 1)
|
|
+ p[0] = av_clip_uint8(c - inner);
|
|
+ if (bottom >= 2)
|
|
+ p[stride] = av_clip_uint8(p[stride] - outer);
|
|
+ }
|
|
+}
|
|
+
|
|
+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) {
|
|
+ int16_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] = 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 inline unsigned bink2g_filter_strength(uint16_t state)
|
|
+{
|
|
+ return (state >> 13) & 3;
|
|
+}
|
|
+
|
|
+static inline int bink2g_filter_map_skip(const uint8_t *map, int position)
|
|
+{
|
|
+ const unsigned bit = position >> 3;
|
|
+
|
|
+ return (map[bit >> 3] >> (bit & 7)) & 1;
|
|
+}
|
|
+
|
|
+static inline int bink2g_mv_discontinuity(const MVectors *a, int ai,
|
|
+ const MVectors *b, int bi)
|
|
+{
|
|
+ return FFABS(a->v[ai][0] - b->v[bi][0]) > 1 ||
|
|
+ FFABS(a->v[ai][1] - b->v[bi][1]) > 1;
|
|
+}
|
|
+
|
|
+static inline void bink2g_force_mv_edge(const MVectors *a, int ai,
|
|
+ const MVectors *b, int bi,
|
|
+ uint16_t left_state,
|
|
+ uint16_t right_state,
|
|
+ unsigned *left, unsigned *right)
|
|
+{
|
|
+ if (!(left_state & 0x8000) && !(right_state & 0x8000) &&
|
|
+ bink2g_mv_discontinuity(a, ai, b, bi))
|
|
+ *left = *right = 2;
|
|
+}
|
|
+
|
|
+static inline void bink2g_select_coding_edge(uint16_t left_state,
|
|
+ uint16_t right_state,
|
|
+ unsigned *left,
|
|
+ unsigned *right)
|
|
+{
|
|
+ const int left_intra = !!(left_state & 0x8000);
|
|
+ const int right_intra = !!(right_state & 0x8000);
|
|
+
|
|
+ if (!left_intra)
|
|
+ *left = 0;
|
|
+ if (!right_intra)
|
|
+ *right = 0;
|
|
+}
|
|
+
|
|
+static inline int bink2g_recon_near(uint16_t a, uint16_t b, int threshold)
|
|
+{
|
|
+ const int16_t ab = (int16_t)(uint16_t)(a - b);
|
|
+ const int16_t ba = (int16_t)(uint16_t)(b - a);
|
|
+
|
|
+ return FFMAX(ab, ba) < threshold;
|
|
+}
|
|
+
|
|
+static inline int bink2g_recon_mulhi(int k, int v)
|
|
+{
|
|
+ return ((int32_t)(int16_t)k * (int16_t)v) >> 16;
|
|
+}
|
|
+
|
|
+static inline int bink2g_recon_curve(int base, int left, int right, int pos)
|
|
+{
|
|
+ switch (pos) {
|
|
+ case 0: return base + bink2g_recon_mulhi(26624, left);
|
|
+ case 1: return base + bink2g_recon_mulhi(18432, left) + (right >> 7);
|
|
+ case 2: return base + bink2g_recon_mulhi(12288, left) + (right >> 5);
|
|
+ case 3: return base + bink2g_recon_mulhi( 7168, left) + (right >> 4);
|
|
+ case 4: return base + bink2g_recon_mulhi( 7168, right) + (left >> 4);
|
|
+ case 5: return base + bink2g_recon_mulhi(12288, right) + (left >> 5);
|
|
+ case 6: return base + bink2g_recon_mulhi(18432, right) + (left >> 7);
|
|
+ default:return base + bink2g_recon_mulhi(26624, right);
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline uint16_t bink2g_recon_state(const DCIPredict *row, int comp,
|
|
+ int blocks_per_mb, int blocks_w,
|
|
+ int block_x, int block_y)
|
|
+{
|
|
+ block_x = av_clip(block_x, 0, blocks_w - 1);
|
|
+ return row[block_x / blocks_per_mb].state[comp]
|
|
+ [block_y * blocks_per_mb + block_x % blocks_per_mb];
|
|
+}
|
|
+
|
|
+static void bink2g_reconstruct_block(uint8_t *dst, int stride,
|
|
+ int width, int height,
|
|
+ uint16_t left, uint16_t target,
|
|
+ uint16_t right, uint16_t up_left,
|
|
+ uint16_t up, uint16_t up_right,
|
|
+ uint16_t down_left, uint16_t down,
|
|
+ uint16_t down_right, int threshold)
|
|
+{
|
|
+ int center[8], top[8], bottom[8];
|
|
+ int d, l, r, u, v, ul, ur, dl, dr;
|
|
+
|
|
+ if (target < 0xE000 || width <= 0 || height <= 0)
|
|
+ return;
|
|
+
|
|
+ d = target & 0x1FFF;
|
|
+ l = bink2g_recon_near(target, left, threshold) ? left & 0x1FFF : d;
|
|
+ r = bink2g_recon_near(target, right, threshold) ? right & 0x1FFF : d;
|
|
+ u = bink2g_recon_near(target, up, threshold) ? up & 0x1FFF : d;
|
|
+ v = bink2g_recon_near(target, down, threshold) ? down & 0x1FFF : d;
|
|
+ ul = bink2g_recon_near(target, up_left, threshold) ? up_left & 0x1FFF : l;
|
|
+ ur = bink2g_recon_near(target, up_right, threshold) ? up_right & 0x1FFF : r;
|
|
+ dl = bink2g_recon_near(target, down_left, threshold) ? down_left & 0x1FFF : l;
|
|
+ dr = bink2g_recon_near(target, down_right, threshold) ? down_right & 0x1FFF : r;
|
|
+
|
|
+ for (int x = 0; x < 8; x++) {
|
|
+ center[x] = bink2g_recon_curve(d + 4, l - d, r - d, x);
|
|
+ top[x] = bink2g_recon_curve(u + 4, ul - u, ur - u, x) - center[x];
|
|
+ bottom[x] = bink2g_recon_curve(v + 4, dl - v, dr - v, x) - center[x];
|
|
+ }
|
|
+
|
|
+ for (int y = 0; y < FFMIN(height, 8); y++) {
|
|
+ for (int x = 0; x < FFMIN(width, 8); x++)
|
|
+ dst[x] = av_clip_uint8(bink2g_recon_curve(center[x], top[x],
|
|
+ bottom[x], y) >> 3);
|
|
+ dst += stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_reconstruct_blocks(Bink2Context *c, uint8_t *dst,
|
|
+ int stride, int comp, int global_y,
|
|
+ const DCIPredict *up_row, int up_by,
|
|
+ const DCIPredict *row, int by,
|
|
+ const DCIPredict *down_row, int down_by)
|
|
+{
|
|
+ const int chroma = comp == 1 || comp == 2;
|
|
+ const int blocks_per_mb = chroma ? 2 : 4;
|
|
+ const int plane_w = chroma ? (c->avctx->width + 1) >> 1 : c->avctx->width;
|
|
+ const int plane_h = chroma ? (c->avctx->height + 1) >> 1 : c->avctx->height;
|
|
+ const int visible_blocks_w = (plane_w + 7) >> 3;
|
|
+ const int coded_blocks_w = ((c->avctx->width + 31) >> 5) * blocks_per_mb;
|
|
+ const int coded_plane_h = ((c->avctx->height + 31) >> 5) *
|
|
+ blocks_per_mb * 8;
|
|
+ const int threshold = (c->frame_flags & 0xFF) << 3;
|
|
+ const int have_up = global_y >= 8;
|
|
+ const int have_down = global_y + 8 < coded_plane_h;
|
|
+
|
|
+ for (int bx = 0; bx < visible_blocks_w; bx++) {
|
|
+ const uint16_t target = bink2g_recon_state(row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx, by);
|
|
+ const uint16_t left = bx ?
|
|
+ bink2g_recon_state(row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx - 1, by) : target;
|
|
+ const uint16_t right = bx + 1 < coded_blocks_w ?
|
|
+ bink2g_recon_state(row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx + 1, by) : target;
|
|
+ const uint16_t up_left = have_up && bx ?
|
|
+ bink2g_recon_state(up_row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx - 1, up_by) : 0;
|
|
+ const uint16_t up = have_up ?
|
|
+ bink2g_recon_state(up_row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx, up_by) : target;
|
|
+ const uint16_t up_right = have_up && bx + 1 < coded_blocks_w ?
|
|
+ bink2g_recon_state(up_row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx + 1, up_by) : 0;
|
|
+ const uint16_t down_left = bx ?
|
|
+ have_down ?
|
|
+ bink2g_recon_state(down_row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx - 1, down_by) :
|
|
+ (target & 0xE000) | (left & 0x1FFF) : 0;
|
|
+ const uint16_t down = have_down ?
|
|
+ bink2g_recon_state(down_row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx, down_by) : target;
|
|
+ const uint16_t down_right = bx + 1 < coded_blocks_w ?
|
|
+ have_down ?
|
|
+ bink2g_recon_state(down_row, comp, blocks_per_mb,
|
|
+ coded_blocks_w, bx + 1, down_by) :
|
|
+ (target & 0xE000) | (right & 0x1FFF) : 0;
|
|
+
|
|
+ bink2g_reconstruct_block(dst + bx * 8, stride,
|
|
+ plane_w - bx * 8, plane_h - global_y,
|
|
+ left, target, right, up_left, up, up_right,
|
|
+ down_left, down, down_right, threshold);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_reconstruct_row(Bink2Context *c, uint8_t *dst[4],
|
|
+ const int stride[4], int y,
|
|
+ const DCIPredict *prev_idc,
|
|
+ const DCIPredict *current_idc,
|
|
+ int is_last)
|
|
+{
|
|
+ for (int comp = 0; comp < 3 + c->has_alpha; comp++) {
|
|
+ const int chroma = comp == 1 || comp == 2;
|
|
+ const int plane = comp == 1 ? 2 : comp == 2 ? 1 : comp;
|
|
+ const int blocks_per_mb = chroma ? 2 : 4;
|
|
+ const int plane_y = chroma ? y >> 1 : y;
|
|
+
|
|
+ if (y > 0) {
|
|
+ const int by = blocks_per_mb - 1;
|
|
+
|
|
+ bink2g_reconstruct_blocks(c, dst[plane] - 8 * stride[plane],
|
|
+ stride[plane], comp, plane_y - 8,
|
|
+ prev_idc, by - 1,
|
|
+ prev_idc, by,
|
|
+ current_idc, 0);
|
|
+ }
|
|
+
|
|
+ for (int by = 0; by < blocks_per_mb - 1; by++) {
|
|
+ const DCIPredict *up_row = by ? current_idc :
|
|
+ y > 0 ? prev_idc : current_idc;
|
|
+ const int up_by = by ? by - 1 :
|
|
+ y > 0 ? blocks_per_mb - 1 : 0;
|
|
+
|
|
+ bink2g_reconstruct_blocks(c, dst[plane] + by * 8 * stride[plane],
|
|
+ stride[plane], comp, plane_y + by * 8,
|
|
+ up_row, up_by,
|
|
+ current_idc, by,
|
|
+ current_idc, by + 1);
|
|
+ }
|
|
+
|
|
+ if (is_last) {
|
|
+ const int by = blocks_per_mb - 1;
|
|
+
|
|
+ bink2g_reconstruct_blocks(c, dst[plane] + by * 8 * stride[plane],
|
|
+ stride[plane], comp, plane_y + by * 8,
|
|
+ current_idc, by - 1,
|
|
+ current_idc, by,
|
|
+ current_idc, by);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_filter_vertical_row(Bink2Context *c, uint8_t *dst[4],
|
|
+ const int stride[4], int comp,
|
|
+ const DCIPredict *row,
|
|
+ const MVPredict *mv_row,
|
|
+ int by, int rel_y)
|
|
+{
|
|
+ const int chroma = comp != 0;
|
|
+ const int plane = comp == 1 ? 2 : comp == 2 ? 1 : 0;
|
|
+ const int blocks_per_mb = chroma ? 2 : 4;
|
|
+ const int plane_w = chroma ? (c->avctx->width + 1) >> 1 : c->avctx->width;
|
|
+ const int blocks_w = (plane_w + 7) >> 3;
|
|
+
|
|
+ if (c->frame_flags & 0x4000)
|
|
+ return;
|
|
+
|
|
+ for (int bx = 1; bx < blocks_w; bx++) {
|
|
+ const int mb = bx / blocks_per_mb;
|
|
+ const int local_x = bx % blocks_per_mb;
|
|
+ const int left_mb = local_x ? mb : mb - 1;
|
|
+ const int left_x = local_x ? local_x - 1 : blocks_per_mb - 1;
|
|
+ const uint16_t left_state = row[left_mb].state[comp]
|
|
+ [by * blocks_per_mb + left_x];
|
|
+ const uint16_t right_state = row[mb].state[comp]
|
|
+ [by * blocks_per_mb + local_x];
|
|
+ unsigned left = bink2g_filter_strength(left_state);
|
|
+ unsigned right = bink2g_filter_strength(right_state);
|
|
+ const int edge_x = bx * (chroma ? 16 : 8);
|
|
+
|
|
+ bink2g_select_coding_edge(left_state, right_state, &left, &right);
|
|
+
|
|
+ if (edge_x >= c->avctx->width ||
|
|
+ bink2g_filter_map_skip(c->col_cbp, edge_x))
|
|
+ continue;
|
|
+
|
|
+ if (chroma || !(bx & 1)) {
|
|
+ const int qrow = chroma ? by : by >> 1;
|
|
+ const int left_q = 2 * qrow + (local_x ? 0 : 1);
|
|
+ const int right_q = 2 * qrow + (local_x ? 1 : 0);
|
|
+
|
|
+ bink2g_force_mv_edge(&mv_row[left_mb].mv, left_q,
|
|
+ &mv_row[mb].mv, right_q,
|
|
+ left_state, right_state, &left, &right);
|
|
+ }
|
|
+
|
|
+ bink2g_filter_vertical_edge(dst[plane] + bx * 8 +
|
|
+ rel_y * stride[plane],
|
|
+ stride[plane], left, right);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_filter_horizontal_row(Bink2Context *c, uint8_t *dst[4],
|
|
+ const int stride[4], int comp,
|
|
+ const DCIPredict *top_row, int top_by,
|
|
+ const MVPredict *top_mv,
|
|
+ const DCIPredict *bottom_row, int bottom_by,
|
|
+ const MVPredict *bottom_mv,
|
|
+ int rel_y, int edge_y, int slice_start)
|
|
+{
|
|
+ const int chroma = comp != 0;
|
|
+ const int plane = comp == 1 ? 2 : comp == 2 ? 1 : 0;
|
|
+ const int blocks_per_mb = chroma ? 2 : 4;
|
|
+ const int plane_w = chroma ? (c->avctx->width + 1) >> 1 : c->avctx->width;
|
|
+ const int blocks_w = (plane_w + 7) >> 3;
|
|
+
|
|
+ if ((c->frame_flags & 0x8000) || edge_y == slice_start ||
|
|
+ edge_y >= c->avctx->height ||
|
|
+ bink2g_filter_map_skip(c->row_cbp, edge_y))
|
|
+ return;
|
|
+
|
|
+ for (int bx = 0; bx < blocks_w; bx++) {
|
|
+ const int mb = bx / blocks_per_mb;
|
|
+ const int local_x = bx % blocks_per_mb;
|
|
+ const uint16_t top_state = top_row[mb].state[comp]
|
|
+ [top_by * blocks_per_mb + local_x];
|
|
+ const uint16_t bottom_state = bottom_row[mb].state[comp]
|
|
+ [bottom_by * blocks_per_mb + local_x];
|
|
+ unsigned top = bink2g_filter_strength(top_state);
|
|
+ unsigned bottom = bink2g_filter_strength(bottom_state);
|
|
+
|
|
+ bink2g_select_coding_edge(top_state, bottom_state, &top, &bottom);
|
|
+
|
|
+ if (chroma || bottom_by == 0 || bottom_by == 2) {
|
|
+ const int qcol = chroma ? local_x : local_x >> 1;
|
|
+ const int top_q = (bottom_by ? 0 : 2) + qcol;
|
|
+ const int bottom_q = (bottom_by ? 2 : 0) + qcol;
|
|
+
|
|
+ bink2g_force_mv_edge(&top_mv[mb].mv, top_q,
|
|
+ &bottom_mv[mb].mv, bottom_q,
|
|
+ top_state, bottom_state, &top, &bottom);
|
|
+ }
|
|
+
|
|
+ bink2g_filter_horizontal_edge(dst[plane] + bx * 8 +
|
|
+ rel_y * stride[plane],
|
|
+ stride[plane], top, bottom);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_postprocess_row(Bink2Context *c, uint8_t *dst[4],
|
|
+ const int stride[4], int y,
|
|
+ int frame_end,
|
|
+ const DCIPredict *prev_idc,
|
|
+ const DCIPredict *current_idc,
|
|
+ const MVPredict *prev_mv,
|
|
+ const MVPredict *current_mv)
|
|
+{
|
|
+ const int is_last = y + 32 >= frame_end;
|
|
+
|
|
+ bink2g_reconstruct_row(c, dst, stride, y,
|
|
+ prev_idc, current_idc, is_last);
|
|
+
|
|
+ for (int comp = 0; comp < 3; comp++) {
|
|
+ const int chroma = comp != 0;
|
|
+ const int blocks_per_mb = chroma ? 2 : 4;
|
|
+
|
|
+ if (y > 0)
|
|
+ bink2g_filter_vertical_row(c, dst, stride, comp, prev_idc,
|
|
+ prev_mv,
|
|
+ blocks_per_mb - 1, -8);
|
|
+ for (int by = 0; by < blocks_per_mb - 1; by++)
|
|
+ bink2g_filter_vertical_row(c, dst, stride, comp, current_idc,
|
|
+ current_mv, by, by * 8);
|
|
+ if (is_last)
|
|
+ bink2g_filter_vertical_row(c, dst, stride, comp, current_idc,
|
|
+ current_mv,
|
|
+ blocks_per_mb - 1,
|
|
+ (blocks_per_mb - 1) * 8);
|
|
+ }
|
|
+
|
|
+ if (y > 0) {
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, 0,
|
|
+ prev_idc, 2, prev_mv,
|
|
+ prev_idc, 3, prev_mv,
|
|
+ -8, y - 8, 0);
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, 0,
|
|
+ prev_idc, 3, prev_mv,
|
|
+ current_idc, 0, current_mv,
|
|
+ 0, y, 0);
|
|
+ for (int comp = 1; comp <= 2; comp++) {
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, comp,
|
|
+ prev_idc, 0, prev_mv,
|
|
+ prev_idc, 1, prev_mv,
|
|
+ -8, y - 16, 0);
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, comp,
|
|
+ prev_idc, 1, prev_mv,
|
|
+ current_idc, 0, current_mv,
|
|
+ 0, y, 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, 0,
|
|
+ current_idc, 0, current_mv,
|
|
+ current_idc, 1, current_mv,
|
|
+ 8, y + 8, 0);
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, 0,
|
|
+ current_idc, 1, current_mv,
|
|
+ current_idc, 2, current_mv,
|
|
+ 16, y + 16, 0);
|
|
+
|
|
+ if (is_last) {
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, 0,
|
|
+ current_idc, 2, current_mv,
|
|
+ current_idc, 3, current_mv,
|
|
+ 24, y + 24, 0);
|
|
+ for (int comp = 1; comp <= 2; comp++)
|
|
+ bink2g_filter_horizontal_row(c, dst, stride, comp,
|
|
+ current_idc, 0, current_mv,
|
|
+ current_idc, 1, current_mv,
|
|
+ 8, y + 16, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bink2g_postprocess_frame(Bink2Context *c, uint8_t *dst[4],
|
|
+ const int stride[4])
|
|
+{
|
|
+ const int mb_width = (c->avctx->width + 31) >> 5;
|
|
+ const int mb_height = (c->avctx->height + 31) >> 5;
|
|
+ const int frame_end = mb_height << 5;
|
|
+
|
|
+ for (int mb_y = 0; mb_y < mb_height; mb_y++) {
|
|
+ const int y = mb_y << 5;
|
|
+ const int prev_y = mb_y ? mb_y - 1 : 0;
|
|
+ const DCIPredict *prev_idc = c->frame_idc + prev_y * mb_width;
|
|
+ const DCIPredict *current_idc = c->frame_idc + mb_y * mb_width;
|
|
+ const MVPredict *prev_mv = c->frame_mv + prev_y * mb_width;
|
|
+ const MVPredict *current_mv = c->frame_mv + mb_y * mb_width;
|
|
+ uint8_t *row_dst[4] = {
|
|
+ dst[0] + y * stride[0],
|
|
+ dst[1] + (y >> 1) * stride[1],
|
|
+ dst[2] + (y >> 1) * stride[2],
|
|
+ c->has_alpha ? dst[3] + y * stride[3] : NULL,
|
|
+ };
|
|
+
|
|
+ bink2g_postprocess_row(c, row_dst, stride, y, frame_end,
|
|
+ prev_idc, current_idc, prev_mv, current_mv);
|
|
+ }
|
|
+}
|
|
+
|
|
+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;
|
|
+ const int mb_width = (w + 31) / 32;
|
|
+ int ret = 0, dq, flags;
|
|
+
|
|
+ memset(c->prev_q, 0, mb_width * sizeof(*c->prev_q));
|
|
+ memset(c->prev_mv, 0, mb_width * sizeof(*c->prev_mv));
|
|
+ memset(c->prev_idc, 0, mb_width * sizeof(*c->prev_idc));
|
|
+ memset(c->current_idc, 0, mb_width * sizeof(*c->current_idc));
|
|
+
|
|
+ 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;
|
|
+ memset(c->current_idc[c->mb_pos].state, 0,
|
|
+ sizeof(c->current_idc[c->mb_pos].state));
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ memcpy(c->frame_idc + (y >> 5) * mb_width, c->current_idc,
|
|
+ mb_width * sizeof(*c->frame_idc));
|
|
+ memcpy(c->frame_mv + (y >> 5) * mb_width, c->current_mv,
|
|
+ mb_width * sizeof(*c->frame_mv));
|
|
+
|
|
+ dst[0] += stride[0] * 32;
|
|
+ dst[1] += stride[1] * 16;
|
|
+ dst[2] += stride[2] * 16;
|
|
+ if (c->has_alpha)
|
|
+ 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 d58c3d889c..92c27e58d4 100644
|
|
--- a/libavcodec/codec_desc.c
|
|
+++ b/libavcodec/codec_desc.c
|
|
@@ -1959,6 +1959,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
|
.long_name = NULL_IF_CONFIG_SMALL("LEAD MCMP"),
|
|
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
|
|
},
|
|
+ {
|
|
+ .id = AV_CODEC_ID_BINKVIDEO2,
|
|
+ .type = AVMEDIA_TYPE_VIDEO,
|
|
+ .name = "binkvideo2",
|
|
+ .long_name = NULL_IF_CONFIG_SMALL("Bink video 2"),
|
|
+ .props = AV_CODEC_PROP_LOSSY,
|
|
+ },
|
|
|
|
/* various PCM "codecs" */
|
|
{
|
|
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
|
|
index 0a8d3bed1e..a7e874c890 100644
|
|
--- a/libavcodec/codec_id.h
|
|
+++ b/libavcodec/codec_id.h
|
|
@@ -322,6 +322,7 @@ enum AVCodecID {
|
|
AV_CODEC_ID_RTV1,
|
|
AV_CODEC_ID_VMIX,
|
|
AV_CODEC_ID_LEAD,
|
|
+ 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 0632d390a2..fbb0238795 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] == 'm' || 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)
|
|
@@ -168,8 +167,11 @@ static int read_header(AVFormatContext *s)
|
|
signature = (vst->codecpar->codec_tag & 0xFFFFFF);
|
|
revision = ((vst->codecpar->codec_tag >> 24) % 0xFF);
|
|
|
|
- if ((signature == AV_RL32("BIK") && (revision == 'k')) ||
|
|
- (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k')))
|
|
+ if (signature == AV_RL32("KB2") && revision == 'm')
|
|
+ avio_skip(pb, 16); /* opaque KB2m header extension */
|
|
+ else if ((signature == AV_RL32("BIK") && 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) {
|