Coverage Report

Created: 2026-07-30 06:27

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