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