Coverage Report

Created: 2026-06-15 06:22

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