xref: /aosp_15_r20/external/libdav1d/src/lr_apply_tmpl.c (revision c09093415860a1c2373dacd84c4fde00c507cdfd)
1*c0909341SAndroid Build Coastguard Worker /*
2*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018, VideoLAN and dav1d authors
3*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018, Two Orioles, LLC
4*c0909341SAndroid Build Coastguard Worker  * All rights reserved.
5*c0909341SAndroid Build Coastguard Worker  *
6*c0909341SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
7*c0909341SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
8*c0909341SAndroid Build Coastguard Worker  *
9*c0909341SAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright notice, this
10*c0909341SAndroid Build Coastguard Worker  *    list of conditions and the following disclaimer.
11*c0909341SAndroid Build Coastguard Worker  *
12*c0909341SAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright notice,
13*c0909341SAndroid Build Coastguard Worker  *    this list of conditions and the following disclaimer in the documentation
14*c0909341SAndroid Build Coastguard Worker  *    and/or other materials provided with the distribution.
15*c0909341SAndroid Build Coastguard Worker  *
16*c0909341SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*c0909341SAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*c0909341SAndroid Build Coastguard Worker  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*c0909341SAndroid Build Coastguard Worker  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20*c0909341SAndroid Build Coastguard Worker  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*c0909341SAndroid Build Coastguard Worker  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*c0909341SAndroid Build Coastguard Worker  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*c0909341SAndroid Build Coastguard Worker  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*c0909341SAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*c0909341SAndroid Build Coastguard Worker  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*c0909341SAndroid Build Coastguard Worker  */
27*c0909341SAndroid Build Coastguard Worker 
28*c0909341SAndroid Build Coastguard Worker #include "config.h"
29*c0909341SAndroid Build Coastguard Worker 
30*c0909341SAndroid Build Coastguard Worker #include <stdio.h>
31*c0909341SAndroid Build Coastguard Worker 
32*c0909341SAndroid Build Coastguard Worker #include "common/intops.h"
33*c0909341SAndroid Build Coastguard Worker 
34*c0909341SAndroid Build Coastguard Worker #include "src/lr_apply.h"
35*c0909341SAndroid Build Coastguard Worker 
lr_stripe(const Dav1dFrameContext * const f,pixel * p,const pixel (* left)[4],int x,int y,const int plane,const int unit_w,const int row_h,const Av1RestorationUnit * const lr,enum LrEdgeFlags edges)36*c0909341SAndroid Build Coastguard Worker static void lr_stripe(const Dav1dFrameContext *const f, pixel *p,
37*c0909341SAndroid Build Coastguard Worker                       const pixel (*left)[4], int x, int y,
38*c0909341SAndroid Build Coastguard Worker                       const int plane, const int unit_w, const int row_h,
39*c0909341SAndroid Build Coastguard Worker                       const Av1RestorationUnit *const lr, enum LrEdgeFlags edges)
40*c0909341SAndroid Build Coastguard Worker {
41*c0909341SAndroid Build Coastguard Worker     const Dav1dDSPContext *const dsp = f->dsp;
42*c0909341SAndroid Build Coastguard Worker     const int chroma = !!plane;
43*c0909341SAndroid Build Coastguard Worker     const int ss_ver = chroma & (f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420);
44*c0909341SAndroid Build Coastguard Worker     const ptrdiff_t stride = f->sr_cur.p.stride[chroma];
45*c0909341SAndroid Build Coastguard Worker     const int sby = (y + (y ? 8 << ss_ver : 0)) >> (6 - ss_ver + f->seq_hdr->sb128);
46*c0909341SAndroid Build Coastguard Worker     const int have_tt = f->c->n_tc > 1;
47*c0909341SAndroid Build Coastguard Worker     const pixel *lpf = f->lf.lr_lpf_line[plane] +
48*c0909341SAndroid Build Coastguard Worker         have_tt * (sby * (4 << f->seq_hdr->sb128) - 4) * PXSTRIDE(stride) + x;
49*c0909341SAndroid Build Coastguard Worker 
50*c0909341SAndroid Build Coastguard Worker     // The first stripe of the frame is shorter by 8 luma pixel rows.
51*c0909341SAndroid Build Coastguard Worker     int stripe_h = imin((64 - 8 * !y) >> ss_ver, row_h - y);
52*c0909341SAndroid Build Coastguard Worker 
53*c0909341SAndroid Build Coastguard Worker     looprestorationfilter_fn lr_fn;
54*c0909341SAndroid Build Coastguard Worker     LooprestorationParams params;
55*c0909341SAndroid Build Coastguard Worker     if (lr->type == DAV1D_RESTORATION_WIENER) {
56*c0909341SAndroid Build Coastguard Worker         int16_t (*const filter)[8] = params.filter;
57*c0909341SAndroid Build Coastguard Worker         filter[0][0] = filter[0][6] = lr->filter_h[0];
58*c0909341SAndroid Build Coastguard Worker         filter[0][1] = filter[0][5] = lr->filter_h[1];
59*c0909341SAndroid Build Coastguard Worker         filter[0][2] = filter[0][4] = lr->filter_h[2];
60*c0909341SAndroid Build Coastguard Worker         filter[0][3] = -(filter[0][0] + filter[0][1] + filter[0][2]) * 2;
61*c0909341SAndroid Build Coastguard Worker #if BITDEPTH != 8
62*c0909341SAndroid Build Coastguard Worker         /* For 8-bit SIMD it's beneficial to handle the +128 separately
63*c0909341SAndroid Build Coastguard Worker          * in order to avoid overflows. */
64*c0909341SAndroid Build Coastguard Worker         filter[0][3] += 128;
65*c0909341SAndroid Build Coastguard Worker #endif
66*c0909341SAndroid Build Coastguard Worker 
67*c0909341SAndroid Build Coastguard Worker         filter[1][0] = filter[1][6] = lr->filter_v[0];
68*c0909341SAndroid Build Coastguard Worker         filter[1][1] = filter[1][5] = lr->filter_v[1];
69*c0909341SAndroid Build Coastguard Worker         filter[1][2] = filter[1][4] = lr->filter_v[2];
70*c0909341SAndroid Build Coastguard Worker         filter[1][3] = 128 - (filter[1][0] + filter[1][1] + filter[1][2]) * 2;
71*c0909341SAndroid Build Coastguard Worker 
72*c0909341SAndroid Build Coastguard Worker         lr_fn = dsp->lr.wiener[!(filter[0][0] | filter[1][0])];
73*c0909341SAndroid Build Coastguard Worker     } else {
74*c0909341SAndroid Build Coastguard Worker         assert(lr->type >= DAV1D_RESTORATION_SGRPROJ);
75*c0909341SAndroid Build Coastguard Worker         const int sgr_idx = lr->type - DAV1D_RESTORATION_SGRPROJ;
76*c0909341SAndroid Build Coastguard Worker         const uint16_t *const sgr_params = dav1d_sgr_params[sgr_idx];
77*c0909341SAndroid Build Coastguard Worker         params.sgr.s0 = sgr_params[0];
78*c0909341SAndroid Build Coastguard Worker         params.sgr.s1 = sgr_params[1];
79*c0909341SAndroid Build Coastguard Worker         params.sgr.w0 = lr->sgr_weights[0];
80*c0909341SAndroid Build Coastguard Worker         params.sgr.w1 = 128 - (lr->sgr_weights[0] + lr->sgr_weights[1]);
81*c0909341SAndroid Build Coastguard Worker 
82*c0909341SAndroid Build Coastguard Worker         lr_fn = dsp->lr.sgr[!!sgr_params[0] + !!sgr_params[1] * 2 - 1];
83*c0909341SAndroid Build Coastguard Worker     }
84*c0909341SAndroid Build Coastguard Worker 
85*c0909341SAndroid Build Coastguard Worker     while (y + stripe_h <= row_h) {
86*c0909341SAndroid Build Coastguard Worker         // Change the HAVE_BOTTOM bit in edges to (sby + 1 != f->sbh || y + stripe_h != row_h)
87*c0909341SAndroid Build Coastguard Worker         edges ^= (-(sby + 1 != f->sbh || y + stripe_h != row_h) ^ edges) & LR_HAVE_BOTTOM;
88*c0909341SAndroid Build Coastguard Worker         lr_fn(p, stride, left, lpf, unit_w, stripe_h, &params, edges HIGHBD_CALL_SUFFIX);
89*c0909341SAndroid Build Coastguard Worker 
90*c0909341SAndroid Build Coastguard Worker         left += stripe_h;
91*c0909341SAndroid Build Coastguard Worker         y += stripe_h;
92*c0909341SAndroid Build Coastguard Worker         p += stripe_h * PXSTRIDE(stride);
93*c0909341SAndroid Build Coastguard Worker         edges |= LR_HAVE_TOP;
94*c0909341SAndroid Build Coastguard Worker         stripe_h = imin(64 >> ss_ver, row_h - y);
95*c0909341SAndroid Build Coastguard Worker         if (stripe_h == 0) break;
96*c0909341SAndroid Build Coastguard Worker         lpf += 4 * PXSTRIDE(stride);
97*c0909341SAndroid Build Coastguard Worker     }
98*c0909341SAndroid Build Coastguard Worker }
99*c0909341SAndroid Build Coastguard Worker 
backup4xU(pixel (* dst)[4],const pixel * src,const ptrdiff_t src_stride,int u)100*c0909341SAndroid Build Coastguard Worker static void backup4xU(pixel (*dst)[4], const pixel *src, const ptrdiff_t src_stride,
101*c0909341SAndroid Build Coastguard Worker                       int u)
102*c0909341SAndroid Build Coastguard Worker {
103*c0909341SAndroid Build Coastguard Worker     for (; u > 0; u--, dst++, src += PXSTRIDE(src_stride))
104*c0909341SAndroid Build Coastguard Worker         pixel_copy(dst, src, 4);
105*c0909341SAndroid Build Coastguard Worker }
106*c0909341SAndroid Build Coastguard Worker 
lr_sbrow(const Dav1dFrameContext * const f,pixel * p,const int y,const int w,const int h,const int row_h,const int plane)107*c0909341SAndroid Build Coastguard Worker static void lr_sbrow(const Dav1dFrameContext *const f, pixel *p, const int y,
108*c0909341SAndroid Build Coastguard Worker                      const int w, const int h, const int row_h, const int plane)
109*c0909341SAndroid Build Coastguard Worker {
110*c0909341SAndroid Build Coastguard Worker     const int chroma = !!plane;
111*c0909341SAndroid Build Coastguard Worker     const int ss_ver = chroma & (f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420);
112*c0909341SAndroid Build Coastguard Worker     const int ss_hor = chroma & (f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444);
113*c0909341SAndroid Build Coastguard Worker     const ptrdiff_t p_stride = f->sr_cur.p.stride[chroma];
114*c0909341SAndroid Build Coastguard Worker 
115*c0909341SAndroid Build Coastguard Worker     const int unit_size_log2 = f->frame_hdr->restoration.unit_size[!!plane];
116*c0909341SAndroid Build Coastguard Worker     const int unit_size = 1 << unit_size_log2;
117*c0909341SAndroid Build Coastguard Worker     const int half_unit_size = unit_size >> 1;
118*c0909341SAndroid Build Coastguard Worker     const int max_unit_size = unit_size + half_unit_size;
119*c0909341SAndroid Build Coastguard Worker 
120*c0909341SAndroid Build Coastguard Worker     // Y coordinate of the sbrow (y is 8 luma pixel rows above row_y)
121*c0909341SAndroid Build Coastguard Worker     const int row_y = y + ((8 >> ss_ver) * !!y);
122*c0909341SAndroid Build Coastguard Worker 
123*c0909341SAndroid Build Coastguard Worker     // FIXME This is an ugly hack to lookup the proper AV1Filter unit for
124*c0909341SAndroid Build Coastguard Worker     // chroma planes. Question: For Multithreaded decoding, is it better
125*c0909341SAndroid Build Coastguard Worker     // to store the chroma LR information with collocated Luma information?
126*c0909341SAndroid Build Coastguard Worker     // In other words. For a chroma restoration unit locate at 128,128 and
127*c0909341SAndroid Build Coastguard Worker     // with a 4:2:0 chroma subsampling, do we store the filter information at
128*c0909341SAndroid Build Coastguard Worker     // the AV1Filter unit located at (128,128) or (256,256)
129*c0909341SAndroid Build Coastguard Worker     // TODO Support chroma subsampling.
130*c0909341SAndroid Build Coastguard Worker     const int shift_hor = 7 - ss_hor;
131*c0909341SAndroid Build Coastguard Worker 
132*c0909341SAndroid Build Coastguard Worker     /* maximum sbrow height is 128 + 8 rows offset */
133*c0909341SAndroid Build Coastguard Worker     ALIGN_STK_16(pixel, pre_lr_border, 2, [128 + 8][4]);
134*c0909341SAndroid Build Coastguard Worker     const Av1RestorationUnit *lr[2];
135*c0909341SAndroid Build Coastguard Worker 
136*c0909341SAndroid Build Coastguard Worker     enum LrEdgeFlags edges = (y > 0 ? LR_HAVE_TOP : 0) | LR_HAVE_RIGHT;
137*c0909341SAndroid Build Coastguard Worker 
138*c0909341SAndroid Build Coastguard Worker     int aligned_unit_pos = row_y & ~(unit_size - 1);
139*c0909341SAndroid Build Coastguard Worker     if (aligned_unit_pos && aligned_unit_pos + half_unit_size > h)
140*c0909341SAndroid Build Coastguard Worker         aligned_unit_pos -= unit_size;
141*c0909341SAndroid Build Coastguard Worker     aligned_unit_pos <<= ss_ver;
142*c0909341SAndroid Build Coastguard Worker     const int sb_idx = (aligned_unit_pos >> 7) * f->sr_sb128w;
143*c0909341SAndroid Build Coastguard Worker     const int unit_idx = ((aligned_unit_pos >> 6) & 1) << 1;
144*c0909341SAndroid Build Coastguard Worker     lr[0] = &f->lf.lr_mask[sb_idx].lr[plane][unit_idx];
145*c0909341SAndroid Build Coastguard Worker     int restore = lr[0]->type != DAV1D_RESTORATION_NONE;
146*c0909341SAndroid Build Coastguard Worker     int x = 0, bit = 0;
147*c0909341SAndroid Build Coastguard Worker     for (; x + max_unit_size <= w; p += unit_size, edges |= LR_HAVE_LEFT, bit ^= 1) {
148*c0909341SAndroid Build Coastguard Worker         const int next_x = x + unit_size;
149*c0909341SAndroid Build Coastguard Worker         const int next_u_idx = unit_idx + ((next_x >> (shift_hor - 1)) & 1);
150*c0909341SAndroid Build Coastguard Worker         lr[!bit] =
151*c0909341SAndroid Build Coastguard Worker             &f->lf.lr_mask[sb_idx + (next_x >> shift_hor)].lr[plane][next_u_idx];
152*c0909341SAndroid Build Coastguard Worker         const int restore_next = lr[!bit]->type != DAV1D_RESTORATION_NONE;
153*c0909341SAndroid Build Coastguard Worker         if (restore_next)
154*c0909341SAndroid Build Coastguard Worker             backup4xU(pre_lr_border[bit], p + unit_size - 4, p_stride, row_h - y);
155*c0909341SAndroid Build Coastguard Worker         if (restore)
156*c0909341SAndroid Build Coastguard Worker             lr_stripe(f, p, pre_lr_border[!bit], x, y, plane, unit_size, row_h,
157*c0909341SAndroid Build Coastguard Worker                       lr[bit], edges);
158*c0909341SAndroid Build Coastguard Worker         x = next_x;
159*c0909341SAndroid Build Coastguard Worker         restore = restore_next;
160*c0909341SAndroid Build Coastguard Worker     }
161*c0909341SAndroid Build Coastguard Worker     if (restore) {
162*c0909341SAndroid Build Coastguard Worker         edges &= ~LR_HAVE_RIGHT;
163*c0909341SAndroid Build Coastguard Worker         const int unit_w = w - x;
164*c0909341SAndroid Build Coastguard Worker         lr_stripe(f, p, pre_lr_border[!bit], x, y, plane, unit_w, row_h, lr[bit], edges);
165*c0909341SAndroid Build Coastguard Worker     }
166*c0909341SAndroid Build Coastguard Worker }
167*c0909341SAndroid Build Coastguard Worker 
bytefn(dav1d_lr_sbrow)168*c0909341SAndroid Build Coastguard Worker void bytefn(dav1d_lr_sbrow)(Dav1dFrameContext *const f, pixel *const dst[3],
169*c0909341SAndroid Build Coastguard Worker                             const int sby)
170*c0909341SAndroid Build Coastguard Worker {
171*c0909341SAndroid Build Coastguard Worker     const int offset_y = 8 * !!sby;
172*c0909341SAndroid Build Coastguard Worker     const ptrdiff_t *const dst_stride = f->sr_cur.p.stride;
173*c0909341SAndroid Build Coastguard Worker     const int restore_planes = f->lf.restore_planes;
174*c0909341SAndroid Build Coastguard Worker     const int not_last = sby + 1 < f->sbh;
175*c0909341SAndroid Build Coastguard Worker 
176*c0909341SAndroid Build Coastguard Worker     if (restore_planes & LR_RESTORE_Y) {
177*c0909341SAndroid Build Coastguard Worker         const int h = f->sr_cur.p.p.h;
178*c0909341SAndroid Build Coastguard Worker         const int w = f->sr_cur.p.p.w;
179*c0909341SAndroid Build Coastguard Worker         const int next_row_y = (sby + 1) << (6 + f->seq_hdr->sb128);
180*c0909341SAndroid Build Coastguard Worker         const int row_h = imin(next_row_y - 8 * not_last, h);
181*c0909341SAndroid Build Coastguard Worker         const int y_stripe = (sby << (6 + f->seq_hdr->sb128)) - offset_y;
182*c0909341SAndroid Build Coastguard Worker         lr_sbrow(f, dst[0] - offset_y * PXSTRIDE(dst_stride[0]), y_stripe, w,
183*c0909341SAndroid Build Coastguard Worker                  h, row_h, 0);
184*c0909341SAndroid Build Coastguard Worker     }
185*c0909341SAndroid Build Coastguard Worker     if (restore_planes & (LR_RESTORE_U | LR_RESTORE_V)) {
186*c0909341SAndroid Build Coastguard Worker         const int ss_ver = f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
187*c0909341SAndroid Build Coastguard Worker         const int ss_hor = f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
188*c0909341SAndroid Build Coastguard Worker         const int h = (f->sr_cur.p.p.h + ss_ver) >> ss_ver;
189*c0909341SAndroid Build Coastguard Worker         const int w = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
190*c0909341SAndroid Build Coastguard Worker         const int next_row_y = (sby + 1) << ((6 - ss_ver) + f->seq_hdr->sb128);
191*c0909341SAndroid Build Coastguard Worker         const int row_h = imin(next_row_y - (8 >> ss_ver) * not_last, h);
192*c0909341SAndroid Build Coastguard Worker         const int offset_uv = offset_y >> ss_ver;
193*c0909341SAndroid Build Coastguard Worker         const int y_stripe = (sby << ((6 - ss_ver) + f->seq_hdr->sb128)) - offset_uv;
194*c0909341SAndroid Build Coastguard Worker         if (restore_planes & LR_RESTORE_U)
195*c0909341SAndroid Build Coastguard Worker             lr_sbrow(f, dst[1] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
196*c0909341SAndroid Build Coastguard Worker                      w, h, row_h, 1);
197*c0909341SAndroid Build Coastguard Worker 
198*c0909341SAndroid Build Coastguard Worker         if (restore_planes & LR_RESTORE_V)
199*c0909341SAndroid Build Coastguard Worker             lr_sbrow(f, dst[2] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe,
200*c0909341SAndroid Build Coastguard Worker                      w, h, row_h, 2);
201*c0909341SAndroid Build Coastguard Worker     }
202*c0909341SAndroid Build Coastguard Worker }
203