Coverage Report

Created: 2026-07-16 06:29

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