Coverage Report

Created: 2026-10-17 06:52

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
643k
{
45
643k
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];
46
643k
    const int is_split = (from == (int) TX_4X4 || depth > 1) ? 0 :
47
643k
        (tx_masks[depth] >> (y_off * 4 + x_off)) & 1;
48
49
643k
    if (is_split) {
50
45.7k
        const enum RectTxfmSize sub = t_dim->sub;
51
45.7k
        const int htw4 = t_dim->w >> 1, hth4 = t_dim->h >> 1;
52
53
45.7k
        decomp_tx(txa, sub, depth + 1, y_off * 2 + 0, x_off * 2 + 0, tx_masks);
54
45.7k
        if (t_dim->w >= t_dim->h)
55
31.5k
            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][0][htw4],
56
31.5k
                      sub, depth + 1, y_off * 2 + 0, x_off * 2 + 1, tx_masks);
57
45.7k
        if (t_dim->h >= t_dim->w) {
58
34.5k
            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][hth4][0],
59
34.5k
                      sub, depth + 1, y_off * 2 + 1, x_off * 2 + 0, tx_masks);
60
34.5k
            if (t_dim->w >= t_dim->h)
61
20.3k
                decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][hth4][htw4],
62
20.3k
                          sub, depth + 1, y_off * 2 + 1, x_off * 2 + 1, tx_masks);
63
34.5k
        }
64
597k
    } else {
65
597k
        const int lw = imin(2, t_dim->lw), lh = imin(2, t_dim->lh);
66
67
597k
#define set_ctx(rep_macro) \
68
3.17M
        for (int y = 0; y < t_dim->h; y++) { \
69
2.57M
            rep_macro(txa[0][0][y], 0, lw); \
70
2.57M
            rep_macro(txa[1][0][y], 0, lh); \
71
2.57M
            txa[0][1][y][0] = t_dim->w; \
72
2.57M
        }
73
597k
        case_set_upto16(t_dim->lw);
74
597k
#undef set_ctx
75
597k
        dav1d_memset_pow2[t_dim->lw](txa[1][1][0], t_dim->h);
76
597k
    }
77
643k
}
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
468k
{
86
468k
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[max_tx];
87
468k
    int y, x;
88
89
468k
    ALIGN_STK_16(uint8_t, txa, 2 /* edge */, [2 /* txsz, step */][32 /* y */][32 /* x */]);
90
952k
    for (int y_off = 0, y = 0; y < h4; y += t_dim->h, y_off++)
91
994k
        for (int x_off = 0, x = 0; x < w4; x += t_dim->w, x_off++)
92
510k
            decomp_tx((uint8_t(*)[2][32][32]) &txa[0][0][y][x],
93
510k
                      max_tx, 0, y_off, x_off, tx_masks);
94
95
    // left block edge
96
468k
    unsigned mask = 1U << by4;
97
2.62M
    for (y = 0; y < h4; y++, mask <<= 1) {
98
2.16M
        const int sidx = mask >= 0x10000;
99
2.16M
        const unsigned smask = mask >> (sidx << 4);
100
2.16M
        masks[0][bx4][imin(txa[0][0][y][0], l[y])][sidx] |= smask;
101
2.16M
    }
102
103
    // top block edge
104
1.79M
    for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
105
1.32M
        const int sidx = mask >= 0x10000;
106
1.32M
        const unsigned smask = mask >> (sidx << 4);
107
1.32M
        masks[1][by4][imin(txa[1][0][0][x], a[x])][sidx] |= smask;
108
1.32M
    }
