lr_apply_tmpl.c (9089B)
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 { 41 const Dav1dDSPContext *const dsp = f->dsp; 42 const int chroma = !!plane; 43 const int ss_ver = chroma & (f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420); 44 const ptrdiff_t stride = f->sr_cur.p.stride[chroma]; 45 const int sby = (y + (y ? 8 << ss_ver : 0)) >> (6 - ss_ver + f->seq_hdr->sb128); 46 const int have_tt = f->c->n_tc > 1; 47 const pixel *lpf = f->lf.lr_lpf_line[plane] + 48 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 int stripe_h = imin((64 - 8 * !y) >> ss_ver, row_h - y); 52 53 looprestorationfilter_fn lr_fn; 54 LooprestorationParams params; 55 if (lr->type == DAV1D_RESTORATION_WIENER) { 56 int16_t (*const filter)[8] = params.filter; 57 filter[0][0] = filter[0][6] = lr->filter_h[0]; 58 filter[0][1] = filter[0][5] = lr->filter_h[1]; 59 filter[0][2] = filter[0][4] = lr->filter_h[2]; 60 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 filter[1][0] = filter[1][6] = lr->filter_v[0]; 68 filter[1][1] = filter[1][5] = lr->filter_v[1]; 69 filter[1][2] = filter[1][4] = lr->filter_v[2]; 70 filter[1][3] = 128 - (filter[1][0] + filter[1][1] + filter[1][2]) * 2; 71 72 lr_fn = dsp->lr.wiener[!(filter[0][0] | filter[1][0])]; 73 } else { 74 assert(lr->type >= DAV1D_RESTORATION_SGRPROJ); 75 const int sgr_idx = lr->type - DAV1D_RESTORATION_SGRPROJ; 76 const uint16_t *const sgr_params = dav1d_sgr_params[sgr_idx]; 77 params.sgr.s0 = sgr_params[0]; 78 params.sgr.s1 = sgr_params[1]; 79 params.sgr.w0 = lr->sgr_weights[0]; 80 params.sgr.w1 = 128 - (lr->sgr_weights[0] + lr->sgr_weights[1]); 81 82 lr_fn = dsp->lr.sgr[!!sgr_params[0] + !!sgr_params[1] * 2 - 1]; 83 } 84 85 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 edges ^= (-(sby + 1 != f->sbh || y + stripe_h != row_h) ^ edges) & LR_HAVE_BOTTOM; 88 lr_fn(p, stride, left, lpf, unit_w, stripe_h, ¶ms, edges HIGHBD_CALL_SUFFIX); 89 90 left += stripe_h; 91 y += stripe_h; 92 p += stripe_h * PXSTRIDE(stride); 93 edges |= LR_HAVE_TOP; 94 stripe_h = imin(64 >> ss_ver, row_h - y); 95 if (stripe_h == 0) break; 96 lpf += 4 * PXSTRIDE(stride); 97 } 98 } 99 100 static void backup4xU(pixel (*dst)[4], const pixel *src, const ptrdiff_t src_stride, 101 int u) 102 { 103 for (; u > 0; u--, dst++, src += PXSTRIDE(src_stride)) 104 pixel_copy(dst, src, 4); 105 } 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 { 110 const int chroma = !!plane; 111 const int ss_ver = chroma & (f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420); 112 const int ss_hor = chroma & (f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444); 113 const ptrdiff_t p_stride = f->sr_cur.p.stride[chroma]; 114 115 const int unit_size_log2 = f->frame_hdr->restoration.unit_size[!!plane]; 116 const int unit_size = 1 << unit_size_log2; 117 const int half_unit_size = unit_size >> 1; 118 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 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 const int shift_hor = 7 - ss_hor; 131 132 /* maximum sbrow height is 128 + 8 rows offset */ 133 ALIGN_STK_16(pixel, pre_lr_border, 2, [128 + 8][4]); 134 const Av1RestorationUnit *lr[2]; 135 136 enum LrEdgeFlags edges = (y > 0 ? LR_HAVE_TOP : 0) | LR_HAVE_RIGHT; 137 138 int aligned_unit_pos = row_y & ~(unit_size - 1); 139 if (aligned_unit_pos && aligned_unit_pos + half_unit_size > h) 140 aligned_unit_pos -= unit_size; 141 aligned_unit_pos <<= ss_ver; 142 const int sb_idx = (aligned_unit_pos >> 7) * f->sr_sb128w; 143 const int unit_idx = ((aligned_unit_pos >> 6) & 1) << 1; 144 lr[0] = &f->lf.lr_mask[sb_idx].lr[plane][unit_idx]; 145 int restore = lr[0]->type != DAV1D_RESTORATION_NONE; 146 int x = 0, bit = 0; 147 for (; x + max_unit_size <= w; p += unit_size, edges |= LR_HAVE_LEFT, bit ^= 1) { 148 const int next_x = x + unit_size; 149 const int next_u_idx = unit_idx + ((next_x >> (shift_hor - 1)) & 1); 150 lr[!bit] = 151 &f->lf.lr_mask[sb_idx + (next_x >> shift_hor)].lr[plane][next_u_idx]; 152 const int restore_next = lr[!bit]->type != DAV1D_RESTORATION_NONE; 153 if (restore_next) 154 backup4xU(pre_lr_border[bit], p + unit_size - 4, p_stride, row_h - y); 155 if (restore) 156 lr_stripe(f, p, pre_lr_border[!bit], x, y, plane, unit_size, row_h, 157 lr[bit], edges); 158 x = next_x; 159 restore = restore_next; 160 } 161 if (restore) { 162 edges &= ~LR_HAVE_RIGHT; 163 const int unit_w = w - x; 164 lr_stripe(f, p, pre_lr_border[!bit], x, y, plane, unit_w, row_h, lr[bit], edges); 165 } 166 } 167 168 void bytefn(dav1d_lr_sbrow)(Dav1dFrameContext *const f, pixel *const dst[3], 169 const int sby) 170 { 171 const int offset_y = 8 * !!sby; 172 const ptrdiff_t *const dst_stride = f->sr_cur.p.stride; 173 const int restore_planes = f->lf.restore_planes; 174 const int not_last = sby + 1 < f->sbh; 175 176 if (restore_planes & LR_RESTORE_Y) { 177 const int h = f->sr_cur.p.p.h; 178 const int w = f->sr_cur.p.p.w; 179 const int next_row_y = (sby + 1) << (6 + f->seq_hdr->sb128); 180 const int row_h = imin(next_row_y - 8 * not_last, h); 181 const int y_stripe = (sby << (6 + f->seq_hdr->sb128)) - offset_y; 182 lr_sbrow(f, dst[0] - offset_y * PXSTRIDE(dst_stride[0]), y_stripe, w, 183 h, row_h, 0); 184 } 185 if (restore_planes & (LR_RESTORE_U | LR_RESTORE_V)) { 186 const int ss_ver = f->sr_cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420; 187 const int ss_hor = f->sr_cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444; 188 const int h = (f->sr_cur.p.p.h + ss_ver) >> ss_ver; 189 const int w = (f->sr_cur.p.p.w + ss_hor) >> ss_hor; 190 const int next_row_y = (sby + 1) << ((6 - ss_ver) + f->seq_hdr->sb128); 191 const int row_h = imin(next_row_y - (8 >> ss_ver) * not_last, h); 192 const int offset_uv = offset_y >> ss_ver; 193 const int y_stripe = (sby << ((6 - ss_ver) + f->seq_hdr->sb128)) - offset_uv; 194 if (restore_planes & LR_RESTORE_U) 195 lr_sbrow(f, dst[1] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe, 196 w, h, row_h, 1); 197 198 if (restore_planes & LR_RESTORE_V) 199 lr_sbrow(f, dst[2] - offset_uv * PXSTRIDE(dst_stride[1]), y_stripe, 200 w, h, row_h, 2); 201 } 202 }