3641 lines · 153.5 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 <errno.h>#include <limits.h>#include <string.h>#ifndef __plan9__#include <stdio.h>#endif#include <inttypes.h> #include "dav1d/data.h" #include "common/intops.h" #include "src/ctx.h"#include "src/decode.h"#include "src/dequant_tables.h"#include "src/env.h"#include "src/film_grain.h"#include "src/log.h"#include "src/qm.h"#include "src/recon.h"#include "src/ref.h"#include "src/tables.h"#include "src/thread_task.h"#include "src/warpmv.h" static void init_quant_tables(const Dav1dSequenceHeader *const seq_hdr,                              const Dav1dFrameHeader *const frame_hdr,                              const int qidx, uint16_t (*dq)[3][2]){    for (int i = 0; i < (frame_hdr->segmentation.enabled ? 8 : 1); i++) {        const int yac = frame_hdr->segmentation.enabled ?            iclip_u8(qidx + frame_hdr->segmentation.seg_data.d[i].delta_q) : qidx;        const int ydc = iclip_u8(yac + frame_hdr->quant.ydc_delta);        const int uac = iclip_u8(yac + frame_hdr->quant.uac_delta);        const int udc = iclip_u8(yac + frame_hdr->quant.udc_delta);        const int vac = iclip_u8(yac + frame_hdr->quant.vac_delta);        const int vdc = iclip_u8(yac + frame_hdr->quant.vdc_delta);         dq[i][0][0] = dav1d_dq_tbl[seq_hdr->hbd][ydc][0];        dq[i][0][1] = dav1d_dq_tbl[seq_hdr->hbd][yac][1];        dq[i][1][0] = dav1d_dq_tbl[seq_hdr->hbd][udc][0];        dq[i][1][1] = dav1d_dq_tbl[seq_hdr->hbd][uac][1];        dq[i][2][0] = dav1d_dq_tbl[seq_hdr->hbd][vdc][0];        dq[i][2][1] = dav1d_dq_tbl[seq_hdr->hbd][vac][1];    }} static int read_mv_component_diff(Dav1dTileContext *const t,                                  CdfMvComponent *const mv_comp,                                  const int have_fp){    Dav1dTileState *const ts = t->ts;    const Dav1dFrameContext *const f = t->f;    const int have_hp = f->frame_hdr->hp;    const int sign = dav1d_msac_decode_bool_adapt(&ts->msac, mv_comp->sign);    const int cl = dav1d_msac_decode_symbol_adapt16(&ts->msac,                                                    mv_comp->classes, 10);    int up, fp, hp;     if (!cl) {        up = dav1d_msac_decode_bool_adapt(&ts->msac, mv_comp->class0);        if (have_fp) {            fp = dav1d_msac_decode_symbol_adapt4(&ts->msac,                                                 mv_comp->class0_fp[up], 3);            hp = have_hp ? dav1d_msac_decode_bool_adapt(&ts->msac,                                                        mv_comp->class0_hp) : 1;        } else {            fp = 3;            hp = 1;        }    } else {        up = 1 << cl;        for (int n = 0; n < cl; n++)            up |= dav1d_msac_decode_bool_adapt(&ts->msac,                                               mv_comp->classN[n]) << n;        if (have_fp) {            fp = dav1d_msac_decode_symbol_adapt4(&ts->msac,                                                 mv_comp->classN_fp, 3);            hp = have_hp ? dav1d_msac_decode_bool_adapt(&ts->msac,                                                        mv_comp->classN_hp) : 1;        } else {            fp = 3;            hp = 1;        }    }     const int diff = ((up << 3) | (fp << 1) | hp) + 1;     return sign ? -diff : diff;} static void read_mv_residual(Dav1dTileContext *const t, mv *const ref_mv,                             CdfMvContext *const mv_cdf, const int have_fp){    switch (dav1d_msac_decode_symbol_adapt4(&t->ts->msac, t->ts->cdf.mv.joint,                                            N_MV_JOINTS - 1))    {    case MV_JOINT_HV:        ref_mv->y += read_mv_component_diff(t, &mv_cdf->comp[0], have_fp);        ref_mv->x += read_mv_component_diff(t, &mv_cdf->comp[1], have_fp);        break;    case MV_JOINT_H:        ref_mv->x += read_mv_component_diff(t, &mv_cdf->comp[1], have_fp);        break;    case MV_JOINT_V:        ref_mv->y += read_mv_component_diff(t, &mv_cdf->comp[0], have_fp);        break;    default:        break;    }} static void read_tx_tree(Dav1dTileContext *const t,                         const enum RectTxfmSize from,                         const int depth, uint16_t *const masks,                         const int x_off, const int y_off){    const Dav1dFrameContext *const f = t->f;    const int bx4 = t->bx & 31, by4 = t->by & 31;    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];    const int txw = t_dim->lw, txh = t_dim->lh;    int is_split;     if (depth < 2 && from > (int) TX_4X4) {        const int cat = 2 * (TX_64X64 - t_dim->max) - depth;        const int a = t->a->tx[bx4] < txw;        const int l = t->l.tx[by4] < txh;         is_split = dav1d_msac_decode_bool_adapt(&t->ts->msac,                       t->ts->cdf.m.txpart[cat][a + l]);        if (is_split)            masks[depth] |= 1 << (y_off * 4 + x_off);    } else {        is_split = 0;    }     if (is_split && t_dim->max > TX_8X8) {        const enum RectTxfmSize sub = t_dim->sub;        const TxfmInfo *const sub_t_dim = &dav1d_txfm_dimensions[sub];        const int txsw = sub_t_dim->w, txsh = sub_t_dim->h;         read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 0);        t->bx += txsw;        if (txw >= txh && t->bx < f->bw)            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 1, y_off * 2 + 0);        t->bx -= txsw;        t->by += txsh;        if (txh >= txw && t->by < f->bh) {            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 1);            t->bx += txsw;            if (txw >= txh && t->bx < f->bw)                read_tx_tree(t, sub, depth + 1, masks,                             x_off * 2 + 1, y_off * 2 + 1);            t->bx -= txsw;        }        t->by -= txsh;    } else {#define set_ctx(type, dir, diridx, off, mul, rep_macro) \        rep_macro(type, t->dir tx, off, is_split ? TX_4X4 : mul * txh)        case_set_upto16(t_dim->h, l., 1, by4);#undef set_ctx#define set_ctx(type, dir, diridx, off, mul, rep_macro) \        rep_macro(type, t->dir tx, off, is_split ? TX_4X4 : mul * txw)        case_set_upto16(t_dim->w, a->, 0, bx4);#undef set_ctx    }} static int neg_deinterleave(int diff, int ref, int max) {    if (!ref) return diff;    if (ref >= (max - 1)) return max - diff - 1;    if (2 * ref < max) {        if (diff <= 2 * ref) {            if (diff & 1)                return ref + ((diff + 1) >> 1);            else                return ref - (diff >> 1);        }        return diff;    } else {        if (diff <= 2 * (max - ref - 1)) {            if (diff & 1)                return ref + ((diff + 1) >> 1);            else                return ref - (diff >> 1);        }        return max - (diff + 1);    }} static void find_matching_ref(const Dav1dTileContext *const t,                              const enum EdgeFlags intra_edge_flags,                              const int bw4, const int bh4,                              const int w4, const int h4,                              const int have_left, const int have_top,                              const int ref, uint64_t masks[2]){    /*const*/ refmvs_block *const *r = &t->rt.r[(t->by & 31) + 5];    int count = 0;    int have_topleft = have_top && have_left;    int have_topright = imax(bw4, bh4) < 32 &&                        have_top && t->bx + bw4 < t->ts->tiling.col_end &&                        (intra_edge_flags & EDGE_I444_TOP_HAS_RIGHT); #define bs(rp) dav1d_block_dimensions[(rp)->bs]#define matches(rp) ((rp)->ref.ref[0] == ref + 1 && (rp)->ref.ref[1] == -1)     if (have_top) {        const refmvs_block *r2 = &r[-1][t->bx];        if (matches(r2)) {            masks[0] |= 1;            count = 1;        }        int aw4 = bs(r2)[0];        if (aw4 >= bw4) {            const int off = t->bx & (aw4 - 1);            if (off) have_topleft = 0;            if (aw4 - off > bw4) have_topright = 0;        } else {            unsigned mask = 1 << aw4;            for (int x = aw4; x < w4; x += aw4) {                r2 += aw4;                if (matches(r2)) {                    masks[0] |= mask;                    if (++count >= 8) return;                }                aw4 = bs(r2)[0];                mask <<= aw4;            }        }    }    if (have_left) {        /*const*/ refmvs_block *const *r2 = r;        if (matches(&r2[0][t->bx - 1])) {            masks[1] |= 1;            if (++count >= 8) return;        }        int lh4 = bs(&r2[0][t->bx - 1])[1];        if (lh4 >= bh4) {            if (t->by & (lh4 - 1)) have_topleft = 0;        } else {            unsigned mask = 1 << lh4;            for (int y = lh4; y < h4; y += lh4) {                r2 += lh4;                if (matches(&r2[0][t->bx - 1])) {                    masks[1] |= mask;                    if (++count >= 8) return;                }                lh4 = bs(&r2[0][t->bx - 1])[1];                mask <<= lh4;            }        }    }    if (have_topleft && matches(&r[-1][t->bx - 1])) {        masks[1] |= 1ULL << 32;        if (++count >= 8) return;    }    if (have_topright && matches(&r[-1][t->bx + bw4])) {        masks[0] |= 1ULL << 32;    }#undef matches} static void derive_warpmv(const Dav1dTileContext *const t,                          const int bw4, const int bh4,                          const uint64_t masks[2], const union mv mv,                          Dav1dWarpedMotionParams *const wmp){    int pts[8][2 /* in, out */][2 /* x, y */], np = 0;    /*const*/ refmvs_block *const *r = &t->rt.r[(t->by & 31) + 5]; #define add_sample(dx, dy, sx, sy, rp) do { \    pts[np][0][0] = 16 * (2 * dx + sx * bs(rp)[0]) - 8; \    pts[np][0][1] = 16 * (2 * dy + sy * bs(rp)[1]) - 8; \    pts[np][1][0] = pts[np][0][0] + (rp)->mv.mv[0].x; \    pts[np][1][1] = pts[np][0][1] + (rp)->mv.mv[0].y; \    np++; \} while (0)     // use masks[] to find the projectable motion vectors in the edges    if ((unsigned) masks[0] == 1 && !(masks[1] >> 32)) {        const int off = t->bx & (bs(&r[-1][t->bx])[0] - 1);        add_sample(-off, 0, 1, -1, &r[-1][t->bx]);    } else for (unsigned off = 0, xmask = (uint32_t) masks[0]; np < 8 && xmask;) { // top        const int tz = ctz(xmask);        off += tz;        xmask >>= tz;        add_sample(off, 0, 1, -1, &r[-1][t->bx + off]);        xmask &= ~1;    }    if (np < 8 && masks[1] == 1) {        const int off = t->by & (bs(&r[0][t->bx - 1])[1] - 1);        add_sample(0, -off, -1, 1, &r[-off][t->bx - 1]);    } else for (unsigned off = 0, ymask = (uint32_t) masks[1]; np < 8 && ymask;) { // left        const int tz = ctz(ymask);        off += tz;        ymask >>= tz;        add_sample(0, off, -1, 1, &r[off][t->bx - 1]);        ymask &= ~1;    }    if (np < 8 && masks[1] >> 32) // top/left        add_sample(0, 0, -1, -1, &r[-1][t->bx - 1]);    if (np < 8 && masks[0] >> 32) // top/right        add_sample(bw4, 0, 1, -1, &r[-1][t->bx + bw4]);    assert(np > 0 && np <= 8);#undef bs     // select according to motion vector difference against a threshold    int mvd[8], ret = 0;    const int thresh = 4 * iclip(imax(bw4, bh4), 4, 28);    for (int i = 0; i < np; i++) {        mvd[i] = abs(pts[i][1][0] - pts[i][0][0] - mv.x) +                 abs(pts[i][1][1] - pts[i][0][1] - mv.y);        if (mvd[i] > thresh)            mvd[i] = -1;        else            ret++;    }    if (!ret) {        ret = 1;    } else for (int i = 0, j = np - 1, k = 0; k < np - ret; k++, i++, j--) {        while (mvd[i] != -1) i++;        while (mvd[j] == -1) j--;        assert(i != j);        if (i > j) break;        // replace the discarded samples;        mvd[i] = mvd[j];        memcpy(pts[i], pts[j], sizeof(*pts));    }     if (!dav1d_find_affine_int(pts, ret, bw4, bh4, mv, wmp, t->bx, t->by) &&        !dav1d_get_shear_params(wmp))    {        wmp->type = DAV1D_WM_TYPE_AFFINE;    } else        wmp->type = DAV1D_WM_TYPE_IDENTITY;} static inline int findoddzero(const uint8_t *buf, int len) {    for (int n = 0; n < len; n++)        if (!buf[n * 2]) return 1;    return 0;} static void read_pal_plane(Dav1dTileContext *const t, Av1Block *const b,                           const int pl, const int sz_ctx,                           const int bx4, const int by4){    Dav1dTileState *const ts = t->ts;    const Dav1dFrameContext *const f = t->f;    const int pal_sz = b->pal_sz[pl] = dav1d_msac_decode_symbol_adapt8(&ts->msac,                                           ts->cdf.m.pal_sz[pl][sz_ctx], 6) + 2;    uint16_t cache[16], used_cache[8];    int l_cache = pl ? t->pal_sz_uv[1][by4] : t->l.pal_sz[by4];    int n_cache = 0;    // don't reuse above palette outside SB64 boundaries    int a_cache = by4 & 15 ? pl ? t->pal_sz_uv[0][bx4] : t->a->pal_sz[bx4] : 0;    const uint16_t *l = t->al_pal[1][by4][pl], *a = t->al_pal[0][bx4][pl];     // fill/sort cache    while (l_cache && a_cache) {        if (*l < *a) {            if (!n_cache || cache[n_cache - 1] != *l)                cache[n_cache++] = *l;            l++;            l_cache--;        } else {            if (*a == *l) {                l++;                l_cache--;            }            if (!n_cache || cache[n_cache - 1] != *a)                cache[n_cache++] = *a;            a++;            a_cache--;        }    }    if (l_cache) {        do {            if (!n_cache || cache[n_cache - 1] != *l)                cache[n_cache++] = *l;            l++;        } while (--l_cache > 0);    } else if (a_cache) {        do {            if (!n_cache || cache[n_cache - 1] != *a)                cache[n_cache++] = *a;            a++;        } while (--a_cache > 0);    }     // find reused cache entries    int i = 0;    for (int n = 0; n < n_cache && i < pal_sz; n++)        if (dav1d_msac_decode_bool_equi(&ts->msac))            used_cache[i++] = cache[n];    const int n_used_cache = i;     // parse new entries    uint16_t *const pal = f->frame_thread.pass ?        f->frame_thread.pal[((t->by >> 1) + (t->bx & 1)) * (f->b4_stride >> 1) +                            ((t->bx >> 1) + (t->by & 1))][pl] : t->scratch.pal[pl];    if (i < pal_sz) {        int prev = pal[i++] = dav1d_msac_decode_bools(&ts->msac, f->cur.p.bpc);         if (i < pal_sz) {            int bits = f->cur.p.bpc - 3 + dav1d_msac_decode_bools(&ts->msac, 2);            const int max = (1 << f->cur.p.bpc) - 1;             do {                const int delta = dav1d_msac_decode_bools(&ts->msac, bits);                prev = pal[i++] = imin(prev + delta + !pl, max);                if (prev + !pl >= max) {                    for (; i < pal_sz; i++)                        pal[i] = max;                    break;                }                bits = imin(bits, 1 + ulog2(max - prev - !pl));            } while (i < pal_sz);        }         // merge cache+new entries        int n = 0, m = n_used_cache;        for (i = 0; i < pal_sz; i++) {            if (n < n_used_cache && (m >= pal_sz || used_cache[n] <= pal[m])) {                pal[i] = used_cache[n++];            } else {                assert(m < pal_sz);                pal[i] = pal[m++];            }        }    } else {        memcpy(pal, used_cache, n_used_cache * sizeof(*used_cache));    }     if (DEBUG_BLOCK_INFO) {        printf("Post-pal[pl=%d,sz=%d,cache_size=%d,used_cache=%d]: r=%d, cache=",               pl, pal_sz, n_cache, n_used_cache, ts->msac.rng);        for (int n = 0; n < n_cache; n++)            printf("%c%02x", n ? ' ' : '[', cache[n]);        printf("%s, pal=", n_cache ? "]" : "[]");        for (int n = 0; n < pal_sz; n++)            printf("%c%02x", n ? ' ' : '[', pal[n]);        printf("]\n");    }} static void read_pal_uv(Dav1dTileContext *const t, Av1Block *const b,                        const int sz_ctx, const int bx4, const int by4){    read_pal_plane(t, b, 1, sz_ctx, bx4, by4);     // V pal coding    Dav1dTileState *const ts = t->ts;    const Dav1dFrameContext *const f = t->f;    uint16_t *const pal = f->frame_thread.pass ?        f->frame_thread.pal[((t->by >> 1) + (t->bx & 1)) * (f->b4_stride >> 1) +                            ((t->bx >> 1) + (t->by & 1))][2] : t->scratch.pal[2];    if (dav1d_msac_decode_bool_equi(&ts->msac)) {        const int bits = f->cur.p.bpc - 4 +                         dav1d_msac_decode_bools(&ts->msac, 2);        int prev = pal[0] = dav1d_msac_decode_bools(&ts->msac, f->cur.p.bpc);        const int max = (1 << f->cur.p.bpc) - 1;        for (int i = 1; i < b->pal_sz[1]; i++) {            int delta = dav1d_msac_decode_bools(&ts->msac, bits);            if (delta && dav1d_msac_decode_bool_equi(&ts->msac)) delta = -delta;            prev = pal[i] = (prev + delta) & max;        }    } else {        for (int i = 0; i < b->pal_sz[1]; i++)            pal[i] = dav1d_msac_decode_bools(&ts->msac, f->cur.p.bpc);

Lines 1–500 of 3641.

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