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