Coverage Report

Created: 2026-09-01 06:57

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