109
110
468k
    if (!skip) {
111
        // inner (tx) left|right edges
112
1.28M
        for (y = 0, mask = 1U << by4; y < h4; y++, mask <<= 1) {
113
1.04M
            const int sidx = mask >= 0x10000U;
114
1.04M
            const unsigned smask = mask >> (sidx << 4);
115
1.04M
            int ltx = txa[0][0][y][0];
116
1.04M
            int step = txa[0][1][y][0];
117
1.14M
            for (x = step; x < w4; x += step) {
118
100k
                const int rtx = txa[0][0][y][x];
119
100k
                masks[0][bx4 + x][imin(rtx, ltx)][sidx] |= smask;
120
100k
                ltx = rtx;
121
100k
                step = txa[0][1][y][x];
122
100k
            }
123
1.04M
        }
124
125
        //            top
126
        // inner (tx) --- edges
127
        //           bottom
128
945k
        for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
129
712k
            const int sidx = mask >= 0x10000U;
130
712k
            const unsigned smask = mask >> (sidx << 4);
131
712k
            int ttx = txa[1][0][0][x];
132
712k
            int step = txa[1][1][0][x];
133
824k
            for (y = step; y < h4; y += step) {
134
111k
                const int btx = txa[1][0][y][x];
135
111k
                masks[1][by4 + y][imin(ttx, btx)][sidx] |= smask;
136
111k
                ttx = btx;
137
111k
                step = txa[1][1][y][x];
138
111k
            }
139
712k
        }
140
232k
    }
141
142
2.62M
    for (y = 0; y < h4; y++)
143
2.16M
        l[y] = txa[0][0][y][w4 - 1];
144
468k
    memcpy(a, txa[1][0][h4 - 1], w4);
