Coverage Report

Created: 2026-05-30 06:10

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