Coverage Report

Created: 2026-05-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/dav1d/src/lr_apply_tmpl.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 <stdio.h>
31
32
#include "common/intops.h"
33
34
#include "src/lr_apply.h"
35
36
static void lr_stripe(const Dav1dFrameContext *const f, pixel *p,
37
                      const pixel (*left)[4], int x, int y,
38
                      const int plane, const int unit_w, const int row_h,
39
                      const Av1RestorationUnit *const lr, enum LrEdgeFlags edges)
40
145k
{
41
145k
    const Dav1dDSPContext *const dsp = f->dsp;
42
145k
    const int chroma = !!plane;
43
145k
    const int ss_ver = chroma & (f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420);
44
145k
    const ptrdiff_t stride = f->sr_cur.p.stride[chroma];
45
145k
    const int sby = (y + (y ? 8 << ss_ver : 0)) >> (6 - ss_ver + f->seq_hdr->sb128);
46
145k
    const int have_tt = f->c->n_tc > 1;
47
145k
    const pixel *lpf = f->lf.lr_lpf_line[plane] +
48
145k
        have_tt * (sby * (4 << f->seq_hdr->sb128) - 4) * PXSTRIDE(stride) + x;
49
50
    // The first stripe of the frame is shorter by 8 luma pixel rows.
51
145k
    int stripe_h = imin((64 - 8 * !y) >> ss_ver, row_h - y);
52
53
145k
    looprestorationfilter_fn lr_fn;
54
145k
    LooprestorationParams params;
55
145k
    if (lr->type == DAV1D_RESTORATION_WIENER) {
56
66.8k
        int16_t (*const filter)[8] = params.filter;
57
66.8k
        filter[0][0] = filter[0][6] = lr->filter_h[0];
58
66.8k
        filter[0][1] = filter[0][5] = lr->filter_h[1];
59
66.8k
        filter[0][2] = filter[0][4] = lr->filter_h[2];
60
66.8k
        filter[0][3] = -(filter[0][0] + filter[0][1] + filter[0][2]) * 2;
61
#if BITDEPTH != 8
62
        /* For 8-bit SIMD it's beneficial to handle the +128 separately
63
         * in order to avoid overflows. */
64
        filter[0][3] += 128;
65
#endif
66
67
66.8k
        filter[1][0] = filter[1][6] = lr->filter_v[0];
68
66.8k
        filter[1][1] = filter[1][5] = lr->filter_v[1];
69
66.8k
        filter[1][2] = filter[1][4] = lr->filter_v[2];
70
66.8k
        filter[1][3] = 128 - (filter[1][0] + filter[1][1] + filter[1][2]) * 2;
71
72
66.8k
        lr_fn = dsp->lr.wiener[!(filter[0][0] | filter[1][0])];
73
78.6k
    } else {
74
78.6k
        assert(lr->type >= DAV1D_RESTORATION_SGRPROJ);
75
78.6k
        const int sgr_idx = lr->type - DAV1D_RESTORATION_SGRPROJ;
76
78.6k
        const uint16_t *const sgr_params = dav1d_sgr_params[sgr_idx];
77
78.6k
        params.sgr.s0 = sgr_params[0];
78
78.6k
        params.sgr.s1 = sgr_params[1];
79
78.6k
        params.sgr.w0 = lr->sgr_weights[0];
80
78.6k
        params.sgr.w1 = 128 - (lr->sgr_weights[0] + lr->sgr_weights[1]);
81
82
78.6k
        lr_fn = dsp->lr.sgr[!!sgr_params[0] + !!sgr_params[1] * 2 - 1];
83
78.6k
    }
84
85
194k
    while (y + stripe_h <= row_h) {
86
        // Change the HAVE_BOTTOM bit in edges to (sby + 1 != f->sbh || y + stripe_h != row_h)
87
194k
        edges ^= (-(sby + 1 != f->sbh || y + stripe_h != row_h) ^ edges) & LR_HAVE_BOTTOM;
88
194k
        lr_fn(p, stride, left, lpf, unit_w, stripe_h, &params, edges HIGHBD_CALL_SUFFIX);
89
90
194k
        left += stripe_h;
91
194k
        y += stripe_h;
92
194k
        p += stripe_h * PXSTRIDE(stride);
93
194k
        edges |= LR_HAVE_TOP;
94
194k
        stripe_h = imin(64 >> ss_ver, row_h - y);
95
194k
        if (stripe_h == 0) break;
96
49.5k
        lpf += 4 * PXSTRIDE(stride);
97
49.5k
    }
98
145k
}
99
100
static void backup4xU(pixel (*dst)[4], const pixel *src, const ptrdiff_t src_stride,
101
                      int u)
