xref: /aosp_15_r20/external/libdav1d/src/intra_edge.c (revision c09093415860a1c2373dacd84c4fde00c507cdfd)
1*c0909341SAndroid Build Coastguard Worker /*
2*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018-2023, VideoLAN and dav1d authors
3*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018-2023, Two Orioles, LLC
4*c0909341SAndroid Build Coastguard Worker  * All rights reserved.
5*c0909341SAndroid Build Coastguard Worker  *
6*c0909341SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
7*c0909341SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
8*c0909341SAndroid Build Coastguard Worker  *
9*c0909341SAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright notice, this
10*c0909341SAndroid Build Coastguard Worker  *    list of conditions and the following disclaimer.
11*c0909341SAndroid Build Coastguard Worker  *
12*c0909341SAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright notice,
13*c0909341SAndroid Build Coastguard Worker  *    this list of conditions and the following disclaimer in the documentation
14*c0909341SAndroid Build Coastguard Worker  *    and/or other materials provided with the distribution.
15*c0909341SAndroid Build Coastguard Worker  *
16*c0909341SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*c0909341SAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*c0909341SAndroid Build Coastguard Worker  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*c0909341SAndroid Build Coastguard Worker  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20*c0909341SAndroid Build Coastguard Worker  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*c0909341SAndroid Build Coastguard Worker  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*c0909341SAndroid Build Coastguard Worker  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*c0909341SAndroid Build Coastguard Worker  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*c0909341SAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*c0909341SAndroid Build Coastguard Worker  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*c0909341SAndroid Build Coastguard Worker  */
27*c0909341SAndroid Build Coastguard Worker 
28*c0909341SAndroid Build Coastguard Worker #include "config.h"
29*c0909341SAndroid Build Coastguard Worker 
30*c0909341SAndroid Build Coastguard Worker #include <stdlib.h>
31*c0909341SAndroid Build Coastguard Worker 
32*c0909341SAndroid Build Coastguard Worker #include "common/attributes.h"
33*c0909341SAndroid Build Coastguard Worker 
34*c0909341SAndroid Build Coastguard Worker #include "src/intra_edge.h"
35*c0909341SAndroid Build Coastguard Worker #include "src/levels.h"
36*c0909341SAndroid Build Coastguard Worker 
37*c0909341SAndroid Build Coastguard Worker struct ModeSelMem {
38*c0909341SAndroid Build Coastguard Worker     EdgeBranch *nwc[3 /* 64x64, 32x32, 16x16 */];
39*c0909341SAndroid Build Coastguard Worker     EdgeTip *nt;
40*c0909341SAndroid Build Coastguard Worker };
41*c0909341SAndroid Build Coastguard Worker 
42*c0909341SAndroid Build Coastguard Worker /* Because we're using 16-bit offsets to refer to other nodes those arrays
43*c0909341SAndroid Build Coastguard Worker  * are placed in a struct to ensure they're consecutive in memory. */
44*c0909341SAndroid Build Coastguard Worker static struct {
45*c0909341SAndroid Build Coastguard Worker     EdgeBranch branch_sb128[1 + 4 + 16 + 64];
46*c0909341SAndroid Build Coastguard Worker     EdgeTip tip_sb128[256];
47*c0909341SAndroid Build Coastguard Worker     EdgeBranch branch_sb64[1 + 4 + 16];
48*c0909341SAndroid Build Coastguard Worker     EdgeTip tip_sb64[64];
49*c0909341SAndroid Build Coastguard Worker } ALIGN(nodes, 16);
50*c0909341SAndroid Build Coastguard Worker 
51*c0909341SAndroid Build Coastguard Worker const EdgeNode *dav1d_intra_edge_tree[2] = {
52*c0909341SAndroid Build Coastguard Worker     (EdgeNode*)nodes.branch_sb128, (EdgeNode*)nodes.branch_sb64
53*c0909341SAndroid Build Coastguard Worker };
54*c0909341SAndroid Build Coastguard Worker 
init_edges(EdgeNode * const node,const enum BlockLevel bl,const enum EdgeFlags edge_flags)55*c0909341SAndroid Build Coastguard Worker static COLD void init_edges(EdgeNode *const node,
56*c0909341SAndroid Build Coastguard Worker                             const enum BlockLevel bl,
57*c0909341SAndroid Build Coastguard Worker                             const enum EdgeFlags edge_flags)
58*c0909341SAndroid Build Coastguard Worker {
59*c0909341SAndroid Build Coastguard Worker     node->o = edge_flags;
60*c0909341SAndroid Build Coastguard Worker     node->h[0] = edge_flags | EDGE_ALL_LEFT_HAS_BOTTOM;
61*c0909341SAndroid Build Coastguard Worker     node->v[0] = edge_flags | EDGE_ALL_TOP_HAS_RIGHT;
62*c0909341SAndroid Build Coastguard Worker 
63*c0909341SAndroid Build Coastguard Worker     if (bl == BL_8X8) {
64*c0909341SAndroid Build Coastguard Worker         EdgeTip *const nt = (EdgeTip *) node;
65*c0909341SAndroid Build Coastguard Worker 
66*c0909341SAndroid Build Coastguard Worker         node->h[1] = edge_flags & (EDGE_ALL_LEFT_HAS_BOTTOM |
67*c0909341SAndroid Build Coastguard Worker                                    EDGE_I420_TOP_HAS_RIGHT);
68*c0909341SAndroid Build Coastguard Worker         node->v[1] = edge_flags & (EDGE_ALL_TOP_HAS_RIGHT |
69*c0909341SAndroid Build Coastguard Worker                                    EDGE_I420_LEFT_HAS_BOTTOM |
70*c0909341SAndroid Build Coastguard Worker                                    EDGE_I422_LEFT_HAS_BOTTOM);
71*c0909341SAndroid Build Coastguard Worker 
72*c0909341SAndroid Build Coastguard Worker         nt->split[0] = (edge_flags & EDGE_ALL_TOP_HAS_RIGHT) |
73*c0909341SAndroid Build Coastguard Worker                        EDGE_I422_LEFT_HAS_BOTTOM;
74*c0909341SAndroid Build Coastguard Worker         nt->split[1] = edge_flags | EDGE_I444_TOP_HAS_RIGHT;
75*c0909341SAndroid Build Coastguard Worker         nt->split[2] = edge_flags & (EDGE_I420_TOP_HAS_RIGHT |
76*c0909341SAndroid Build Coastguard Worker                                      EDGE_I420_LEFT_HAS_BOTTOM |
77*c0909341SAndroid Build Coastguard Worker                                      EDGE_I422_LEFT_HAS_BOTTOM);
78*c0909341SAndroid Build Coastguard Worker     } else {
79*c0909341SAndroid Build Coastguard Worker         EdgeBranch *const nwc = (EdgeBranch *) node;
80*c0909341SAndroid Build Coastguard Worker 
81*c0909341SAndroid Build Coastguard Worker         node->h[1] = edge_flags & EDGE_ALL_LEFT_HAS_BOTTOM;
82*c0909341SAndroid Build Coastguard Worker         node->v[1] = edge_flags & EDGE_ALL_TOP_HAS_RIGHT;
83*c0909341SAndroid Build Coastguard Worker 
84*c0909341SAndroid Build Coastguard Worker         nwc->h4 = EDGE_ALL_LEFT_HAS_BOTTOM;
85*c0909341SAndroid Build Coastguard Worker         nwc->v4 = EDGE_ALL_TOP_HAS_RIGHT;
86*c0909341SAndroid Build Coastguard Worker         if (bl == BL_16X16) {
87*c0909341SAndroid Build Coastguard Worker             nwc->h4 |= edge_flags & EDGE_I420_TOP_HAS_RIGHT;
88*c0909341SAndroid Build Coastguard Worker             nwc->v4 |= edge_flags & (EDGE_I420_LEFT_HAS_BOTTOM |
89*c0909341SAndroid Build Coastguard Worker                                      EDGE_I422_LEFT_HAS_BOTTOM);
90*c0909341SAndroid Build Coastguard Worker         }
91*c0909341SAndroid Build Coastguard Worker     }
92*c0909341SAndroid Build Coastguard Worker }
93*c0909341SAndroid Build Coastguard Worker 
94*c0909341SAndroid Build Coastguard Worker #define PTR_OFFSET(a, b) ((uint16_t)((uintptr_t)(b) - (uintptr_t)(a)))
95*c0909341SAndroid Build Coastguard Worker 
init_mode_node(EdgeBranch * const nwc,const enum BlockLevel bl,struct ModeSelMem * const mem,const int top_has_right,const int left_has_bottom)96*c0909341SAndroid Build Coastguard Worker static COLD void init_mode_node(EdgeBranch *const nwc,
97*c0909341SAndroid Build Coastguard Worker                                const enum BlockLevel bl,
98*c0909341SAndroid Build Coastguard Worker                                struct ModeSelMem *const mem,
99*c0909341SAndroid Build Coastguard Worker                                const int top_has_right,
100*c0909341SAndroid Build Coastguard Worker                                const int left_has_bottom)
101*c0909341SAndroid Build Coastguard Worker {
102*c0909341SAndroid Build Coastguard Worker     init_edges(&nwc->node, bl,
103*c0909341SAndroid Build Coastguard Worker                (top_has_right ? EDGE_ALL_TOP_HAS_RIGHT : 0) |
104*c0909341SAndroid Build Coastguard Worker                (left_has_bottom ? EDGE_ALL_LEFT_HAS_BOTTOM : 0));
105*c0909341SAndroid Build Coastguard Worker     if (bl == BL_16X16) {
106*c0909341SAndroid Build Coastguard Worker         for (int n = 0; n < 4; n++) {
107*c0909341SAndroid Build Coastguard Worker             EdgeTip *const nt = mem->nt++;
108*c0909341SAndroid Build Coastguard Worker             nwc->split_offset[n] = PTR_OFFSET(nwc, nt);
109*c0909341SAndroid Build Coastguard Worker             init_edges(&nt->node, bl + 1,
110*c0909341SAndroid Build Coastguard Worker                        ((n == 3 || (n == 1 && !top_has_right)) ? 0 :
111*c0909341SAndroid Build Coastguard Worker                         EDGE_ALL_TOP_HAS_RIGHT) |
112*c0909341SAndroid Build Coastguard Worker                        (!(n == 0 || (n == 2 && left_has_bottom)) ? 0 :
113*c0909341SAndroid Build Coastguard Worker                         EDGE_ALL_LEFT_HAS_BOTTOM));
114*c0909341SAndroid Build Coastguard Worker         }
115*c0909341SAndroid Build Coastguard Worker     } else {
116*c0909341SAndroid Build Coastguard Worker         for (int n = 0; n < 4; n++) {
117*c0909341SAndroid Build Coastguard Worker             EdgeBranch *const nwc_child = mem->nwc[bl]++;
118*c0909341SAndroid Build Coastguard Worker             nwc->split_offset[n] = PTR_OFFSET(nwc, nwc_child);
119*c0909341SAndroid Build Coastguard Worker             init_mode_node(nwc_child, bl + 1, mem,
120*c0909341SAndroid Build Coastguard Worker                            !(n == 3 || (n == 1 && !top_has_right)),
121*c0909341SAndroid Build Coastguard Worker                            n == 0 || (n == 2 && left_has_bottom));
122*c0909341SAndroid Build Coastguard Worker         }
123*c0909341SAndroid Build Coastguard Worker     }
124*c0909341SAndroid Build Coastguard Worker }
125*c0909341SAndroid Build Coastguard Worker 
dav1d_init_intra_edge_tree(void)126*c0909341SAndroid Build Coastguard Worker COLD void dav1d_init_intra_edge_tree(void) {
127*c0909341SAndroid Build Coastguard Worker     // This function is guaranteed to be called only once
128*c0909341SAndroid Build Coastguard Worker     struct ModeSelMem mem;
129*c0909341SAndroid Build Coastguard Worker 
130*c0909341SAndroid Build Coastguard Worker     mem.nwc[BL_128X128] = &nodes.branch_sb128[1];
131*c0909341SAndroid Build Coastguard Worker     mem.nwc[BL_64X64] = &nodes.branch_sb128[1 + 4];
132*c0909341SAndroid Build Coastguard Worker     mem.nwc[BL_32X32] = &nodes.branch_sb128[1 + 4 + 16];
133*c0909341SAndroid Build Coastguard Worker     mem.nt = nodes.tip_sb128;
134*c0909341SAndroid Build Coastguard Worker     init_mode_node(nodes.branch_sb128, BL_128X128, &mem, 1, 0);
135*c0909341SAndroid Build Coastguard Worker     assert(mem.nwc[BL_128X128] == &nodes.branch_sb128[1 + 4]);
136*c0909341SAndroid Build Coastguard Worker     assert(mem.nwc[BL_64X64] == &nodes.branch_sb128[1 + 4 + 16]);
137*c0909341SAndroid Build Coastguard Worker     assert(mem.nwc[BL_32X32] == &nodes.branch_sb128[1 + 4 + 16 + 64]);
138*c0909341SAndroid Build Coastguard Worker     assert(mem.nt == &nodes.tip_sb128[256]);
139*c0909341SAndroid Build Coastguard Worker 
140*c0909341SAndroid Build Coastguard Worker     mem.nwc[BL_128X128] = NULL;
141*c0909341SAndroid Build Coastguard Worker     mem.nwc[BL_64X64] = &nodes.branch_sb64[1];
142*c0909341SAndroid Build Coastguard Worker     mem.nwc[BL_32X32] = &nodes.branch_sb64[1 + 4];
143*c0909341SAndroid Build Coastguard Worker     mem.nt = nodes.tip_sb64;
144*c0909341SAndroid Build Coastguard Worker     init_mode_node(nodes.branch_sb64, BL_64X64, &mem, 1, 0);
145*c0909341SAndroid Build Coastguard Worker     assert(mem.nwc[BL_64X64] == &nodes.branch_sb64[1 + 4]);
146*c0909341SAndroid Build Coastguard Worker     assert(mem.nwc[BL_32X32] == &nodes.branch_sb64[1 + 4 + 16]);
147*c0909341SAndroid Build Coastguard Worker     assert(mem.nt == &nodes.tip_sb64[64]);
148*c0909341SAndroid Build Coastguard Worker }
149