Coverage Report

Created: 2026-05-30 06:08

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