Coverage Report

Created: 2026-10-17 06:50

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
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
}