blob: 0ac80ab377f18b2352103a7cebfce023a74ce81b [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xubde4ac82016-11-28 15:26:06 -08002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xubde4ac82016-11-28 15:26:06 -08004 * 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.
Yaowu Xuc27fc142016-08-22 16:08:15 -070010 */
11
12#include <assert.h>
13#include <float.h>
14#include <limits.h>
15#include <math.h>
16
Yaowu Xuf883b422016-08-30 14:01:10 -070017#include "./aom_scale_rtcd.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070018
Yaowu Xuf883b422016-08-30 14:01:10 -070019#include "aom_dsp/aom_dsp_common.h"
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -070020#include "aom_dsp/binary_codes_writer.h"
21#include "aom_dsp/psnr.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070022#include "aom_mem/aom_mem.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070023#include "aom_ports/mem.h"
Jingning Han041c67b2017-04-14 21:39:26 -070024#include "aom_ports/system_state.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070025
26#include "av1/common/onyxc_int.h"
27#include "av1/common/quant_common.h"
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080028#include "av1/common/restoration.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070029
Tom Finegan17ce8b12017-02-08 12:46:31 -080030#include "av1/encoder/av1_quantize.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070031#include "av1/encoder/encoder.h"
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -070032#include "av1/encoder/mathutils.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070033#include "av1/encoder/picklpf.h"
34#include "av1/encoder/pickrst.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070035
Debargha Mukherjeefdbe3f72017-04-06 12:09:19 -070036// When set to RESTORE_WIENER or RESTORE_SGRPROJ only those are allowed.
Tom Finegan8af64ae2017-09-07 08:13:06 -070037// When set to RESTORE_TYPES we allow switchable.
Tom Finegan50c62ee2017-09-07 12:44:16 -070038static const RestorationType force_restore_type = RESTORE_TYPES;
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -070039
40// Number of Wiener iterations
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -070041#define NUM_WIENER_ITERS 5
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -070042
Debargha Mukherjee5d89a632016-09-17 13:16:58 -070043typedef double (*search_restore_type)(const YV12_BUFFER_CONFIG *src,
Debargha Mukherjee00c54332017-03-03 15:44:17 -080044 AV1_COMP *cpi, int partial_frame,
Debargha Mukherjeed48f5732017-05-19 14:58:07 -070045 int plane, RestorationInfo *info,
Debargha Mukherjee994ccd72017-01-06 11:18:23 -080046 RestorationType *rest_level,
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -070047 int64_t *best_tile_cost,
David Barker9666e752016-12-08 11:25:47 +000048 YV12_BUFFER_CONFIG *dst_frame);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -070049
Debargha Mukherjeeb3c43bc2017-02-01 13:09:03 -080050const int frame_level_restore_bits[RESTORE_TYPES] = { 2, 2, 2, 2 };
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070051
52static int64_t sse_restoration_tile(const YV12_BUFFER_CONFIG *src,
David Barker9666e752016-12-08 11:25:47 +000053 const YV12_BUFFER_CONFIG *dst,
54 const AV1_COMMON *cm, int h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080055 int width, int v_start, int height,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080056 int components_pattern) {
57 int64_t filt_err = 0;
Debargha Mukherjeed7489142017-01-05 13:58:16 -080058 (void)cm;
59 // Y and UV components cannot be mixed
60 assert(components_pattern == 1 || components_pattern == 2 ||
61 components_pattern == 4 || components_pattern == 6);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020062#if CONFIG_HIGHBITDEPTH
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070063 if (cm->use_highbitdepth) {
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080064 if ((components_pattern >> AOM_PLANE_Y) & 1) {
65 filt_err +=
66 aom_highbd_get_y_sse_part(src, dst, h_start, width, v_start, height);
67 }
68 if ((components_pattern >> AOM_PLANE_U) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080069 filt_err +=
70 aom_highbd_get_u_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080071 }
72 if ((components_pattern >> AOM_PLANE_V) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080073 filt_err +=
74 aom_highbd_get_v_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080075 }
76 return filt_err;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070077 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020078#endif // CONFIG_HIGHBITDEPTH
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080079 if ((components_pattern >> AOM_PLANE_Y) & 1) {
80 filt_err += aom_get_y_sse_part(src, dst, h_start, width, v_start, height);
81 }
82 if ((components_pattern >> AOM_PLANE_U) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080083 filt_err += aom_get_u_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080084 }
85 if ((components_pattern >> AOM_PLANE_V) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080086 filt_err += aom_get_v_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080087 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070088 return filt_err;
89}
90
David Barker60a055b2017-01-18 15:10:43 +000091static int64_t sse_restoration_frame(AV1_COMMON *const cm,
92 const YV12_BUFFER_CONFIG *src,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080093 const YV12_BUFFER_CONFIG *dst,
94 int components_pattern) {
95 int64_t filt_err = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020096#if CONFIG_HIGHBITDEPTH
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080097 if (cm->use_highbitdepth) {
98 if ((components_pattern >> AOM_PLANE_Y) & 1) {
99 filt_err += aom_highbd_get_y_sse(src, dst);
100 }
101 if ((components_pattern >> AOM_PLANE_U) & 1) {
102 filt_err += aom_highbd_get_u_sse(src, dst);
103 }
104 if ((components_pattern >> AOM_PLANE_V) & 1) {
105 filt_err += aom_highbd_get_v_sse(src, dst);
106 }
107 return filt_err;
108 }
David Barker60a055b2017-01-18 15:10:43 +0000109#else
110 (void)cm;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200111#endif // CONFIG_HIGHBITDEPTH
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800112 if ((components_pattern >> AOM_PLANE_Y) & 1) {
113 filt_err = aom_get_y_sse(src, dst);
114 }
115 if ((components_pattern >> AOM_PLANE_U) & 1) {
116 filt_err += aom_get_u_sse(src, dst);
117 }
118 if ((components_pattern >> AOM_PLANE_V) & 1) {
119 filt_err += aom_get_v_sse(src, dst);
120 }
121 return filt_err;
122}
123
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700124static int64_t try_restoration_tile(const YV12_BUFFER_CONFIG *src,
125 AV1_COMP *const cpi, RestorationInfo *rsi,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800126 int components_pattern, int partial_frame,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100127 int tile_idx,
David Barker9666e752016-12-08 11:25:47 +0000128 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700129 AV1_COMMON *const cm = &cpi->common;
Debargha Mukherjeed7489142017-01-05 13:58:16 -0800130
131 // Y and UV components cannot be mixed
132 assert(components_pattern == 1 || components_pattern == 2 ||
133 components_pattern == 4 || components_pattern == 6);
134
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +0100135 const int is_uv = components_pattern > 1;
136 const int width = src->crop_widths[is_uv];
137 const int height = src->crop_heights[is_uv];
138
139 const int rtile_size = cm->rst_info[is_uv].restoration_tilesize;
140 const int ss_y = is_uv && cm->subsampling_y;
141
142 int nhtiles, nvtiles;
143 av1_get_rest_ntiles(width, height, rtile_size, &nhtiles, &nvtiles);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700144
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800145 av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
146 partial_frame, dst_frame);
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100147 RestorationTileLimits limits = av1_get_rest_tile_limits(
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +0100148 tile_idx, nhtiles, nvtiles, rtile_size, width, height, ss_y);
149 int64_t filt_err = sse_restoration_tile(
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100150 src, dst_frame, cm, limits.h_start, limits.h_end - limits.h_start,
151 limits.v_start, limits.v_end - limits.v_start, components_pattern);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700152
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700153 return filt_err;
154}
155
156static int64_t try_restoration_frame(const YV12_BUFFER_CONFIG *src,
Yaowu Xuf883b422016-08-30 14:01:10 -0700157 AV1_COMP *const cpi, RestorationInfo *rsi,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800158 int components_pattern, int partial_frame,
David Barker9666e752016-12-08 11:25:47 +0000159 YV12_BUFFER_CONFIG *dst_frame) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700160 AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700161 int64_t filt_err;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800162 av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
163 partial_frame, dst_frame);
David Barker60a055b2017-01-18 15:10:43 +0000164 filt_err = sse_restoration_frame(cm, src, dst_frame, components_pattern);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700165 return filt_err;
166}
167
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100168static int64_t get_pixel_proj_error(const uint8_t *src8, int width, int height,
169 int src_stride, const uint8_t *dat8,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100170 int dat_stride, int use_highbitdepth,
David Barker3a0df182016-12-21 10:44:52 +0000171 int32_t *flt1, int flt1_stride,
172 int32_t *flt2, int flt2_stride, int *xqd) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700173 int i, j;
174 int64_t err = 0;
175 int xq[2];
176 decode_xq(xqd, xq);
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100177 if (!use_highbitdepth) {
David Barker3a0df182016-12-21 10:44:52 +0000178 const uint8_t *src = src8;
179 const uint8_t *dat = dat8;
180 for (i = 0; i < height; ++i) {
181 for (j = 0; j < width; ++j) {
182 const int32_t u =
183 (int32_t)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
184 const int32_t f1 = (int32_t)flt1[i * flt1_stride + j] - u;
185 const int32_t f2 = (int32_t)flt2[i * flt2_stride + j] - u;
David Barkerce110cc2017-02-22 10:38:59 +0000186 const int32_t v = xq[0] * f1 + xq[1] * f2 + (u << SGRPROJ_PRJ_BITS);
David Barker3a0df182016-12-21 10:44:52 +0000187 const int32_t e =
188 ROUND_POWER_OF_TWO(v, SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS) -
189 src[i * src_stride + j];
190 err += e * e;
191 }
192 }
193 } else {
194 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
195 const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
196 for (i = 0; i < height; ++i) {
197 for (j = 0; j < width; ++j) {
198 const int32_t u =
199 (int32_t)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
200 const int32_t f1 = (int32_t)flt1[i * flt1_stride + j] - u;
201 const int32_t f2 = (int32_t)flt2[i * flt2_stride + j] - u;
David Barkerce110cc2017-02-22 10:38:59 +0000202 const int32_t v = xq[0] * f1 + xq[1] * f2 + (u << SGRPROJ_PRJ_BITS);
David Barker3a0df182016-12-21 10:44:52 +0000203 const int32_t e =
204 ROUND_POWER_OF_TWO(v, SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS) -
205 src[i * src_stride + j];
206 err += e * e;
207 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700208 }
209 }
210 return err;
211}
212
Debargha Mukherjee749f5cd2017-05-31 11:26:51 -0700213#define USE_SGRPROJ_REFINEMENT_SEARCH 1
214static int64_t finer_search_pixel_proj_error(
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100215 const uint8_t *src8, int width, int height, int src_stride,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100216 const uint8_t *dat8, int dat_stride, int use_highbitdepth, int32_t *flt1,
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100217 int flt1_stride, int32_t *flt2, int flt2_stride, int start_step, int *xqd) {
Debargha Mukherjee749f5cd2017-05-31 11:26:51 -0700218 int64_t err = get_pixel_proj_error(src8, width, height, src_stride, dat8,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100219 dat_stride, use_highbitdepth, flt1,
220 flt1_stride, flt2, flt2_stride, xqd);
Debargha Mukherjee749f5cd2017-05-31 11:26:51 -0700221 (void)start_step;
222#if USE_SGRPROJ_REFINEMENT_SEARCH
223 int64_t err2;
224 int tap_min[] = { SGRPROJ_PRJ_MIN0, SGRPROJ_PRJ_MIN1 };
225 int tap_max[] = { SGRPROJ_PRJ_MAX0, SGRPROJ_PRJ_MAX1 };
226 for (int s = start_step; s >= 1; s >>= 1) {
227 for (int p = 0; p < 2; ++p) {
228 int skip = 0;
229 do {
230 if (xqd[p] - s >= tap_min[p]) {
231 xqd[p] -= s;
232 err2 = get_pixel_proj_error(src8, width, height, src_stride, dat8,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100233 dat_stride, use_highbitdepth, flt1,
234 flt1_stride, flt2, flt2_stride, xqd);
Debargha Mukherjee749f5cd2017-05-31 11:26:51 -0700235 if (err2 > err) {
236 xqd[p] += s;
237 } else {
238 err = err2;
239 skip = 1;
240 // At the highest step size continue moving in the same direction
241 if (s == start_step) continue;
242 }
243 }
244 break;
245 } while (1);
246 if (skip) break;
247 do {
248 if (xqd[p] + s <= tap_max[p]) {
249 xqd[p] += s;
250 err2 = get_pixel_proj_error(src8, width, height, src_stride, dat8,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100251 dat_stride, use_highbitdepth, flt1,
252 flt1_stride, flt2, flt2_stride, xqd);
Debargha Mukherjee749f5cd2017-05-31 11:26:51 -0700253 if (err2 > err) {
254 xqd[p] -= s;
255 } else {
256 err = err2;
257 // At the highest step size continue moving in the same direction
258 if (s == start_step) continue;
259 }
260 }
261 break;
262 } while (1);
263 }
264 }
265#endif // USE_SGRPROJ_REFINEMENT_SEARCH
266 return err;
267}
268
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100269static void get_proj_subspace(const uint8_t *src8, int width, int height,
David Barker3a0df182016-12-21 10:44:52 +0000270 int src_stride, uint8_t *dat8, int dat_stride,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100271 int use_highbitdepth, int32_t *flt1,
272 int flt1_stride, int32_t *flt2, int flt2_stride,
273 int *xq) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700274 int i, j;
275 double H[2][2] = { { 0, 0 }, { 0, 0 } };
276 double C[2] = { 0, 0 };
277 double Det;
278 double x[2];
279 const int size = width * height;
280
Jingning Han041c67b2017-04-14 21:39:26 -0700281 aom_clear_system_state();
282
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800283 // Default
284 xq[0] = 0;
285 xq[1] = 0;
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100286 if (!use_highbitdepth) {
David Barker3a0df182016-12-21 10:44:52 +0000287 const uint8_t *src = src8;
288 const uint8_t *dat = dat8;
289 for (i = 0; i < height; ++i) {
290 for (j = 0; j < width; ++j) {
291 const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
292 const double s =
293 (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
294 const double f1 = (double)flt1[i * flt1_stride + j] - u;
295 const double f2 = (double)flt2[i * flt2_stride + j] - u;
296 H[0][0] += f1 * f1;
297 H[1][1] += f2 * f2;
298 H[0][1] += f1 * f2;
299 C[0] += f1 * s;
300 C[1] += f2 * s;
301 }
302 }
303 } else {
304 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
305 const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
306 for (i = 0; i < height; ++i) {
307 for (j = 0; j < width; ++j) {
308 const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
309 const double s =
310 (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
311 const double f1 = (double)flt1[i * flt1_stride + j] - u;
312 const double f2 = (double)flt2[i * flt2_stride + j] - u;
313 H[0][0] += f1 * f1;
314 H[1][1] += f2 * f2;
315 H[0][1] += f1 * f2;
316 C[0] += f1 * s;
317 C[1] += f2 * s;
318 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700319 }
320 }
321 H[0][0] /= size;
322 H[0][1] /= size;
323 H[1][1] /= size;
324 H[1][0] = H[0][1];
325 C[0] /= size;
326 C[1] /= size;
327 Det = (H[0][0] * H[1][1] - H[0][1] * H[1][0]);
328 if (Det < 1e-8) return; // ill-posed, return default values
329 x[0] = (H[1][1] * C[0] - H[0][1] * C[1]) / Det;
330 x[1] = (H[0][0] * C[1] - H[1][0] * C[0]) / Det;
331 xq[0] = (int)rint(x[0] * (1 << SGRPROJ_PRJ_BITS));
332 xq[1] = (int)rint(x[1] * (1 << SGRPROJ_PRJ_BITS));
333}
334
335void encode_xq(int *xq, int *xqd) {
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800336 xqd[0] = xq[0];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700337 xqd[0] = clamp(xqd[0], SGRPROJ_PRJ_MIN0, SGRPROJ_PRJ_MAX0);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800338 xqd[1] = (1 << SGRPROJ_PRJ_BITS) - xqd[0] - xq[1];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700339 xqd[1] = clamp(xqd[1], SGRPROJ_PRJ_MIN1, SGRPROJ_PRJ_MAX1);
340}
341
342static void search_selfguided_restoration(uint8_t *dat8, int width, int height,
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100343 int dat_stride, const uint8_t *src8,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100344 int src_stride, int use_highbitdepth,
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700345 int bit_depth, int pu_width,
346 int pu_height, int *eps, int *xqd,
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100347 int32_t *rstbuf) {
David Barker3a0df182016-12-21 10:44:52 +0000348 int32_t *flt1 = rstbuf;
Debargha Mukherjee519dbcf2016-12-16 03:13:02 -0800349 int32_t *flt2 = flt1 + RESTORATION_TILEPELS_MAX;
David Barker506eb722017-03-08 13:35:49 +0000350 int ep, bestep = 0;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700351 int64_t err, besterr = -1;
352 int exqd[2], bestxqd[2] = { 0, 0 };
Debargha Mukherjee22bbe4c2017-08-31 12:30:10 -0700353 int flt1_stride = ((width + 7) & ~7) + 8;
354 int flt2_stride = ((width + 7) & ~7) + 8;
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700355 assert(pu_width == (RESTORATION_PROC_UNIT_SIZE >> 1) ||
356 pu_width == RESTORATION_PROC_UNIT_SIZE);
357 assert(pu_height == (RESTORATION_PROC_UNIT_SIZE >> 1) ||
358 pu_height == RESTORATION_PROC_UNIT_SIZE);
Yaowu Xu069cc312017-09-06 09:03:03 -0700359#if !CONFIG_HIGHBITDEPTH
360 (void)bit_depth;
361#endif
David Barker3a0df182016-12-21 10:44:52 +0000362
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700363 for (ep = 0; ep < SGRPROJ_PARAMS; ep++) {
364 int exq[2];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200365#if CONFIG_HIGHBITDEPTH
Rupert Swarbrick32d150b2017-09-04 10:35:51 +0100366 if (use_highbitdepth) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700367 uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700368 for (int i = 0; i < height; i += pu_height)
369 for (int j = 0; j < width; j += pu_width) {
370 const int w = AOMMIN(pu_width, width - j);
371 const int h = AOMMIN(pu_height, height - i);
372 uint16_t *dat_p = dat + i * dat_stride + j;
373 int32_t *flt1_p = flt1 + i * flt1_stride + j;
374 int32_t *flt2_p = flt2 + i * flt2_stride + j;
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800375#if USE_HIGHPASS_IN_SGRPROJ
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700376 av1_highpass_filter_highbd(dat_p, w, h, dat_stride, flt1_p,
377 flt1_stride, sgr_params[ep].corner,
378 sgr_params[ep].edge);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800379#else
Debargha Mukherjee22bbe4c2017-08-31 12:30:10 -0700380 av1_selfguided_restoration_highbd(
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700381 dat_p, w, h, dat_stride, flt1_p, flt1_stride, bit_depth,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -0700382 sgr_params[ep].r1, sgr_params[ep].e1);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800383#endif // USE_HIGHPASS_IN_SGRPROJ
Debargha Mukherjee22bbe4c2017-08-31 12:30:10 -0700384 av1_selfguided_restoration_highbd(
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700385 dat_p, w, h, dat_stride, flt2_p, flt2_stride, bit_depth,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -0700386 sgr_params[ep].r2, sgr_params[ep].e2);
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700387 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700388 } else {
David Barker506eb722017-03-08 13:35:49 +0000389#endif
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700390 for (int i = 0; i < height; i += pu_height)
391 for (int j = 0; j < width; j += pu_width) {
392 const int w = AOMMIN(pu_width, width - j);
393 const int h = AOMMIN(pu_height, height - i);
394 uint8_t *dat_p = dat8 + i * dat_stride + j;
395 int32_t *flt1_p = flt1 + i * flt1_stride + j;
396 int32_t *flt2_p = flt2 + i * flt2_stride + j;
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800397#if USE_HIGHPASS_IN_SGRPROJ
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700398 av1_highpass_filter(dat_p, w, h, dat_stride, flt1_p, flt1_stride,
399 sgr_params[ep].corner, sgr_params[ep].edge);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800400#else
Debargha Mukherjee22bbe4c2017-08-31 12:30:10 -0700401 av1_selfguided_restoration(dat_p, w, h, dat_stride, flt1_p, flt1_stride,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -0700402 sgr_params[ep].r1, sgr_params[ep].e1);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800403#endif // USE_HIGHPASS_IN_SGRPROJ
Debargha Mukherjee22bbe4c2017-08-31 12:30:10 -0700404 av1_selfguided_restoration(dat_p, w, h, dat_stride, flt2_p,
405 flt2_stride, sgr_params[ep].r2,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -0700406 sgr_params[ep].e2);
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700407 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200408#if CONFIG_HIGHBITDEPTH
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700409 }
David Barker506eb722017-03-08 13:35:49 +0000410#endif
Debargha Mukherjee7ae7aea2017-05-04 15:17:17 -0700411 aom_clear_system_state();
David Barker3a0df182016-12-21 10:44:52 +0000412 get_proj_subspace(src8, width, height, src_stride, dat8, dat_stride,
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700413 use_highbitdepth, flt1, flt1_stride, flt2, flt2_stride,
414 exq);
Debargha Mukherjee7ae7aea2017-05-04 15:17:17 -0700415 aom_clear_system_state();
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700416 encode_xq(exq, exqd);
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700417 err = finer_search_pixel_proj_error(
418 src8, width, height, src_stride, dat8, dat_stride, use_highbitdepth,
419 flt1, flt1_stride, flt2, flt2_stride, 2, exqd);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700420 if (besterr == -1 || err < besterr) {
421 bestep = ep;
422 besterr = err;
423 bestxqd[0] = exqd[0];
424 bestxqd[1] = exqd[1];
425 }
426 }
427 *eps = bestep;
428 xqd[0] = bestxqd[0];
429 xqd[1] = bestxqd[1];
430}
431
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -0700432static int count_sgrproj_bits(SgrprojInfo *sgrproj_info,
433 SgrprojInfo *ref_sgrproj_info) {
434 int bits = SGRPROJ_PARAMS_BITS;
435 bits += aom_count_primitive_refsubexpfin(
436 SGRPROJ_PRJ_MAX0 - SGRPROJ_PRJ_MIN0 + 1, SGRPROJ_PRJ_SUBEXP_K,
437 ref_sgrproj_info->xqd[0] - SGRPROJ_PRJ_MIN0,
438 sgrproj_info->xqd[0] - SGRPROJ_PRJ_MIN0);
439 bits += aom_count_primitive_refsubexpfin(
440 SGRPROJ_PRJ_MAX1 - SGRPROJ_PRJ_MIN1 + 1, SGRPROJ_PRJ_SUBEXP_K,
441 ref_sgrproj_info->xqd[1] - SGRPROJ_PRJ_MIN1,
442 sgrproj_info->xqd[1] - SGRPROJ_PRJ_MIN1);
443 return bits;
444}
445
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100446struct rest_search_ctxt {
447 const YV12_BUFFER_CONFIG *src;
448 AV1_COMP *cpi;
449 uint8_t *dgd_buffer;
450 const uint8_t *src_buffer;
451 int dgd_stride;
452 int src_stride;
453 int partial_frame;
454 RestorationInfo *info;
455 RestorationType *type;
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -0700456 int64_t *best_tile_cost;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100457 int plane;
458 int plane_width;
459 int plane_height;
460 int nrtiles_x;
461 int nrtiles_y;
462 YV12_BUFFER_CONFIG *dst_frame;
463};
464
465// Fill in ctxt. Returns the number of restoration tiles for this plane
466static INLINE int init_rest_search_ctxt(
467 const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, int partial_frame, int plane,
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -0700468 RestorationInfo *info, RestorationType *type, int64_t *best_tile_cost,
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100469 YV12_BUFFER_CONFIG *dst_frame, struct rest_search_ctxt *ctxt) {
470 AV1_COMMON *const cm = &cpi->common;
471 ctxt->src = src;
472 ctxt->cpi = cpi;
473 ctxt->partial_frame = partial_frame;
474 ctxt->info = info;
475 ctxt->type = type;
476 ctxt->best_tile_cost = best_tile_cost;
477 ctxt->plane = plane;
478 ctxt->dst_frame = dst_frame;
479
480 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +0100481 const int is_uv = plane != AOM_PLANE_Y;
482 ctxt->plane_width = src->crop_widths[is_uv];
483 ctxt->plane_height = src->crop_heights[is_uv];
484 ctxt->src_buffer = src->buffers[plane];
485 ctxt->src_stride = src->strides[is_uv];
486 ctxt->dgd_buffer = dgd->buffers[plane];
487 ctxt->dgd_stride = dgd->strides[is_uv];
488 assert(src->crop_widths[is_uv] == dgd->crop_widths[is_uv]);
489 assert(src->crop_heights[is_uv] == dgd->crop_heights[is_uv]);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100490
491 return av1_get_rest_ntiles(ctxt->plane_width, ctxt->plane_height,
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +0100492 cm->rst_info[plane].restoration_tilesize,
493 &ctxt->nrtiles_x, &ctxt->nrtiles_y);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100494}
495
496typedef void (*rtile_visitor_t)(const struct rest_search_ctxt *search_ctxt,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100497 int rtile_idx,
498 const RestorationTileLimits *limits, void *arg);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100499
500static void foreach_rtile_in_tile(const struct rest_search_ctxt *ctxt,
501 int tile_row, int tile_col,
502 rtile_visitor_t fun, void *arg) {
503 const AV1_COMMON *const cm = &ctxt->cpi->common;
504 const RestorationInfo *rsi = ctxt->cpi->rst_search;
Dominic Symesc27f5422017-10-03 09:58:17 +0200505 TileInfo tile_info;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100506
Dominic Symesc27f5422017-10-03 09:58:17 +0200507 av1_tile_set_row(&tile_info, cm, tile_row);
508 av1_tile_set_col(&tile_info, cm, tile_col);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100509
Dominic Symesc27f5422017-10-03 09:58:17 +0200510 int tile_col_start = tile_info.mi_col_start * MI_SIZE;
511 int tile_col_end = tile_info.mi_col_end * MI_SIZE;
512 int tile_row_start = tile_info.mi_row_start * MI_SIZE;
513 int tile_row_end = tile_info.mi_row_end * MI_SIZE;
514 if (ctxt->plane > 0) {
515 tile_col_start = ROUND_POWER_OF_TWO(tile_col_start, cm->subsampling_x);
516 tile_col_end = ROUND_POWER_OF_TWO(tile_col_end, cm->subsampling_x);
517 tile_row_start = ROUND_POWER_OF_TWO(tile_row_start, cm->subsampling_y);
518 tile_row_end = ROUND_POWER_OF_TWO(tile_row_end, cm->subsampling_y);
519 }
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100520
Rupert Swarbrickb66894a2017-10-06 15:11:01 +0100521#if CONFIG_FRAME_SUPERRES
522 // If upscaling is enabled, the tile limits need scaling to match the
523 // upscaled frame where the restoration tiles live. To do this, scale up the
524 // top-left and bottom-right of the tile.
525 if (!av1_superres_unscaled(cm)) {
Urvang Joshi69fde2e2017-10-09 15:34:18 -0700526 av1_calculate_unscaled_superres_size(&tile_col_start, &tile_row_start,
527 cm->superres_scale_denominator);
528 av1_calculate_unscaled_superres_size(&tile_col_end, &tile_row_end,
529 cm->superres_scale_denominator);
Rupert Swarbrickb66894a2017-10-06 15:11:01 +0100530 // Make sure we don't fall off the bottom-right of the frame.
531 tile_col_end = AOMMIN(tile_col_end, ctxt->plane_width);
532 tile_row_end = AOMMIN(tile_row_end, ctxt->plane_height);
533 }
534#endif // CONFIG_FRAME_SUPERRES
535
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100536 const int rtile_size = rsi->restoration_tilesize;
Dominic Symesc27f5422017-10-03 09:58:17 +0200537 const int rtile_col0 = (tile_col_start + rtile_size - 1) / rtile_size;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100538 const int rtile_col1 =
Dominic Symesc27f5422017-10-03 09:58:17 +0200539 AOMMIN((tile_col_end + rtile_size - 1) / rtile_size, ctxt->nrtiles_x);
540 const int rtile_row0 = (tile_row_start + rtile_size - 1) / rtile_size;
541 const int rtile_row1 =
542 AOMMIN((tile_row_end + rtile_size - 1) / rtile_size, ctxt->nrtiles_y);
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +0100543 const int ss_y = ctxt->plane > 0 && cm->subsampling_y;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100544
545 for (int rtile_row = rtile_row0; rtile_row < rtile_row1; ++rtile_row) {
546 for (int rtile_col = rtile_col0; rtile_col < rtile_col1; ++rtile_col) {
547 const int rtile_idx = rtile_row * ctxt->nrtiles_x + rtile_col;
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100548 RestorationTileLimits limits = av1_get_rest_tile_limits(
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +0100549 rtile_idx, ctxt->nrtiles_x, ctxt->nrtiles_y, rtile_size,
550 ctxt->plane_width, ctxt->plane_height, ss_y);
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100551 fun(ctxt, rtile_idx, &limits, arg);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100552 }
553 }
554}
555
556static void search_sgrproj_for_rtile(const struct rest_search_ctxt *ctxt,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100557 int rtile_idx,
558 const RestorationTileLimits *limits,
559 void *arg) {
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100560 const MACROBLOCK *const x = &ctxt->cpi->td.mb;
561 const AV1_COMMON *const cm = &ctxt->cpi->common;
562 RestorationInfo *rsi = ctxt->cpi->rst_search;
563 SgrprojInfo *sgrproj_info = ctxt->info->sgrproj_info;
564
565 SgrprojInfo *ref_sgrproj_info = (SgrprojInfo *)arg;
566
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100567 int64_t err =
568 sse_restoration_tile(ctxt->src, cm->frame_to_show, cm, limits->h_start,
569 limits->h_end - limits->h_start, limits->v_start,
570 limits->v_end - limits->v_start, (1 << ctxt->plane));
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100571 // #bits when a tile is not restored
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -0700572 int bits = x->sgrproj_restore_cost[0];
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100573 double cost_norestore = RDCOST_DBL(x->rdmult, (bits >> 4), err);
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -0700574 ctxt->best_tile_cost[rtile_idx] = INT64_MAX;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100575
576 RestorationInfo *plane_rsi = &rsi[ctxt->plane];
577 SgrprojInfo *rtile_sgrproj_info = &plane_rsi->sgrproj_info[rtile_idx];
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100578 uint8_t *dgd_start =
579 ctxt->dgd_buffer + limits->v_start * ctxt->dgd_stride + limits->h_start;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100580 const uint8_t *src_start =
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100581 ctxt->src_buffer + limits->v_start * ctxt->src_stride + limits->h_start;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100582
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700583 search_selfguided_restoration(
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100584 dgd_start, limits->h_end - limits->h_start,
585 limits->v_end - limits->v_start, ctxt->dgd_stride, src_start,
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700586 ctxt->src_stride,
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100587#if CONFIG_HIGHBITDEPTH
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700588 cm->use_highbitdepth, cm->bit_depth,
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100589#else
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700590 0, 8,
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100591#endif // CONFIG_HIGHBITDEPTH
Debargha Mukherjee7a5587a2017-08-31 07:41:30 -0700592 rsi[ctxt->plane].procunit_width, rsi[ctxt->plane].procunit_height,
593 &rtile_sgrproj_info->ep, rtile_sgrproj_info->xqd,
594 cm->rst_internal.tmpbuf);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100595 plane_rsi->restoration_type[rtile_idx] = RESTORE_SGRPROJ;
596 err = try_restoration_tile(ctxt->src, ctxt->cpi, rsi, (1 << ctxt->plane),
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +0100597 ctxt->partial_frame, rtile_idx, ctxt->dst_frame);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100598 bits =
599 count_sgrproj_bits(&plane_rsi->sgrproj_info[rtile_idx], ref_sgrproj_info)
600 << AV1_PROB_COST_SHIFT;
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -0700601 bits += x->sgrproj_restore_cost[1];
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100602 double cost_sgrproj = RDCOST_DBL(x->rdmult, (bits >> 4), err);
603 if (cost_sgrproj >= cost_norestore) {
604 ctxt->type[rtile_idx] = RESTORE_NONE;
605 } else {
606 ctxt->type[rtile_idx] = RESTORE_SGRPROJ;
607 *ref_sgrproj_info = sgrproj_info[rtile_idx] =
608 plane_rsi->sgrproj_info[rtile_idx];
609 ctxt->best_tile_cost[rtile_idx] = err;
610 }
611 plane_rsi->restoration_type[rtile_idx] = RESTORE_NONE;
612}
613
Debargha Mukherjeed48f5732017-05-19 14:58:07 -0700614static double search_sgrproj(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
615 int partial_frame, int plane,
616 RestorationInfo *info, RestorationType *type,
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -0700617 int64_t *best_tile_cost,
Debargha Mukherjeed48f5732017-05-19 14:58:07 -0700618 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -0700619 const MACROBLOCK *const x = &cpi->td.mb;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100620 struct rest_search_ctxt ctxt;
621 const int nrtiles =
622 init_rest_search_ctxt(src, cpi, partial_frame, plane, info, type,
623 best_tile_cost, dst_frame, &ctxt);
624
625 RestorationInfo *plane_rsi = &cpi->rst_search[plane];
626 plane_rsi->frame_restoration_type = RESTORE_SGRPROJ;
627 for (int rtile_idx = 0; rtile_idx < nrtiles; ++rtile_idx) {
628 plane_rsi->restoration_type[rtile_idx] = RESTORE_NONE;
Debargha Mukherjeed48f5732017-05-19 14:58:07 -0700629 }
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100630
631 // Compute best Sgrproj filters for each rtile, one (encoder/decoder)
632 // tile at a time.
633 const AV1_COMMON *const cm = &cpi->common;
Debargha Mukherjeee168a782017-08-31 12:30:10 -0700634#if CONFIG_HIGHBITDEPTH
635 if (cm->use_highbitdepth)
636 extend_frame_highbd(CONVERT_TO_SHORTPTR(ctxt.dgd_buffer), ctxt.plane_width,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -0700637 ctxt.plane_height, ctxt.dgd_stride, SGRPROJ_BORDER_HORZ,
638 SGRPROJ_BORDER_VERT);
Debargha Mukherjeee168a782017-08-31 12:30:10 -0700639 else
640#endif
641 extend_frame(ctxt.dgd_buffer, ctxt.plane_width, ctxt.plane_height,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -0700642 ctxt.dgd_stride, SGRPROJ_BORDER_HORZ, SGRPROJ_BORDER_VERT);
Debargha Mukherjeee168a782017-08-31 12:30:10 -0700643
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100644 for (int tile_row = 0; tile_row < cm->tile_rows; ++tile_row) {
645 for (int tile_col = 0; tile_col < cm->tile_cols; ++tile_col) {
646 SgrprojInfo ref_sgrproj_info;
647 set_default_sgrproj(&ref_sgrproj_info);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100648 foreach_rtile_in_tile(&ctxt, tile_row, tile_col, search_sgrproj_for_rtile,
649 &ref_sgrproj_info);
650 }
651 }
652
653 // Cost for Sgrproj filtering
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -0700654 SgrprojInfo ref_sgrproj_info;
655 set_default_sgrproj(&ref_sgrproj_info);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100656 SgrprojInfo *sgrproj_info = info->sgrproj_info;
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -0700657
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100658 int bits = frame_level_restore_bits[plane_rsi->frame_restoration_type]
659 << AV1_PROB_COST_SHIFT;
660 for (int rtile_idx = 0; rtile_idx < nrtiles; ++rtile_idx) {
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -0700661 bits += x->sgrproj_restore_cost[type[rtile_idx] != RESTORE_NONE];
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100662 plane_rsi->sgrproj_info[rtile_idx] = sgrproj_info[rtile_idx];
663 if (type[rtile_idx] == RESTORE_SGRPROJ) {
664 bits += count_sgrproj_bits(&plane_rsi->sgrproj_info[rtile_idx],
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -0700665 &ref_sgrproj_info)
666 << AV1_PROB_COST_SHIFT;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100667 ref_sgrproj_info = plane_rsi->sgrproj_info[rtile_idx];
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -0700668 }
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100669 plane_rsi->restoration_type[rtile_idx] = type[rtile_idx];
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -0700670 }
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -0700671 int64_t err = try_restoration_frame(src, cpi, cpi->rst_search, (1 << plane),
672 partial_frame, dst_frame);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100673 double cost_sgrproj = RDCOST_DBL(cpi->td.mb.rdmult, (bits >> 4), err);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700674 return cost_sgrproj;
675}
676
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100677static double find_average(const uint8_t *src, int h_start, int h_end,
678 int v_start, int v_end, int stride) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700679 uint64_t sum = 0;
680 double avg = 0;
681 int i, j;
Jingning Han041c67b2017-04-14 21:39:26 -0700682 aom_clear_system_state();
Yaowu Xuc27fc142016-08-22 16:08:15 -0700683 for (i = v_start; i < v_end; i++)
684 for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
685 avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
686 return avg;
687}
688
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100689static void compute_stats(int wiener_win, const uint8_t *dgd,
690 const uint8_t *src, int h_start, int h_end,
691 int v_start, int v_end, int dgd_stride,
692 int src_stride, double *M, double *H) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700693 int i, j, k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800694 double Y[WIENER_WIN2];
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700695 const int wiener_win2 = wiener_win * wiener_win;
696 const int wiener_halfwin = (wiener_win >> 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700697 const double avg =
698 find_average(dgd, h_start, h_end, v_start, v_end, dgd_stride);
699
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700700 memset(M, 0, sizeof(*M) * wiener_win2);
701 memset(H, 0, sizeof(*H) * wiener_win2 * wiener_win2);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700702 for (i = v_start; i < v_end; i++) {
703 for (j = h_start; j < h_end; j++) {
704 const double X = (double)src[i * src_stride + j] - avg;
705 int idx = 0;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700706 for (k = -wiener_halfwin; k <= wiener_halfwin; k++) {
707 for (l = -wiener_halfwin; l <= wiener_halfwin; l++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700708 Y[idx] = (double)dgd[(i + l) * dgd_stride + (j + k)] - avg;
709 idx++;
710 }
711 }
Debargha Mukherjeea1a1e362017-10-04 20:01:03 -0700712 assert(idx == wiener_win2);
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700713 for (k = 0; k < wiener_win2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700714 M[k] += Y[k] * X;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700715 H[k * wiener_win2 + k] += Y[k] * Y[k];
716 for (l = k + 1; l < wiener_win2; ++l) {
David Barker33f3bfd2017-01-06 15:34:50 +0000717 // H is a symmetric matrix, so we only need to fill out the upper
718 // triangle here. We can copy it down to the lower triangle outside
719 // the (i, j) loops.
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700720 H[k * wiener_win2 + l] += Y[k] * Y[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700721 }
722 }
723 }
724 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700725 for (k = 0; k < wiener_win2; ++k) {
726 for (l = k + 1; l < wiener_win2; ++l) {
727 H[l * wiener_win2 + k] = H[k * wiener_win2 + l];
David Barker33f3bfd2017-01-06 15:34:50 +0000728 }
729 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700730}
731
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200732#if CONFIG_HIGHBITDEPTH
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100733static double find_average_highbd(const uint16_t *src, int h_start, int h_end,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700734 int v_start, int v_end, int stride) {
735 uint64_t sum = 0;
736 double avg = 0;
737 int i, j;
Jingning Han041c67b2017-04-14 21:39:26 -0700738 aom_clear_system_state();
Yaowu Xuc27fc142016-08-22 16:08:15 -0700739 for (i = v_start; i < v_end; i++)
740 for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
741 avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
742 return avg;
743}
744
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100745static void compute_stats_highbd(int wiener_win, const uint8_t *dgd8,
746 const uint8_t *src8, int h_start, int h_end,
747 int v_start, int v_end, int dgd_stride,
748 int src_stride, double *M, double *H) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700749 int i, j, k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800750 double Y[WIENER_WIN2];
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700751 const int wiener_win2 = wiener_win * wiener_win;
752 const int wiener_halfwin = (wiener_win >> 1);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +0100753 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
754 const uint16_t *dgd = CONVERT_TO_SHORTPTR(dgd8);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700755 const double avg =
756 find_average_highbd(dgd, h_start, h_end, v_start, v_end, dgd_stride);
757
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700758 memset(M, 0, sizeof(*M) * wiener_win2);
759 memset(H, 0, sizeof(*H) * wiener_win2 * wiener_win2);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700760 for (i = v_start; i < v_end; i++) {
761 for (j = h_start; j < h_end; j++) {
762 const double X = (double)src[i * src_stride + j] - avg;
763 int idx = 0;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700764 for (k = -wiener_halfwin; k <= wiener_halfwin; k++) {
765 for (l = -wiener_halfwin; l <= wiener_halfwin; l++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700766 Y[idx] = (double)dgd[(i + l) * dgd_stride + (j + k)] - avg;
767 idx++;
768 }
769 }
Debargha Mukherjeea1a1e362017-10-04 20:01:03 -0700770 assert(idx == wiener_win2);
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700771 for (k = 0; k < wiener_win2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700772 M[k] += Y[k] * X;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700773 H[k * wiener_win2 + k] += Y[k] * Y[k];
774 for (l = k + 1; l < wiener_win2; ++l) {
David Barker33f3bfd2017-01-06 15:34:50 +0000775 // H is a symmetric matrix, so we only need to fill out the upper
776 // triangle here. We can copy it down to the lower triangle outside
777 // the (i, j) loops.
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700778 H[k * wiener_win2 + l] += Y[k] * Y[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700779 }
780 }
781 }
782 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700783 for (k = 0; k < wiener_win2; ++k) {
784 for (l = k + 1; l < wiener_win2; ++l) {
785 H[l * wiener_win2 + k] = H[k * wiener_win2 + l];
David Barker33f3bfd2017-01-06 15:34:50 +0000786 }
787 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700788}
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200789#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700790
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700791static INLINE int wrap_index(int i, int wiener_win) {
792 const int wiener_halfwin1 = (wiener_win >> 1) + 1;
793 return (i >= wiener_halfwin1 ? wiener_win - 1 - i : i);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700794}
795
796// Fix vector b, update vector a
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700797static void update_a_sep_sym(int wiener_win, double **Mc, double **Hc,
798 double *a, double *b) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700799 int i, j;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800800 double S[WIENER_WIN];
Debargha Mukherjee6ae588f2017-04-14 00:40:02 -0700801 double A[WIENER_HALFWIN1], B[WIENER_HALFWIN1 * WIENER_HALFWIN1];
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700802 const int wiener_win2 = wiener_win * wiener_win;
803 const int wiener_halfwin1 = (wiener_win >> 1) + 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700804 memset(A, 0, sizeof(A));
805 memset(B, 0, sizeof(B));
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700806 for (i = 0; i < wiener_win; i++) {
807 for (j = 0; j < wiener_win; ++j) {
808 const int jj = wrap_index(j, wiener_win);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700809 A[jj] += Mc[i][j] * b[i];
810 }
811 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700812 for (i = 0; i < wiener_win; i++) {
813 for (j = 0; j < wiener_win; j++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700814 int k, l;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700815 for (k = 0; k < wiener_win; ++k)
816 for (l = 0; l < wiener_win; ++l) {
817 const int kk = wrap_index(k, wiener_win);
818 const int ll = wrap_index(l, wiener_win);
819 B[ll * wiener_halfwin1 + kk] +=
820 Hc[j * wiener_win + i][k * wiener_win2 + l] * b[i] * b[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700821 }
822 }
823 }
824 // Normalization enforcement in the system of equations itself
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700825 for (i = 0; i < wiener_halfwin1 - 1; ++i)
Yaowu Xuc27fc142016-08-22 16:08:15 -0700826 A[i] -=
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700827 A[wiener_halfwin1 - 1] * 2 +
828 B[i * wiener_halfwin1 + wiener_halfwin1 - 1] -
829 2 * B[(wiener_halfwin1 - 1) * wiener_halfwin1 + (wiener_halfwin1 - 1)];
830 for (i = 0; i < wiener_halfwin1 - 1; ++i)
831 for (j = 0; j < wiener_halfwin1 - 1; ++j)
832 B[i * wiener_halfwin1 + j] -=
833 2 * (B[i * wiener_halfwin1 + (wiener_halfwin1 - 1)] +
834 B[(wiener_halfwin1 - 1) * wiener_halfwin1 + j] -
835 2 * B[(wiener_halfwin1 - 1) * wiener_halfwin1 +
836 (wiener_halfwin1 - 1)]);
837 if (linsolve(wiener_halfwin1 - 1, B, wiener_halfwin1, A, S)) {
838 S[wiener_halfwin1 - 1] = 1.0;
839 for (i = wiener_halfwin1; i < wiener_win; ++i) {
840 S[i] = S[wiener_win - 1 - i];
841 S[wiener_halfwin1 - 1] -= 2 * S[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700842 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700843 memcpy(a, S, wiener_win * sizeof(*a));
Yaowu Xuc27fc142016-08-22 16:08:15 -0700844 }
845}
846
847// Fix vector a, update vector b
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700848static void update_b_sep_sym(int wiener_win, double **Mc, double **Hc,
849 double *a, double *b) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700850 int i, j;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800851 double S[WIENER_WIN];
Debargha Mukherjee6ae588f2017-04-14 00:40:02 -0700852 double A[WIENER_HALFWIN1], B[WIENER_HALFWIN1 * WIENER_HALFWIN1];
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700853 const int wiener_win2 = wiener_win * wiener_win;
854 const int wiener_halfwin1 = (wiener_win >> 1) + 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700855 memset(A, 0, sizeof(A));
856 memset(B, 0, sizeof(B));
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700857 for (i = 0; i < wiener_win; i++) {
858 const int ii = wrap_index(i, wiener_win);
859 for (j = 0; j < wiener_win; j++) A[ii] += Mc[i][j] * a[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700860 }
861
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700862 for (i = 0; i < wiener_win; i++) {
863 for (j = 0; j < wiener_win; j++) {
864 const int ii = wrap_index(i, wiener_win);
865 const int jj = wrap_index(j, wiener_win);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700866 int k, l;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700867 for (k = 0; k < wiener_win; ++k)
868 for (l = 0; l < wiener_win; ++l)
869 B[jj * wiener_halfwin1 + ii] +=
870 Hc[i * wiener_win + j][k * wiener_win2 + l] * a[k] * a[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700871 }
872 }
873 // Normalization enforcement in the system of equations itself
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700874 for (i = 0; i < wiener_halfwin1 - 1; ++i)
Yaowu Xuc27fc142016-08-22 16:08:15 -0700875 A[i] -=
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700876 A[wiener_halfwin1 - 1] * 2 +
877 B[i * wiener_halfwin1 + wiener_halfwin1 - 1] -
878 2 * B[(wiener_halfwin1 - 1) * wiener_halfwin1 + (wiener_halfwin1 - 1)];
879 for (i = 0; i < wiener_halfwin1 - 1; ++i)
880 for (j = 0; j < wiener_halfwin1 - 1; ++j)
881 B[i * wiener_halfwin1 + j] -=
882 2 * (B[i * wiener_halfwin1 + (wiener_halfwin1 - 1)] +
883 B[(wiener_halfwin1 - 1) * wiener_halfwin1 + j] -
884 2 * B[(wiener_halfwin1 - 1) * wiener_halfwin1 +
885 (wiener_halfwin1 - 1)]);
886 if (linsolve(wiener_halfwin1 - 1, B, wiener_halfwin1, A, S)) {
887 S[wiener_halfwin1 - 1] = 1.0;
888 for (i = wiener_halfwin1; i < wiener_win; ++i) {
889 S[i] = S[wiener_win - 1 - i];
890 S[wiener_halfwin1 - 1] -= 2 * S[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700891 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700892 memcpy(b, S, wiener_win * sizeof(*b));
Yaowu Xuc27fc142016-08-22 16:08:15 -0700893 }
894}
895
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700896static int wiener_decompose_sep_sym(int wiener_win, double *M, double *H,
897 double *a, double *b) {
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -0700898 static const int init_filt[WIENER_WIN] = {
899 WIENER_FILT_TAP0_MIDV, WIENER_FILT_TAP1_MIDV, WIENER_FILT_TAP2_MIDV,
900 WIENER_FILT_TAP3_MIDV, WIENER_FILT_TAP2_MIDV, WIENER_FILT_TAP1_MIDV,
901 WIENER_FILT_TAP0_MIDV,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700902 };
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800903 double *Hc[WIENER_WIN2];
904 double *Mc[WIENER_WIN];
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700905 int i, j, iter;
906 const int plane_off = (WIENER_WIN - wiener_win) >> 1;
907 const int wiener_win2 = wiener_win * wiener_win;
908 for (i = 0; i < wiener_win; i++) {
909 a[i] = b[i] = (double)init_filt[i + plane_off] / WIENER_FILT_STEP;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700910 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700911 for (i = 0; i < wiener_win; i++) {
912 Mc[i] = M + i * wiener_win;
913 for (j = 0; j < wiener_win; j++) {
914 Hc[i * wiener_win + j] =
915 H + i * wiener_win * wiener_win2 + j * wiener_win;
916 }
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -0700917 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700918
919 iter = 1;
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -0700920 while (iter < NUM_WIENER_ITERS) {
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700921 update_a_sep_sym(wiener_win, Mc, Hc, a, b);
922 update_b_sep_sym(wiener_win, Mc, Hc, a, b);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700923 iter++;
924 }
925 return 1;
926}
927
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800928// Computes the function x'*H*x - x'*M for the learned 2D filter x, and compares
Yaowu Xuc27fc142016-08-22 16:08:15 -0700929// against identity filters; Final score is defined as the difference between
930// the function values
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700931static double compute_score(int wiener_win, double *M, double *H,
932 InterpKernel vfilt, InterpKernel hfilt) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800933 double ab[WIENER_WIN * WIENER_WIN];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700934 int i, k, l;
935 double P = 0, Q = 0;
936 double iP = 0, iQ = 0;
937 double Score, iScore;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800938 double a[WIENER_WIN], b[WIENER_WIN];
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700939 const int plane_off = (WIENER_WIN - wiener_win) >> 1;
940 const int wiener_win2 = wiener_win * wiener_win;
Jingning Han041c67b2017-04-14 21:39:26 -0700941
942 aom_clear_system_state();
943
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800944 a[WIENER_HALFWIN] = b[WIENER_HALFWIN] = 1.0;
945 for (i = 0; i < WIENER_HALFWIN; ++i) {
946 a[i] = a[WIENER_WIN - i - 1] = (double)vfilt[i] / WIENER_FILT_STEP;
947 b[i] = b[WIENER_WIN - i - 1] = (double)hfilt[i] / WIENER_FILT_STEP;
948 a[WIENER_HALFWIN] -= 2 * a[i];
949 b[WIENER_HALFWIN] -= 2 * b[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700950 }
Debargha Mukherjeea1a1e362017-10-04 20:01:03 -0700951 memset(ab, 0, sizeof(ab));
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700952 for (k = 0; k < wiener_win; ++k) {
953 for (l = 0; l < wiener_win; ++l)
954 ab[k * wiener_win + l] = a[l + plane_off] * b[k + plane_off];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700955 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700956 for (k = 0; k < wiener_win2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700957 P += ab[k] * M[k];
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700958 for (l = 0; l < wiener_win2; ++l)
959 Q += ab[k] * H[k * wiener_win2 + l] * ab[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700960 }
961 Score = Q - 2 * P;
962
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700963 iP = M[wiener_win2 >> 1];
964 iQ = H[(wiener_win2 >> 1) * wiener_win2 + (wiener_win2 >> 1)];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700965 iScore = iQ - 2 * iP;
966
967 return Score - iScore;
968}
969
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700970static void quantize_sym_filter(int wiener_win, double *f, InterpKernel fi) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700971 int i;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700972 const int wiener_halfwin = (wiener_win >> 1);
973 for (i = 0; i < wiener_halfwin; ++i) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800974 fi[i] = RINT(f[i] * WIENER_FILT_STEP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700975 }
976 // Specialize for 7-tap filter
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700977 if (wiener_win == WIENER_WIN) {
978 fi[0] = CLIP(fi[0], WIENER_FILT_TAP0_MINV, WIENER_FILT_TAP0_MAXV);
979 fi[1] = CLIP(fi[1], WIENER_FILT_TAP1_MINV, WIENER_FILT_TAP1_MAXV);
980 fi[2] = CLIP(fi[2], WIENER_FILT_TAP2_MINV, WIENER_FILT_TAP2_MAXV);
981 } else {
982 fi[2] = CLIP(fi[1], WIENER_FILT_TAP2_MINV, WIENER_FILT_TAP2_MAXV);
983 fi[1] = CLIP(fi[0], WIENER_FILT_TAP1_MINV, WIENER_FILT_TAP1_MAXV);
984 fi[0] = 0;
985 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800986 // Satisfy filter constraints
987 fi[WIENER_WIN - 1] = fi[0];
988 fi[WIENER_WIN - 2] = fi[1];
989 fi[WIENER_WIN - 3] = fi[2];
David Barker1e8e6b92017-01-13 13:45:51 +0000990 // The central element has an implicit +WIENER_FILT_STEP
991 fi[3] = -2 * (fi[0] + fi[1] + fi[2]);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800992}
993
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700994static int count_wiener_bits(int wiener_win, WienerInfo *wiener_info,
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -0700995 WienerInfo *ref_wiener_info) {
996 int bits = 0;
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -0700997 if (wiener_win == WIENER_WIN)
998 bits += aom_count_primitive_refsubexpfin(
999 WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1,
1000 WIENER_FILT_TAP0_SUBEXP_K,
1001 ref_wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV,
1002 wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV);
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -07001003 bits += aom_count_primitive_refsubexpfin(
1004 WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
1005 WIENER_FILT_TAP1_SUBEXP_K,
1006 ref_wiener_info->vfilter[1] - WIENER_FILT_TAP1_MINV,
1007 wiener_info->vfilter[1] - WIENER_FILT_TAP1_MINV);
1008 bits += aom_count_primitive_refsubexpfin(
1009 WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
1010 WIENER_FILT_TAP2_SUBEXP_K,
1011 ref_wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV,
1012 wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV);
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -07001013 if (wiener_win == WIENER_WIN)
1014 bits += aom_count_primitive_refsubexpfin(
1015 WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1,
1016 WIENER_FILT_TAP0_SUBEXP_K,
1017 ref_wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV,
1018 wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV);
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -07001019 bits += aom_count_primitive_refsubexpfin(
1020 WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
1021 WIENER_FILT_TAP1_SUBEXP_K,
1022 ref_wiener_info->hfilter[1] - WIENER_FILT_TAP1_MINV,
1023 wiener_info->hfilter[1] - WIENER_FILT_TAP1_MINV);
1024 bits += aom_count_primitive_refsubexpfin(
1025 WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
1026 WIENER_FILT_TAP2_SUBEXP_K,
1027 ref_wiener_info->hfilter[2] - WIENER_FILT_TAP2_MINV,
1028 wiener_info->hfilter[2] - WIENER_FILT_TAP2_MINV);
1029 return bits;
1030}
1031
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001032#define USE_WIENER_REFINEMENT_SEARCH 1
1033static int64_t finer_tile_search_wiener(const YV12_BUFFER_CONFIG *src,
1034 AV1_COMP *cpi, RestorationInfo *rsi,
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -07001035 int start_step, int plane,
1036 int wiener_win, int tile_idx,
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001037 int partial_frame,
1038 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -07001039 const int plane_off = (WIENER_WIN - wiener_win) >> 1;
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001040 int64_t err = try_restoration_tile(src, cpi, rsi, 1 << plane, partial_frame,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001041 tile_idx, dst_frame);
Debargha Mukherjee749f5cd2017-05-31 11:26:51 -07001042 (void)start_step;
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001043#if USE_WIENER_REFINEMENT_SEARCH
1044 int64_t err2;
1045 int tap_min[] = { WIENER_FILT_TAP0_MINV, WIENER_FILT_TAP1_MINV,
1046 WIENER_FILT_TAP2_MINV };
1047 int tap_max[] = { WIENER_FILT_TAP0_MAXV, WIENER_FILT_TAP1_MAXV,
1048 WIENER_FILT_TAP2_MAXV };
1049 // printf("err pre = %"PRId64"\n", err);
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -07001050 for (int s = start_step; s >= 1; s >>= 1) {
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -07001051 for (int p = plane_off; p < WIENER_HALFWIN; ++p) {
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -07001052 int skip = 0;
1053 do {
1054 if (rsi[plane].wiener_info[tile_idx].hfilter[p] - s >= tap_min[p]) {
1055 rsi[plane].wiener_info[tile_idx].hfilter[p] -= s;
1056 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_WIN - p - 1] -= s;
1057 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_HALFWIN] += 2 * s;
1058 err2 = try_restoration_tile(src, cpi, rsi, 1 << plane, partial_frame,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001059 tile_idx, dst_frame);
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -07001060 if (err2 > err) {
1061 rsi[plane].wiener_info[tile_idx].hfilter[p] += s;
1062 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_WIN - p - 1] += s;
1063 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_HALFWIN] -= 2 * s;
1064 } else {
1065 err = err2;
1066 skip = 1;
1067 // At the highest step size continue moving in the same direction
1068 if (s == start_step) continue;
1069 }
1070 }
1071 break;
1072 } while (1);
1073 if (skip) break;
1074 do {
1075 if (rsi[plane].wiener_info[tile_idx].hfilter[p] + s <= tap_max[p]) {
1076 rsi[plane].wiener_info[tile_idx].hfilter[p] += s;
1077 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_WIN - p - 1] += s;
1078 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_HALFWIN] -= 2 * s;
1079 err2 = try_restoration_tile(src, cpi, rsi, 1 << plane, partial_frame,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001080 tile_idx, dst_frame);
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -07001081 if (err2 > err) {
1082 rsi[plane].wiener_info[tile_idx].hfilter[p] -= s;
1083 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_WIN - p - 1] -= s;
1084 rsi[plane].wiener_info[tile_idx].hfilter[WIENER_HALFWIN] += 2 * s;
1085 } else {
1086 err = err2;
1087 // At the highest step size continue moving in the same direction
1088 if (s == start_step) continue;
1089 }
1090 }
1091 break;
1092 } while (1);
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001093 }
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -07001094 for (int p = plane_off; p < WIENER_HALFWIN; ++p) {
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -07001095 int skip = 0;
1096 do {
1097 if (rsi[plane].wiener_info[tile_idx].vfilter[p] - s >= tap_min[p]) {
1098 rsi[plane].wiener_info[tile_idx].vfilter[p] -= s;
1099 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_WIN - p - 1] -= s;
1100 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_HALFWIN] += 2 * s;
1101 err2 = try_restoration_tile(src, cpi, rsi, 1 << plane, partial_frame,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001102 tile_idx, dst_frame);
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -07001103 if (err2 > err) {
1104 rsi[plane].wiener_info[tile_idx].vfilter[p] += s;
1105 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_WIN - p - 1] += s;
1106 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_HALFWIN] -= 2 * s;
1107 } else {
1108 err = err2;
1109 skip = 1;
1110 // At the highest step size continue moving in the same direction
1111 if (s == start_step) continue;
1112 }
1113 }
1114 break;
1115 } while (1);
1116 if (skip) break;
1117 do {
1118 if (rsi[plane].wiener_info[tile_idx].vfilter[p] + s <= tap_max[p]) {
1119 rsi[plane].wiener_info[tile_idx].vfilter[p] += s;
1120 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_WIN - p - 1] += s;
1121 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_HALFWIN] -= 2 * s;
1122 err2 = try_restoration_tile(src, cpi, rsi, 1 << plane, partial_frame,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001123 tile_idx, dst_frame);
Debargha Mukherjee0c18b2c2017-05-15 21:15:30 -07001124 if (err2 > err) {
1125 rsi[plane].wiener_info[tile_idx].vfilter[p] -= s;
1126 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_WIN - p - 1] -= s;
1127 rsi[plane].wiener_info[tile_idx].vfilter[WIENER_HALFWIN] += 2 * s;
1128 } else {
1129 err = err2;
1130 // At the highest step size continue moving in the same direction
1131 if (s == start_step) continue;
1132 }
1133 }
1134 break;
1135 } while (1);
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001136 }
1137 }
1138// printf("err post = %"PRId64"\n", err);
1139#endif // USE_WIENER_REFINEMENT_SEARCH
1140 return err;
1141}
1142
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001143static void search_wiener_for_rtile(const struct rest_search_ctxt *ctxt,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001144 int rtile_idx,
1145 const RestorationTileLimits *limits,
1146 void *arg) {
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001147 const MACROBLOCK *const x = &ctxt->cpi->td.mb;
1148 const AV1_COMMON *const cm = &ctxt->cpi->common;
1149 RestorationInfo *rsi = ctxt->cpi->rst_search;
1150
1151 const int wiener_win =
1152 (ctxt->plane == AOM_PLANE_Y) ? WIENER_WIN : WIENER_WIN_CHROMA;
1153
1154 double M[WIENER_WIN2];
1155 double H[WIENER_WIN2 * WIENER_WIN2];
1156 double vfilterd[WIENER_WIN], hfilterd[WIENER_WIN];
1157
1158 WienerInfo *ref_wiener_info = (WienerInfo *)arg;
1159
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001160 int64_t err =
1161 sse_restoration_tile(ctxt->src, cm->frame_to_show, cm, limits->h_start,
1162 limits->h_end - limits->h_start, limits->v_start,
1163 limits->v_end - limits->v_start, (1 << ctxt->plane));
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001164 // #bits when a tile is not restored
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -07001165 int bits = x->wiener_restore_cost[0];
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001166 double cost_norestore = RDCOST_DBL(x->rdmult, (bits >> 4), err);
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -07001167 ctxt->best_tile_cost[rtile_idx] = INT64_MAX;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001168
1169#if CONFIG_HIGHBITDEPTH
1170 if (cm->use_highbitdepth)
1171 compute_stats_highbd(wiener_win, ctxt->dgd_buffer, ctxt->src_buffer,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001172 limits->h_start, limits->h_end, limits->v_start,
1173 limits->v_end, ctxt->dgd_stride, ctxt->src_stride, M,
1174 H);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001175 else
1176#endif // CONFIG_HIGHBITDEPTH
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001177 compute_stats(wiener_win, ctxt->dgd_buffer, ctxt->src_buffer,
1178 limits->h_start, limits->h_end, limits->v_start,
1179 limits->v_end, ctxt->dgd_stride, ctxt->src_stride, M, H);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001180
1181 ctxt->type[rtile_idx] = RESTORE_WIENER;
1182
1183 if (!wiener_decompose_sep_sym(wiener_win, M, H, vfilterd, hfilterd)) {
1184 ctxt->type[rtile_idx] = RESTORE_NONE;
1185 return;
1186 }
1187
1188 RestorationInfo *plane_rsi = &rsi[ctxt->plane];
1189 WienerInfo *rtile_wiener_info = &plane_rsi->wiener_info[rtile_idx];
1190 quantize_sym_filter(wiener_win, vfilterd, rtile_wiener_info->vfilter);
1191 quantize_sym_filter(wiener_win, hfilterd, rtile_wiener_info->hfilter);
1192
1193 // Filter score computes the value of the function x'*A*x - x'*b for the
1194 // learned filter and compares it against identity filer. If there is no
1195 // reduction in the function, the filter is reverted back to identity
1196 double score = compute_score(wiener_win, M, H, rtile_wiener_info->vfilter,
1197 rtile_wiener_info->hfilter);
1198 if (score > 0.0) {
1199 ctxt->type[rtile_idx] = RESTORE_NONE;
1200 return;
1201 }
1202 aom_clear_system_state();
1203
1204 plane_rsi->restoration_type[rtile_idx] = RESTORE_WIENER;
1205 err = finer_tile_search_wiener(ctxt->src, ctxt->cpi, rsi, 4, ctxt->plane,
1206 wiener_win, rtile_idx, ctxt->partial_frame,
1207 ctxt->dst_frame);
1208 if (wiener_win != WIENER_WIN) {
1209 assert(rtile_wiener_info->vfilter[0] == 0 &&
1210 rtile_wiener_info->vfilter[WIENER_WIN - 1] == 0);
1211 assert(rtile_wiener_info->hfilter[0] == 0 &&
1212 rtile_wiener_info->hfilter[WIENER_WIN - 1] == 0);
1213 }
1214 bits = count_wiener_bits(wiener_win, rtile_wiener_info, ref_wiener_info)
1215 << AV1_PROB_COST_SHIFT;
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -07001216 bits += x->wiener_restore_cost[1];
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001217 double cost_wiener = RDCOST_DBL(x->rdmult, (bits >> 4), err);
1218 if (cost_wiener >= cost_norestore) {
1219 ctxt->type[rtile_idx] = RESTORE_NONE;
1220 } else {
1221 ctxt->type[rtile_idx] = RESTORE_WIENER;
1222 *ref_wiener_info = ctxt->info->wiener_info[rtile_idx] = *rtile_wiener_info;
1223 ctxt->best_tile_cost[rtile_idx] = err;
1224 }
1225 plane_rsi->restoration_type[rtile_idx] = RESTORE_NONE;
1226}
1227
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001228static double search_wiener(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
1229 int partial_frame, int plane, RestorationInfo *info,
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -07001230 RestorationType *type, int64_t *best_tile_cost,
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001231 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -07001232 const MACROBLOCK *const x = &cpi->td.mb;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001233 struct rest_search_ctxt ctxt;
1234 const int nrtiles =
1235 init_rest_search_ctxt(src, cpi, partial_frame, plane, info, type,
1236 best_tile_cost, dst_frame, &ctxt);
1237
1238 RestorationInfo *plane_rsi = &cpi->rst_search[plane];
1239 plane_rsi->frame_restoration_type = RESTORE_WIENER;
1240 for (int tile_idx = 0; tile_idx < nrtiles; ++tile_idx) {
1241 plane_rsi->restoration_type[tile_idx] = RESTORE_NONE;
1242 }
1243
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001244 AV1_COMMON *const cm = &cpi->common;
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001245// Construct a (WIENER_HALFWIN)-pixel border around the frame
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -07001246// Note use this border to gather stats even though the actual filter
1247// may use less border on the top/bottom of a processing unit.
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001248#if CONFIG_HIGHBITDEPTH
1249 if (cm->use_highbitdepth)
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001250 extend_frame_highbd(CONVERT_TO_SHORTPTR(ctxt.dgd_buffer), ctxt.plane_width,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -07001251 ctxt.plane_height, ctxt.dgd_stride, WIENER_HALFWIN,
1252 WIENER_HALFWIN);
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001253 else
1254#endif
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001255 extend_frame(ctxt.dgd_buffer, ctxt.plane_width, ctxt.plane_height,
Debargha Mukherjee1330dfd2017-09-03 22:22:27 -07001256 ctxt.dgd_stride, WIENER_HALFWIN, WIENER_HALFWIN);
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001257
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001258 // Compute best Wiener filters for each rtile, one (encoder/decoder)
1259 // tile at a time.
1260 for (int tile_row = 0; tile_row < cm->tile_rows; ++tile_row) {
1261 for (int tile_col = 0; tile_col < cm->tile_cols; ++tile_col) {
1262 WienerInfo ref_wiener_info;
1263 set_default_wiener(&ref_wiener_info);
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001264
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001265 foreach_rtile_in_tile(&ctxt, tile_row, tile_col, search_wiener_for_rtile,
1266 &ref_wiener_info);
David Barker33f3bfd2017-01-06 15:34:50 +00001267 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001268 }
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001269
1270 // cost for Wiener filtering
1271 WienerInfo ref_wiener_info;
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -07001272 set_default_wiener(&ref_wiener_info);
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001273 int bits = frame_level_restore_bits[plane_rsi->frame_restoration_type]
1274 << AV1_PROB_COST_SHIFT;
1275 WienerInfo *wiener_info = info->wiener_info;
1276 const int wiener_win =
1277 (plane == AOM_PLANE_Y) ? WIENER_WIN : WIENER_WIN_CHROMA;
1278
1279 for (int tile_idx = 0; tile_idx < nrtiles; ++tile_idx) {
Debargha Mukherjeebc732ef2017-10-12 12:40:25 -07001280 bits += x->wiener_restore_cost[type[tile_idx] != RESTORE_NONE];
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001281 plane_rsi->wiener_info[tile_idx] = wiener_info[tile_idx];
1282
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001283 if (type[tile_idx] == RESTORE_WIENER) {
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001284 bits += count_wiener_bits(wiener_win, &plane_rsi->wiener_info[tile_idx],
Debargha Mukherjee1cb757c2017-08-21 02:46:31 -07001285 &ref_wiener_info)
1286 << AV1_PROB_COST_SHIFT;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001287 ref_wiener_info = plane_rsi->wiener_info[tile_idx];
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001288 }
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001289 plane_rsi->restoration_type[tile_idx] = type[tile_idx];
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001290 }
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001291 int64_t err = try_restoration_frame(src, cpi, cpi->rst_search, 1 << plane,
1292 partial_frame, dst_frame);
1293 double cost_wiener = RDCOST_DBL(cpi->td.mb.rdmult, (bits >> 4), err);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001294
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001295 return cost_wiener;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001296}
1297
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001298static double search_norestore(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001299 int partial_frame, int plane,
1300 RestorationInfo *info, RestorationType *type,
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -07001301 int64_t *best_tile_cost,
David Barker9666e752016-12-08 11:25:47 +00001302 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -07001303 int64_t err;
1304 double cost_norestore;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001305 int bits;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001306 MACROBLOCK *x = &cpi->td.mb;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001307 AV1_COMMON *const cm = &cpi->common;
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +01001308 int tile_idx, nhtiles, nvtiles;
1309
1310 const int is_uv = plane > 0;
1311 const int ss_y = plane > 0 && cm->subsampling_y;
1312 const int width = src->crop_widths[is_uv];
1313 const int height = src->crop_heights[is_uv];
1314
1315 const int rtile_size = cm->rst_info[plane].restoration_tilesize;
1316
1317 const int ntiles =
1318 av1_get_rest_ntiles(width, height, rtile_size, &nhtiles, &nvtiles);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001319 (void)info;
David Barker9666e752016-12-08 11:25:47 +00001320 (void)dst_frame;
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001321 (void)partial_frame;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001322
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001323 info->frame_restoration_type = RESTORE_NONE;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001324 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001325 RestorationTileLimits limits = av1_get_rest_tile_limits(
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +01001326 tile_idx, nhtiles, nvtiles, rtile_size, width, height, ss_y);
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001327 err = sse_restoration_tile(src, cm->frame_to_show, cm, limits.h_start,
1328 limits.h_end - limits.h_start, limits.v_start,
1329 limits.v_end - limits.v_start, 1 << plane);
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001330 type[tile_idx] = RESTORE_NONE;
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -07001331 best_tile_cost[tile_idx] = err;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001332 }
1333 // RD cost associated with no restoration
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001334 err = sse_restoration_frame(cm, src, cm->frame_to_show, (1 << plane));
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001335 bits = frame_level_restore_bits[RESTORE_NONE] << AV1_PROB_COST_SHIFT;
Urvang Joshi70006e42017-06-14 16:08:55 -07001336 cost_norestore = RDCOST_DBL(x->rdmult, (bits >> 4), err);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001337 return cost_norestore;
1338}
1339
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001340struct switchable_rest_search_ctxt {
1341 SgrprojInfo sgrproj_info;
1342 WienerInfo wiener_info;
1343 RestorationType *const *restore_types;
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -07001344 int64_t *const *tile_cost;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001345 double cost_switchable;
1346};
1347
1348static void search_switchable_for_rtile(const struct rest_search_ctxt *ctxt,
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001349 int rtile_idx,
1350 const RestorationTileLimits *limits,
1351 void *arg) {
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001352 const MACROBLOCK *x = &ctxt->cpi->td.mb;
1353 RestorationInfo *rsi = &ctxt->cpi->common.rst_info[ctxt->plane];
1354 struct switchable_rest_search_ctxt *swctxt =
1355 (struct switchable_rest_search_ctxt *)arg;
1356
Rupert Swarbrick5d2e7292017-09-26 11:32:17 +01001357 (void)limits;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001358
1359 double best_cost =
1360 RDCOST_DBL(x->rdmult, (x->switchable_restore_cost[RESTORE_NONE] >> 4),
1361 swctxt->tile_cost[RESTORE_NONE][rtile_idx]);
1362 rsi->restoration_type[rtile_idx] = RESTORE_NONE;
1363 for (RestorationType r = 1; r < RESTORE_SWITCHABLE_TYPES; r++) {
Debargha Mukherjee1b4ccc22017-09-30 13:33:03 -07001364 if (force_restore_type != RESTORE_TYPES)
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001365 if (r != force_restore_type) continue;
1366 int tilebits = 0;
1367 if (swctxt->restore_types[r][rtile_idx] != r) continue;
1368 if (r == RESTORE_WIENER)
1369 tilebits += count_wiener_bits(
1370 (ctxt->plane == AOM_PLANE_Y ? WIENER_WIN : WIENER_WIN - 2),
1371 &rsi->wiener_info[rtile_idx], &swctxt->wiener_info);
1372 else if (r == RESTORE_SGRPROJ)
1373 tilebits += count_sgrproj_bits(&rsi->sgrproj_info[rtile_idx],
1374 &swctxt->sgrproj_info);
1375 tilebits <<= AV1_PROB_COST_SHIFT;
1376 tilebits += x->switchable_restore_cost[r];
1377 double cost =
1378 RDCOST_DBL(x->rdmult, tilebits >> 4, swctxt->tile_cost[r][rtile_idx]);
1379
1380 if (cost < best_cost) {
1381 rsi->restoration_type[rtile_idx] = r;
1382 best_cost = cost;
1383 }
1384 }
1385 if (rsi->restoration_type[rtile_idx] == RESTORE_WIENER)
1386 swctxt->wiener_info = rsi->wiener_info[rtile_idx];
1387 else if (rsi->restoration_type[rtile_idx] == RESTORE_SGRPROJ)
1388 swctxt->sgrproj_info = rsi->sgrproj_info[rtile_idx];
Debargha Mukherjee1b4ccc22017-09-30 13:33:03 -07001389 if (force_restore_type != RESTORE_TYPES)
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001390 assert(rsi->restoration_type[rtile_idx] == force_restore_type ||
1391 rsi->restoration_type[rtile_idx] == RESTORE_NONE);
1392 swctxt->cost_switchable += best_cost;
1393}
1394
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001395static double search_switchable_restoration(
Debargha Mukherjee2dd982e2017-06-05 13:55:12 -07001396 const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, int partial_frame, int plane,
Debargha Mukherjee6f0566e2017-06-23 13:15:33 -07001397 RestorationType *const restore_types[RESTORE_SWITCHABLE_TYPES],
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -07001398 int64_t *const tile_cost[RESTORE_SWITCHABLE_TYPES], RestorationInfo *rsi) {
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001399 const AV1_COMMON *const cm = &cpi->common;
1400 struct rest_search_ctxt ctxt;
1401 init_rest_search_ctxt(src, cpi, partial_frame, plane, NULL, NULL, NULL, NULL,
1402 &ctxt);
1403 struct switchable_rest_search_ctxt swctxt;
1404 swctxt.restore_types = restore_types;
1405 swctxt.tile_cost = tile_cost;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001406
1407 rsi->frame_restoration_type = RESTORE_SWITCHABLE;
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001408 int bits = frame_level_restore_bits[rsi->frame_restoration_type]
1409 << AV1_PROB_COST_SHIFT;
1410 swctxt.cost_switchable = RDCOST_DBL(cpi->td.mb.rdmult, bits >> 4, 0);
Debargha Mukherjeecfc12f32017-04-18 07:03:32 -07001411
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001412 for (int tile_row = 0; tile_row < cm->tile_rows; ++tile_row) {
1413 for (int tile_col = 0; tile_col < cm->tile_cols; ++tile_col) {
1414 set_default_sgrproj(&swctxt.sgrproj_info);
1415 set_default_wiener(&swctxt.wiener_info);
1416 foreach_rtile_in_tile(&ctxt, tile_row, tile_col,
1417 search_switchable_for_rtile, &swctxt);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001418 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001419 }
Rupert Swarbrick09b5b162017-08-31 16:32:29 +01001420
1421 return swctxt.cost_switchable;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001422}
1423
1424void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Yaowu Xuf883b422016-08-30 14:01:10 -07001425 LPF_PICK_METHOD method) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001426 static search_restore_type search_restore_fun[RESTORE_SWITCHABLE_TYPES] = {
Debargha Mukherjee4bfd72e2017-03-08 22:20:31 -08001427 search_norestore, search_wiener, search_sgrproj,
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001428 };
Yaowu Xuf883b422016-08-30 14:01:10 -07001429 AV1_COMMON *const cm = &cpi->common;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001430 double cost_restore[RESTORE_TYPES];
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -07001431 int64_t *tile_cost[RESTORE_SWITCHABLE_TYPES];
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001432 RestorationType *restore_types[RESTORE_SWITCHABLE_TYPES];
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001433 double best_cost_restore;
1434 RestorationType r, best_restore;
Debargha Mukherjee2dd982e2017-06-05 13:55:12 -07001435 const int ywidth = src->y_crop_width;
1436 const int yheight = src->y_crop_height;
1437 const int uvwidth = src->uv_crop_width;
1438 const int uvheight = src->uv_crop_height;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001439
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +01001440 const int ntiles_y = av1_get_rest_ntiles(
1441 ywidth, yheight, cm->rst_info[0].restoration_tilesize, NULL, NULL);
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -07001442 const int ntiles_uv = av1_get_rest_ntiles(
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +01001443 uvwidth, uvheight, cm->rst_info[1].restoration_tilesize, NULL, NULL);
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001444
1445 // Assume ntiles_uv is never larger that ntiles_y and so the same arrays work.
Rupert Swarbrick64b8bbd2017-10-16 15:53:07 +01001446 assert(ntiles_uv <= ntiles_y);
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001447 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) {
Debargha Mukherjee0c65e0a2017-10-08 09:19:39 -07001448 tile_cost[r] = (int64_t *)aom_malloc(sizeof(*tile_cost[0]) * ntiles_y);
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001449 restore_types[r] =
1450 (RestorationType *)aom_malloc(sizeof(*restore_types[0]) * ntiles_y);
1451 }
1452
1453 for (int plane = AOM_PLANE_Y; plane <= AOM_PLANE_V; ++plane) {
1454 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; ++r) {
1455 cost_restore[r] = DBL_MAX;
Tom Finegan8af64ae2017-09-07 08:13:06 -07001456 if (force_restore_type != RESTORE_TYPES)
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001457 if (r != RESTORE_NONE && r != force_restore_type) continue;
1458 cost_restore[r] =
1459 search_restore_fun[r](src, cpi, method == LPF_PICK_FROM_SUBIMAGE,
1460 plane, &cm->rst_info[plane], restore_types[r],
1461 tile_cost[r], &cpi->trial_frame_rst);
1462 }
1463 if (plane == AOM_PLANE_Y)
Debargha Mukherjee2dd982e2017-06-05 13:55:12 -07001464 cost_restore[RESTORE_SWITCHABLE] = search_switchable_restoration(
Debargha Mukherjee6f0566e2017-06-23 13:15:33 -07001465 src, cpi, method == LPF_PICK_FROM_SUBIMAGE, plane, restore_types,
1466 tile_cost, &cm->rst_info[plane]);
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001467 else
1468 cost_restore[RESTORE_SWITCHABLE] = DBL_MAX;
1469 best_cost_restore = DBL_MAX;
1470 best_restore = 0;
1471 for (r = 0; r < RESTORE_TYPES; ++r) {
Tom Finegan8af64ae2017-09-07 08:13:06 -07001472 if (force_restore_type != RESTORE_TYPES)
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001473 if (r != RESTORE_NONE && r != force_restore_type) continue;
1474 if (cost_restore[r] < best_cost_restore) {
1475 best_restore = r;
1476 best_cost_restore = cost_restore[r];
1477 }
1478 }
1479 cm->rst_info[plane].frame_restoration_type = best_restore;
Tom Finegan8af64ae2017-09-07 08:13:06 -07001480 if (force_restore_type != RESTORE_TYPES)
Debargha Mukherjeed48f5732017-05-19 14:58:07 -07001481 assert(best_restore == force_restore_type ||
1482 best_restore == RESTORE_NONE);
1483 if (best_restore != RESTORE_SWITCHABLE) {
1484 const int nt = (plane == AOM_PLANE_Y ? ntiles_y : ntiles_uv);
1485 memcpy(cm->rst_info[plane].restoration_type, restore_types[best_restore],
1486 nt * sizeof(restore_types[best_restore][0]));
Debargha Mukherjeed23ceea2017-05-18 20:33:52 -07001487 }
1488 }
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001489 /*
Debargha Mukherjeee39e2ee2017-05-11 03:38:03 -07001490 printf("Frame %d/%d restore types: %d %d %d\n", cm->current_video_frame,
1491 cm->show_frame, cm->rst_info[0].frame_restoration_type,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001492 cm->rst_info[1].frame_restoration_type,
1493 cm->rst_info[2].frame_restoration_type);
Debargha Mukherjeeb3c43bc2017-02-01 13:09:03 -08001494 printf("Frame %d/%d frame_restore_type %d : %f %f %f %f\n",
1495 cm->current_video_frame, cm->show_frame,
1496 cm->rst_info[0].frame_restoration_type, cost_restore[0],
1497 cost_restore[1], cost_restore[2], cost_restore[3]);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001498 */
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001499
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001500 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) {
1501 aom_free(tile_cost[r]);
1502 aom_free(restore_types[r]);
1503 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001504}