Coverage Report

Created: 2026-09-13 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
1.78M
{
45
1.78M
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];
46
1.78M
    const int is_split = (from == (int) TX_4X4 || depth > 1) ? 0 :
47
1.78M
        (tx_masks[depth] >> (y_off * 4 + x_off)) & 1;
48
49
1.78M
    if (is_split) {
50
106k
        const enum RectTxfmSize sub = t_dim->sub;
51
106k
        const int htw4 = t_dim->w >> 1, hth4 = t_dim->h >> 1;
52
53
106k
        decomp_tx(txa, sub, depth + 1, y_off * 2 + 0, x_off * 2 + 0, tx_masks);
54
106k
        if (t_dim->w >= t_dim->h)
55
82.1k
            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][0][htw4],
56
82.1k
                      sub, depth + 1, y_off * 2 + 0, x_off * 2 + 1, tx_masks);
57
106k
        if (t_dim->h >= t_dim->w) {
58
78.5k
            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][hth4][0],
59
78.5k
                      sub, depth + 1, y_off * 2 + 1, x_off * 2 + 0, tx_masks);
60
78.5k
            if (t_dim->w >= t_dim->h)
61
53.9k
                decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][hth4][htw4],
62
53.9k
                          sub, depth + 1, y_off * 2 + 1, x_off * 2 + 1, tx_masks);
63
78.5k
        }
64
1.67M
    } else {
65
1.67M
        const int lw = imin(2, t_dim->lw), lh = imin(2, t_dim->lh);
66
67
1.67M
#define set_ctx(rep_macro) \
68
7.53M
        for (int y = 0; y < t_dim->h; y++) { \
69
5.85M
            rep_macro(txa[0][0][y], 0, lw); \
70
5.85M
            rep_macro(txa[1][0][y], 0, lh); \
71
5.85M
            txa[0][1][y][0] = t_dim->w; \
72
5.85M
        }
73
1.67M
        case_set_upto16(t_dim->lw);
74
1.67M
#undef set_ctx
75
1.67M
        dav1d_memset_pow2[t_dim->lw](txa[1][1][0], t_dim->h);
76
1.67M
    }
77
1.78M
}
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
976k
{
86
976k
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[max_tx];
87
976k
    int y, x;
88
89
976k
    ALIGN_STK_16(uint8_t, txa, 2 /* edge */, [2 /* txsz, step */][32 /* y */][32 /* x */]);
90
2.06M
    for (int y_off = 0, y = 0; y < h4; y += t_dim->h, y_off++)
91
2.55M
        for (int x_off = 0, x = 0; x < w4; x += t_dim->w, x_off++)
92
1.46M
            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][y][x],
93
1.46M
                      max_tx, 0, y_off, x_off, tx_masks);
94
95
    // left block edge
96
976k
    unsigned mask = 1U << by4;
97
5.42M
    for (y = 0; y < h4; y++, mask <<= 1) {
98
4.44M
        const int sidx = mask >= 0x10000;
99
4.44M
        const unsigned smask = mask >> (sidx << 4);
100
4.44M
        masks[0][bx4][imin(txa[0][0][y][0], l[y])][sidx] |= smask;
101
4.44M
    }
102
103
    // top block edge
104
4.01M
    for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
105
3.04M
        const int sidx = mask >= 0x10000;
106
3.04M
        const unsigned smask = mask >> (sidx << 4);
107
3.04M
        masks[1][by4][imin(txa[1][0][0][x], a[x])][sidx] |= smask;
108
3.04M
    }
