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