tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lf_mask.c (18626B)


      1 /*
      2 * Copyright © 2018, VideoLAN and dav1d authors
      3 * Copyright © 2018, Two Orioles, LLC
      4 * All rights reserved.
      5 *
      6 * Redistribution and use in source and binary forms, with or without
      7 * modification, are permitted provided that the following conditions are met:
      8 *
      9 * 1. Redistributions of source code must retain the above copyright notice, this
     10 *    list of conditions and the following disclaimer.
     11 *
     12 * 2. Redistributions in binary form must reproduce the above copyright notice,
     13 *    this list of conditions and the following disclaimer in the documentation
     14 *    and/or other materials provided with the distribution.
     15 *
     16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27 
     28 #include "config.h"
     29 
     30 #include <string.h>
     31 
     32 #include "common/intops.h"
     33 
     34 #include "src/ctx.h"
     35 #include "src/levels.h"
     36 #include "src/lf_mask.h"
     37 #include "src/tables.h"
     38 
     39 static void decomp_tx(uint8_t (*const txa)[2 /* txsz, step */][32 /* y */][32 /* x */],
     40                      const enum RectTxfmSize from,
     41                      const int depth,
     42                      const int y_off, const int x_off,
     43                      const uint16_t *const tx_masks)
     44 {
     45    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];
     46    const int is_split = (from == (int) TX_4X4 || depth > 1) ? 0 :
     47        (tx_masks[depth] >> (y_off * 4 + x_off)) & 1;
     48 
     49    if (is_split) {
     50        const enum RectTxfmSize sub = t_dim->sub;
     51        const int htw4 = t_dim->w >> 1, hth4 = t_dim->h >> 1;
     52 
     53        decomp_tx(txa, sub, depth + 1, y_off * 2 + 0, x_off * 2 + 0, tx_masks);
     54        if (t_dim->w >= t_dim->h)
     55            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][0][htw4],
     56                      sub, depth + 1, y_off * 2 + 0, x_off * 2 + 1, tx_masks);
     57        if (t_dim->h >= t_dim->w) {
     58            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][hth4][0],
     59                      sub, depth + 1, y_off * 2 + 1, x_off * 2 + 0, tx_masks);
     60            if (t_dim->w >= t_dim->h)
     61                decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][hth4][htw4],
     62                          sub, depth + 1, y_off * 2 + 1, x_off * 2 + 1, tx_masks);
     63        }
     64    } else {
     65        const int lw = imin(2, t_dim->lw), lh = imin(2, t_dim->lh);
     66 
     67 #define set_ctx(rep_macro) \
     68        for (int y = 0; y < t_dim->h; y++) { \
     69            rep_macro(txa[0][0][y], 0, lw); \
     70            rep_macro(txa[1][0][y], 0, lh); \
     71            txa[0][1][y][0] = t_dim->w; \
     72        }
     73        case_set_upto16(t_dim->lw);
     74 #undef set_ctx
     75        dav1d_memset_pow2[t_dim->lw](txa[1][1][0], t_dim->h);
     76    }
     77 }
     78 
     79 static inline void mask_edges_inter(uint16_t (*const masks)[32][3][2],
     80                                    const int by4, const int bx4,
     81                                    const int w4, const int h4, const int skip,
     82                                    const enum RectTxfmSize max_tx,
     83                                    const uint16_t *const tx_masks,
     84                                    uint8_t *const a, uint8_t *const l)
     85 {
     86    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[max_tx];
     87    int y, x;
     88 
     89    ALIGN_STK_16(uint8_t, txa, 2 /* edge */, [2 /* txsz, step */][32 /* y */][32 /* x */]);
     90    for (int y_off = 0, y = 0; y < h4; y += t_dim->h, y_off++)
     91        for (int x_off = 0, x = 0; x < w4; x += t_dim->w, x_off++)
     92            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][y][x],
     93                      max_tx, 0, y_off, x_off, tx_masks);
     94 
     95    // left block edge
     96    unsigned mask = 1U << by4;
     97    for (y = 0; y < h4; y++, mask <<= 1) {
     98        const int sidx = mask >= 0x10000;
     99        const unsigned smask = mask >> (sidx << 4);
    100        masks[0][bx4][imin(txa[0][0][y][0], l[y])][sidx] |= smask;
    101    }
    102 
    103    // top block edge
    104    for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
    105        const int sidx = mask >= 0x10000;
    106        const unsigned smask = mask >> (sidx << 4);
    107        masks[1][by4][imin(txa[1][0][0][x], a[x])][sidx] |= smask;
    108    }
    109 
    110    if (!skip) {
    111        // inner (tx) left|right edges
    112        for (y = 0, mask = 1U << by4; y < h4; y++, mask <<= 1) {
    113            const int sidx = mask >= 0x10000U;
    114            const unsigned smask = mask >> (sidx << 4);
    115            int ltx = txa[0][0][y][0];
    116            int step = txa[0][1][y][0];
    117            for (x = step; x < w4; x += step) {
    118                const int rtx = txa[0][0][y][x];
    119                masks[0][bx4 + x][imin(rtx, ltx)][sidx] |= smask;
    120                ltx = rtx;
    121                step = txa[0][1][y][x];
    122            }
    123        }
    124 
    125        //            top
    126        // inner (tx) --- edges
    127        //           bottom
    128        for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
    129            const int sidx = mask >= 0x10000U;
    130            const unsigned smask = mask >> (sidx << 4);
    131            int ttx = txa[1][0][0][x];
    132            int step = txa[1][1][0][x];
    133            for (y = step; y < h4; y += step) {
    134                const int btx = txa[1][0][y][x];
    135                masks[1][by4 + y][imin(ttx, btx)][sidx] |= smask;
    136                ttx = btx;
    137                step = txa[1][1][y][x];
    138            }
    139        }
    140    }
    141 
    142    for (y = 0; y < h4; y++)
    143        l[y] = txa[0][0][y][w4 - 1];
    144    memcpy(a, txa[1][0][h4 - 1], w4);
    145 }
    146 
    147 static inline void mask_edges_intra(uint16_t (*const masks)[32][3][2],
    148                                    const int by4, const int bx4,
    149                                    const int w4, const int h4,
    150                                    const enum RectTxfmSize tx,
    151                                    uint8_t *const a, uint8_t *const l)
    152 {
    153    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[tx];
    154    const int twl4 = t_dim->lw, thl4 = t_dim->lh;
    155    const int twl4c = imin(2, twl4), thl4c = imin(2, thl4);
    156    int y, x;
    157 
    158    // left block edge
    159    unsigned mask = 1U << by4;
    160    for (y = 0; y < h4; y++, mask <<= 1) {
    161        const int sidx = mask >= 0x10000;
    162        const unsigned smask = mask >> (sidx << 4);
    163        masks[0][bx4][imin(twl4c, l[y])][sidx] |= smask;
    164    }
    165 
    166    // top block edge
    167    for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
    168        const int sidx = mask >= 0x10000;
    169        const unsigned smask = mask >> (sidx << 4);
    170        masks[1][by4][imin(thl4c, a[x])][sidx] |= smask;
    171    }
    172 
    173    // inner (tx) left|right edges
    174    const int hstep = t_dim->w;
    175    unsigned t = 1U << by4;
    176    unsigned inner = (unsigned) ((((uint64_t) t) << h4) - t);
    177    unsigned inner1 = inner & 0xffff, inner2 = inner >> 16;
    178    for (x = hstep; x < w4; x += hstep) {
    179        if (inner1) masks[0][bx4 + x][twl4c][0] |= inner1;
    180        if (inner2) masks[0][bx4 + x][twl4c][1] |= inner2;
    181    }
    182 
    183    //            top
    184    // inner (tx) --- edges
    185    //           bottom
    186    const int vstep = t_dim->h;
    187    t = 1U << bx4;
    188    inner = (unsigned) ((((uint64_t) t) << w4) - t);
    189    inner1 = inner & 0xffff;
    190    inner2 = inner >> 16;
    191    for (y = vstep; y < h4; y += vstep) {
    192        if (inner1) masks[1][by4 + y][thl4c][0] |= inner1;
    193        if (inner2) masks[1][by4 + y][thl4c][1] |= inner2;
    194    }
    195 
    196    dav1d_memset_likely_pow2(a, thl4c, w4);
    197    dav1d_memset_likely_pow2(l, twl4c, h4);
    198 }
    199 
    200 static void mask_edges_chroma(uint16_t (*const masks)[32][2][2],
    201                              const int cby4, const int cbx4,
    202                              const int cw4, const int ch4,
    203                              const int skip_inter,
    204                              const enum RectTxfmSize tx,
    205                              uint8_t *const a, uint8_t *const l,
    206                              const int ss_hor, const int ss_ver)
    207 {
    208    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[tx];
    209    const int twl4 = t_dim->lw, thl4 = t_dim->lh;
    210    const int twl4c = !!twl4, thl4c = !!thl4;
    211    int y, x;
    212    const int vbits = 4 - ss_ver, hbits = 4 - ss_hor;
    213    const int vmask = 16 >> ss_ver, hmask = 16 >> ss_hor;
    214    const unsigned vmax = 1 << vmask, hmax = 1 << hmask;
    215 
    216    // left block edge
    217    unsigned mask = 1U << cby4;
    218    for (y = 0; y < ch4; y++, mask <<= 1) {
    219        const int sidx = mask >= vmax;
    220        const unsigned smask = mask >> (sidx << vbits);
    221        masks[0][cbx4][imin(twl4c, l[y])][sidx] |= smask;
    222    }
    223 
    224    // top block edge
    225    for (x = 0, mask = 1U << cbx4; x < cw4; x++, mask <<= 1) {
    226        const int sidx = mask >= hmax;
    227        const unsigned smask = mask >> (sidx << hbits);
    228        masks[1][cby4][imin(thl4c, a[x])][sidx] |= smask;
    229    }
    230 
    231    if (!skip_inter) {
    232        // inner (tx) left|right edges
    233        const int hstep = t_dim->w;
    234        unsigned t = 1U << cby4;
    235        unsigned inner = (unsigned) ((((uint64_t) t) << ch4) - t);
    236        unsigned inner1 = inner & ((1 << vmask) - 1), inner2 = inner >> vmask;
    237        for (x = hstep; x < cw4; x += hstep) {
    238            if (inner1) masks[0][cbx4 + x][twl4c][0] |= inner1;
    239            if (inner2) masks[0][cbx4 + x][twl4c][1] |= inner2;
    240        }
    241 
    242        //            top
    243        // inner (tx) --- edges
    244        //           bottom
    245        const int vstep = t_dim->h;
    246        t = 1U << cbx4;
    247        inner = (unsigned) ((((uint64_t) t) << cw4) - t);
    248        inner1 = inner & ((1 << hmask) - 1), inner2 = inner >> hmask;
    249        for (y = vstep; y < ch4; y += vstep) {
    250            if (inner1) masks[1][cby4 + y][thl4c][0] |= inner1;
    251            if (inner2) masks[1][cby4 + y][thl4c][1] |= inner2;
    252        }
    253    }
    254 
    255    dav1d_memset_likely_pow2(a, thl4c, cw4);
    256    dav1d_memset_likely_pow2(l, twl4c, ch4);
    257 }
    258 
    259 void dav1d_create_lf_mask_intra(Av1Filter *const lflvl,
    260                                uint8_t (*const level_cache)[4],
    261                                const ptrdiff_t b4_stride,
    262                                const uint8_t (*filter_level)[8][2],
    263                                const int bx, const int by,
    264                                const int iw, const int ih,
    265                                const enum BlockSize bs,
    266                                const enum RectTxfmSize ytx,
    267                                const enum RectTxfmSize uvtx,
    268                                const enum Dav1dPixelLayout layout,
    269                                uint8_t *const ay, uint8_t *const ly,
    270                                uint8_t *const auv, uint8_t *const luv)
    271 {
    272    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
    273    const int bw4 = imin(iw - bx, b_dim[0]);
    274    const int bh4 = imin(ih - by, b_dim[1]);
    275    const int bx4 = bx & 31;
    276    const int by4 = by & 31;
    277    assert(bw4 >= 0 && bh4 >= 0);
    278 
    279    if (bw4 && bh4) {
    280        uint8_t (*level_cache_ptr)[4] = level_cache + by * b4_stride + bx;
    281        for (int y = 0; y < bh4; y++) {
    282            for (int x = 0; x < bw4; x++) {
    283                level_cache_ptr[x][0] = filter_level[0][0][0];
    284                level_cache_ptr[x][1] = filter_level[1][0][0];
    285            }
    286            level_cache_ptr += b4_stride;
    287        }
    288 
    289        mask_edges_intra(lflvl->filter_y, by4, bx4, bw4, bh4, ytx, ay, ly);
    290    }
    291 
    292    if (!auv) return;
    293 
    294    const int ss_ver = layout == DAV1D_PIXEL_LAYOUT_I420;
    295    const int ss_hor = layout != DAV1D_PIXEL_LAYOUT_I444;
    296    const int cbw4 = imin(((iw + ss_hor) >> ss_hor) - (bx >> ss_hor),
    297                          (b_dim[0] + ss_hor) >> ss_hor);
    298    const int cbh4 = imin(((ih + ss_ver) >> ss_ver) - (by >> ss_ver),
    299                          (b_dim[1] + ss_ver) >> ss_ver);
    300    assert(cbw4 >= 0 && cbh4 >= 0);
    301 
    302    if (!cbw4 || !cbh4) return;
    303 
    304    const int cbx4 = bx4 >> ss_hor;
    305    const int cby4 = by4 >> ss_ver;
    306 
    307    uint8_t (*level_cache_ptr)[4] =
    308        level_cache + (by >> ss_ver) * b4_stride + (bx >> ss_hor);
    309    for (int y = 0; y < cbh4; y++) {
    310        for (int x = 0; x < cbw4; x++) {
    311            level_cache_ptr[x][2] = filter_level[2][0][0];
    312            level_cache_ptr[x][3] = filter_level[3][0][0];
    313        }
    314        level_cache_ptr += b4_stride;
    315    }
    316 
    317    mask_edges_chroma(lflvl->filter_uv, cby4, cbx4, cbw4, cbh4, 0, uvtx,
    318                      auv, luv, ss_hor, ss_ver);
    319 }
    320 
    321 void dav1d_create_lf_mask_inter(Av1Filter *const lflvl,
    322                                uint8_t (*const level_cache)[4],
    323                                const ptrdiff_t b4_stride,
    324                                const uint8_t (*filter_level)[8][2],
    325                                const int bx, const int by,
    326                                const int iw, const int ih,
    327                                const int skip, const enum BlockSize bs,
    328                                const enum RectTxfmSize max_ytx,
    329                                const uint16_t *const tx_masks,
    330                                const enum RectTxfmSize uvtx,
    331                                const enum Dav1dPixelLayout layout,
    332                                uint8_t *const ay, uint8_t *const ly,
    333                                uint8_t *const auv, uint8_t *const luv)
    334 {
    335    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
    336    const int bw4 = imin(iw - bx, b_dim[0]);
    337    const int bh4 = imin(ih - by, b_dim[1]);
    338    const int bx4 = bx & 31;
    339    const int by4 = by & 31;
    340    assert(bw4 >= 0 && bh4 >= 0);
    341 
    342    if (bw4 && bh4) {
    343        uint8_t (*level_cache_ptr)[4] = level_cache + by * b4_stride + bx;
    344        for (int y = 0; y < bh4; y++) {
    345            for (int x = 0; x < bw4; x++) {
    346                level_cache_ptr[x][0] = filter_level[0][0][0];
    347                level_cache_ptr[x][1] = filter_level[1][0][0];
    348            }
    349            level_cache_ptr += b4_stride;
    350        }
    351 
    352        mask_edges_inter(lflvl->filter_y, by4, bx4, bw4, bh4, skip,
    353                         max_ytx, tx_masks, ay, ly);
    354    }
    355 
    356    if (!auv) return;
    357 
    358    const int ss_ver = layout == DAV1D_PIXEL_LAYOUT_I420;
    359    const int ss_hor = layout != DAV1D_PIXEL_LAYOUT_I444;
    360    const int cbw4 = imin(((iw + ss_hor) >> ss_hor) - (bx >> ss_hor),
    361                          (b_dim[0] + ss_hor) >> ss_hor);
    362    const int cbh4 = imin(((ih + ss_ver) >> ss_ver) - (by >> ss_ver),
    363                          (b_dim[1] + ss_ver) >> ss_ver);
    364    assert(cbw4 >= 0 && cbh4 >= 0);
    365 
    366    if (!cbw4 || !cbh4) return;
    367 
    368    const int cbx4 = bx4 >> ss_hor;
    369    const int cby4 = by4 >> ss_ver;
    370 
    371    uint8_t (*level_cache_ptr)[4] =
    372        level_cache + (by >> ss_ver) * b4_stride + (bx >> ss_hor);
    373    for (int y = 0; y < cbh4; y++) {
    374        for (int x = 0; x < cbw4; x++) {
    375            level_cache_ptr[x][2] = filter_level[2][0][0];
    376            level_cache_ptr[x][3] = filter_level[3][0][0];
    377        }
    378        level_cache_ptr += b4_stride;
    379    }
    380 
    381    mask_edges_chroma(lflvl->filter_uv, cby4, cbx4, cbw4, cbh4, skip, uvtx,
    382                      auv, luv, ss_hor, ss_ver);
    383 }
    384 
    385 void dav1d_calc_eih(Av1FilterLUT *const lim_lut, const int filter_sharpness) {
    386    // set E/I/H values from loopfilter level
    387    const int sharp = filter_sharpness;
    388    for (int level = 0; level < 64; level++) {
    389        int limit = level;
    390 
    391        if (sharp > 0) {
    392            limit >>= (sharp + 3) >> 2;
    393            limit = imin(limit, 9 - sharp);
    394        }
    395        limit = imax(limit, 1);
    396 
    397        lim_lut->i[level] = limit;
    398        lim_lut->e[level] = 2 * (level + 2) + limit;
    399    }
    400    lim_lut->sharp[0] = (sharp + 3) >> 2;
    401    lim_lut->sharp[1] = sharp ? 9 - sharp : 0xff;
    402 }
    403 
    404 static void calc_lf_value(uint8_t (*const lflvl_values)[2],
    405                          const int base_lvl, const int lf_delta,
    406                          const int seg_delta,
    407                          const Dav1dLoopfilterModeRefDeltas *const mr_delta)
    408 {
    409    const int base = iclip(iclip(base_lvl + lf_delta, 0, 63) + seg_delta, 0, 63);
    410 
    411    if (!mr_delta) {
    412        memset(lflvl_values, base, sizeof(*lflvl_values) * 8);
    413    } else {
    414        const int sh = base >= 32;
    415        lflvl_values[0][0] = lflvl_values[0][1] =
    416            iclip(base + (mr_delta->ref_delta[0] * (1 << sh)), 0, 63);
    417        for (int r = 1; r < 8; r++) {
    418            for (int m = 0; m < 2; m++) {
    419                const int delta =
    420                    mr_delta->mode_delta[m] + mr_delta->ref_delta[r];
    421                lflvl_values[r][m] = iclip(base + (delta * (1 << sh)), 0, 63);
    422            }
    423        }
    424    }
    425 }
    426 
    427 static inline void calc_lf_value_chroma(uint8_t (*const lflvl_values)[2],
    428                                        const int base_lvl, const int lf_delta,
    429                                        const int seg_delta,
    430                                        const Dav1dLoopfilterModeRefDeltas *const mr_delta)
    431 {
    432    if (!base_lvl)
    433        memset(lflvl_values, 0, sizeof(*lflvl_values) * 8);
    434    else
    435        calc_lf_value(lflvl_values, base_lvl, lf_delta, seg_delta, mr_delta);
    436 }
    437 
    438 void dav1d_calc_lf_values(uint8_t (*const lflvl_values)[4][8][2],
    439                          const Dav1dFrameHeader *const hdr,
    440                          const int8_t lf_delta[4])
    441 {
    442    const int n_seg = hdr->segmentation.enabled ? 8 : 1;
    443 
    444    if (!hdr->loopfilter.level_y[0] && !hdr->loopfilter.level_y[1]) {
    445        memset(lflvl_values, 0, sizeof(*lflvl_values) * n_seg);
    446        return;
    447    }
    448 
    449    const Dav1dLoopfilterModeRefDeltas *const mr_deltas =
    450        hdr->loopfilter.mode_ref_delta_enabled ?
    451        &hdr->loopfilter.mode_ref_deltas : NULL;
    452    for (int s = 0; s < n_seg; s++) {
    453        const Dav1dSegmentationData *const segd =
    454            hdr->segmentation.enabled ? &hdr->segmentation.seg_data.d[s] : NULL;
    455 
    456        calc_lf_value(lflvl_values[s][0], hdr->loopfilter.level_y[0],
    457                      lf_delta[0], segd ? segd->delta_lf_y_v : 0, mr_deltas);
    458        calc_lf_value(lflvl_values[s][1], hdr->loopfilter.level_y[1],
    459                      lf_delta[hdr->delta.lf.multi ? 1 : 0],
    460                      segd ? segd->delta_lf_y_h : 0, mr_deltas);
    461        calc_lf_value_chroma(lflvl_values[s][2], hdr->loopfilter.level_u,
    462                             lf_delta[hdr->delta.lf.multi ? 2 : 0],
    463                             segd ? segd->delta_lf_u : 0, mr_deltas);
    464        calc_lf_value_chroma(lflvl_values[s][3], hdr->loopfilter.level_v,
    465                             lf_delta[hdr->delta.lf.multi ? 3 : 0],
    466                             segd ? segd->delta_lf_v : 0, mr_deltas);
    467    }
    468 }