109
110
976k
    if (!skip) {
111
        // inner (tx) left|right edges
112
3.06M
        for (y = 0, mask = 1U << by4; y < h4; y++, mask <<= 1) {
113
2.47M
            const int sidx = mask >= 0x10000U;
114
2.47M
            const unsigned smask = mask >> (sidx << 4);
115
2.47M
            int ltx = txa[0][0][y][0];
116
2.47M
            int step = txa[0][1][y][0];
117
3.04M
            for (x = step; x < w4; x += step) {
118
567k
                const int rtx = txa[0][0][y][x];
119
567k
                masks[0][bx4 + x][imin(rtx, ltx)][sidx] |= smask;
120
567k
                ltx = rtx;
121
567k
                step = txa[0][1][y][x];
122
567k
            }
123
2.47M
        }
124
125
        //            top
126
        // inner (tx) --- edges
127
        //           bottom
128
2.50M
        for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
129
1.91M
            const int sidx = mask >= 0x10000U;
130
1.91M
            const unsigned smask = mask >> (sidx << 4);
131
1.91M
            int ttx = txa[1][0][0][x];
132
1.91M
            int step = txa[1][1][0][x];
133
2.51M
            for (y = step; y < h4; y += step) {
134
593k
                const int btx = txa[1][0][y][x];
135
593k
                masks[1][by4 + y][imin(ttx, btx)][sidx] |= smask;
136
593k
                ttx = btx;
137
593k
                step = txa[1][1][y][x];
138
593k
            }
139
1.91M
        }
140
588k
    }
141
142
5.42M
    for (y = 0; y < h4; y++)
143
4.44M
        l[y] = txa[0][0][y][w4 - 1];
144
976k
    memcpy(a, txa[1][0][h4 - 1], w4);
145
976k
}
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
2.28M
{
153
2.28M
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[tx];
154
2.28M
    const int twl4 = t_dim->lw, thl4 = t_dim->lh;
155
2.28M
    const int twl4c = imin(2, twl4), thl4c = imin(2, thl4);
156
2.28M
    int y, x;
157
158
    // left block edge
159
2.28M
    unsigned mask = 1U << by4;
160
12.8M
    for (y = 0; y < h4; y++, mask <<= 1) {
161
10.5M
        const int sidx = mask >= 0x10000;
162
10.5M
        const unsigned smask = mask >> (sidx << 4);
163
10.5M
        masks[0][bx4][imin(twl4c, l[y])][sidx] |= smask;
164
10.5M
    }
165
166
    // top block edge
167
11.7M
    for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
168
9.44M
        const int sidx = mask >= 0x10000;
169
9.44M
        const unsigned smask = mask >> (sidx << 4);
170
9.44M
        masks[1][by4][imin(thl4c, a[x])][sidx] |= smask;
171
9.44M
    }
172
173
    // inner (tx) left|right edges
174
2.28M
    const int hstep = t_dim->w;
175
2.28M
    unsigned t = 1U << by4;
176
2.28M
    unsigned inner = (unsigned) ((((uint64_t) t) << h4) - t);
177
2.28M
    unsigned inner1 = inner & 0xffff, inner2 = inner >> 16;
178
2.90M
    for (x = hstep; x < w4; x += hstep) {
179
625k
        if (inner1) masks[0][bx4 + x][twl4c][0] |= inner1;
180
625k
        if (inner2) masks[0][bx4 + x][twl4c][1] |= inner2;
181
625k
    }
182
183
    //            top
184
    // inner (tx) --- edges
185
    //           bottom
186
2.28M
    const int vstep = t_dim->h;
187
2.28M
    t = 1U << bx4;
188
2.28M
    inner = (unsigned) ((((uint64_t) t) << w4) - t);
189
2.28M
    inner1 = inner & 0xffff;
190
2.28M
    inner2 = inner >> 16;
191
3.03M
    for (y = vstep; y < h4; y += vstep) {
192
756k
        if (inner1) masks[1][by4 + y][thl4c][0] |= inner1;
193
756k
        if (inner2) masks[1][by4 + y][thl4c][1] |= inner2;
194
756k
    }
195
196
2.28M
    dav1d_memset_likely_pow2(a, thl4c, w4);
197
2.28M
    dav1d_memset_likely_pow2(l, twl4c, h4);