102
71.1k
{
103
3.49M
    for (; u > 0; u--, dst++, src += PXSTRIDE(src_stride))
104
3.42M
        pixel_copy(dst, src, 4);
105
71.1k
}
106
107
static void lr_sbrow(const Dav1dFrameContext *const f, pixel *p, const int y,
108
                     const int w, const int h, const int row_h, const int plane)
109
187k
{
110
187k
    const int chroma = !!plane;
111
187k
    const int ss_ver = chroma & (f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420);
112
187k
    const int ss_hor = chroma & (f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444);
113
187k
    const ptrdiff_t p_stride = f->sr_cur.p.stride[chroma];
114
115
187k
    const int unit_size_log2 = f->frame_hdr->restoration.unit_size[!!plane];
116
187k
    const int unit_size = 1 << unit_size_log2;
117
187k
    const int half_unit_size = unit_size >> 1;
118
187k
    const int max_unit_size = unit_size + half_unit_size;
119
120
    // Y coordinate of the sbrow (y is 8 luma pixel rows above row_y)
121
187k
    const int row_y = y + ((8 >> ss_ver) * !!y);
122
123
    // FIXME This is an ugly hack to lookup the proper AV1Filter unit for
124
    // chroma planes. Question: For Multithreaded decoding, is it better
125
    // to store the chroma LR information with collocated Luma information?
126
    // In other words. For a chroma restoration unit locate at 128,128 and
127
    // with a 4:2:0 chroma subsampling, do we store the filter information at
128
    // the AV1Filter unit located at (128,128) or (256,256)
129
    // TODO Support chroma subsampling.
130
187k
    const int shift_hor = 7 - ss_hor;
131
132
    /* maximum sbrow height is 128 + 8 rows offset */
133
187k
    ALIGN_STK_16(pixel, pre_lr_border, 2, [128 + 8][4]);
134
187k
    const Av1RestorationUnit *lr[2];
135
136
187k
    enum LrEdgeFlags edges = (y > 0 ? LR_HAVE_TOP : 0) | LR_HAVE_RIGHT;
137
138
187k
    int aligned_unit_pos = row_y & ~(unit_size - 1);
139
187k
    if (aligned_unit_pos && aligned_unit_pos + half_unit_size > h)
140
10.6k
        aligned_unit_pos -= unit_size;
141
187k
    aligned_unit_pos <<= ss_ver;
142
187k
    const int sb_idx = (aligned_unit_pos >> 7) * f->sr_sb128w;
143
187k
    const int unit_idx = ((aligned_unit_pos >> 6) & 1) << 1;
144
187k
    lr[0] = &f->lf.lr_mask[sb_idx].lr[plane][unit_idx];
145
187k
    int restore = lr[0]->type != DAV1D_RESTORATION_NONE;
146
187k
    int x = 0, bit = 0;
147
368k
    for (; x + max_unit_size <= w; p += unit_size, edges |= LR_HAVE_LEFT, bit ^= 1) {
148
180k
        const int next_x = x + unit_size;
149
180k
        const int next_u_idx = unit_idx + ((next_x >> (shift_hor - 1)) & 1);
150
180k
        lr[!bit] =
151
180k
            &f->lf.lr_mask[sb_idx + (next_x >> shift_hor)].lr[plane][next_u_idx];
152
180k
        const int restore_next = lr[!bit]->type != DAV1D_RESTORATION_NONE;
153
180k
        if (restore_next)
154
71.1k
            backup4xU(pre_lr_border[bit], p + unit_size - 4, p_stride, row_h - y);
155
180k
        if (restore)
156
70.7k
            lr_stripe(f, p, pre_lr_border[!bit], x, y, plane, unit_size, row_h,
157
70.7k
                      lr[bit], edges);
158
180k
        x = next_x;
159
180k
        restore = restore_next;
160
180k
    }
161
187k
    if (restore) {
162
74.7k
        edges &= ~LR_HAVE_RIGHT;
163
74.7k
        const int unit_w = w - x;
164
74.7k
        lr_stripe(f, p, pre_lr_border[!bit], x, y, plane, unit_w, row_h, lr[bit], edges);
165
74.7k
    }
166
187k
}
167
168
void bytefn(dav1d_lr_sbrow)(Dav1dFrameContext *const f, pixel *const dst[3],
169
                            const int sby)
