Coverage Report

Created: 2026-10-17 06:56

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