198
2.28M
}
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
2.46M
{
208
2.46M
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[tx];
209
2.46M
    const int twl4 = t_dim->lw, thl4 = t_dim->lh;
210
2.46M
    const int twl4c = !!twl4, thl4c = !!thl4;
211
2.46M
    int y, x;
212
2.46M
    const int vbits = 4 - ss_ver, hbits = 4 - ss_hor;
213
2.46M
    const int vmask = 16 >> ss_ver, hmask = 16 >> ss_hor;
214
2.46M
    const unsigned vmax = 1 << vmask, hmax = 1 << hmask;
215
216
    // left block edge
217
2.46M
    unsigned mask = 1U << cby4;
218
10.6M
    for (y = 0; y < ch4; y++, mask <<= 1) {
219
8.19M
        const int sidx = mask >= vmax;
220
8.19M
        const unsigned smask = mask >> (sidx << vbits);
221
8.19M
        masks[0][cbx4][imin(twl4c, l[y])][sidx] |= smask;
222
8.19M
    }
223
224
    // top block edge
225
9.70M
    for (x = 0, mask = 1U << cbx4; x < cw4; x++, mask <<= 1) {
226
7.23M
        const int sidx = mask >= hmax;
227
7.23M
        const unsigned smask = mask >> (sidx << hbits);
228
7.23M
        masks[1][cby4][imin(thl4c, a[x])][sidx] |= smask;
229
7.23M
    }
230
231
2.46M
    if (!skip_inter) {
232
        // inner (tx) left|right edges
233
2.20M
        const int hstep = t_dim->w;
234
2.20M
        unsigned t = 1U << cby4;
235
2.20M
        unsigned inner = (unsigned) ((((uint64_t) t) << ch4) - t);
236
2.20M
        unsigned inner1 = inner & ((1 << vmask) - 1), inner2 = inner >> vmask;
237
2.47M
        for (x = hstep; x < cw4; x += hstep) {
238
272k
            if (inner1) masks[0][cbx4 + x][twl4c][0] |= inner1;
239
272k
            if (inner2) masks[0][cbx4 + x][twl4c][1] |= inner2;
240
272k
        }
241
242
        //            top
243
        // inner (tx) --- edges
244
        //           bottom
245
2.20M
        const int vstep = t_dim->h;
246
2.20M
        t = 1U << cbx4;
247
2.20M
        inner = (unsigned) ((((uint64_t) t) << cw4) - t);
248
2.20M
        inner1 = inner & ((1 << hmask) - 1), inner2 = inner >> hmask;
249
2.50M
        for (y = vstep; y < ch4; y += vstep) {
250
298k
            if (inner1) masks[1][cby4 + y][thl4c][0] |= inner1;
251
298k
            if (inner2) masks[1][cby4 + y][thl4c][1] |= inner2;
252
298k
        }
253
2.20M
    }
254
255
2.46M
    dav1d_memset_likely_pow2(a, thl4c, cw4);
256
2.46M
    dav1d_memset_likely_pow2(l, twl4c, ch4);
257
2.46M
}
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
2.50M
{
272
2.50M
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
273
2.50M
    const int bw4 = imin(iw - bx, b_dim[0]);
274
2.50M
    const int bh4 = imin(ih - by, b_dim[1]);
275
2.50M
    const int bx4 = bx & 31;
276
2.50M
    const int by4 = by & 31;
277
2.50M
    assert(bw4 >= 0 && bh4 >= 0);
278
279
2.50M
    if (bw4 && bh4) {
280
2.28M
        uint8_t (*level_cache_ptr)[4] = level_cache + by * b4_stride + bx;
281
12.8M
        for (int y = 0; y < bh4; y++) {
282
85.7M
            for (int x = 0; x < bw4; x++) {
283
75.2M
                level_cache_ptr[x][0] = filter_level[0][0][0];
284
75.2M
                level_cache_ptr[x][1] = filter_level[1][0][0];
285
75.2M
            }
286
10.5M
            level_cache_ptr += b4_stride;
287
10.5M
        }
288
289
2.28M
        mask_edges_intra(lflvl->filter_y, by4, bx4, bw4, bh4, ytx, ay, ly);
290
2.28M
    }
291
292
2.50M
    if (!auv) return;
293
294
1.89M
    const int ss_ver = layout == DAV1D_PIXEL_LAYOUT_I420;
295
1.89M
    const int ss_hor = layout != DAV1D_PIXEL_LAYOUT_I444;
296
1.89M
    const int cbw4 = imin(((iw + ss_hor) >> ss_hor) - (bx >> ss_hor),
297
1.89M
                          (b_dim[0] + ss_hor) >> ss_hor);
298
1.89M
    const int cbh4 = imin(((ih + ss_ver) >> ss_ver) - (by >> ss_ver),
299
1.89M
                          (b_dim[1] + ss_ver) >> ss_ver);
300
1.89M
    assert(cbw4 >= 0 && cbh4 >= 0);
301
302
1.89M
    if (!cbw4 || !cbh4) return;
303
304
1.75M
    const int cbx4 = bx4 >> ss_hor;
305
1.75M
    const int cby4 = by4 >> ss_ver;
306
307
1.75M
    uint8_t (*level_cache_ptr)[4] =
308
1.75M
        level_cache + (by >> ss_ver) * b4_stride + (bx >> ss_hor);
309
7.65M
    for (int y = 0; y < cbh4; y++) {
310
40.2M
        for (int x = 0; x < cbw4; x++) {
311
34.3M
            level_cache_ptr[x][2] = filter_level[2][0][0];
312
34.3M
            level_cache_ptr[x][3] = filter_level[3][0][0];
313
34.3M
        }
314
5.89M
        level_cache_ptr += b4_stride;
315
5.89M
    }
316
317
1.75M
    mask_edges_chroma(lflvl->filter_uv, cby4, cbx4, cbw4, cbh4, 0, uvtx,
318
1.75M
                      auv, luv, ss_hor, ss_ver);
319
1.75M
}
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
1.05M
{
335
1.05M
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
336
1.05M
    const int bw4 = imin(iw - bx, b_dim[0]);
337
1.05M
    const int bh4 = imin(ih - by, b_dim[1]);
338
1.05M
    const int bx4 = bx & 31;
339
1.05M
    const int by4 = by & 31;
340
1.05M
    assert(bw4 >= 0 && bh4 >= 0);
341
342
1.05M
    if (bw4 && bh4) {
343
977k
        uint8_t (*level_cache_ptr)[4] = level_cache + by * b4_stride + bx;
344
5.42M
        for (int y = 0; y < bh4; y++) {
345
23.7M
            for (int x = 0; x < bw4; x++) {
346
19.3M
                level_cache_ptr[x][0] = filter_level[0][0][0];
347
19.3M
                level_cache_ptr[x][1] = filter_level[1][0][0];
348
19.3M
            }
349
4.44M
            level_cache_ptr += b4_stride;
350
4.44M
        }
351
352
977k
        mask_edges_inter(lflvl->filter_y, by4, bx4, bw4, bh4, skip,
353
977k
                         max_ytx, tx_masks, ay, ly);
354
977k
    }
355
356
1.05M
    if (!auv) return;
357
358
724k
    const int ss_ver = layout == DAV1D_PIXEL_LAYOUT_I420;
359
724k
    const int ss_hor = layout != DAV1D_PIXEL_LAYOUT_I444;
360
724k
    const int cbw4 = imin(((iw + ss_hor) >> ss_hor) - (bx >> ss_hor),
361
724k
                          (b_dim[0] + ss_hor) >> ss_hor);
362
724k
    const int cbh4 = imin(((ih + ss_ver) >> ss_ver) - (by >> ss_ver),
363
724k
                          (b_dim[1] + ss_ver) >> ss_ver);
364
724k
    assert(cbw4 >= 0 && cbh4 >= 0);
365
366
724k
    if (!cbw4 || !cbh4) return;
367
368
712k
    const int cbx4 = bx4 >> ss_hor;
369
712k
    const int cby4 = by4 >> ss_ver;
370
371
712k
    uint8_t (*level_cache_ptr)[4] =
372
712k
        level_cache + (by >> ss_ver) * b4_stride + (bx >> ss_hor);
373
3.00M
    for (int y = 0; y < cbh4; y++) {
374
12.0M
        for (int x = 0; x < cbw4; x++) {
375
9.74M
            level_cache_ptr[x][2] = filter_level[2][0][0];
376
9.74M
            level_cache_ptr[x][3] = filter_level[3][0][0];
377
9.74M
        }
378
2.29M
        level_cache_ptr += b4_stride;
379
2.29M
    }
380
381
712k
    mask_edges_chroma(lflvl->filter_uv, cby4, cbx4, cbw4, cbh4, skip, uvtx,
382
712k
                      auv, luv, ss_hor, ss_ver);
383
712k
}
384
385
172k
void dav1d_calc_eih(Av1FilterLUT *const lim_lut, const int filter_sharpness) {
386
    // set E/I/H values from loopfilter level
387
172k
    const int sharp = filter_sharpness;
388
11.1M
    for (int level = 0; level < 64; level++) {
389
11.0M
        int limit = level;
390
391
11.0M
        if (sharp > 0) {
392
6.85M
            limit >>= (sharp + 3) >> 2;
393
6.85M
            limit = imin(limit, 9 - sharp);
394
6.85M
        }
395
11.0M
        limit = imax(limit, 1);
396
397
11.0M
        lim_lut->i[level] = limit;
398
11.0M
        lim_lut->e[level] = 2 * (level + 2) + limit;
399
11.0M
    }
400
172k
    lim_lut->sharp[0] = (sharp + 3) >> 2;
401
172k
    lim_lut->sharp[1] = sharp ? 9 - sharp : 0xff;
402
172k
}
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
3.92M
{
409
3.92M
    const int base = iclip(iclip(base_lvl + lf_delta, 0, 63) + seg_delta, 0, 63);
410
411
3.92M
    if (!mr_delta) {
412
3.18M
        memset(lflvl_values, base, sizeof(*lflvl_values) * 8);
413
3.18M
    } else {
414
746k
        const int sh = base >= 32;
415
746k
        lflvl_values[0][0] = lflvl_values[0][1] =
416
746k
            iclip(base + (mr_delta->ref_delta[0] * (1 << sh)), 0, 63);
417
5.96M
        for (int r = 1; r < 8; r++) {
418
15.6M
            for (int m = 0; m < 2; m++) {
419
10.4M
                const int delta =
420
10.4M
                    mr_delta->mode_delta[m] + mr_delta->ref_delta[r];
421
10.4M
                lflvl_values[r][m] = iclip(base + (delta * (1 << sh)), 0, 63);
422
10.4M
            }
423
5.22M
        }
424
746k
    }
425
3.92M
}
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
2.22M
{
432
2.22M
    if (!base_lvl)
433
523k
        memset(lflvl_values, 0, sizeof(*lflvl_values) * 8);
434
1.70M
    else
435
1.70M
        calc_lf_value(lflvl_values, base_lvl, lf_delta, seg_delta, mr_delta);
436
2.22M
}
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
339k
{
442
339k
    const int n_seg = hdr->segmentation.enabled ? 8 : 1;
443
444
339k
    if (!hdr->loopfilter.level_y[0] && !hdr->loopfilter.level_y[1]) {
445
44.0k
        memset(lflvl_values, 0, sizeof(*lflvl_values) * n_seg);
446
44.0k
        return;
447
44.0k
    }
448
449
295k
    const Dav1dLoopfilterModeRefDeltas *const mr_deltas =
450
295k
        hdr->loopfilter.mode_ref_delta_enabled ?
451
295k
        &hdr->loopfilter.mode_ref_deltas : NULL;
452
1.40M
    for (int s = 0; s < n_seg; s++) {
453
1.11M
        const Dav1dSegmentationData *const segd =
454
1.11M
            hdr->segmentation.enabled ? &hdr->segmentation.seg_data.d[s] : NULL;
455
456
1.11M
        calc_lf_value(lflvl_values[s][0], hdr->loopfilter.level_y[0],
457
1.11M
                      lf_delta[0], segd ? segd->delta_lf_y_v : 0, mr_deltas);
458
1.11M
        calc_lf_value(lflvl_values[s][1], hdr->loopfilter.level_y[1],
459
1.11M
                      lf_delta[hdr->delta.lf.multi ? 1 : 0],
460
1.11M
                      segd ? segd->delta_lf_y_h : 0, mr_deltas);
461
1.11M
        calc_lf_value_chroma(lflvl_values[s][2], hdr->loopfilter.level_u,
462
1.11M
                             lf_delta[hdr->delta.lf.multi ? 2 : 0],
463
1.11M
                             segd ? segd->delta_lf_u : 0, mr_deltas);
464
1.11M
        calc_lf_value_chroma(lflvl_values[s][3], hdr->loopfilter.level_v,
465
1.11M
                             lf_delta[hdr->delta.lf.multi ? 3 : 0],
466
1.11M
                             segd ? segd->delta_lf_v : 0, mr_deltas);
467
1.11M
    }
468
295k
}