145
468k
}
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
403k
{
153
403k
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[tx];
154
403k
    const int twl4 = t_dim->lw, thl4 = t_dim->lh;
155
403k
    const int twl4c = imin(2, twl4), thl4c = imin(2, thl4);
156
403k
    int y, x;
157
158
    // left block edge
159
403k
    unsigned mask = 1U << by4;
160
2.04M
    for (y = 0; y < h4; y++, mask <<= 1) {
161
1.64M
        const int sidx = mask >= 0x10000;
162
1.64M
        const unsigned smask = mask >> (sidx << 4);
163
1.64M
        masks[0][bx4][imin(twl4c, l[y])][sidx] |= smask;
164
1.64M
    }
165
166
    // top block edge
167
1.84M
    for (x = 0, mask = 1U << bx4; x < w4; x++, mask <<= 1) {
168
1.44M
        const int sidx = mask >= 0x10000;
169
1.44M
        const unsigned smask = mask >> (sidx << 4);
170
1.44M
        masks[1][by4][imin(thl4c, a[x])][sidx] |= smask;
171
1.44M
    }
172
173
    // inner (tx) left|right edges
174
403k
    const int hstep = t_dim->w;
175
403k
    unsigned t = 1U << by4;
176
403k
    unsigned inner = (unsigned) ((((uint64_t) t) << h4) - t);
177
403k
    unsigned inner1 = inner & 0xffff, inner2 = inner >> 16;
178
506k
    for (x = hstep; x < w4; x += hstep) {
179
102k
        if (inner1) masks[0][bx4 + x][twl4c][0] |= inner1;
180
102k
        if (inner2) masks[0][bx4 + x][twl4c][1] |= inner2;
181
102k
    }
182
183
    //            top
184
    // inner (tx) --- edges
185
    //           bottom
186
403k
    const int vstep = t_dim->h;
187
403k
    t = 1U << bx4;
188
403k
    inner = (unsigned) ((((uint64_t) t) << w4) - t);
189
403k
    inner1 = inner & 0xffff;
190
403k
    inner2 = inner >> 16;
191
527k
    for (y = vstep; y < h4; y += vstep) {
192
123k
        if (inner1) masks[1][by4 + y][thl4c][0] |= inner1;
193
123k
        if (inner2) masks[1][by4 + y][thl4c][1] |= inner2;
194
123k
    }
195
196
403k
    dav1d_memset_likely_pow2(a, thl4c, w4);
197
403k
    dav1d_memset_likely_pow2(l, twl4c, h4);
198
403k
}
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
645k
{
208
645k
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[tx];
209
645k
    const int twl4 = t_dim->lw, thl4 = t_dim->lh;
210
645k
    const int twl4c = !!twl4, thl4c = !!thl4;
211
645k
    int y, x;
212
645k
    const int vbits = 4 - ss_ver, hbits = 4 - ss_hor;
213
645k
    const int vmask = 16 >> ss_ver, hmask = 16 >> ss_hor;
214
645k
    const unsigned vmax = 1 << vmask, hmax = 1 << hmask;
215
216
    // left block edge
217
645k
    unsigned mask = 1U << cby4;
218
2.85M
    for (y = 0; y < ch4; y++, mask <<= 1) {
219
2.21M
        const int sidx = mask >= vmax;
220
2.21M
        const unsigned smask = mask >> (sidx << vbits);
221
2.21M
        masks[0][cbx4][imin(twl4c, l[y])][sidx] |= smask;
222
2.21M
    }
223
224
    // top block edge
225
2.42M
    for (x = 0, mask = 1U << cbx4; x < cw4; x++, mask <<= 1) {
226
1.78M
        const int sidx = mask >= hmax;
227
1.78M
        const unsigned smask = mask >> (sidx << hbits);
228
1.78M
        masks[1][cby4][imin(thl4c, a[x])][sidx] |= smask;
229
1.78M
    }
230
231
645k
    if (!skip_inter) {
232
        // inner (tx) left|right edges
233
497k
        const int hstep = t_dim->w;
234
497k
        unsigned t = 1U << cby4;
235
497k
        unsigned inner = (unsigned) ((((uint64_t) t) << ch4) - t);
236
497k
        unsigned inner1 = inner & ((1 << vmask) - 1), inner2 = inner >> vmask;
237
551k
        for (x = hstep; x < cw4; x += hstep) {
238
54.2k
            if (inner1) masks[0][cbx4 + x][twl4c][0] |= inner1;
239
54.2k
            if (inner2) masks[0][cbx4 + x][twl4c][1] |= inner2;
240
54.2k
        }
241
242
        //            top
243
        // inner (tx) --- edges
244
        //           bottom
245
497k
        const int vstep = t_dim->h;
246
497k
        t = 1U << cbx4;
247
497k
        inner = (unsigned) ((((uint64_t) t) << cw4) - t);
248
497k
        inner1 = inner & ((1 << hmask) - 1), inner2 = inner >> hmask;
249
560k
        for (y = vstep; y < ch4; y += vstep) {
250
63.1k
            if (inner1) masks[1][cby4 + y][thl4c][0] |= inner1;
251
63.1k
            if (inner2) masks[1][cby4 + y][thl4c][1] |= inner2;
252
63.1k
        }
253
497k
    }
254
255
645k
    dav1d_memset_likely_pow2(a, thl4c, cw4);
256
645k
    dav1d_memset_likely_pow2(l, twl4c, ch4);
257
645k
}
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.51M
{
265
1.51M
    union alias16 v = (union alias16) { .u8 = { v0, v1 }};
266
267
7.52M
    for (int y = 0; y < bh; y++) {
268
29.7M
        for (int x = 0; x < bw; x++)
269
23.7M
            ((union alias16 *) &level_cache_ptr[x][0])->u16 = v.u16;
270
6.00M
        level_cache_ptr += b_stride;
271
6.00M
    }
272
1.51M
}
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
504k
{
287
504k
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
288
504k
    const int bw4 = imin(iw - bx, b_dim[0]);
289
504k
    const int bh4 = imin(ih - by, b_dim[1]);
290
504k
    const int bx4 = bx & 31;
291
504k
    const int by4 = by & 31;
292
504k
    assert(bw4 >= 0 && bh4 >= 0);
293
294
504k
    if (bw4 && bh4) {
295
403k
        uint8_t (*level_cache_ptr)[4] = level_cache + by * b4_stride + bx;
296
297
403k
        fill_levelcache_block(level_cache_ptr, b4_stride, bw4, bh4,
298
403k
                              filter_level[0][0][0], filter_level[1][0][0]);
299
403k
        mask_edges_intra(lflvl->filter_y, by4, bx4, bw4, bh4, ytx, ay, ly);
300
403k
    }
301
302
504k
    if (!auv) return;
303
304
394k
    const int ss_ver = layout == DAV1D_PIXEL_LAYOUT_I420;
305
394k
    const int ss_hor = layout != DAV1D_PIXEL_LAYOUT_I444;
306
394k
    const int cbw4 = imin(((iw + ss_hor) >> ss_hor) - (bx >> ss_hor),
307
394k
                          (b_dim[0] + ss_hor) >> ss_hor);
308
394k
    const int cbh4 = imin(((ih + ss_ver) >> ss_ver) - (by >> ss_ver),
309
394k
                          (b_dim[1] + ss_ver) >> ss_ver);
310
394k
    assert(cbw4 >= 0 && cbh4 >= 0);
311
312
394k
    if (!cbw4 || !cbh4) return;
313
314
328k
    const int cbx4 = bx4 >> ss_hor;
315
328k
    const int cby4 = by4 >> ss_ver;
316
317
328k
    uint8_t (*level_cache_ptr)[4] =
318
328k
        level_cache + (by >> ss_ver) * b4_stride + (bx >> ss_hor);
319
320
328k
    fill_levelcache_block((uint8_t(*)[4]) &level_cache_ptr[0][2], b4_stride,
321
328k
                          cbw4, cbh4, filter_level[2][0][0],
322
328k
                          filter_level[3][0][0]);
323
328k
    mask_edges_chroma(lflvl->filter_uv, cby4, cbx4, cbw4, cbh4, 0, uvtx,
324
328k
                      auv, luv, ss_hor, ss_ver);
325
328k
}
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
509k
{
341
509k
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
342
509k
    const int bw4 = imin(iw - bx, b_dim[0]);
343
509k
    const int bh4 = imin(ih - by, b_dim[1]);
344
509k
    const int bx4 = bx & 31;
345
509k
    const int by4 = by & 31;
346
509k
    assert(bw4 >= 0 && bh4 >= 0);
347
348
509k
    if (bw4 && bh4) {
349
468k
        uint8_t (*level_cache_ptr)[4] = level_cache + by * b4_stride + bx;
350
351
468k
        fill_levelcache_block(level_cache_ptr, b4_stride, bw4, bh4,
352
468k
                              filter_level[0][0][0], filter_level[1][0][0]);
353
468k
        mask_edges_inter(lflvl->filter_y, by4, bx4, bw4, bh4, skip,
354
468k
                         max_ytx, tx_masks, ay, ly);
355
468k
    }
356
357
509k
    if (!auv) return;
358
359
315k
    const int ss_ver = layout == DAV1D_PIXEL_LAYOUT_I420;
360
315k
    const int ss_hor = layout != DAV1D_PIXEL_LAYOUT_I444;
361
315k
    const int cbw4 = imin(((iw + ss_hor) >> ss_hor) - (bx >> ss_hor),
362
315k
                          (b_dim[0] + ss_hor) >> ss_hor);
363
315k
    const int cbh4 = imin(((ih + ss_ver) >> ss_ver) - (by >> ss_ver),
364
315k
                          (b_dim[1] + ss_ver) >> ss_ver);
365
315k
    assert(cbw4 >= 0 && cbh4 >= 0);
366
367
315k
    if (!cbw4 || !cbh4) return;
368
369
314k
    const int cbx4 = bx4 >> ss_hor;
370
314k
    const int cby4 = by4 >> ss_ver;
371
372
314k
    uint8_t (*level_cache_ptr)[4] =
373
314k
        level_cache + (by >> ss_ver) * b4_stride + (bx >> ss_hor);
374
375
314k
    fill_levelcache_block((uint8_t(*)[4]) &level_cache_ptr[0][2], b4_stride,
376
314k
                          cbw4, cbh4, filter_level[2][0][0],
377
314k
                          filter_level[3][0][0]);
378
314k
    mask_edges_chroma(lflvl->filter_uv, cby4, cbx4, cbw4, cbh4, skip, uvtx,
379
314k
                      auv, luv, ss_hor, ss_ver);
380
314k
}
381
382
62.6k
void dav1d_calc_eih(Av1FilterLUT *const lim_lut, const int filter_sharpness) {
383
    // set E/I/H values from loopfilter level
384
62.6k
    const int sharp = filter_sharpness;
385
4.07M
    for (int level = 0; level < 64; level++) {
386
4.00M
        int limit = level;
387
388
4.00M
        if (sharp > 0) {
389
2.41M
            limit >>= (sharp + 3) >> 2;
390
2.41M
            limit = imin(limit, 9 - sharp);
391
2.41M
        }
392
4.00M
        limit = imax(limit, 1);
393
394
4.00M
        lim_lut->i[level] = limit;
395
4.00M
        lim_lut->e[level] = 2 * (level + 2) + limit;
396
4.00M
    }
397
62.6k
    lim_lut->sharp[0] = (sharp + 3) >> 2;
398
62.6k
    lim_lut->sharp[1] = sharp ? 9 - sharp : 0xff;
399
62.6k
}
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
1.82M
{
406
1.82M
    const int base = iclip(iclip(base_lvl + lf_delta, 0, 63) + seg_delta, 0, 63);
407
408
1.82M
    if (!mr_delta) {
409
1.57M
        memset(lflvl_values, base, sizeof(*lflvl_values) * 8);
410
1.57M
    } else {
411
256k
        const int sh = base >= 32;
412
256k
        lflvl_values[0][0] = lflvl_values[0][1] =
413
256k
            iclip(base + (mr_delta->ref_delta[0] * (1 << sh)), 0, 63);
414
2.05M
        for (int r = 1; r < 8; r++) {
415
5.39M
            for (int m = 0; m < 2; m++) {
416
3.59M
                const int delta =
417
3.59M
                    mr_delta->mode_delta[m] + mr_delta->ref_delta[r];
418
3.59M
                lflvl_values[r][m] = iclip(base + (delta * (1 << sh)), 0, 63);
419
3.59M
            }
420
1.79M
        }
421
256k
    }
422
1.82M
}
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
1.05M
{
429
1.05M
    if (!base_lvl)
430
285k
        memset(lflvl_values, 0, sizeof(*lflvl_values) * 8);
431
772k
    else
432
772k
        calc_lf_value(lflvl_values, base_lvl, lf_delta, seg_delta, mr_delta);
433
1.05M
}
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
139k
{
439
139k
    const int n_seg = hdr->segmentation.enabled ? 8 : 1;
440
441
139k
    if (!hdr->loopfilter.level_y[0] && !hdr->loopfilter.level_y[1]) {
442
16.5k
        memset(lflvl_values, 0, sizeof(*lflvl_values) * n_seg);
443
16.5k
        return;
444
16.5k
    }
445
446
123k
    const Dav1dLoopfilterModeRefDeltas *const mr_deltas =
447
123k
        hdr->loopfilter.mode_ref_delta_enabled ?
448
123k
        &hdr->loopfilter.mode_ref_deltas : NULL;
449
652k
    for (int s = 0; s < n_seg; s++) {
450
528k
        const Dav1dSegmentationData *const segd =
451
528k
            hdr->segmentation.enabled ? &hdr->segmentation.seg_data.d[s] : NULL;
452
453
528k
        calc_lf_value(lflvl_values[s][0], hdr->loopfilter.level_y[0],
454
528k
                      lf_delta[0], segd ? segd->delta_lf_y_v : 0, mr_deltas);
455
528k
        calc_lf_value(lflvl_values[s][1], hdr->loopfilter.level_y[1],
456
528k
                      lf_delta[hdr->delta.lf.multi ? 1 : 0],
457
528k
                      segd ? segd->delta_lf_y_h : 0, mr_deltas);
458
528k
        calc_lf_value_chroma(lflvl_values[s][2], hdr->loopfilter.level_u,
459
528k
                             lf_delta[hdr->delta.lf.multi ? 2 : 0],
460
528k
                             segd ? segd->delta_lf_u : 0, mr_deltas);
461
528k
        calc_lf_value_chroma(lflvl_values[s][3], hdr->loopfilter.level_v,
462
528k
                             lf_delta[hdr->delta.lf.multi ? 3 : 0],
463
528k
                             segd ? segd->delta_lf_v : 0, mr_deltas);
464
528k
    }
465
123k
}