Coverage Report

Created: 2026-05-30 06:06

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