Coverage Report

Created: 2026-09-13 06:32

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