2064 lines · 95.3 KB · C
RawDownload
/* * Copyright © 2018, VideoLAN and dav1d authors * Copyright © 2018, Two Orioles, LLC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this *    list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, *    this list of conditions and the following disclaimer in the documentation *    and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include <string.h>#ifndef __plan9__#include <stdio.h>#endif #include "common/attributes.h"#include "common/bitdepth.h"#include "common/dump.h"#include "common/intops.h" #include "src/cdef_apply.h"#include "src/ctx.h"#include "src/ipred_prepare.h"#include "src/lf_apply.h"#include "src/lr_apply.h"#include "src/recon.h"#include "src/scan.h"#include "src/tables.h"#include "src/wedge.h" static inline unsigned read_golomb(MsacContext *const msac) {    int len = 0;    unsigned val = 1;     while (!dav1d_msac_decode_bool_equi(msac) && len < 32) len++;    while (len--) val = (val << 1) + dav1d_msac_decode_bool_equi(msac);     return val - 1;} static inline unsigned get_skip_ctx(const TxfmInfo *const t_dim,                                    const enum BlockSize bs,                                    const uint8_t *const a,                                    const uint8_t *const l,                                    const int chroma,                                    const enum Dav1dPixelLayout layout){    const uint8_t *const b_dim = dav1d_block_dimensions[bs];     if (chroma) {        const int ss_ver = layout == DAV1D_PIXEL_LAYOUT_I420;        const int ss_hor = layout != DAV1D_PIXEL_LAYOUT_I444;        const int not_one_blk = b_dim[2] - (!!b_dim[2] && ss_hor) > t_dim->lw ||                                b_dim[3] - (!!b_dim[3] && ss_ver) > t_dim->lh;        unsigned ca, cl; #define MERGE_CTX(dir, type, no_val) \        c##dir = *(const type *) dir != no_val; \        break         switch (t_dim->lw) {        /* For some reason the MSVC CRT _wassert() function is not flagged as         * __declspec(noreturn), so when using those headers the compiler will         * expect execution to continue after an assertion has been triggered         * and will therefore complain about the use of uninitialized variables         * when compiled in debug mode if we put the default case at the end. */        default: assert(0); /* fall-through */        case TX_4X4:   MERGE_CTX(a, uint8_t,  0x40);        case TX_8X8:   MERGE_CTX(a, uint16_t, 0x4040);        case TX_16X16: MERGE_CTX(a, uint32_t, 0x40404040U);        case TX_32X32: MERGE_CTX(a, uint64_t, 0x4040404040404040ULL);        }        switch (t_dim->lh) {        default: assert(0); /* fall-through */        case TX_4X4:   MERGE_CTX(l, uint8_t,  0x40);        case TX_8X8:   MERGE_CTX(l, uint16_t, 0x4040);        case TX_16X16: MERGE_CTX(l, uint32_t, 0x40404040U);        case TX_32X32: MERGE_CTX(l, uint64_t, 0x4040404040404040ULL);        }#undef MERGE_CTX         return 7 + not_one_blk * 3 + ca + cl;    } else if (b_dim[2] == t_dim->lw && b_dim[3] == t_dim->lh) {        return 0;    } else {        unsigned la, ll; #define MERGE_CTX(dir, type, tx) \        if (tx == TX_64X64) { \            uint64_t tmp = *(const uint64_t *) dir; \            tmp |= *(const uint64_t *) &dir[8]; \            l##dir = (unsigned) (tmp >> 32) | (unsigned) tmp; \        } else \            l##dir = *(const type *) dir; \        if (tx == TX_32X32) l##dir |= *(const type *) &dir[sizeof(type)]; \        if (tx >= TX_16X16) l##dir |= l##dir >> 16; \        if (tx >= TX_8X8)   l##dir |= l##dir >> 8; \        break         switch (t_dim->lw) {        default: assert(0); /* fall-through */        case TX_4X4:   MERGE_CTX(a, uint8_t,  TX_4X4);        case TX_8X8:   MERGE_CTX(a, uint16_t, TX_8X8);        case TX_16X16: MERGE_CTX(a, uint32_t, TX_16X16);        case TX_32X32: MERGE_CTX(a, uint32_t, TX_32X32);        case TX_64X64: MERGE_CTX(a, uint32_t, TX_64X64);        }        switch (t_dim->lh) {        default: assert(0); /* fall-through */        case TX_4X4:   MERGE_CTX(l, uint8_t,  TX_4X4);        case TX_8X8:   MERGE_CTX(l, uint16_t, TX_8X8);        case TX_16X16: MERGE_CTX(l, uint32_t, TX_16X16);        case TX_32X32: MERGE_CTX(l, uint32_t, TX_32X32);        case TX_64X64: MERGE_CTX(l, uint32_t, TX_64X64);        }#undef MERGE_CTX         return dav1d_skip_ctx[umin(la & 0x3F, 4)][umin(ll & 0x3F, 4)];    }} static inline unsigned get_dc_sign_ctx(const int /*enum RectTxfmSize*/ tx,                                       const uint8_t *const a,                                       const uint8_t *const l){    uint64_t mask = 0xC0C0C0C0C0C0C0C0ULL, mul = 0x0101010101010101ULL;    int s; #if ARCH_X86_64 && defined(__GNUC__)    /* Coerce compilers into producing better code. For some reason     * every x86-64 compiler is awful at handling 64-bit constants. */    __asm__("" : "+r"(mask), "+r"(mul));#endif     switch(tx) {    default: assert(0); /* fall-through */    case TX_4X4: {        int t = *(const uint8_t *) a >> 6;        t    += *(const uint8_t *) l >> 6;        s = t - 1 - 1;        break;    }    case TX_8X8: {        uint32_t t = *(const uint16_t *) a & (uint32_t) mask;        t         += *(const uint16_t *) l & (uint32_t) mask;        t *= 0x04040404U;        s = (int) (t >> 24) - 2 - 2;        break;    }    case TX_16X16: {        uint32_t t = (*(const uint32_t *) a & (uint32_t) mask) >> 6;        t         += (*(const uint32_t *) l & (uint32_t) mask) >> 6;        t *= (uint32_t) mul;        s = (int) (t >> 24) - 4 - 4;        break;    }    case TX_32X32: {        uint64_t t = (*(const uint64_t *) a & mask) >> 6;        t         += (*(const uint64_t *) l & mask) >> 6;        t *= mul;        s = (int) (t >> 56) - 8 - 8;        break;    }    case TX_64X64: {        uint64_t t = (*(const uint64_t *) &a[0] & mask) >> 6;        t         += (*(const uint64_t *) &a[8] & mask) >> 6;        t         += (*(const uint64_t *) &l[0] & mask) >> 6;        t         += (*(const uint64_t *) &l[8] & mask) >> 6;        t *= mul;        s = (int) (t >> 56) - 16 - 16;        break;    }    case RTX_4X8: {        uint32_t t = *(const uint8_t  *) a & (uint32_t) mask;        t         += *(const uint16_t *) l & (uint32_t) mask;        t *= 0x04040404U;        s = (int) (t >> 24) - 1 - 2;        break;    }    case RTX_8X4: {        uint32_t t = *(const uint16_t *) a & (uint32_t) mask;        t         += *(const uint8_t  *) l & (uint32_t) mask;        t *= 0x04040404U;        s = (int) (t >> 24) - 2 - 1;        break;    }    case RTX_8X16: {        uint32_t t = *(const uint16_t *) a & (uint32_t) mask;        t         += *(const uint32_t *) l & (uint32_t) mask;        t = (t >> 6) * (uint32_t) mul;        s = (int) (t >> 24) - 2 - 4;        break;    }    case RTX_16X8: {        uint32_t t = *(const uint32_t *) a & (uint32_t) mask;        t         += *(const uint16_t *) l & (uint32_t) mask;        t = (t >> 6) * (uint32_t) mul;        s = (int) (t >> 24) - 4 - 2;        break;    }    case RTX_16X32: {        uint64_t t = *(const uint32_t *) a & (uint32_t) mask;        t         += *(const uint64_t *) l & mask;        t = (t >> 6) * mul;        s = (int) (t >> 56) - 4 - 8;        break;    }    case RTX_32X16: {        uint64_t t = *(const uint64_t *) a & mask;        t         += *(const uint32_t *) l & (uint32_t) mask;        t = (t >> 6) * mul;        s = (int) (t >> 56) - 8 - 4;        break;    }    case RTX_32X64: {        uint64_t t = (*(const uint64_t *) &a[0] & mask) >> 6;        t         += (*(const uint64_t *) &l[0] & mask) >> 6;        t         += (*(const uint64_t *) &l[8] & mask) >> 6;        t *= mul;        s = (int) (t >> 56) - 8 - 16;        break;    }    case RTX_64X32: {        uint64_t t = (*(const uint64_t *) &a[0] & mask) >> 6;        t         += (*(const uint64_t *) &a[8] & mask) >> 6;        t         += (*(const uint64_t *) &l[0] & mask) >> 6;        t *= mul;        s = (int) (t >> 56) - 16 - 8;        break;    }    case RTX_4X16: {        uint32_t t = *(const uint8_t  *) a & (uint32_t) mask;        t         += *(const uint32_t *) l & (uint32_t) mask;        t = (t >> 6) * (uint32_t) mul;        s = (int) (t >> 24) - 1 - 4;        break;    }    case RTX_16X4: {        uint32_t t = *(const uint32_t *) a & (uint32_t) mask;        t         += *(const uint8_t  *) l & (uint32_t) mask;        t = (t >> 6) * (uint32_t) mul;        s = (int) (t >> 24) - 4 - 1;        break;    }    case RTX_8X32: {        uint64_t t = *(const uint16_t *) a & (uint32_t) mask;        t         += *(const uint64_t *) l & mask;        t = (t >> 6) * mul;        s = (int) (t >> 56) - 2 - 8;        break;    }    case RTX_32X8: {        uint64_t t = *(const uint64_t *) a & mask;        t         += *(const uint16_t *) l & (uint32_t) mask;        t = (t >> 6) * mul;        s = (int) (t >> 56) - 8 - 2;        break;    }    case RTX_16X64: {        uint64_t t = *(const uint32_t *) a & (uint32_t) mask;        t         += *(const uint64_t *) &l[0] & mask;        t = (t >> 6) + ((*(const uint64_t *) &l[8] & mask) >> 6);        t *= mul;        s = (int) (t >> 56) - 4 - 16;        break;    }    case RTX_64X16: {        uint64_t t = *(const uint64_t *) &a[0] & mask;        t         += *(const uint32_t *) l & (uint32_t) mask;        t = (t >> 6) + ((*(const uint64_t *) &a[8] & mask) >> 6);        t *= mul;        s = (int) (t >> 56) - 16 - 4;        break;    }    }     return (s != 0) + (s > 0);} static inline unsigned get_lo_ctx(const uint8_t *const levels,                                  const enum TxClass tx_class,                                  unsigned *const hi_mag,                                  const uint8_t (*const ctx_offsets)[5],                                  const unsigned x, const unsigned y,                                  const ptrdiff_t stride){    unsigned mag = levels[0 * stride + 1] + levels[1 * stride + 0];    unsigned offset;    if (tx_class == TX_CLASS_2D) {        mag += levels[1 * stride + 1];        *hi_mag = mag;        mag += levels[0 * stride + 2] + levels[2 * stride + 0];        offset = ctx_offsets[umin(y, 4)][umin(x, 4)];    } else {        mag += levels[0 * stride + 2];        *hi_mag = mag;        mag += levels[0 * stride + 3] + levels[0 * stride + 4];        offset = 26 + (y > 1 ? 10 : y * 5);    }    return offset + (mag > 512 ? 4 : (mag + 64) >> 7);} static int decode_coefs(Dav1dTileContext *const t,                        uint8_t *const a, uint8_t *const l,                        const enum RectTxfmSize tx, const enum BlockSize bs,                        const Av1Block *const b, const int intra,                        const int plane, coef *cf,                        enum TxfmType *const txtp, uint8_t *res_ctx){    Dav1dTileState *const ts = t->ts;    const int chroma = !!plane;    const Dav1dFrameContext *const f = t->f;    const int lossless = f->frame_hdr->segmentation.lossless[b->seg_id];    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[tx];    const int dbg = DEBUG_BLOCK_INFO && plane && 0;     if (dbg)        printf("Start: r=%d\n", ts->msac.rng);     // does this block have any non-zero coefficients    const int sctx = get_skip_ctx(t_dim, bs, a, l, chroma, f->cur.p.layout);    const int all_skip = dav1d_msac_decode_bool_adapt(&ts->msac,                             ts->cdf.coef.skip[t_dim->ctx][sctx]);    if (dbg)        printf("Post-non-zero[%d][%d][%d]: r=%d\n",               t_dim->ctx, sctx, all_skip, ts->msac.rng);    if (all_skip) {        *res_ctx = 0x40;        *txtp = lossless * WHT_WHT; /* lossless ? WHT_WHT : DCT_DCT */        return -1;    }     // transform type (chroma: derived, luma: explicitly coded)    if (lossless) {        assert(t_dim->max == TX_4X4);        *txtp = WHT_WHT;    } else if (t_dim->max + intra >= TX_64X64) {        *txtp = DCT_DCT;    } else if (chroma) {        // inferred from either the luma txtp (inter) or a LUT (intra)        *txtp = intra ? dav1d_txtp_from_uvmode[b->uv_mode] :                        get_uv_inter_txtp(t_dim, *txtp);    } else if (!f->frame_hdr->segmentation.qidx[b->seg_id]) {        // In libaom, lossless is checked by a literal qidx == 0, but not all        // such blocks are actually lossless. The remainder gets an implicit        // transform type (for luma)        *txtp = DCT_DCT;    } else {        unsigned idx;        if (intra) {            const enum IntraPredMode y_mode_nofilt = b->y_mode == FILTER_PRED ?                dav1d_filter_mode_to_y_mode[b->y_angle] : b->y_mode;            if (f->frame_hdr->reduced_txtp_set || t_dim->min == TX_16X16) {                idx = dav1d_msac_decode_symbol_adapt4(&ts->msac,                          ts->cdf.m.txtp_intra2[t_dim->min][y_mode_nofilt], 4);                *txtp = dav1d_tx_types_per_set[idx + 0];            } else {                idx = dav1d_msac_decode_symbol_adapt8(&ts->msac,                          ts->cdf.m.txtp_intra1[t_dim->min][y_mode_nofilt], 6);                *txtp = dav1d_tx_types_per_set[idx + 5];            }            if (dbg)                printf("Post-txtp-intra[%d->%d][%d][%d->%d]: r=%d\n",                       tx, t_dim->min, y_mode_nofilt, idx, *txtp, ts->msac.rng);        } else {            if (f->frame_hdr->reduced_txtp_set || t_dim->max == TX_32X32) {                idx = dav1d_msac_decode_bool_adapt(&ts->msac,                          ts->cdf.m.txtp_inter3[t_dim->min]);                *txtp = (idx - 1) & IDTX; /* idx ? DCT_DCT : IDTX */            } else if (t_dim->min == TX_16X16) {                idx = dav1d_msac_decode_symbol_adapt16(&ts->msac,                          ts->cdf.m.txtp_inter2, 11);                *txtp = dav1d_tx_types_per_set[idx + 12];            } else {                idx = dav1d_msac_decode_symbol_adapt16(&ts->msac,                          ts->cdf.m.txtp_inter1[t_dim->min], 15);                *txtp = dav1d_tx_types_per_set[idx + 24];            }            if (dbg)                printf("Post-txtp-inter[%d->%d][%d->%d]: r=%d\n",                       tx, t_dim->min, idx, *txtp, ts->msac.rng);        }    }     // find end-of-block (eob)    int eob_bin;    const int tx2dszctx = imin(t_dim->lw, TX_32X32) + imin(t_dim->lh, TX_32X32);    const enum TxClass tx_class = dav1d_tx_type_class[*txtp];    const int is_1d = tx_class != TX_CLASS_2D;    switch (tx2dszctx) {#define case_sz(sz, bin, ns, is_1d) \    case sz: { \        uint16_t *const eob_bin_cdf = ts->cdf.coef.eob_bin_##bin[chroma]is_1d; \        eob_bin = dav1d_msac_decode_symbol_adapt##ns(&ts->msac, eob_bin_cdf, 4 + sz); \        break; \    }    case_sz(0,   16,  4, [is_1d]);    case_sz(1,   32,  8, [is_1d]);    case_sz(2,   64,  8, [is_1d]);    case_sz(3,  128,  8, [is_1d]);    case_sz(4,  256, 16, [is_1d]);    case_sz(5,  512, 16,        );    case_sz(6, 1024, 16,        );#undef case_sz    }    if (dbg)        printf("Post-eob_bin_%d[%d][%d][%d]: r=%d\n",               16 << tx2dszctx, chroma, is_1d, eob_bin, ts->msac.rng);    int eob;    if (eob_bin > 1) {        uint16_t *const eob_hi_bit_cdf =            ts->cdf.coef.eob_hi_bit[t_dim->ctx][chroma][eob_bin];        const int eob_hi_bit = dav1d_msac_decode_bool_adapt(&ts->msac, eob_hi_bit_cdf);        if (dbg)            printf("Post-eob_hi_bit[%d][%d][%d][%d]: r=%d\n",                   t_dim->ctx, chroma, eob_bin, eob_hi_bit, ts->msac.rng);        eob = ((eob_hi_bit | 2) << (eob_bin - 2)) |              dav1d_msac_decode_bools(&ts->msac, eob_bin - 2);        if (dbg)            printf("Post-eob[%d]: r=%d\n", eob, ts->msac.rng);    } else {        eob = eob_bin;    }     // base tokens    uint16_t (*const eob_cdf)[4] = ts->cdf.coef.eob_base_tok[t_dim->ctx][chroma];    uint16_t (*const hi_cdf)[4] = ts->cdf.coef.br_tok[imin(t_dim->ctx, 3)][chroma];    const uint16_t *const scan = dav1d_scans[tx][tx_class];    int dc_tok;     if (eob) {        uint16_t (*const lo_cdf)[4] = ts->cdf.coef.base_tok[t_dim->ctx][chroma];        uint8_t *const levels = t->scratch.levels; // bits 0-5: tok, 6-7: lo_tok        const int sw = imin(t_dim->w, 8), sh = imin(t_dim->h, 8);        const unsigned shift = 2 + imin(t_dim->lh, 3), mask = 4 * sh - 1;         /* eob */        unsigned rc = scan[eob], x = rc >> shift, y = rc & mask;        unsigned ctx = 1 + (eob > sw * sh * 2) + (eob > sw * sh * 4);        int eob_tok = dav1d_msac_decode_symbol_adapt4(&ts->msac, eob_cdf[ctx], 2);        int tok = eob_tok + 1;        int level_tok = tok * 0x41;        unsigned mag;        if (dbg)            printf("Post-lo_tok[%d][%d][%d][%d=%d=%d]: r=%d\n",                   t_dim->ctx, chroma, ctx, eob, rc, tok, ts->msac.rng); #define DECODE_COEFS_CLASS(tx_class) \        if (eob_tok == 2) { \            ctx = (tx_class == TX_CLASS_2D ? (x | y) > 1 : \                   tx_class == TX_CLASS_H ? x != 0 : y != 0) ? 14 : 7; \            tok = dav1d_msac_decode_hi_tok(&ts->msac, hi_cdf[ctx]); \            level_tok = tok + (3 << 6); \            if (dbg) \                printf("Post-hi_tok[%d][%d][%d][%d=%d=%d]: r=%d\n", \                       imin(t_dim->ctx, 3), chroma, ctx, eob, rc, tok, \                       ts->msac.rng); \        } \        cf[rc] = tok; \        if (tx_class == TX_CLASS_H) \            /* Transposing reduces the stride and padding requirements */ \            levels[y * stride + x] = (uint8_t) level_tok; \        else \            levels[x * stride + y] = (uint8_t) level_tok; \        for (int i = eob - 1; i > 0; i--) { /* ac */ \            if (tx_class == TX_CLASS_H) \                rc = i, x = rc & mask, y = rc >> shift; \            else \                rc = scan[i], x = rc >> shift, y = rc & mask; \            assert(x < 32 && y < 32); \            uint8_t *const level = levels + x * stride + y; \            ctx = get_lo_ctx(level, tx_class, &mag, lo_ctx_offsets, x, y, stride); \            if (tx_class == TX_CLASS_2D) \                y |= x; \            tok = dav1d_msac_decode_symbol_adapt4(&ts->msac, lo_cdf[ctx], 3); \            level_tok = tok * 0x41; \            if (dbg) \                printf("Post-lo_tok[%d][%d][%d][%d=%d=%d]: r=%d\n", \                       t_dim->ctx, chroma, ctx, i, rc, tok, ts->msac.rng); \            if (tok == 3) { \                mag &= 63; \

Lines 1–500 of 2064.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t