Coverage Report

Created: 2026-08-13 07:20

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