170
96.5k
{
171
96.5k
    const int offset_y = 8 * !!sby;
172
96.5k
    const ptrdiff_t *const dst_stride = f->sr_cur.p.stride;
173
96.5k
    const int restore_planes = f->lf.restore_planes;
174
96.5k
    const int not_last = sby + 1 < f->sbh;
175
176
96.5k
    if (restore_planes & LR_RESTORE_Y) {
177
85.6k
        const int h = f->sr_cur.p.p.h;
178
85.6k
        const int w = f->sr_cur.p.p.w;
179
85.6k
        const int next_row_y = (sby + 1) << (6 + f->seq_hdr->sb128);
180
85.6k
        const int row_h = imin(next_row_y - 8 * not_last, h);
181
85.6k
        const int y_stripe = (sby << (6 + f->seq_hdr->sb128)) - offset_y;
182
85.6k
        lr_sbrow(f, dst[0] - offset_y * PXSTRIDE(dst_stride[0]), y_stripe, w,
183
85.6k
                 h, row_h, 0);
184
85.6k
    }
185
96.5k
    if (restore_planes & (LR_RESTORE_U | LR_RESTORE_V)) {
186
79.2k
        const int ss_ver = f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
187
79.2k
        const int ss_hor = f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
188
79.2k
        const int h = (f->sr_cur.p.p.h + ss_ver) >> ss_ver;
189
79.2k
        const int w = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
190
79.2k
        const int next_row_y = (sby + 1) << ((6 - ss_ver) + f->seq_hdr->sb128);
191
79.2k
        const int row_h = imin(next_row_y - (8 >> ss_ver) * not_last, h);
192
79.2k
        const int offset_uv = offset_y >> ss_ver;
193
79.2k
        const int y_stripe = (sby << ((6 - ss_ver) + f->seq_hdr->sb128)) - offset_uv;
194
79.2k
        if (restore_planes & LR_RESTORE_U)
195
32.7k
            lr_sbrow(f, dst[1] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
196
32.7k
                     w, h, row_h, 1);
197
198
79.2k
        if (restore_planes & LR_RESTORE_V)
199
69.0k
            lr_sbrow(f, dst[2] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
200
69.0k
                     w, h, row_h, 2);
201
79.2k
    }
202
96.5k
}
dav1d_lr_sbrow_8bpc
Line
Count
Source
170
55.6k
{
171
55.6k
    const int offset_y = 8 * !!sby;
172
55.6k
    const ptrdiff_t *const dst_stride = f->sr_cur.p.stride;
173
55.6k
    const int restore_planes = f->lf.restore_planes;
174
55.6k
    const int not_last = sby + 1 < f->sbh;
175
176
55.6k
    if (restore_planes & LR_RESTORE_Y) {
177
49.3k
        const int h = f->sr_cur.p.p.h;
178
49.3k
        const int w = f->sr_cur.p.p.w;
179
49.3k
        const int next_row_y = (sby + 1) << (6 + f->seq_hdr->sb128);
180
49.3k
        const int row_h = imin(next_row_y - 8 * not_last, h);
181
49.3k
        const int y_stripe = (sby << (6 + f->seq_hdr->sb128)) - offset_y;
182
49.3k
        lr_sbrow(f, dst[0] - offset_y * PXSTRIDE(dst_stride[0]), y_stripe, w,
183
49.3k
                 h, row_h, 0);
184
49.3k
    }
185
55.6k
    if (restore_planes & (LR_RESTORE_U | LR_RESTORE_V)) {
186
46.4k
        const int ss_ver = f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
187
46.4k
        const int ss_hor = f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
188
46.4k
        const int h = (f->sr_cur.p.p.h + ss_ver) >> ss_ver;
189
46.4k
        const int w = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
190
46.4k
        const int next_row_y = (sby + 1) << ((6 - ss_ver) + f->seq_hdr->sb128);
191
46.4k
        const int row_h = imin(next_row_y - (8 >> ss_ver) * not_last, h);
192
46.4k
        const int offset_uv = offset_y >> ss_ver;
193
46.4k
        const int y_stripe = (sby << ((6 - ss_ver) + f->seq_hdr->sb128)) - offset_uv;
194
46.4k
        if (restore_planes & LR_RESTORE_U)
195
18.1k
            lr_sbrow(f, dst[1] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
196
18.1k
                     w, h, row_h, 1);
197
198
46.4k
        if (restore_planes & LR_RESTORE_V)
199
39.3k
            lr_sbrow(f, dst[2] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
200
39.3k
                     w, h, row_h, 2);
201
46.4k
    }
202
55.6k
}
dav1d_lr_sbrow_16bpc
Line
Count
Source
170
40.9k
{
171
40.9k
    const int offset_y = 8 * !!sby;
172
40.9k
    const ptrdiff_t *const dst_stride = f->sr_cur.p.stride;
173
40.9k
    const int restore_planes = f->lf.restore_planes;
174
40.9k
    const int not_last = sby + 1 < f->sbh;
175
176
40.9k
    if (restore_planes & LR_RESTORE_Y) {
177
36.3k
        const int h = f->sr_cur.p.p.h;
178
36.3k
        const int w = f->sr_cur.p.p.w;
179
36.3k
        const int next_row_y = (sby + 1) << (6 + f->seq_hdr->sb128);
180
36.3k
        const int row_h = imin(next_row_y - 8 * not_last, h);
181
36.3k
        const int y_stripe = (sby << (6 + f->seq_hdr->sb128)) - offset_y;
182
36.3k
        lr_sbrow(f, dst[0] - offset_y * PXSTRIDE(dst_stride[0]), y_stripe, w,
183
36.3k
                 h, row_h, 0);
184
36.3k
    }
185
40.9k
    if (restore_planes & (LR_RESTORE_U | LR_RESTORE_V)) {
186
32.7k
        const int ss_ver = f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
187
32.7k
        const int ss_hor = f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
188
32.7k
        const int h = (f->sr_cur.p.p.h + ss_ver) >> ss_ver;
189
32.7k
        const int w = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
190
32.7k
        const int next_row_y = (sby + 1) << ((6 - ss_ver) + f->seq_hdr->sb128);
191
32.7k
        const int row_h = imin(next_row_y - (8 >> ss_ver) * not_last, h);
192
32.7k
        const int offset_uv = offset_y >> ss_ver;
193
32.7k
        const int y_stripe = (sby << ((6 - ss_ver) + f->seq_hdr->sb128)) - offset_uv;
194
32.7k
        if (restore_planes & LR_RESTORE_U)
195
14.5k
            lr_sbrow(f, dst[1] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
196
14.5k
                     w, h, row_h, 1);
197
198
32.7k
        if (restore_planes & LR_RESTORE_V)
199
29.7k
            lr_sbrow(f, dst[2] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
200
29.7k
                     w, h, row_h, 2);
201
32.7k
    }
202
40.9k
}