blob: aa06313d657dbe1a7fbb81147f0a5447e47b51c0 [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 *
Yaowu Xuc27fc142016-08-22 16:08:15 -070011 */
12
13#include <math.h>
14
Yaowu Xuf883b422016-08-30 14:01:10 -070015#include "./aom_config.h"
16#include "./aom_dsp_rtcd.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070017#include "av1/common/onyxc_int.h"
18#include "av1/common/restoration.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070019#include "aom_dsp/aom_dsp_common.h"
20#include "aom_mem/aom_mem.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070021#include "aom_ports/mem.h"
22
Debargha Mukherjee3981be92016-11-21 09:35:44 -080023static int domaintxfmrf_vtable[DOMAINTXFMRF_ITERS][DOMAINTXFMRF_PARAMS][256];
24
Debargha Mukherjee818e42a2016-12-12 11:52:56 -080025// Whether to filter only y or not
26static const int override_y_only[RESTORE_TYPES] = { 1, 1, 1, 1, 1 };
27
Debargha Mukherjee3981be92016-11-21 09:35:44 -080028static const int domaintxfmrf_params[DOMAINTXFMRF_PARAMS] = {
29 48, 52, 56, 60, 64, 68, 72, 76, 80, 82, 84, 86, 88,
30 90, 92, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
31 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
32 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 132, 134,
33 136, 138, 140, 142, 146, 150, 154, 158, 162, 166, 170, 174
34};
35
Debargha Mukherjee8f209a82016-10-12 10:47:01 -070036const sgr_params_type sgr_params[SGRPROJ_PARAMS] = {
37 // r1, eps1, r2, eps2
38 { 2, 27, 1, 11 }, { 2, 31, 1, 12 }, { 2, 37, 1, 12 }, { 2, 44, 1, 12 },
39 { 2, 49, 1, 13 }, { 2, 54, 1, 14 }, { 2, 60, 1, 15 }, { 2, 68, 1, 15 },
40};
41
Yaowu Xuc27fc142016-08-22 16:08:15 -070042typedef void (*restore_func_type)(uint8_t *data8, int width, int height,
43 int stride, RestorationInternal *rst,
44 uint8_t *tmpdata8, int tmpstride);
Yaowu Xuf883b422016-08-30 14:01:10 -070045#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070046typedef void (*restore_func_highbd_type)(uint8_t *data8, int width, int height,
47 int stride, RestorationInternal *rst,
48 uint8_t *tmpdata8, int tmpstride,
49 int bit_depth);
Yaowu Xuf883b422016-08-30 14:01:10 -070050#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070051
Debargha Mukherjee3981be92016-11-21 09:35:44 -080052static void GenDomainTxfmRFVtable() {
53 int i, j;
54 const double sigma_s = sqrt(2.0);
55 for (i = 0; i < DOMAINTXFMRF_ITERS; ++i) {
56 const int nm = (1 << (DOMAINTXFMRF_ITERS - i - 1));
57 const double A = exp(-DOMAINTXFMRF_MULT / (sigma_s * nm));
58 for (j = 0; j < DOMAINTXFMRF_PARAMS; ++j) {
59 const double sigma_r =
60 (double)domaintxfmrf_params[j] / DOMAINTXFMRF_SIGMA_SCALE;
61 const double scale = sigma_s / sigma_r;
62 int k;
63 for (k = 0; k < 256; ++k) {
64 domaintxfmrf_vtable[i][j][k] =
65 RINT(DOMAINTXFMRF_VTABLE_PREC * pow(A, 1.0 + k * scale));
66 }
67 }
68 }
69}
70
Debargha Mukherjee0e67b252016-12-08 09:22:44 -080071void av1_loop_restoration_precal() { GenDomainTxfmRFVtable(); }
Yaowu Xuc27fc142016-08-22 16:08:15 -070072
Yaowu Xuf883b422016-08-30 14:01:10 -070073void av1_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi,
74 int kf, int width, int height) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070075 int i, tile_idx;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070076 rst->rsi = rsi;
77 rst->keyframe = kf;
Yaowu Xuc27fc142016-08-22 16:08:15 -070078 rst->subsampling_x = 0;
79 rst->subsampling_y = 0;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070080 rst->ntiles =
clang-formatbda8d612016-09-19 15:55:46 -070081 av1_get_rest_ntiles(width, height, &rst->tile_width, &rst->tile_height,
82 &rst->nhtiles, &rst->nvtiles);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070083 if (rsi->frame_restoration_type == RESTORE_WIENER) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070084 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
Debargha Mukherjee3981be92016-11-21 09:35:44 -080085 if (rsi->wiener_info[tile_idx].level) {
86 rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] =
87 rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] =
88 RESTORATION_FILT_STEP;
89 for (i = 0; i < RESTORATION_HALFWIN; ++i) {
90 rsi->wiener_info[tile_idx].vfilter[RESTORATION_WIN - 1 - i] =
91 rsi->wiener_info[tile_idx].vfilter[i];
92 rsi->wiener_info[tile_idx].hfilter[RESTORATION_WIN - 1 - i] =
93 rsi->wiener_info[tile_idx].hfilter[i];
94 rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] -=
95 2 * rsi->wiener_info[tile_idx].vfilter[i];
96 rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] -=
97 2 * rsi->wiener_info[tile_idx].hfilter[i];
98 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070099 }
100 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700101 } else if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700102 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700103 if (rsi->restoration_type[tile_idx] == RESTORE_WIENER) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700104 rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] =
105 rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] =
106 RESTORATION_FILT_STEP;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700107 for (i = 0; i < RESTORATION_HALFWIN; ++i) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700108 rsi->wiener_info[tile_idx].vfilter[RESTORATION_WIN - 1 - i] =
109 rsi->wiener_info[tile_idx].vfilter[i];
110 rsi->wiener_info[tile_idx].hfilter[RESTORATION_WIN - 1 - i] =
111 rsi->wiener_info[tile_idx].hfilter[i];
112 rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] -=
113 2 * rsi->wiener_info[tile_idx].vfilter[i];
114 rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] -=
115 2 * rsi->wiener_info[tile_idx].hfilter[i];
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700116 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700117 }
118 }
119 }
120}
121
Yaowu Xuc27fc142016-08-22 16:08:15 -0700122uint8_t hor_sym_filter(uint8_t *d, int *hfilter) {
123 int32_t s =
124 (1 << (RESTORATION_FILT_BITS - 1)) + d[0] * hfilter[RESTORATION_HALFWIN];
125 int i;
126 for (i = 1; i <= RESTORATION_HALFWIN; ++i)
127 s += (d[i] + d[-i]) * hfilter[RESTORATION_HALFWIN + i];
128 return clip_pixel(s >> RESTORATION_FILT_BITS);
129}
130
131uint8_t ver_sym_filter(uint8_t *d, int stride, int *vfilter) {
132 int32_t s =
133 (1 << (RESTORATION_FILT_BITS - 1)) + d[0] * vfilter[RESTORATION_HALFWIN];
134 int i;
135 for (i = 1; i <= RESTORATION_HALFWIN; ++i)
136 s += (d[i * stride] + d[-i * stride]) * vfilter[RESTORATION_HALFWIN + i];
137 return clip_pixel(s >> RESTORATION_FILT_BITS);
138}
139
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700140static void loop_wiener_filter_tile(uint8_t *data, int tile_idx, int width,
141 int height, int stride,
142 RestorationInternal *rst, uint8_t *tmpdata,
143 int tmpstride) {
144 const int tile_width = rst->tile_width >> rst->subsampling_x;
145 const int tile_height = rst->tile_height >> rst->subsampling_y;
146 int i, j;
147 int h_start, h_end, v_start, v_end;
148 uint8_t *data_p, *tmpdata_p;
149
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700150 if (rst->rsi->wiener_info[tile_idx].level == 0) return;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700151 // Filter row-wise
152 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
153 tile_width, tile_height, width, height, 1, 0,
154 &h_start, &h_end, &v_start, &v_end);
155 data_p = data + h_start + v_start * stride;
156 tmpdata_p = tmpdata + h_start + v_start * tmpstride;
157 for (i = 0; i < (v_end - v_start); ++i) {
158 for (j = 0; j < (h_end - h_start); ++j) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700159 *tmpdata_p++ =
160 hor_sym_filter(data_p++, rst->rsi->wiener_info[tile_idx].hfilter);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700161 }
162 data_p += stride - (h_end - h_start);
163 tmpdata_p += tmpstride - (h_end - h_start);
164 }
165 // Filter col-wise
166 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
167 tile_width, tile_height, width, height, 0, 1,
168 &h_start, &h_end, &v_start, &v_end);
169 data_p = data + h_start + v_start * stride;
170 tmpdata_p = tmpdata + h_start + v_start * tmpstride;
171 for (i = 0; i < (v_end - v_start); ++i) {
172 for (j = 0; j < (h_end - h_start); ++j) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700173 *data_p++ = ver_sym_filter(tmpdata_p++, tmpstride,
174 rst->rsi->wiener_info[tile_idx].vfilter);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700175 }
176 data_p += stride - (h_end - h_start);
177 tmpdata_p += tmpstride - (h_end - h_start);
178 }
179}
180
Yaowu Xuc27fc142016-08-22 16:08:15 -0700181static void loop_wiener_filter(uint8_t *data, int width, int height, int stride,
182 RestorationInternal *rst, uint8_t *tmpdata,
183 int tmpstride) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700184 int tile_idx;
185 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700186 uint8_t *data_p, *tmpdata_p;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700187 // Initialize tmp buffer
188 data_p = data;
189 tmpdata_p = tmpdata;
190 for (i = 0; i < height; ++i) {
191 memcpy(tmpdata_p, data_p, sizeof(*data_p) * width);
192 data_p += stride;
193 tmpdata_p += tmpstride;
194 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700195 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700196 loop_wiener_filter_tile(data, tile_idx, width, height, stride, rst, tmpdata,
197 tmpstride);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700198 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700199}
Yaowu Xuc27fc142016-08-22 16:08:15 -0700200
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700201static void boxsum(int64_t *src, int width, int height, int src_stride, int r,
202 int sqr, int64_t *dst, int dst_stride, int64_t *tmp,
203 int tmp_stride) {
204 int i, j;
205
206 if (sqr) {
207 for (j = 0; j < width; ++j) tmp[j] = src[j] * src[j];
208 for (j = 0; j < width; ++j)
209 for (i = 1; i < height; ++i)
210 tmp[i * tmp_stride + j] =
211 tmp[(i - 1) * tmp_stride + j] +
212 src[i * src_stride + j] * src[i * src_stride + j];
213 } else {
214 memcpy(tmp, src, sizeof(*tmp) * width);
215 for (j = 0; j < width; ++j)
216 for (i = 1; i < height; ++i)
217 tmp[i * tmp_stride + j] =
218 tmp[(i - 1) * tmp_stride + j] + src[i * src_stride + j];
219 }
220 for (i = 0; i <= r; ++i)
221 memcpy(&dst[i * dst_stride], &tmp[(i + r) * tmp_stride],
222 sizeof(*tmp) * width);
223 for (i = r + 1; i < height - r; ++i)
224 for (j = 0; j < width; ++j)
225 dst[i * dst_stride + j] =
226 tmp[(i + r) * tmp_stride + j] - tmp[(i - r - 1) * tmp_stride + j];
227 for (i = height - r; i < height; ++i)
228 for (j = 0; j < width; ++j)
229 dst[i * dst_stride + j] = tmp[(height - 1) * tmp_stride + j] -
230 tmp[(i - r - 1) * tmp_stride + j];
231
232 for (i = 0; i < height; ++i) tmp[i * tmp_stride] = dst[i * dst_stride];
233 for (i = 0; i < height; ++i)
234 for (j = 1; j < width; ++j)
235 tmp[i * tmp_stride + j] =
236 tmp[i * tmp_stride + j - 1] + dst[i * src_stride + j];
237
238 for (j = 0; j <= r; ++j)
239 for (i = 0; i < height; ++i)
240 dst[i * dst_stride + j] = tmp[i * tmp_stride + j + r];
241 for (j = r + 1; j < width - r; ++j)
242 for (i = 0; i < height; ++i)
243 dst[i * dst_stride + j] =
244 tmp[i * tmp_stride + j + r] - tmp[i * tmp_stride + j - r - 1];
245 for (j = width - r; j < width; ++j)
246 for (i = 0; i < height; ++i)
247 dst[i * dst_stride + j] =
248 tmp[i * tmp_stride + width - 1] - tmp[i * tmp_stride + j - r - 1];
249}
250
251static void boxnum(int width, int height, int r, int8_t *num, int num_stride) {
252 int i, j;
Debargha Mukherjee1ee98b62016-12-07 11:24:13 -0800253 for (i = 0; i <= AOMMIN(r, height - 1); ++i) {
254 for (j = 0; j <= AOMMIN(r, width - 1); ++j) {
255 num[i * num_stride + j] =
256 AOMMIN(r + 1 + i, height) * AOMMIN(r + 1 + j, width);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700257 num[i * num_stride + (width - 1 - j)] = num[i * num_stride + j];
258 num[(height - 1 - i) * num_stride + j] = num[i * num_stride + j];
259 num[(height - 1 - i) * num_stride + (width - 1 - j)] =
260 num[i * num_stride + j];
261 }
262 }
Debargha Mukherjee1ee98b62016-12-07 11:24:13 -0800263 for (j = 0; j <= AOMMIN(r, width - 1); ++j) {
264 const int val = AOMMIN(2 * r + 1, height) * AOMMIN(r + 1 + j, width);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700265 for (i = r + 1; i < height - r; ++i) {
266 num[i * num_stride + j] = val;
267 num[i * num_stride + (width - 1 - j)] = val;
268 }
269 }
Debargha Mukherjee1ee98b62016-12-07 11:24:13 -0800270 for (i = 0; i <= AOMMIN(r, height - 1); ++i) {
271 const int val = AOMMIN(2 * r + 1, width) * AOMMIN(r + 1 + i, height);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700272 for (j = r + 1; j < width - r; ++j) {
273 num[i * num_stride + j] = val;
274 num[(height - 1 - i) * num_stride + j] = val;
275 }
276 }
277 for (i = r + 1; i < height - r; ++i) {
278 for (j = r + 1; j < width - r; ++j) {
Debargha Mukherjee1ee98b62016-12-07 11:24:13 -0800279 num[i * num_stride + j] =
280 AOMMIN(2 * r + 1, height) * AOMMIN(2 * r + 1, width);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700281 }
282 }
283}
284
285void decode_xq(int *xqd, int *xq) {
286 xq[0] = -xqd[0];
287 xq[1] = (1 << SGRPROJ_PRJ_BITS) - xq[0] - xqd[1];
288}
289
290#define APPROXIMATE_SGR 1
291void av1_selfguided_restoration(int64_t *dgd, int width, int height, int stride,
292 int bit_depth, int r, int eps, void *tmpbuf) {
293 int64_t *A = (int64_t *)tmpbuf;
294 int64_t *B = A + RESTORATION_TILEPELS_MAX;
295 int64_t *T = B + RESTORATION_TILEPELS_MAX;
296 int8_t num[RESTORATION_TILEPELS_MAX];
297 int i, j;
298 eps <<= 2 * (bit_depth - 8);
299
300 boxsum(dgd, width, height, stride, r, 0, B, width, T, width);
301 boxsum(dgd, width, height, stride, r, 1, A, width, T, width);
302 boxnum(width, height, r, num, width);
303 for (i = 0; i < height; ++i) {
304 for (j = 0; j < width; ++j) {
305 const int k = i * width + j;
306 const int n = num[k];
307 int64_t den;
308 A[k] = A[k] * n - B[k] * B[k];
309 den = A[k] + n * n * eps;
310 A[k] = ((A[k] << SGRPROJ_SGR_BITS) + (den >> 1)) / den;
311 B[k] = ((SGRPROJ_SGR - A[k]) * B[k] + (n >> 1)) / n;
312 }
313 }
314#if APPROXIMATE_SGR
315 i = 0;
316 j = 0;
317 {
318 const int k = i * width + j;
319 const int l = i * stride + j;
320 const int nb = 3;
321 const int64_t a =
322 3 * A[k] + 2 * A[k + 1] + 2 * A[k + width] + A[k + width + 1];
323 const int64_t b =
324 3 * B[k] + 2 * B[k + 1] + 2 * B[k + width] + B[k + width + 1];
325 const int64_t v =
326 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
327 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
328 }
329 i = 0;
330 j = width - 1;
331 {
332 const int k = i * width + j;
333 const int l = i * stride + j;
334 const int nb = 3;
335 const int64_t a =
336 3 * A[k] + 2 * A[k - 1] + 2 * A[k + width] + A[k + width - 1];
337 const int64_t b =
338 3 * B[k] + 2 * B[k - 1] + 2 * B[k + width] + B[k + width - 1];
339 const int64_t v =
340 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
341 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
342 }
343 i = height - 1;
344 j = 0;
345 {
346 const int k = i * width + j;
347 const int l = i * stride + j;
348 const int nb = 3;
349 const int64_t a =
350 3 * A[k] + 2 * A[k + 1] + 2 * A[k - width] + A[k - width + 1];
351 const int64_t b =
352 3 * B[k] + 2 * B[k + 1] + 2 * B[k - width] + B[k - width + 1];
353 const int64_t v =
354 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
355 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
356 }
357 i = height - 1;
358 j = width - 1;
359 {
360 const int k = i * width + j;
361 const int l = i * stride + j;
362 const int nb = 3;
363 const int64_t a =
364 3 * A[k] + 2 * A[k - 1] + 2 * A[k - width] + A[k - width - 1];
365 const int64_t b =
366 3 * B[k] + 2 * B[k - 1] + 2 * B[k - width] + B[k - width - 1];
367 const int64_t v =
368 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
369 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
370 }
371 i = 0;
372 for (j = 1; j < width - 1; ++j) {
373 const int k = i * width + j;
374 const int l = i * stride + j;
375 const int nb = 3;
376 const int64_t a = A[k] + 2 * (A[k - 1] + A[k + 1]) + A[k + width] +
377 A[k + width - 1] + A[k + width + 1];
378 const int64_t b = B[k] + 2 * (B[k - 1] + B[k + 1]) + B[k + width] +
379 B[k + width - 1] + B[k + width + 1];
380 const int64_t v =
381 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
382 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
383 }
384 i = height - 1;
385 for (j = 1; j < width - 1; ++j) {
386 const int k = i * width + j;
387 const int l = i * stride + j;
388 const int nb = 3;
389 const int64_t a = A[k] + 2 * (A[k - 1] + A[k + 1]) + A[k - width] +
390 A[k - width - 1] + A[k - width + 1];
391 const int64_t b = B[k] + 2 * (B[k - 1] + B[k + 1]) + B[k - width] +
392 B[k - width - 1] + B[k - width + 1];
393 const int64_t v =
394 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
395 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
396 }
397 j = 0;
398 for (i = 1; i < height - 1; ++i) {
399 const int k = i * width + j;
400 const int l = i * stride + j;
401 const int nb = 3;
402 const int64_t a = A[k] + 2 * (A[k - width] + A[k + width]) + A[k + 1] +
403 A[k - width + 1] + A[k + width + 1];
404 const int64_t b = B[k] + 2 * (B[k - width] + B[k + width]) + B[k + 1] +
405 B[k - width + 1] + B[k + width + 1];
406 const int64_t v =
407 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
408 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
409 }
410 j = width - 1;
411 for (i = 1; i < height - 1; ++i) {
412 const int k = i * width + j;
413 const int l = i * stride + j;
414 const int nb = 3;
415 const int64_t a = A[k] + 2 * (A[k - width] + A[k + width]) + A[k - 1] +
416 A[k - width - 1] + A[k + width - 1];
417 const int64_t b = B[k] + 2 * (B[k - width] + B[k + width]) + B[k - 1] +
418 B[k - width - 1] + B[k + width - 1];
419 const int64_t v =
420 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
421 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
422 }
423 for (i = 1; i < height - 1; ++i) {
424 for (j = 1; j < width - 1; ++j) {
425 const int k = i * width + j;
426 const int l = i * stride + j;
427 const int nb = 5;
428 const int64_t a =
429 (A[k] + A[k - 1] + A[k + 1] + A[k - width] + A[k + width]) * 4 +
430 (A[k - 1 - width] + A[k - 1 + width] + A[k + 1 - width] +
431 A[k + 1 + width]) *
432 3;
433 const int64_t b =
434 (B[k] + B[k - 1] + B[k + 1] + B[k - width] + B[k + width]) * 4 +
435 (B[k - 1 - width] + B[k - 1 + width] + B[k + 1 - width] +
436 B[k + 1 + width]) *
437 3;
438 const int64_t v =
439 (((a * dgd[l] + b) << SGRPROJ_RST_BITS) + (1 << nb) / 2) >> nb;
440 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
441 }
442 }
443#else
444 if (r > 1) boxnum(width, height, r = 1, num, width);
445 boxsum(A, width, height, width, r, 0, A, width, T, width);
446 boxsum(B, width, height, width, r, 0, B, width, T, width);
447 for (i = 0; i < height; ++i) {
448 for (j = 0; j < width; ++j) {
449 const int k = i * width + j;
450 const int l = i * stride + j;
451 const int n = num[k];
452 const int64_t v =
453 (((A[k] * dgd[l] + B[k]) << SGRPROJ_RST_BITS) + (n >> 1)) / n;
454 dgd[l] = ROUND_POWER_OF_TWO(v, SGRPROJ_SGR_BITS);
455 }
456 }
457#endif // APPROXIMATE_SGR
458}
459
460static void apply_selfguided_restoration(int64_t *dat, int width, int height,
461 int stride, int bit_depth, int eps,
462 int *xqd, void *tmpbuf) {
463 int xq[2];
464 int64_t *flt1 = (int64_t *)tmpbuf;
465 int64_t *flt2 = flt1 + RESTORATION_TILEPELS_MAX;
466 uint8_t *tmpbuf2 = (uint8_t *)(flt2 + RESTORATION_TILEPELS_MAX);
467 int i, j;
468 for (i = 0; i < height; ++i) {
469 for (j = 0; j < width; ++j) {
470 assert(i * width + j < RESTORATION_TILEPELS_MAX);
471 flt1[i * width + j] = dat[i * stride + j];
472 flt2[i * width + j] = dat[i * stride + j];
473 }
474 }
475 av1_selfguided_restoration(flt1, width, height, width, bit_depth,
476 sgr_params[eps].r1, sgr_params[eps].e1, tmpbuf2);
477 av1_selfguided_restoration(flt2, width, height, width, bit_depth,
478 sgr_params[eps].r2, sgr_params[eps].e2, tmpbuf2);
479 decode_xq(xqd, xq);
480 for (i = 0; i < height; ++i) {
481 for (j = 0; j < width; ++j) {
482 const int k = i * width + j;
483 const int l = i * stride + j;
484 const int64_t u = ((int64_t)dat[l] << SGRPROJ_RST_BITS);
485 const int64_t f1 = (int64_t)flt1[k] - u;
486 const int64_t f2 = (int64_t)flt2[k] - u;
487 const int64_t v = xq[0] * f1 + xq[1] * f2 + (u << SGRPROJ_PRJ_BITS);
488 const int16_t w =
489 (int16_t)ROUND_POWER_OF_TWO(v, SGRPROJ_PRJ_BITS + SGRPROJ_RST_BITS);
490 dat[l] = w;
491 }
492 }
493}
494
495static void loop_sgrproj_filter_tile(uint8_t *data, int tile_idx, int width,
496 int height, int stride,
497 RestorationInternal *rst, void *tmpbuf) {
498 const int tile_width = rst->tile_width >> rst->subsampling_x;
499 const int tile_height = rst->tile_height >> rst->subsampling_y;
500 int i, j;
501 int h_start, h_end, v_start, v_end;
502 uint8_t *data_p;
Debargha Mukherjeee166e252016-12-01 07:04:46 -0800503 int64_t *dat = (int64_t *)tmpbuf;
504 tmpbuf = (uint8_t *)tmpbuf + RESTORATION_TILEPELS_MAX * sizeof(*dat);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700505
506 if (rst->rsi->sgrproj_info[tile_idx].level == 0) return;
507 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
508 tile_width, tile_height, width, height, 0, 0,
509 &h_start, &h_end, &v_start, &v_end);
510 data_p = data + h_start + v_start * stride;
511 for (i = 0; i < (v_end - v_start); ++i) {
512 for (j = 0; j < (h_end - h_start); ++j) {
513 dat[i * (h_end - h_start) + j] = data_p[i * stride + j];
514 }
515 }
516 apply_selfguided_restoration(dat, h_end - h_start, v_end - v_start,
517 h_end - h_start, 8,
518 rst->rsi->sgrproj_info[tile_idx].ep,
519 rst->rsi->sgrproj_info[tile_idx].xqd, tmpbuf);
520 for (i = 0; i < (v_end - v_start); ++i) {
521 for (j = 0; j < (h_end - h_start); ++j) {
Debargha Mukherjeeaa229d62016-11-30 18:40:22 -0800522 data_p[i * stride + j] = clip_pixel((int)dat[i * (h_end - h_start) + j]);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700523 }
524 }
525}
526
527static void loop_sgrproj_filter(uint8_t *data, int width, int height,
528 int stride, RestorationInternal *rst,
529 uint8_t *tmpdata, int tmpstride) {
530 int tile_idx;
531 uint8_t *tmpbuf = aom_malloc(SGRPROJ_TMPBUF_SIZE);
532 (void)tmpdata;
533 (void)tmpstride;
534 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
535 loop_sgrproj_filter_tile(data, tile_idx, width, height, stride, rst,
536 tmpbuf);
537 }
538 aom_free(tmpbuf);
539}
540
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800541static void apply_domaintxfmrf_hor(int iter, int param, uint8_t *img, int width,
542 int height, int img_stride, int32_t *dat,
543 int dat_stride) {
544 int i, j;
545 for (i = 0; i < height; ++i) {
546 uint8_t *ip = &img[i * img_stride];
547 int32_t *dp = &dat[i * dat_stride];
548 *dp *= DOMAINTXFMRF_VTABLE_PREC;
549 dp++;
550 ip++;
551 // left to right
552 for (j = 1; j < width; ++j, dp++, ip++) {
553 const int v = domaintxfmrf_vtable[iter][param][abs(ip[0] - ip[-1])];
554 dp[0] = dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
555 ((v * dp[-1] + DOMAINTXFMRF_VTABLE_PREC / 2) >>
556 DOMAINTXFMRF_VTABLE_PRECBITS);
557 }
558 // right to left
559 dp -= 2;
560 ip -= 2;
561 for (j = width - 2; j >= 0; --j, dp--, ip--) {
562 const int v = domaintxfmrf_vtable[iter][param][abs(ip[1] - ip[0])];
563 dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + v * dp[1] +
564 DOMAINTXFMRF_VTABLE_PREC / 2) >>
565 DOMAINTXFMRF_VTABLE_PRECBITS;
566 }
567 }
568}
569
570static void apply_domaintxfmrf_ver(int iter, int param, uint8_t *img, int width,
571 int height, int img_stride, int32_t *dat,
572 int dat_stride) {
573 int i, j;
574 for (j = 0; j < width; ++j) {
575 uint8_t *ip = &img[j];
576 int32_t *dp = &dat[j];
577 dp += dat_stride;
578 ip += img_stride;
579 // top to bottom
580 for (i = 1; i < height; ++i, dp += dat_stride, ip += img_stride) {
581 const int v =
582 domaintxfmrf_vtable[iter][param][abs(ip[0] - ip[-img_stride])];
583 dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
584 (dp[-dat_stride] * v + DOMAINTXFMRF_VTABLE_PREC / 2)) >>
585 DOMAINTXFMRF_VTABLE_PRECBITS;
586 }
587 // bottom to top
588 dp -= 2 * dat_stride;
589 ip -= 2 * img_stride;
590 for (i = height - 2; i >= 0; --i, dp -= dat_stride, ip -= img_stride) {
591 const int v =
592 domaintxfmrf_vtable[iter][param][abs(ip[img_stride] - ip[0])];
593 dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + dp[dat_stride] * v +
594 DOMAINTXFMRF_VTABLE_PREC / 2) >>
595 DOMAINTXFMRF_VTABLE_PRECBITS;
596 }
597 }
598}
599
600static void apply_domaintxfmrf_reduce_prec(int32_t *dat, int width, int height,
601 int dat_stride) {
602 int i, j;
603 for (i = 0; i < height; ++i) {
604 for (j = 0; j < width; ++j) {
605 dat[i * dat_stride + j] = ROUND_POWER_OF_TWO_SIGNED(
606 dat[i * dat_stride + j], DOMAINTXFMRF_VTABLE_PRECBITS);
607 }
608 }
609}
610
611void av1_domaintxfmrf_restoration(uint8_t *dgd, int width, int height,
612 int stride, int param) {
613 int32_t dat[RESTORATION_TILEPELS_MAX];
614 int i, j, t;
615 for (i = 0; i < height; ++i) {
616 for (j = 0; j < width; ++j) {
617 dat[i * width + j] = dgd[i * stride + j];
618 }
619 }
620 for (t = 0; t < DOMAINTXFMRF_ITERS; ++t) {
621 apply_domaintxfmrf_hor(t, param, dgd, width, height, stride, dat, width);
622 apply_domaintxfmrf_ver(t, param, dgd, width, height, stride, dat, width);
623 apply_domaintxfmrf_reduce_prec(dat, width, height, width);
624 }
625 for (i = 0; i < height; ++i) {
626 for (j = 0; j < width; ++j) {
627 dgd[i * stride + j] = clip_pixel(dat[i * width + j]);
628 }
629 }
630}
631
632static void loop_domaintxfmrf_filter_tile(uint8_t *data, int tile_idx,
633 int width, int height, int stride,
634 RestorationInternal *rst,
635 void *tmpbuf) {
636 const int tile_width = rst->tile_width >> rst->subsampling_x;
637 const int tile_height = rst->tile_height >> rst->subsampling_y;
638 int h_start, h_end, v_start, v_end;
639 (void)tmpbuf;
640
641 if (rst->rsi->domaintxfmrf_info[tile_idx].level == 0) return;
642 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
643 tile_width, tile_height, width, height, 0, 0,
644 &h_start, &h_end, &v_start, &v_end);
645 av1_domaintxfmrf_restoration(data + h_start + v_start * stride,
646 h_end - h_start, v_end - v_start, stride,
647 rst->rsi->domaintxfmrf_info[tile_idx].sigma_r);
648}
649
650static void loop_domaintxfmrf_filter(uint8_t *data, int width, int height,
651 int stride, RestorationInternal *rst,
652 uint8_t *tmpdata, int tmpstride) {
653 int tile_idx;
654 (void)tmpdata;
655 (void)tmpstride;
656 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
657 loop_domaintxfmrf_filter_tile(data, tile_idx, width, height, stride, rst,
658 NULL);
659 }
660}
661
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700662static void loop_switchable_filter(uint8_t *data, int width, int height,
663 int stride, RestorationInternal *rst,
664 uint8_t *tmpdata, int tmpstride) {
665 int i, tile_idx;
666 uint8_t *data_p, *tmpdata_p;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700667 uint8_t *tmpbuf = aom_malloc(SGRPROJ_TMPBUF_SIZE);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700668
669 // Initialize tmp buffer
670 data_p = data;
671 tmpdata_p = tmpdata;
672 for (i = 0; i < height; ++i) {
673 memcpy(tmpdata_p, data_p, sizeof(*data_p) * width);
674 data_p += stride;
675 tmpdata_p += tmpstride;
676 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700677 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
Debargha Mukherjee0e67b252016-12-08 09:22:44 -0800678 if (rst->rsi->restoration_type[tile_idx] == RESTORE_WIENER) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700679 loop_wiener_filter_tile(data, tile_idx, width, height, stride, rst,
680 tmpdata, tmpstride);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700681 } else if (rst->rsi->restoration_type[tile_idx] == RESTORE_SGRPROJ) {
682 loop_sgrproj_filter_tile(data, tile_idx, width, height, stride, rst,
683 tmpbuf);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800684 } else if (rst->rsi->restoration_type[tile_idx] == RESTORE_DOMAINTXFMRF) {
685 loop_domaintxfmrf_filter_tile(data, tile_idx, width, height, stride, rst,
686 tmpbuf);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700687 }
688 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700689 aom_free(tmpbuf);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700690}
691
Yaowu Xuf883b422016-08-30 14:01:10 -0700692#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700693uint16_t hor_sym_filter_highbd(uint16_t *d, int *hfilter, int bd) {
694 int32_t s =
695 (1 << (RESTORATION_FILT_BITS - 1)) + d[0] * hfilter[RESTORATION_HALFWIN];
696 int i;
697 for (i = 1; i <= RESTORATION_HALFWIN; ++i)
698 s += (d[i] + d[-i]) * hfilter[RESTORATION_HALFWIN + i];
699 return clip_pixel_highbd(s >> RESTORATION_FILT_BITS, bd);
700}
701
702uint16_t ver_sym_filter_highbd(uint16_t *d, int stride, int *vfilter, int bd) {
703 int32_t s =
704 (1 << (RESTORATION_FILT_BITS - 1)) + d[0] * vfilter[RESTORATION_HALFWIN];
705 int i;
706 for (i = 1; i <= RESTORATION_HALFWIN; ++i)
707 s += (d[i * stride] + d[-i * stride]) * vfilter[RESTORATION_HALFWIN + i];
708 return clip_pixel_highbd(s >> RESTORATION_FILT_BITS, bd);
709}
710
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700711static void loop_wiener_filter_tile_highbd(uint16_t *data, int tile_idx,
712 int width, int height, int stride,
713 RestorationInternal *rst,
714 uint16_t *tmpdata, int tmpstride,
715 int bit_depth) {
716 const int tile_width = rst->tile_width >> rst->subsampling_x;
717 const int tile_height = rst->tile_height >> rst->subsampling_y;
718 int h_start, h_end, v_start, v_end;
719 int i, j;
720 uint16_t *data_p, *tmpdata_p;
721
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700722 if (rst->rsi->wiener_info[tile_idx].level == 0) return;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700723 // Filter row-wise
724 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
725 tile_width, tile_height, width, height, 1, 0,
726 &h_start, &h_end, &v_start, &v_end);
727 data_p = data + h_start + v_start * stride;
728 tmpdata_p = tmpdata + h_start + v_start * tmpstride;
729 for (i = 0; i < (v_end - v_start); ++i) {
730 for (j = 0; j < (h_end - h_start); ++j) {
731 *tmpdata_p++ = hor_sym_filter_highbd(
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700732 data_p++, rst->rsi->wiener_info[tile_idx].hfilter, bit_depth);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700733 }
734 data_p += stride - (h_end - h_start);
735 tmpdata_p += tmpstride - (h_end - h_start);
736 }
737 // Filter col-wise
738 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
739 tile_width, tile_height, width, height, 0, 1,
740 &h_start, &h_end, &v_start, &v_end);
741 data_p = data + h_start + v_start * stride;
742 tmpdata_p = tmpdata + h_start + v_start * tmpstride;
743 for (i = 0; i < (v_end - v_start); ++i) {
744 for (j = 0; j < (h_end - h_start); ++j) {
745 *data_p++ = ver_sym_filter_highbd(tmpdata_p++, tmpstride,
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700746 rst->rsi->wiener_info[tile_idx].vfilter,
747 bit_depth);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700748 }
749 data_p += stride - (h_end - h_start);
750 tmpdata_p += tmpstride - (h_end - h_start);
751 }
752}
753
Yaowu Xuc27fc142016-08-22 16:08:15 -0700754static void loop_wiener_filter_highbd(uint8_t *data8, int width, int height,
755 int stride, RestorationInternal *rst,
756 uint8_t *tmpdata8, int tmpstride,
757 int bit_depth) {
758 uint16_t *data = CONVERT_TO_SHORTPTR(data8);
759 uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8);
Debargha Mukherjeeaa229d62016-11-30 18:40:22 -0800760 int tile_idx, i;
761 uint16_t *data_p, *tmpdata_p;
762
763 // Initialize tmp buffer
764 data_p = data;
765 tmpdata_p = tmpdata;
766 for (i = 0; i < height; ++i) {
767 memcpy(tmpdata_p, data_p, sizeof(*data_p) * width);
768 data_p += stride;
769 tmpdata_p += tmpstride;
770 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700771 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700772 loop_wiener_filter_tile_highbd(data, tile_idx, width, height, stride, rst,
773 tmpdata, tmpstride, bit_depth);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700774 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700775}
Yaowu Xuc27fc142016-08-22 16:08:15 -0700776
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700777static void loop_sgrproj_filter_tile_highbd(uint16_t *data, int tile_idx,
778 int width, int height, int stride,
779 RestorationInternal *rst,
780 int bit_depth, void *tmpbuf) {
781 const int tile_width = rst->tile_width >> rst->subsampling_x;
782 const int tile_height = rst->tile_height >> rst->subsampling_y;
783 int i, j;
784 int h_start, h_end, v_start, v_end;
785 uint16_t *data_p;
Debargha Mukherjeee166e252016-12-01 07:04:46 -0800786 int64_t *dat = (int64_t *)tmpbuf;
787 tmpbuf = (uint8_t *)tmpbuf + RESTORATION_TILEPELS_MAX * sizeof(*dat);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700788
789 if (rst->rsi->sgrproj_info[tile_idx].level == 0) return;
790 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
791 tile_width, tile_height, width, height, 0, 0,
792 &h_start, &h_end, &v_start, &v_end);
793 data_p = data + h_start + v_start * stride;
794 for (i = 0; i < (v_end - v_start); ++i) {
795 for (j = 0; j < (h_end - h_start); ++j) {
796 dat[i * (h_end - h_start) + j] = data_p[i * stride + j];
797 }
798 }
799 apply_selfguided_restoration(dat, h_end - h_start, v_end - v_start,
800 h_end - h_start, bit_depth,
801 rst->rsi->sgrproj_info[tile_idx].ep,
802 rst->rsi->sgrproj_info[tile_idx].xqd, tmpbuf);
803 for (i = 0; i < (v_end - v_start); ++i) {
804 for (j = 0; j < (h_end - h_start); ++j) {
805 data_p[i * stride + j] =
Debargha Mukherjeeaa229d62016-11-30 18:40:22 -0800806 clip_pixel_highbd((int)dat[i * (h_end - h_start) + j], bit_depth);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700807 }
808 }
809}
810
811static void loop_sgrproj_filter_highbd(uint8_t *data8, int width, int height,
812 int stride, RestorationInternal *rst,
813 uint8_t *tmpdata8, int tmpstride,
814 int bit_depth) {
815 int tile_idx;
816 uint16_t *data = CONVERT_TO_SHORTPTR(data8);
817 uint8_t *tmpbuf = aom_malloc(SGRPROJ_TMPBUF_SIZE);
818 (void)tmpdata8;
819 (void)tmpstride;
820 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
821 loop_sgrproj_filter_tile_highbd(data, tile_idx, width, height, stride, rst,
822 bit_depth, tmpbuf);
823 }
824 aom_free(tmpbuf);
825}
826
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800827static void apply_domaintxfmrf_hor_highbd(int iter, int param, uint16_t *img,
828 int width, int height, int img_stride,
829 int32_t *dat, int dat_stride,
830 int bd) {
831 const int shift = (bd - 8);
832 int i, j;
833 for (i = 0; i < height; ++i) {
834 uint16_t *ip = &img[i * img_stride];
835 int32_t *dp = &dat[i * dat_stride];
836 *dp *= DOMAINTXFMRF_VTABLE_PREC;
837 dp++;
838 ip++;
839 // left to right
840 for (j = 1; j < width; ++j, dp++, ip++) {
841 const int v =
842 domaintxfmrf_vtable[iter][param]
843 [abs((ip[0] >> shift) - (ip[-1] >> shift))];
844 dp[0] = dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
845 ((v * dp[-1] + DOMAINTXFMRF_VTABLE_PREC / 2) >>
846 DOMAINTXFMRF_VTABLE_PRECBITS);
847 }
848 // right to left
849 dp -= 2;
850 ip -= 2;
851 for (j = width - 2; j >= 0; --j, dp--, ip--) {
852 const int v =
853 domaintxfmrf_vtable[iter][param]
854 [abs((ip[1] >> shift) - (ip[0] >> shift))];
855 dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + v * dp[1] +
856 DOMAINTXFMRF_VTABLE_PREC / 2) >>
857 DOMAINTXFMRF_VTABLE_PRECBITS;
858 }
859 }
860}
861
862static void apply_domaintxfmrf_ver_highbd(int iter, int param, uint16_t *img,
863 int width, int height, int img_stride,
864 int32_t *dat, int dat_stride,
865 int bd) {
866 int i, j;
867 const int shift = (bd - 8);
868 for (j = 0; j < width; ++j) {
869 uint16_t *ip = &img[j];
870 int32_t *dp = &dat[j];
871 dp += dat_stride;
872 ip += img_stride;
873 // top to bottom
874 for (i = 1; i < height; ++i, dp += dat_stride, ip += img_stride) {
875 const int v = domaintxfmrf_vtable[iter][param][abs(
876 (ip[0] >> shift) - (ip[-img_stride] >> shift))];
877 dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
878 (dp[-dat_stride] * v + DOMAINTXFMRF_VTABLE_PREC / 2)) >>
879 DOMAINTXFMRF_VTABLE_PRECBITS;
880 }
881 // bottom to top
882 dp -= 2 * dat_stride;
883 ip -= 2 * img_stride;
884 for (i = height - 2; i >= 0; --i, dp -= dat_stride, ip -= img_stride) {
885 const int v = domaintxfmrf_vtable[iter][param][abs(
886 (ip[img_stride] >> shift) - (ip[0] >> shift))];
887 dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + dp[dat_stride] * v +
888 DOMAINTXFMRF_VTABLE_PREC / 2) >>
889 DOMAINTXFMRF_VTABLE_PRECBITS;
890 }
891 }
892}
893
894void av1_domaintxfmrf_restoration_highbd(uint16_t *dgd, int width, int height,
895 int stride, int param, int bit_depth) {
896 int32_t dat[RESTORATION_TILEPELS_MAX];
897 int i, j, t;
898 for (i = 0; i < height; ++i) {
899 for (j = 0; j < width; ++j) {
900 dat[i * width + j] = dgd[i * stride + j];
901 }
902 }
903 for (t = 0; t < DOMAINTXFMRF_ITERS; ++t) {
904 apply_domaintxfmrf_hor_highbd(t, param, dgd, width, height, stride, dat,
905 width, bit_depth);
906 apply_domaintxfmrf_ver_highbd(t, param, dgd, width, height, stride, dat,
907 width, bit_depth);
908 apply_domaintxfmrf_reduce_prec(dat, width, height, width);
909 }
910 for (i = 0; i < height; ++i) {
911 for (j = 0; j < width; ++j) {
912 dgd[i * stride + j] = clip_pixel_highbd(dat[i * width + j], bit_depth);
913 }
914 }
915}
916
917static void loop_domaintxfmrf_filter_tile_highbd(uint16_t *data, int tile_idx,
918 int width, int height,
919 int stride,
920 RestorationInternal *rst,
921 int bit_depth, void *tmpbuf) {
922 const int tile_width = rst->tile_width >> rst->subsampling_x;
923 const int tile_height = rst->tile_height >> rst->subsampling_y;
924 int h_start, h_end, v_start, v_end;
925 (void)tmpbuf;
926
927 if (rst->rsi->domaintxfmrf_info[tile_idx].level == 0) return;
928 av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
929 tile_width, tile_height, width, height, 0, 0,
930 &h_start, &h_end, &v_start, &v_end);
931 av1_domaintxfmrf_restoration_highbd(
932 data + h_start + v_start * stride, h_end - h_start, v_end - v_start,
933 stride, rst->rsi->domaintxfmrf_info[tile_idx].sigma_r, bit_depth);
934}
935
936static void loop_domaintxfmrf_filter_highbd(uint8_t *data8, int width,
937 int height, int stride,
938 RestorationInternal *rst,
939 uint8_t *tmpdata, int tmpstride,
940 int bit_depth) {
941 int tile_idx;
942 uint16_t *data = CONVERT_TO_SHORTPTR(data8);
943 (void)tmpdata;
944 (void)tmpstride;
945 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
946 loop_domaintxfmrf_filter_tile_highbd(data, tile_idx, width, height, stride,
947 rst, bit_depth, NULL);
948 }
949}
950
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700951static void loop_switchable_filter_highbd(uint8_t *data8, int width, int height,
952 int stride, RestorationInternal *rst,
953 uint8_t *tmpdata8, int tmpstride,
954 int bit_depth) {
955 uint16_t *data = CONVERT_TO_SHORTPTR(data8);
956 uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700957 uint8_t *tmpbuf = aom_malloc(SGRPROJ_TMPBUF_SIZE);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700958 int i, tile_idx;
959 uint16_t *data_p, *tmpdata_p;
960
961 // Initialize tmp buffer
962 data_p = data;
963 tmpdata_p = tmpdata;
964 for (i = 0; i < height; ++i) {
965 memcpy(tmpdata_p, data_p, sizeof(*data_p) * width);
966 data_p += stride;
967 tmpdata_p += tmpstride;
968 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700969 for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
Debargha Mukherjee0e67b252016-12-08 09:22:44 -0800970 if (rst->rsi->restoration_type[tile_idx] == RESTORE_WIENER) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700971 loop_wiener_filter_tile_highbd(data, tile_idx, width, height, stride, rst,
972 tmpdata, tmpstride, bit_depth);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700973 } else if (rst->rsi->restoration_type[tile_idx] == RESTORE_SGRPROJ) {
974 loop_sgrproj_filter_tile_highbd(data, tile_idx, width, height, stride,
975 rst, bit_depth, tmpbuf);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800976 } else if (rst->rsi->restoration_type[tile_idx] == RESTORE_DOMAINTXFMRF) {
977 loop_domaintxfmrf_filter_tile_highbd(data, tile_idx, width, height,
978 stride, rst, bit_depth, tmpbuf);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700979 }
980 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700981 aom_free(tmpbuf);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700982}
Yaowu Xuf883b422016-08-30 14:01:10 -0700983#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700984
Yaowu Xuf883b422016-08-30 14:01:10 -0700985void av1_loop_restoration_rows(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
986 int start_mi_row, int end_mi_row, int y_only) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700987 const int ywidth = frame->y_crop_width;
988 const int ystride = frame->y_stride;
989 const int uvwidth = frame->uv_crop_width;
990 const int uvstride = frame->uv_stride;
991 const int ystart = start_mi_row << MI_SIZE_LOG2;
992 const int uvstart = ystart >> cm->subsampling_y;
993 int yend = end_mi_row << MI_SIZE_LOG2;
994 int uvend = yend >> cm->subsampling_y;
Debargha Mukherjee0e67b252016-12-08 09:22:44 -0800995 restore_func_type restore_funcs[RESTORE_TYPES] = { NULL, loop_wiener_filter,
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800996 loop_sgrproj_filter,
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800997 loop_domaintxfmrf_filter,
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700998 loop_switchable_filter };
999#if CONFIG_AOM_HIGHBITDEPTH
1000 restore_func_highbd_type restore_funcs_highbd[RESTORE_TYPES] = {
Debargha Mukherjee0e67b252016-12-08 09:22:44 -08001001 NULL, loop_wiener_filter_highbd, loop_sgrproj_filter_highbd,
1002 loop_domaintxfmrf_filter_highbd, loop_switchable_filter_highbd
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001003 };
1004#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001005 restore_func_type restore_func =
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001006 restore_funcs[cm->rst_internal.rsi->frame_restoration_type];
Yaowu Xuf883b422016-08-30 14:01:10 -07001007#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001008 restore_func_highbd_type restore_func_highbd =
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001009 restore_funcs_highbd[cm->rst_internal.rsi->frame_restoration_type];
Yaowu Xuf883b422016-08-30 14:01:10 -07001010#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001011 YV12_BUFFER_CONFIG tmp_buf;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001012
1013 if (cm->rst_internal.rsi->frame_restoration_type == RESTORE_NONE) return;
1014
Yaowu Xuc27fc142016-08-22 16:08:15 -07001015 memset(&tmp_buf, 0, sizeof(YV12_BUFFER_CONFIG));
1016
Yaowu Xuf883b422016-08-30 14:01:10 -07001017 yend = AOMMIN(yend, cm->height);
1018 uvend = AOMMIN(uvend, cm->subsampling_y ? (cm->height + 1) >> 1 : cm->height);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001019
Yaowu Xuf883b422016-08-30 14:01:10 -07001020 if (aom_realloc_frame_buffer(
Yaowu Xuc27fc142016-08-22 16:08:15 -07001021 &tmp_buf, cm->width, cm->height, cm->subsampling_x, cm->subsampling_y,
Yaowu Xuf883b422016-08-30 14:01:10 -07001022#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001023 cm->use_highbitdepth,
1024#endif
Yaowu Xu671f2bd2016-09-30 15:07:57 -07001025 AOM_BORDER_IN_PIXELS, cm->byte_alignment, NULL, NULL, NULL) < 0)
Yaowu Xuf883b422016-08-30 14:01:10 -07001026 aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
Yaowu Xuc27fc142016-08-22 16:08:15 -07001027 "Failed to allocate tmp restoration buffer");
1028
Debargha Mukherjee818e42a2016-12-12 11:52:56 -08001029 if (y_only == 0)
1030 y_only = override_y_only[cm->rst_internal.rsi->frame_restoration_type];
1031
Yaowu Xuf883b422016-08-30 14:01:10 -07001032#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001033 if (cm->use_highbitdepth)
1034 restore_func_highbd(frame->y_buffer + ystart * ystride, ywidth,
1035 yend - ystart, ystride, &cm->rst_internal,
1036 tmp_buf.y_buffer + ystart * tmp_buf.y_stride,
1037 tmp_buf.y_stride, cm->bit_depth);
1038 else
Yaowu Xuf883b422016-08-30 14:01:10 -07001039#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001040 restore_func(frame->y_buffer + ystart * ystride, ywidth, yend - ystart,
1041 ystride, &cm->rst_internal,
1042 tmp_buf.y_buffer + ystart * tmp_buf.y_stride,
1043 tmp_buf.y_stride);
1044 if (!y_only) {
1045 cm->rst_internal.subsampling_x = cm->subsampling_x;
1046 cm->rst_internal.subsampling_y = cm->subsampling_y;
Yaowu Xuf883b422016-08-30 14:01:10 -07001047#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001048 if (cm->use_highbitdepth) {
1049 restore_func_highbd(frame->u_buffer + uvstart * uvstride, uvwidth,
1050 uvend - uvstart, uvstride, &cm->rst_internal,
1051 tmp_buf.u_buffer + uvstart * tmp_buf.uv_stride,
1052 tmp_buf.uv_stride, cm->bit_depth);
1053 restore_func_highbd(frame->v_buffer + uvstart * uvstride, uvwidth,
1054 uvend - uvstart, uvstride, &cm->rst_internal,
1055 tmp_buf.v_buffer + uvstart * tmp_buf.uv_stride,
1056 tmp_buf.uv_stride, cm->bit_depth);
1057 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07001058#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001059 restore_func(frame->u_buffer + uvstart * uvstride, uvwidth,
1060 uvend - uvstart, uvstride, &cm->rst_internal,
1061 tmp_buf.u_buffer + uvstart * tmp_buf.uv_stride,
1062 tmp_buf.uv_stride);
1063 restore_func(frame->v_buffer + uvstart * uvstride, uvwidth,
1064 uvend - uvstart, uvstride, &cm->rst_internal,
1065 tmp_buf.v_buffer + uvstart * tmp_buf.uv_stride,
1066 tmp_buf.uv_stride);
Yaowu Xuf883b422016-08-30 14:01:10 -07001067#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001068 }
Yaowu Xuf883b422016-08-30 14:01:10 -07001069#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001070 }
Yaowu Xuf883b422016-08-30 14:01:10 -07001071 aom_free_frame_buffer(&tmp_buf);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001072}
1073
Yaowu Xuf883b422016-08-30 14:01:10 -07001074void av1_loop_restoration_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
1075 RestorationInfo *rsi, int y_only,
1076 int partial_frame) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001077 int start_mi_row, end_mi_row, mi_rows_to_filter;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001078 if (rsi->frame_restoration_type != RESTORE_NONE) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001079 start_mi_row = 0;
1080 mi_rows_to_filter = cm->mi_rows;
1081 if (partial_frame && cm->mi_rows > 8) {
1082 start_mi_row = cm->mi_rows >> 1;
1083 start_mi_row &= 0xfffffff8;
Yaowu Xuf883b422016-08-30 14:01:10 -07001084 mi_rows_to_filter = AOMMAX(cm->mi_rows / 8, 8);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001085 }
1086 end_mi_row = start_mi_row + mi_rows_to_filter;
Yaowu Xuf883b422016-08-30 14:01:10 -07001087 av1_loop_restoration_init(&cm->rst_internal, rsi,
1088 cm->frame_type == KEY_FRAME, cm->width,
1089 cm->height);
1090 av1_loop_restoration_rows(frame, cm, start_mi_row, end_mi_row, y_only);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001091 }
1092}