Coverage Report

Created: 2026-10-28 06:18

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