tor-browser

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

intra_edge.c (6025B)


      1 /*
      2 * Copyright © 2018-2023, VideoLAN and dav1d authors
      3 * Copyright © 2018-2023, 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 <stdlib.h>
     31 
     32 #include "common/attributes.h"
     33 
     34 #include "src/intra_edge.h"
     35 #include "src/levels.h"
     36 
     37 struct ModeSelMem {
     38    EdgeBranch *nwc[3 /* 64x64, 32x32, 16x16 */];
     39    EdgeTip *nt;
     40 };
     41 
     42 /* Because we're using 16-bit offsets to refer to other nodes those arrays
     43 * are placed in a struct to ensure they're consecutive in memory. */
     44 static struct {
     45    EdgeBranch branch_sb128[1 + 4 + 16 + 64];
     46    EdgeTip tip_sb128[256];
     47    EdgeBranch branch_sb64[1 + 4 + 16];
     48    EdgeTip tip_sb64[64];
     49 } ALIGN(nodes, 16);
     50 
     51 const EdgeNode *dav1d_intra_edge_tree[2] = {
     52    (EdgeNode*)nodes.branch_sb128, (EdgeNode*)nodes.branch_sb64
     53 };
     54 
     55 static COLD void init_edges(EdgeNode *const node,
     56                            const enum BlockLevel bl,
     57                            const enum EdgeFlags edge_flags)
     58 {
     59    node->o = edge_flags;
     60    node->h[0] = edge_flags | EDGE_ALL_LEFT_HAS_BOTTOM;
     61    node->v[0] = edge_flags | EDGE_ALL_TOP_HAS_RIGHT;
     62 
     63    if (bl == BL_8X8) {
     64        EdgeTip *const nt = (EdgeTip *) node;
     65 
     66        node->h[1] = edge_flags & (EDGE_ALL_LEFT_HAS_BOTTOM |
     67                                   EDGE_I420_TOP_HAS_RIGHT);
     68        node->v[1] = edge_flags & (EDGE_ALL_TOP_HAS_RIGHT |
     69                                   EDGE_I420_LEFT_HAS_BOTTOM |
     70                                   EDGE_I422_LEFT_HAS_BOTTOM);
     71 
     72        nt->split[0] = (edge_flags & EDGE_ALL_TOP_HAS_RIGHT) |
     73                       EDGE_I422_LEFT_HAS_BOTTOM;
     74        nt->split[1] = edge_flags | EDGE_I444_TOP_HAS_RIGHT;
     75        nt->split[2] = edge_flags & (EDGE_I420_TOP_HAS_RIGHT |
     76                                     EDGE_I420_LEFT_HAS_BOTTOM |
     77                                     EDGE_I422_LEFT_HAS_BOTTOM);
     78    } else {
     79        EdgeBranch *const nwc = (EdgeBranch *) node;
     80 
     81        node->h[1] = edge_flags & EDGE_ALL_LEFT_HAS_BOTTOM;
     82        node->v[1] = edge_flags & EDGE_ALL_TOP_HAS_RIGHT;
     83 
     84        nwc->h4 = EDGE_ALL_LEFT_HAS_BOTTOM;
     85        nwc->v4 = EDGE_ALL_TOP_HAS_RIGHT;
     86        if (bl == BL_16X16) {
     87            nwc->h4 |= edge_flags & EDGE_I420_TOP_HAS_RIGHT;
     88            nwc->v4 |= edge_flags & (EDGE_I420_LEFT_HAS_BOTTOM |
     89                                     EDGE_I422_LEFT_HAS_BOTTOM);
     90        }
     91    }
     92 }
     93 
     94 #define PTR_OFFSET(a, b) ((uint16_t)((uintptr_t)(b) - (uintptr_t)(a)))
     95 
     96 static COLD void init_mode_node(EdgeBranch *const nwc,
     97                               const enum BlockLevel bl,
     98                               struct ModeSelMem *const mem,
     99                               const int top_has_right,
    100                               const int left_has_bottom)
    101 {
    102    init_edges(&nwc->node, bl,
    103               (top_has_right ? EDGE_ALL_TOP_HAS_RIGHT : 0) |
    104               (left_has_bottom ? EDGE_ALL_LEFT_HAS_BOTTOM : 0));
    105    if (bl == BL_16X16) {
    106        for (int n = 0; n < 4; n++) {
    107            EdgeTip *const nt = mem->nt++;
    108            nwc->split_offset[n] = PTR_OFFSET(nwc, nt);
    109            init_edges(&nt->node, bl + 1,
    110                       ((n == 3 || (n == 1 && !top_has_right)) ? 0 :
    111                        EDGE_ALL_TOP_HAS_RIGHT) |
    112                       (!(n == 0 || (n == 2 && left_has_bottom)) ? 0 :
    113                        EDGE_ALL_LEFT_HAS_BOTTOM));
    114        }
    115    } else {
    116        for (int n = 0; n < 4; n++) {
    117            EdgeBranch *const nwc_child = mem->nwc[bl]++;
    118            nwc->split_offset[n] = PTR_OFFSET(nwc, nwc_child);
    119            init_mode_node(nwc_child, bl + 1, mem,
    120                           !(n == 3 || (n == 1 && !top_has_right)),
    121                           n == 0 || (n == 2 && left_has_bottom));
    122        }
    123    }
    124 }
    125 
    126 COLD void dav1d_init_intra_edge_tree(void) {
    127    // This function is guaranteed to be called only once
    128    struct ModeSelMem mem;
    129 
    130    mem.nwc[BL_128X128] = &nodes.branch_sb128[1];
    131    mem.nwc[BL_64X64] = &nodes.branch_sb128[1 + 4];
    132    mem.nwc[BL_32X32] = &nodes.branch_sb128[1 + 4 + 16];
    133    mem.nt = nodes.tip_sb128;
    134    init_mode_node(nodes.branch_sb128, BL_128X128, &mem, 1, 0);
    135    assert(mem.nwc[BL_128X128] == &nodes.branch_sb128[1 + 4]);
    136    assert(mem.nwc[BL_64X64] == &nodes.branch_sb128[1 + 4 + 16]);
    137    assert(mem.nwc[BL_32X32] == &nodes.branch_sb128[1 + 4 + 16 + 64]);
    138    assert(mem.nt == &nodes.tip_sb128[256]);
    139 
    140    mem.nwc[BL_128X128] = NULL;
    141    mem.nwc[BL_64X64] = &nodes.branch_sb64[1];
    142    mem.nwc[BL_32X32] = &nodes.branch_sb64[1 + 4];
    143    mem.nt = nodes.tip_sb64;
    144    init_mode_node(nodes.branch_sb64, BL_64X64, &mem, 1, 0);
    145    assert(mem.nwc[BL_64X64] == &nodes.branch_sb64[1 + 4]);
    146    assert(mem.nwc[BL_32X32] == &nodes.branch_sb64[1 + 4 + 16]);
    147    assert(mem.nt == &nodes.tip_sb64[64]);
    148 }