Coverage Report

Created: 2026-07-25 07:06

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