[FFmpeg-devel] [PATCH 2/2] avcodec: add bink2 video decoder
Paul B Mahol
onemda at gmail.com
Sun Apr 7 11:00:09 EEST 2019
On 4/7/19, Peter Ross <pross at xvid.org> wrote:
> On Wed, Mar 27, 2019 at 09:21:47PM +0100, Paul B Mahol wrote:
>> Signed-off-by: Paul B Mahol <onemda at gmail.com>
>> ---
>> Missing deblocking.
>> ---
>> configure | 1 +
>> libavcodec/Makefile | 1 +
>> libavcodec/allcodecs.c | 1 +
>> libavcodec/avcodec.h | 1 +
>> libavcodec/bink2.c | 787 +++++++++++++++++++++++
>> libavcodec/bink2f.c | 1139 +++++++++++++++++++++++++++++++++
>> libavcodec/bink2g.c | 1342 +++++++++++++++++++++++++++++++++++++++
>> libavcodec/codec_desc.c | 7 +
>> libavformat/bink.c | 3 +-
>
> my comments below.
>
> this is a mammoth amount of work deserving of a better quality review.
>
>> +++ b/libavcodec/bink2.c
>> @@ -0,0 +1,787 @@
>> +/*
>> + * Bink video 2 decoder
>> + * Copyright (c) 2014 Konstantin Shishkov
>> + * Copyright (c) 2019 Paul B Mahol
>> + *
>
>> +static const uint8_t luma_repos[] = {
>> + 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15,
>> +};
>
> identical to msvideo1enc.c remap
> consider moving to libavcodec/mathops.h
>
>> +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,
>> +};
>
> this is so close to ff_dirac_qscale_tab it is not funny.
>
>> + 3, 24, 11, 18, 25, 13, 14, 4,
>> + 15, 5, 6, 7, 12, 19, 20, 21,
>> + 22, 23, 26, 27, 28, 29, 30, 31,
>> + 32, 33, 34, 35, 36, 37, 38, 39,
>> + 40, 41, 42, 43, 44, 45, 46, 47,
>> + 48, 49, 50, 51, 52, 53, 54, 55,
>> + 56, 57, 58, 59, 60, 61, 62, 63
>> +};
>> +
>> +static const uint8_t bink2g_scan[64] = {
>> + 0, 8, 1, 2, 9, 16, 24, 17,
>> + 10, 3, 4, 11, 18, 25, 32, 40,
>> + 33, 26, 19, 12, 5, 6, 13, 20,
>> + 27, 34, 41, 48, 56, 49, 42, 35,
>> + 28, 21, 14, 7, 15, 22, 29, 36,
>> + 43, 50, 57, 58, 51, 44, 37, 30,
>> + 23, 31, 38, 45, 52, 59, 60, 53,
>> + 46, 39, 47, 54, 61, 62, 55, 63,
>> +};
>
> this table has more white space than the other scan tables...
>
>> +enum BlockTypes {
>> + INTRA_BLOCK = 0, ///< intra DCT block
>> + SKIP_BLOCK, ///< skipped block
>> + MOTION_BLOCK, ///< block is copied from previous frame with some
>> offset
>> + RESIDUE_BLOCK, ///< motion block with some difference added
>> +};
>> +
>> +static const uint8_t ones_count[16] = {
>> + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
>> +};
>
> duplicate of libavcodec/vc1_mc.c popcount4
>
>> +static int bink2_decode_frame(AVCodecContext *avctx, void *data,
>> + int *got_frame, AVPacket *pkt)
>> +{
>> + Bink2Context * const c = avctx->priv_data;
>> + GetBitContext *gb = &c->gb;
>> + AVFrame *frame = data;
>> + uint8_t *dst[4];
>> + uint8_t *src[4];
>> + int stride[4];
>> + int sstride[4];
>> + uint32_t off = 0;
>> + int is_kf = !!(pkt->flags & AV_PKT_FLAG_KEY);
>> + int ret, w, h;
>> + int height_a;
>> +
>> + w = avctx->width;
>> + h = avctx->height;
>> + ret = ff_set_dimensions(avctx, FFALIGN(w, 32), FFALIGN(h, 32));
>> + if (ret < 0)
>> + return ret;
>> + avctx->width = w;
>> + avctx->height = h;
>> +
>> + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
>> + return ret;
>
> ret error handling style is inconsistent
>
>> +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);
>
> check error code?
>
>> + 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);
>
> ditto.
>
>> +
>> + 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;
>> +}
>> +
>
> some of the bink2 f/g functions are identical except for the input/output
> type.
> i guess not much can be done about that as macros will make it more ugly.
>
>> +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;
>
> caps here makes actually it less readble.
>
>> + dc[i] = bink2f_average_block(src + x + X * 8 + (y + Y * 8) *
>> stride, stride);
>> + }
>> +}
>
>> +static int bink2g_get_type(GetBitContext *gb, int *lru)
>> +{
>> + int val;
>> +
>> + ff_dlog(NULL, " type show %X @ %d\n", show_bits(gb, 4),
>> get_bits_count(gb));
>> + switch (get_unary(gb, 1, 3)) {
>> + case 0:
>> + val = lru[0];
>> + break;
>> + case 1:
>> + val = lru[1];
>> + FFSWAP(int, lru[0], lru[1]);
>> + break;
>> + case 2:
>> + val = lru[3];
>> + FFSWAP(int, lru[2], lru[3]);
>> + break;
>> + case 3:
>> + val = lru[2];
>> + FFSWAP(int, lru[1], lru[2]);
>> + break;
>> + }
>
> cases 1-3 could be collapsed.
I do not see how.
>> +
>> + return val;
>> +}
>> +
>> +static int bink2g_decode_dq(GetBitContext *gb)
>> +{
>> + int dq = get_unary(gb, 1, 4);
>> +
>> + if (dq == 3)
>> + dq += get_bits1(gb);
>> + else if (dq == 4)
>> + dq += get_bits(gb, 5) + 1;
>> + if (dq && get_bits1(gb))
>> + dq = -dq;
>> +
>> + return dq;
>> +}
>> +
>> +typedef uint8_t byte;
>> +typedef int8_t sbyte;
>> +typedef unsigned uint;
>
> but why?
>
>> +static void bink2g_get_cbp_flags(GetBitContext *gb, int offset, int size,
>> uint8_t *dst)
>> +{
>> + unsigned flag;
>> + int i, j;
>> + byte bVar4;
>> + sbyte sVar5;
>> + byte bVar6;
>> + int iVar7;
>> + int uVar8;
>> + int uVar9;
>> + int local_20;
>> + int local_1c;
>
> those variable names are not meaningful enough. in fact they look computer
> generated.
Yes, that code needs some refactoring.
>
> -- Peter
> (A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
>
More information about the ffmpeg-devel
mailing list