blob: 7121bfb83626fae805c357de8784c4a9e6898915 [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
19#include "aom_dsp/psnr.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070020#include "aom_dsp/aom_dsp_common.h"
21#include "aom_mem/aom_mem.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070022#include "aom_ports/mem.h"
23
24#include "av1/common/onyxc_int.h"
25#include "av1/common/quant_common.h"
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080026#include "av1/common/restoration.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070027
Tom Finegan17ce8b12017-02-08 12:46:31 -080028#include "av1/encoder/av1_quantize.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070029#include "av1/encoder/encoder.h"
30#include "av1/encoder/picklpf.h"
31#include "av1/encoder/pickrst.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070032
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -070033// When set to 1, only RESTORE_WIENER or RESTORE_NONE are allowed
34#define FORCE_RESTORE_WIENER_ONLY 0
35
36// Number of Wiener iterations
37#define NUM_WIENER_ITERS 10
38
Debargha Mukherjee5d89a632016-09-17 13:16:58 -070039typedef double (*search_restore_type)(const YV12_BUFFER_CONFIG *src,
Debargha Mukherjee00c54332017-03-03 15:44:17 -080040 AV1_COMP *cpi, int partial_frame,
41 RestorationInfo *info,
Debargha Mukherjee994ccd72017-01-06 11:18:23 -080042 RestorationType *rest_level,
David Barker9666e752016-12-08 11:25:47 +000043 double *best_tile_cost,
44 YV12_BUFFER_CONFIG *dst_frame);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -070045
Debargha Mukherjeeb3c43bc2017-02-01 13:09:03 -080046const int frame_level_restore_bits[RESTORE_TYPES] = { 2, 2, 2, 2 };
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070047
48static int64_t sse_restoration_tile(const YV12_BUFFER_CONFIG *src,
David Barker9666e752016-12-08 11:25:47 +000049 const YV12_BUFFER_CONFIG *dst,
50 const AV1_COMMON *cm, int h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080051 int width, int v_start, int height,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080052 int components_pattern) {
53 int64_t filt_err = 0;
Debargha Mukherjeed7489142017-01-05 13:58:16 -080054 (void)cm;
55 // Y and UV components cannot be mixed
56 assert(components_pattern == 1 || components_pattern == 2 ||
57 components_pattern == 4 || components_pattern == 6);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070058#if CONFIG_AOM_HIGHBITDEPTH
59 if (cm->use_highbitdepth) {
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080060 if ((components_pattern >> AOM_PLANE_Y) & 1) {
61 filt_err +=
62 aom_highbd_get_y_sse_part(src, dst, h_start, width, v_start, height);
63 }
64 if ((components_pattern >> AOM_PLANE_U) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080065 filt_err +=
66 aom_highbd_get_u_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080067 }
68 if ((components_pattern >> AOM_PLANE_V) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080069 filt_err +=
70 aom_highbd_get_v_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080071 }
72 return filt_err;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070073 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070074#endif // CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080075 if ((components_pattern >> AOM_PLANE_Y) & 1) {
76 filt_err += aom_get_y_sse_part(src, dst, h_start, width, v_start, height);
77 }
78 if ((components_pattern >> AOM_PLANE_U) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080079 filt_err += aom_get_u_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080080 }
81 if ((components_pattern >> AOM_PLANE_V) & 1) {
Debargha Mukherjeed7489142017-01-05 13:58:16 -080082 filt_err += aom_get_v_sse_part(src, dst, h_start, width, v_start, height);
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080083 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070084 return filt_err;
85}
86
David Barker60a055b2017-01-18 15:10:43 +000087static int64_t sse_restoration_frame(AV1_COMMON *const cm,
88 const YV12_BUFFER_CONFIG *src,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080089 const YV12_BUFFER_CONFIG *dst,
90 int components_pattern) {
91 int64_t filt_err = 0;
92#if CONFIG_AOM_HIGHBITDEPTH
93 if (cm->use_highbitdepth) {
94 if ((components_pattern >> AOM_PLANE_Y) & 1) {
95 filt_err += aom_highbd_get_y_sse(src, dst);
96 }
97 if ((components_pattern >> AOM_PLANE_U) & 1) {
98 filt_err += aom_highbd_get_u_sse(src, dst);
99 }
100 if ((components_pattern >> AOM_PLANE_V) & 1) {
101 filt_err += aom_highbd_get_v_sse(src, dst);
102 }
103 return filt_err;
104 }
David Barker60a055b2017-01-18 15:10:43 +0000105#else
106 (void)cm;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800107#endif // CONFIG_AOM_HIGHBITDEPTH
108 if ((components_pattern >> AOM_PLANE_Y) & 1) {
109 filt_err = aom_get_y_sse(src, dst);
110 }
111 if ((components_pattern >> AOM_PLANE_U) & 1) {
112 filt_err += aom_get_u_sse(src, dst);
113 }
114 if ((components_pattern >> AOM_PLANE_V) & 1) {
115 filt_err += aom_get_v_sse(src, dst);
116 }
117 return filt_err;
118}
119
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700120static int64_t try_restoration_tile(const YV12_BUFFER_CONFIG *src,
121 AV1_COMP *const cpi, RestorationInfo *rsi,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800122 int components_pattern, int partial_frame,
123 int tile_idx, int subtile_idx,
124 int subtile_bits,
David Barker9666e752016-12-08 11:25:47 +0000125 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700126 AV1_COMMON *const cm = &cpi->common;
127 int64_t filt_err;
128 int tile_width, tile_height, nhtiles, nvtiles;
129 int h_start, h_end, v_start, v_end;
Debargha Mukherjeed7489142017-01-05 13:58:16 -0800130 int ntiles, width, height;
131
132 // Y and UV components cannot be mixed
133 assert(components_pattern == 1 || components_pattern == 2 ||
134 components_pattern == 4 || components_pattern == 6);
135
136 if (components_pattern == 1) { // Y only
137 width = src->y_crop_width;
138 height = src->y_crop_height;
139 } else { // Color
140 width = src->uv_crop_width;
141 height = src->uv_crop_height;
142 }
Debargha Mukherjee1008c1e2017-03-06 19:18:43 -0800143 ntiles = av1_get_rest_ntiles(
144 width, height, cm->rst_info[components_pattern > 1].restoration_tilesize,
145 &tile_width, &tile_height, &nhtiles, &nvtiles);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700146 (void)ntiles;
147
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800148 av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
149 partial_frame, dst_frame);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700150 av1_get_rest_tile_limits(tile_idx, subtile_idx, subtile_bits, nhtiles,
Debargha Mukherjeed7489142017-01-05 13:58:16 -0800151 nvtiles, tile_width, tile_height, width, height, 0,
152 0, &h_start, &h_end, &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +0000153 filt_err = sse_restoration_tile(src, dst_frame, cm, h_start, h_end - h_start,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800154 v_start, v_end - v_start, components_pattern);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700155
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700156 return filt_err;
157}
158
159static int64_t try_restoration_frame(const YV12_BUFFER_CONFIG *src,
Yaowu Xuf883b422016-08-30 14:01:10 -0700160 AV1_COMP *const cpi, RestorationInfo *rsi,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800161 int components_pattern, int partial_frame,
David Barker9666e752016-12-08 11:25:47 +0000162 YV12_BUFFER_CONFIG *dst_frame) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700163 AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700164 int64_t filt_err;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800165 av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
166 partial_frame, dst_frame);
David Barker60a055b2017-01-18 15:10:43 +0000167 filt_err = sse_restoration_frame(cm, src, dst_frame, components_pattern);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700168 return filt_err;
169}
170
David Barker3a0df182016-12-21 10:44:52 +0000171static int64_t get_pixel_proj_error(uint8_t *src8, int width, int height,
172 int src_stride, uint8_t *dat8,
173 int dat_stride, int bit_depth,
174 int32_t *flt1, int flt1_stride,
175 int32_t *flt2, int flt2_stride, int *xqd) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700176 int i, j;
177 int64_t err = 0;
178 int xq[2];
179 decode_xq(xqd, xq);
David Barker3a0df182016-12-21 10:44:52 +0000180 if (bit_depth == 8) {
181 const uint8_t *src = src8;
182 const uint8_t *dat = dat8;
183 for (i = 0; i < height; ++i) {
184 for (j = 0; j < width; ++j) {
185 const int32_t u =
186 (int32_t)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
187 const int32_t f1 = (int32_t)flt1[i * flt1_stride + j] - u;
188 const int32_t f2 = (int32_t)flt2[i * flt2_stride + j] - u;
David Barkerce110cc2017-02-22 10:38:59 +0000189 const int32_t v = xq[0] * f1 + xq[1] * f2 + (u << SGRPROJ_PRJ_BITS);
David Barker3a0df182016-12-21 10:44:52 +0000190 const int32_t e =
191 ROUND_POWER_OF_TWO(v, SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS) -
192 src[i * src_stride + j];
193 err += e * e;
194 }
195 }
196 } else {
197 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
198 const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
199 for (i = 0; i < height; ++i) {
200 for (j = 0; j < width; ++j) {
201 const int32_t u =
202 (int32_t)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
203 const int32_t f1 = (int32_t)flt1[i * flt1_stride + j] - u;
204 const int32_t f2 = (int32_t)flt2[i * flt2_stride + j] - u;
David Barkerce110cc2017-02-22 10:38:59 +0000205 const int32_t v = xq[0] * f1 + xq[1] * f2 + (u << SGRPROJ_PRJ_BITS);
David Barker3a0df182016-12-21 10:44:52 +0000206 const int32_t e =
207 ROUND_POWER_OF_TWO(v, SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS) -
208 src[i * src_stride + j];
209 err += e * e;
210 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700211 }
212 }
213 return err;
214}
215
David Barker3a0df182016-12-21 10:44:52 +0000216static void get_proj_subspace(uint8_t *src8, int width, int height,
217 int src_stride, uint8_t *dat8, int dat_stride,
218 int bit_depth, int32_t *flt1, int flt1_stride,
219 int32_t *flt2, int flt2_stride, int *xq) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700220 int i, j;
221 double H[2][2] = { { 0, 0 }, { 0, 0 } };
222 double C[2] = { 0, 0 };
223 double Det;
224 double x[2];
225 const int size = width * height;
226
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800227 // Default
228 xq[0] = 0;
229 xq[1] = 0;
David Barker3a0df182016-12-21 10:44:52 +0000230 if (bit_depth == 8) {
231 const uint8_t *src = src8;
232 const uint8_t *dat = dat8;
233 for (i = 0; i < height; ++i) {
234 for (j = 0; j < width; ++j) {
235 const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
236 const double s =
237 (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
238 const double f1 = (double)flt1[i * flt1_stride + j] - u;
239 const double f2 = (double)flt2[i * flt2_stride + j] - u;
240 H[0][0] += f1 * f1;
241 H[1][1] += f2 * f2;
242 H[0][1] += f1 * f2;
243 C[0] += f1 * s;
244 C[1] += f2 * s;
245 }
246 }
247 } else {
248 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
249 const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
250 for (i = 0; i < height; ++i) {
251 for (j = 0; j < width; ++j) {
252 const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
253 const double s =
254 (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
255 const double f1 = (double)flt1[i * flt1_stride + j] - u;
256 const double f2 = (double)flt2[i * flt2_stride + j] - u;
257 H[0][0] += f1 * f1;
258 H[1][1] += f2 * f2;
259 H[0][1] += f1 * f2;
260 C[0] += f1 * s;
261 C[1] += f2 * s;
262 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700263 }
264 }
265 H[0][0] /= size;
266 H[0][1] /= size;
267 H[1][1] /= size;
268 H[1][0] = H[0][1];
269 C[0] /= size;
270 C[1] /= size;
271 Det = (H[0][0] * H[1][1] - H[0][1] * H[1][0]);
272 if (Det < 1e-8) return; // ill-posed, return default values
273 x[0] = (H[1][1] * C[0] - H[0][1] * C[1]) / Det;
274 x[1] = (H[0][0] * C[1] - H[1][0] * C[0]) / Det;
275 xq[0] = (int)rint(x[0] * (1 << SGRPROJ_PRJ_BITS));
276 xq[1] = (int)rint(x[1] * (1 << SGRPROJ_PRJ_BITS));
277}
278
279void encode_xq(int *xq, int *xqd) {
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800280 xqd[0] = xq[0];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700281 xqd[0] = clamp(xqd[0], SGRPROJ_PRJ_MIN0, SGRPROJ_PRJ_MAX0);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800282 xqd[1] = (1 << SGRPROJ_PRJ_BITS) - xqd[0] - xq[1];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700283 xqd[1] = clamp(xqd[1], SGRPROJ_PRJ_MIN1, SGRPROJ_PRJ_MAX1);
284}
285
286static void search_selfguided_restoration(uint8_t *dat8, int width, int height,
287 int dat_stride, uint8_t *src8,
288 int src_stride, int bit_depth,
David Barker3a0df182016-12-21 10:44:52 +0000289 int *eps, int *xqd, int32_t *rstbuf) {
290 int32_t *flt1 = rstbuf;
Debargha Mukherjee519dbcf2016-12-16 03:13:02 -0800291 int32_t *flt2 = flt1 + RESTORATION_TILEPELS_MAX;
David Barker3a0df182016-12-21 10:44:52 +0000292 int32_t *tmpbuf2 = flt2 + RESTORATION_TILEPELS_MAX;
David Barker506eb722017-03-08 13:35:49 +0000293 int ep, bestep = 0;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700294 int64_t err, besterr = -1;
295 int exqd[2], bestxqd[2] = { 0, 0 };
David Barker3a0df182016-12-21 10:44:52 +0000296
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700297 for (ep = 0; ep < SGRPROJ_PARAMS; ep++) {
298 int exq[2];
David Barker506eb722017-03-08 13:35:49 +0000299#if CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700300 if (bit_depth > 8) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700301 uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800302#if USE_HIGHPASS_IN_SGRPROJ
303 av1_highpass_filter_highbd(dat, width, height, dat_stride, flt1, width,
David Barkereed824e2017-03-10 11:35:22 +0000304 sgr_params[ep].corner, sgr_params[ep].edge);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800305#else
David Barker506eb722017-03-08 13:35:49 +0000306 av1_selfguided_restoration_highbd(dat, width, height, dat_stride, flt1,
307 width, bit_depth, sgr_params[ep].r1,
308 sgr_params[ep].e1, tmpbuf2);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800309#endif // USE_HIGHPASS_IN_SGRPROJ
David Barker506eb722017-03-08 13:35:49 +0000310 av1_selfguided_restoration_highbd(dat, width, height, dat_stride, flt2,
311 width, bit_depth, sgr_params[ep].r2,
312 sgr_params[ep].e2, tmpbuf2);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700313 } else {
David Barker506eb722017-03-08 13:35:49 +0000314#endif
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800315#if USE_HIGHPASS_IN_SGRPROJ
316 av1_highpass_filter(dat8, width, height, dat_stride, flt1, width,
David Barkereed824e2017-03-10 11:35:22 +0000317 sgr_params[ep].corner, sgr_params[ep].edge);
Debargha Mukherjeeb7bb0972017-03-09 06:47:43 -0800318#else
319 av1_selfguided_restoration(dat8, width, height, dat_stride, flt1, width,
320 sgr_params[ep].r1, sgr_params[ep].e1, tmpbuf2);
321#endif // USE_HIGHPASS_IN_SGRPROJ
David Barker506eb722017-03-08 13:35:49 +0000322 av1_selfguided_restoration(dat8, width, height, dat_stride, flt2, width,
David Barker4d2af5d2017-03-09 11:46:50 +0000323 sgr_params[ep].r2, sgr_params[ep].e2, tmpbuf2);
David Barker506eb722017-03-08 13:35:49 +0000324#if CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700325 }
David Barker506eb722017-03-08 13:35:49 +0000326#endif
David Barker3a0df182016-12-21 10:44:52 +0000327 get_proj_subspace(src8, width, height, src_stride, dat8, dat_stride,
328 bit_depth, flt1, width, flt2, width, exq);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700329 encode_xq(exq, exqd);
David Barker3a0df182016-12-21 10:44:52 +0000330 err =
331 get_pixel_proj_error(src8, width, height, src_stride, dat8, dat_stride,
332 bit_depth, flt1, width, flt2, width, exqd);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700333 if (besterr == -1 || err < besterr) {
334 bestep = ep;
335 besterr = err;
336 bestxqd[0] = exqd[0];
337 bestxqd[1] = exqd[1];
338 }
339 }
340 *eps = bestep;
341 xqd[0] = bestxqd[0];
342 xqd[1] = bestxqd[1];
343}
344
345static double search_sgrproj(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Debargha Mukherjee00c54332017-03-03 15:44:17 -0800346 int partial_frame, RestorationInfo *info,
347 RestorationType *type, double *best_tile_cost,
David Barker9666e752016-12-08 11:25:47 +0000348 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700349 SgrprojInfo *sgrproj_info = info->sgrproj_info;
350 double err, cost_norestore, cost_sgrproj;
351 int bits;
352 MACROBLOCK *x = &cpi->td.mb;
353 AV1_COMMON *const cm = &cpi->common;
354 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800355 RestorationInfo *rsi = &cpi->rst_search[0];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700356 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
357 int h_start, h_end, v_start, v_end;
Debargha Mukherjee874d36d2016-12-14 16:53:17 -0800358 // Allocate for the src buffer at high precision
Debargha Mukherjee1008c1e2017-03-06 19:18:43 -0800359 const int ntiles = av1_get_rest_ntiles(
360 cm->width, cm->height, cm->rst_info[0].restoration_tilesize, &tile_width,
361 &tile_height, &nhtiles, &nvtiles);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800362 rsi->frame_restoration_type = RESTORE_SGRPROJ;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700363
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800364 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
365 rsi->restoration_type[tile_idx] = RESTORE_NONE;
366 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700367 // Compute best Sgrproj filters for each tile
368 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
369 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
370 tile_height, cm->width, cm->height, 0, 0, &h_start,
371 &h_end, &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +0000372 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -0800373 h_end - h_start, v_start, v_end - v_start, 1);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700374 // #bits when a tile is not restored
375 bits = av1_cost_bit(RESTORE_NONE_SGRPROJ_PROB, 0);
376 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
377 best_tile_cost[tile_idx] = DBL_MAX;
378 search_selfguided_restoration(
379 dgd->y_buffer + v_start * dgd->y_stride + h_start, h_end - h_start,
380 v_end - v_start, dgd->y_stride,
381 src->y_buffer + v_start * src->y_stride + h_start, src->y_stride,
382#if CONFIG_AOM_HIGHBITDEPTH
383 cm->bit_depth,
384#else
385 8,
386#endif // CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800387 &rsi->sgrproj_info[tile_idx].ep, rsi->sgrproj_info[tile_idx].xqd,
David Barker3a0df182016-12-21 10:44:52 +0000388 cm->rst_internal.tmpbuf);
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800389 rsi->restoration_type[tile_idx] = RESTORE_SGRPROJ;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800390 err = try_restoration_tile(src, cpi, rsi, 1, partial_frame, tile_idx, 0, 0,
David Barker9666e752016-12-08 11:25:47 +0000391 dst_frame);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700392 bits = SGRPROJ_BITS << AV1_PROB_COST_SHIFT;
393 bits += av1_cost_bit(RESTORE_NONE_SGRPROJ_PROB, 1);
394 cost_sgrproj = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
395 if (cost_sgrproj >= cost_norestore) {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800396 type[tile_idx] = RESTORE_NONE;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700397 } else {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800398 type[tile_idx] = RESTORE_SGRPROJ;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800399 memcpy(&sgrproj_info[tile_idx], &rsi->sgrproj_info[tile_idx],
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700400 sizeof(sgrproj_info[tile_idx]));
401 bits = SGRPROJ_BITS << AV1_PROB_COST_SHIFT;
402 best_tile_cost[tile_idx] = RDCOST_DBL(
403 x->rdmult, x->rddiv,
404 (bits + cpi->switchable_restore_cost[RESTORE_SGRPROJ]) >> 4, err);
405 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800406 rsi->restoration_type[tile_idx] = RESTORE_NONE;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700407 }
408 // Cost for Sgrproj filtering
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800409 bits = frame_level_restore_bits[rsi->frame_restoration_type]
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700410 << AV1_PROB_COST_SHIFT;
411 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
412 bits +=
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800413 av1_cost_bit(RESTORE_NONE_SGRPROJ_PROB, type[tile_idx] != RESTORE_NONE);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800414 memcpy(&rsi->sgrproj_info[tile_idx], &sgrproj_info[tile_idx],
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700415 sizeof(sgrproj_info[tile_idx]));
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800416 if (type[tile_idx] == RESTORE_SGRPROJ) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700417 bits += (SGRPROJ_BITS << AV1_PROB_COST_SHIFT);
418 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800419 rsi->restoration_type[tile_idx] = type[tile_idx];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700420 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800421 err = try_restoration_frame(src, cpi, rsi, 1, partial_frame, dst_frame);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700422 cost_sgrproj = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
423
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700424 return cost_sgrproj;
425}
426
Yaowu Xuc27fc142016-08-22 16:08:15 -0700427static double find_average(uint8_t *src, int h_start, int h_end, int v_start,
428 int v_end, int stride) {
429 uint64_t sum = 0;
430 double avg = 0;
431 int i, j;
432 for (i = v_start; i < v_end; i++)
433 for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
434 avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
435 return avg;
436}
437
438static void compute_stats(uint8_t *dgd, uint8_t *src, int h_start, int h_end,
439 int v_start, int v_end, int dgd_stride,
440 int src_stride, double *M, double *H) {
441 int i, j, k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800442 double Y[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700443 const double avg =
444 find_average(dgd, h_start, h_end, v_start, v_end, dgd_stride);
445
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800446 memset(M, 0, sizeof(*M) * WIENER_WIN2);
447 memset(H, 0, sizeof(*H) * WIENER_WIN2 * WIENER_WIN2);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700448 for (i = v_start; i < v_end; i++) {
449 for (j = h_start; j < h_end; j++) {
450 const double X = (double)src[i * src_stride + j] - avg;
451 int idx = 0;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800452 for (k = -WIENER_HALFWIN; k <= WIENER_HALFWIN; k++) {
453 for (l = -WIENER_HALFWIN; l <= WIENER_HALFWIN; l++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700454 Y[idx] = (double)dgd[(i + l) * dgd_stride + (j + k)] - avg;
455 idx++;
456 }
457 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800458 for (k = 0; k < WIENER_WIN2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700459 M[k] += Y[k] * X;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800460 H[k * WIENER_WIN2 + k] += Y[k] * Y[k];
461 for (l = k + 1; l < WIENER_WIN2; ++l) {
David Barker33f3bfd2017-01-06 15:34:50 +0000462 // H is a symmetric matrix, so we only need to fill out the upper
463 // triangle here. We can copy it down to the lower triangle outside
464 // the (i, j) loops.
465 H[k * WIENER_WIN2 + l] += Y[k] * Y[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700466 }
467 }
468 }
469 }
David Barker33f3bfd2017-01-06 15:34:50 +0000470 for (k = 0; k < WIENER_WIN2; ++k) {
471 for (l = k + 1; l < WIENER_WIN2; ++l) {
472 H[l * WIENER_WIN2 + k] = H[k * WIENER_WIN2 + l];
473 }
474 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700475}
476
Yaowu Xuf883b422016-08-30 14:01:10 -0700477#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700478static double find_average_highbd(uint16_t *src, int h_start, int h_end,
479 int v_start, int v_end, int stride) {
480 uint64_t sum = 0;
481 double avg = 0;
482 int i, j;
483 for (i = v_start; i < v_end; i++)
484 for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
485 avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
486 return avg;
487}
488
489static void compute_stats_highbd(uint8_t *dgd8, uint8_t *src8, int h_start,
490 int h_end, int v_start, int v_end,
491 int dgd_stride, int src_stride, double *M,
492 double *H) {
493 int i, j, k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800494 double Y[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700495 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
496 uint16_t *dgd = CONVERT_TO_SHORTPTR(dgd8);
497 const double avg =
498 find_average_highbd(dgd, h_start, h_end, v_start, v_end, dgd_stride);
499
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800500 memset(M, 0, sizeof(*M) * WIENER_WIN2);
501 memset(H, 0, sizeof(*H) * WIENER_WIN2 * WIENER_WIN2);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700502 for (i = v_start; i < v_end; i++) {
503 for (j = h_start; j < h_end; j++) {
504 const double X = (double)src[i * src_stride + j] - avg;
505 int idx = 0;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800506 for (k = -WIENER_HALFWIN; k <= WIENER_HALFWIN; k++) {
507 for (l = -WIENER_HALFWIN; l <= WIENER_HALFWIN; l++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700508 Y[idx] = (double)dgd[(i + l) * dgd_stride + (j + k)] - avg;
509 idx++;
510 }
511 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800512 for (k = 0; k < WIENER_WIN2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700513 M[k] += Y[k] * X;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800514 H[k * WIENER_WIN2 + k] += Y[k] * Y[k];
515 for (l = k + 1; l < WIENER_WIN2; ++l) {
David Barker33f3bfd2017-01-06 15:34:50 +0000516 // H is a symmetric matrix, so we only need to fill out the upper
517 // triangle here. We can copy it down to the lower triangle outside
518 // the (i, j) loops.
519 H[k * WIENER_WIN2 + l] += Y[k] * Y[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700520 }
521 }
522 }
523 }
David Barker33f3bfd2017-01-06 15:34:50 +0000524 for (k = 0; k < WIENER_WIN2; ++k) {
525 for (l = k + 1; l < WIENER_WIN2; ++l) {
526 H[l * WIENER_WIN2 + k] = H[k * WIENER_WIN2 + l];
527 }
528 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700529}
Yaowu Xuf883b422016-08-30 14:01:10 -0700530#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700531
532// Solves Ax = b, where x and b are column vectors
533static int linsolve(int n, double *A, int stride, double *b, double *x) {
534 int i, j, k;
535 double c;
536 // Partial pivoting
537 for (i = n - 1; i > 0; i--) {
538 if (A[(i - 1) * stride] < A[i * stride]) {
539 for (j = 0; j < n; j++) {
540 c = A[i * stride + j];
541 A[i * stride + j] = A[(i - 1) * stride + j];
542 A[(i - 1) * stride + j] = c;
543 }
544 c = b[i];
545 b[i] = b[i - 1];
546 b[i - 1] = c;
547 }
548 }
549 // Forward elimination
550 for (k = 0; k < n - 1; k++) {
551 for (i = k; i < n - 1; i++) {
552 c = A[(i + 1) * stride + k] / A[k * stride + k];
553 for (j = 0; j < n; j++) A[(i + 1) * stride + j] -= c * A[k * stride + j];
554 b[i + 1] -= c * b[k];
555 }
556 }
557 // Backward substitution
558 for (i = n - 1; i >= 0; i--) {
559 if (fabs(A[i * stride + i]) < 1e-10) return 0;
560 c = 0;
561 for (j = i + 1; j <= n - 1; j++) c += A[i * stride + j] * x[j];
562 x[i] = (b[i] - c) / A[i * stride + i];
563 }
564 return 1;
565}
566
567static INLINE int wrap_index(int i) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800568 return (i >= WIENER_HALFWIN1 ? WIENER_WIN - 1 - i : i);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700569}
570
571// Fix vector b, update vector a
572static void update_a_sep_sym(double **Mc, double **Hc, double *a, double *b) {
573 int i, j;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800574 double S[WIENER_WIN];
575 double A[WIENER_WIN], B[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700576 int w, w2;
577 memset(A, 0, sizeof(A));
578 memset(B, 0, sizeof(B));
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800579 for (i = 0; i < WIENER_WIN; i++) {
580 for (j = 0; j < WIENER_WIN; ++j) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700581 const int jj = wrap_index(j);
582 A[jj] += Mc[i][j] * b[i];
583 }
584 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800585 for (i = 0; i < WIENER_WIN; i++) {
586 for (j = 0; j < WIENER_WIN; j++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700587 int k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800588 for (k = 0; k < WIENER_WIN; ++k)
589 for (l = 0; l < WIENER_WIN; ++l) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700590 const int kk = wrap_index(k);
591 const int ll = wrap_index(l);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800592 B[ll * WIENER_HALFWIN1 + kk] +=
593 Hc[j * WIENER_WIN + i][k * WIENER_WIN2 + l] * b[i] * b[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700594 }
595 }
596 }
597 // Normalization enforcement in the system of equations itself
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800598 w = WIENER_WIN;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700599 w2 = (w >> 1) + 1;
600 for (i = 0; i < w2 - 1; ++i)
601 A[i] -=
602 A[w2 - 1] * 2 + B[i * w2 + w2 - 1] - 2 * B[(w2 - 1) * w2 + (w2 - 1)];
603 for (i = 0; i < w2 - 1; ++i)
604 for (j = 0; j < w2 - 1; ++j)
605 B[i * w2 + j] -= 2 * (B[i * w2 + (w2 - 1)] + B[(w2 - 1) * w2 + j] -
606 2 * B[(w2 - 1) * w2 + (w2 - 1)]);
607 if (linsolve(w2 - 1, B, w2, A, S)) {
608 S[w2 - 1] = 1.0;
609 for (i = w2; i < w; ++i) {
610 S[i] = S[w - 1 - i];
611 S[w2 - 1] -= 2 * S[i];
612 }
613 memcpy(a, S, w * sizeof(*a));
614 }
615}
616
617// Fix vector a, update vector b
618static void update_b_sep_sym(double **Mc, double **Hc, double *a, double *b) {
619 int i, j;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800620 double S[WIENER_WIN];
621 double A[WIENER_WIN], B[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700622 int w, w2;
623 memset(A, 0, sizeof(A));
624 memset(B, 0, sizeof(B));
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800625 for (i = 0; i < WIENER_WIN; i++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700626 const int ii = wrap_index(i);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800627 for (j = 0; j < WIENER_WIN; j++) A[ii] += Mc[i][j] * a[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700628 }
629
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800630 for (i = 0; i < WIENER_WIN; i++) {
631 for (j = 0; j < WIENER_WIN; j++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700632 const int ii = wrap_index(i);
633 const int jj = wrap_index(j);
634 int k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800635 for (k = 0; k < WIENER_WIN; ++k)
636 for (l = 0; l < WIENER_WIN; ++l)
637 B[jj * WIENER_HALFWIN1 + ii] +=
638 Hc[i * WIENER_WIN + j][k * WIENER_WIN2 + l] * a[k] * a[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700639 }
640 }
641 // Normalization enforcement in the system of equations itself
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800642 w = WIENER_WIN;
643 w2 = WIENER_HALFWIN1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700644 for (i = 0; i < w2 - 1; ++i)
645 A[i] -=
646 A[w2 - 1] * 2 + B[i * w2 + w2 - 1] - 2 * B[(w2 - 1) * w2 + (w2 - 1)];
647 for (i = 0; i < w2 - 1; ++i)
648 for (j = 0; j < w2 - 1; ++j)
649 B[i * w2 + j] -= 2 * (B[i * w2 + (w2 - 1)] + B[(w2 - 1) * w2 + j] -
650 2 * B[(w2 - 1) * w2 + (w2 - 1)]);
651 if (linsolve(w2 - 1, B, w2, A, S)) {
652 S[w2 - 1] = 1.0;
653 for (i = w2; i < w; ++i) {
654 S[i] = S[w - 1 - i];
655 S[w2 - 1] -= 2 * S[i];
656 }
657 memcpy(b, S, w * sizeof(*b));
658 }
659}
660
661static int wiener_decompose_sep_sym(double *M, double *H, double *a,
662 double *b) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800663 static const double init_filt[WIENER_WIN] = {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700664 0.035623, -0.127154, 0.211436, 0.760190, 0.211436, -0.127154, 0.035623,
665 };
666 int i, j, iter;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800667 double *Hc[WIENER_WIN2];
668 double *Mc[WIENER_WIN];
669 for (i = 0; i < WIENER_WIN; i++) {
670 Mc[i] = M + i * WIENER_WIN;
671 for (j = 0; j < WIENER_WIN; j++) {
672 Hc[i * WIENER_WIN + j] =
673 H + i * WIENER_WIN * WIENER_WIN2 + j * WIENER_WIN;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700674 }
675 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800676 memcpy(a, init_filt, sizeof(*a) * WIENER_WIN);
677 memcpy(b, init_filt, sizeof(*b) * WIENER_WIN);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700678
679 iter = 1;
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -0700680 while (iter < NUM_WIENER_ITERS) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700681 update_a_sep_sym(Mc, Hc, a, b);
682 update_b_sep_sym(Mc, Hc, a, b);
683 iter++;
684 }
685 return 1;
686}
687
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800688// Computes the function x'*H*x - x'*M for the learned 2D filter x, and compares
Yaowu Xuc27fc142016-08-22 16:08:15 -0700689// against identity filters; Final score is defined as the difference between
690// the function values
David Barker1e8e6b92017-01-13 13:45:51 +0000691static double compute_score(double *M, double *H, InterpKernel vfilt,
692 InterpKernel hfilt) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800693 double ab[WIENER_WIN * WIENER_WIN];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700694 int i, k, l;
695 double P = 0, Q = 0;
696 double iP = 0, iQ = 0;
697 double Score, iScore;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800698 double a[WIENER_WIN], b[WIENER_WIN];
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800699 a[WIENER_HALFWIN] = b[WIENER_HALFWIN] = 1.0;
700 for (i = 0; i < WIENER_HALFWIN; ++i) {
701 a[i] = a[WIENER_WIN - i - 1] = (double)vfilt[i] / WIENER_FILT_STEP;
702 b[i] = b[WIENER_WIN - i - 1] = (double)hfilt[i] / WIENER_FILT_STEP;
703 a[WIENER_HALFWIN] -= 2 * a[i];
704 b[WIENER_HALFWIN] -= 2 * b[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700705 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800706 for (k = 0; k < WIENER_WIN; ++k) {
707 for (l = 0; l < WIENER_WIN; ++l) ab[k * WIENER_WIN + l] = a[l] * b[k];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700708 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800709 for (k = 0; k < WIENER_WIN2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700710 P += ab[k] * M[k];
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800711 for (l = 0; l < WIENER_WIN2; ++l)
712 Q += ab[k] * H[k * WIENER_WIN2 + l] * ab[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700713 }
714 Score = Q - 2 * P;
715
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800716 iP = M[WIENER_WIN2 >> 1];
717 iQ = H[(WIENER_WIN2 >> 1) * WIENER_WIN2 + (WIENER_WIN2 >> 1)];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700718 iScore = iQ - 2 * iP;
719
720 return Score - iScore;
721}
722
David Barker1e8e6b92017-01-13 13:45:51 +0000723static void quantize_sym_filter(double *f, InterpKernel fi) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700724 int i;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800725 for (i = 0; i < WIENER_HALFWIN; ++i) {
726 fi[i] = RINT(f[i] * WIENER_FILT_STEP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700727 }
728 // Specialize for 7-tap filter
729 fi[0] = CLIP(fi[0], WIENER_FILT_TAP0_MINV, WIENER_FILT_TAP0_MAXV);
730 fi[1] = CLIP(fi[1], WIENER_FILT_TAP1_MINV, WIENER_FILT_TAP1_MAXV);
731 fi[2] = CLIP(fi[2], WIENER_FILT_TAP2_MINV, WIENER_FILT_TAP2_MAXV);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800732 // Satisfy filter constraints
733 fi[WIENER_WIN - 1] = fi[0];
734 fi[WIENER_WIN - 2] = fi[1];
735 fi[WIENER_WIN - 3] = fi[2];
David Barker1e8e6b92017-01-13 13:45:51 +0000736 // The central element has an implicit +WIENER_FILT_STEP
737 fi[3] = -2 * (fi[0] + fi[1] + fi[2]);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800738}
739
740static double search_wiener_uv(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Debargha Mukherjee00c54332017-03-03 15:44:17 -0800741 int partial_frame, int plane,
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800742 RestorationInfo *info, RestorationType *type,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800743 YV12_BUFFER_CONFIG *dst_frame) {
744 WienerInfo *wiener_info = info->wiener_info;
745 AV1_COMMON *const cm = &cpi->common;
746 RestorationInfo *rsi = cpi->rst_search;
747 int64_t err;
748 int bits;
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800749 double cost_wiener, cost_norestore, cost_wiener_frame, cost_norestore_frame;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800750 MACROBLOCK *x = &cpi->td.mb;
751 double M[WIENER_WIN2];
752 double H[WIENER_WIN2 * WIENER_WIN2];
753 double vfilterd[WIENER_WIN], hfilterd[WIENER_WIN];
754 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
755 const int width = src->uv_crop_width;
756 const int height = src->uv_crop_height;
757 const int src_stride = src->uv_stride;
758 const int dgd_stride = dgd->uv_stride;
759 double score;
760 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800761 int h_start, h_end, v_start, v_end;
Debargha Mukherjee1008c1e2017-03-06 19:18:43 -0800762 const int ntiles =
763 av1_get_rest_ntiles(width, height, cm->rst_info[1].restoration_tilesize,
764 &tile_width, &tile_height, &nhtiles, &nvtiles);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800765 assert(width == dgd->uv_crop_width);
766 assert(height == dgd->uv_crop_height);
767
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800768 rsi[plane].frame_restoration_type = RESTORE_NONE;
David Barker60a055b2017-01-18 15:10:43 +0000769 err = sse_restoration_frame(cm, src, cm->frame_to_show, (1 << plane));
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800770 bits = 0;
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800771 cost_norestore_frame = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800772
773 rsi[plane].frame_restoration_type = RESTORE_WIENER;
David Barker33f3bfd2017-01-06 15:34:50 +0000774
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800775 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
776 rsi[plane].restoration_type[tile_idx] = RESTORE_NONE;
777 }
778
779 // Compute best Wiener filters for each tile
780 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
781 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
782 tile_height, width, height, 0, 0, &h_start, &h_end,
783 &v_start, &v_end);
784 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
785 h_end - h_start, v_start, v_end - v_start,
786 1 << plane);
787 // #bits when a tile is not restored
788 bits = av1_cost_bit(RESTORE_NONE_WIENER_PROB, 0);
789 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
790 // best_tile_cost[tile_idx] = DBL_MAX;
791
792 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
793 tile_height, width, height, WIENER_HALFWIN,
794 WIENER_HALFWIN, &h_start, &h_end, &v_start,
795 &v_end);
David Barker33f3bfd2017-01-06 15:34:50 +0000796 if (plane == AOM_PLANE_U) {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800797#if CONFIG_AOM_HIGHBITDEPTH
798 if (cm->use_highbitdepth)
799 compute_stats_highbd(dgd->u_buffer, src->u_buffer, h_start, h_end,
800 v_start, v_end, dgd_stride, src_stride, M, H);
801 else
802#endif // CONFIG_AOM_HIGHBITDEPTH
803 compute_stats(dgd->u_buffer, src->u_buffer, h_start, h_end, v_start,
804 v_end, dgd_stride, src_stride, M, H);
David Barker33f3bfd2017-01-06 15:34:50 +0000805 } else if (plane == AOM_PLANE_V) {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800806#if CONFIG_AOM_HIGHBITDEPTH
807 if (cm->use_highbitdepth)
808 compute_stats_highbd(dgd->v_buffer, src->v_buffer, h_start, h_end,
809 v_start, v_end, dgd_stride, src_stride, M, H);
810 else
811#endif // CONFIG_AOM_HIGHBITDEPTH
812 compute_stats(dgd->v_buffer, src->v_buffer, h_start, h_end, v_start,
813 v_end, dgd_stride, src_stride, M, H);
David Barker33f3bfd2017-01-06 15:34:50 +0000814 } else {
815 assert(0);
816 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800817
818 type[tile_idx] = RESTORE_WIENER;
819
820 if (!wiener_decompose_sep_sym(M, H, vfilterd, hfilterd)) {
821 type[tile_idx] = RESTORE_NONE;
822 continue;
David Barker33f3bfd2017-01-06 15:34:50 +0000823 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800824 quantize_sym_filter(vfilterd, rsi[plane].wiener_info[tile_idx].vfilter);
825 quantize_sym_filter(hfilterd, rsi[plane].wiener_info[tile_idx].hfilter);
David Barker33f3bfd2017-01-06 15:34:50 +0000826
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800827 // Filter score computes the value of the function x'*A*x - x'*b for the
828 // learned filter and compares it against identity filer. If there is no
829 // reduction in the function, the filter is reverted back to identity
830 score = compute_score(M, H, rsi[plane].wiener_info[tile_idx].vfilter,
831 rsi[plane].wiener_info[tile_idx].hfilter);
832 if (score > 0.0) {
833 type[tile_idx] = RESTORE_NONE;
834 continue;
835 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800836
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800837 rsi[plane].restoration_type[tile_idx] = RESTORE_WIENER;
838 err = try_restoration_tile(src, cpi, rsi, 1 << plane, partial_frame,
839 tile_idx, 0, 0, dst_frame);
840 bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT;
841 bits += av1_cost_bit(RESTORE_NONE_WIENER_PROB, 1);
842 cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
843 if (cost_wiener >= cost_norestore) {
844 type[tile_idx] = RESTORE_NONE;
845 } else {
846 type[tile_idx] = RESTORE_WIENER;
847 memcpy(&wiener_info[tile_idx], &rsi[plane].wiener_info[tile_idx],
848 sizeof(wiener_info[tile_idx]));
849 }
850 rsi[plane].restoration_type[tile_idx] = RESTORE_NONE;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800851 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800852 // Cost for Wiener filtering
853 bits = 0;
854 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
855 bits +=
856 av1_cost_bit(RESTORE_NONE_WIENER_PROB, type[tile_idx] != RESTORE_NONE);
857 memcpy(&rsi[plane].wiener_info[tile_idx], &wiener_info[tile_idx],
858 sizeof(wiener_info[tile_idx]));
859 if (type[tile_idx] == RESTORE_WIENER) {
860 bits += (WIENER_FILT_BITS << AV1_PROB_COST_SHIFT);
861 }
862 rsi[plane].restoration_type[tile_idx] = type[tile_idx];
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800863 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800864 err = try_restoration_frame(src, cpi, rsi, 1 << plane, partial_frame,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800865 dst_frame);
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800866 cost_wiener_frame = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
867
868 if (cost_wiener_frame < cost_norestore_frame) {
869 info->frame_restoration_type = RESTORE_WIENER;
870 } else {
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800871 info->frame_restoration_type = RESTORE_NONE;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800872 }
873
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800874 return info->frame_restoration_type == RESTORE_WIENER ? cost_wiener_frame
875 : cost_norestore_frame;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700876}
877
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700878static double search_wiener(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Debargha Mukherjee00c54332017-03-03 15:44:17 -0800879 int partial_frame, RestorationInfo *info,
880 RestorationType *type, double *best_tile_cost,
David Barker9666e752016-12-08 11:25:47 +0000881 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700882 WienerInfo *wiener_info = info->wiener_info;
Yaowu Xuf883b422016-08-30 14:01:10 -0700883 AV1_COMMON *const cm = &cpi->common;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800884 RestorationInfo *rsi = cpi->rst_search;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700885 int64_t err;
886 int bits;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700887 double cost_wiener, cost_norestore;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700888 MACROBLOCK *x = &cpi->td.mb;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800889 double M[WIENER_WIN2];
890 double H[WIENER_WIN2 * WIENER_WIN2];
891 double vfilterd[WIENER_WIN], hfilterd[WIENER_WIN];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700892 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
893 const int width = cm->width;
894 const int height = cm->height;
895 const int src_stride = src->y_stride;
896 const int dgd_stride = dgd->y_stride;
897 double score;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700898 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700899 int h_start, h_end, v_start, v_end;
Debargha Mukherjee1008c1e2017-03-06 19:18:43 -0800900 const int ntiles =
901 av1_get_rest_ntiles(width, height, cm->rst_info[0].restoration_tilesize,
902 &tile_width, &tile_height, &nhtiles, &nvtiles);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700903 assert(width == dgd->y_crop_width);
904 assert(height == dgd->y_crop_height);
905 assert(width == src->y_crop_width);
906 assert(height == src->y_crop_height);
907
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800908 rsi->frame_restoration_type = RESTORE_WIENER;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700909
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800910 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
911 rsi->restoration_type[tile_idx] = RESTORE_NONE;
912 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700913
David Barker33f3bfd2017-01-06 15:34:50 +0000914// Construct a (WIENER_HALFWIN)-pixel border around the frame
915#if CONFIG_AOM_HIGHBITDEPTH
916 if (cm->use_highbitdepth)
917 extend_frame_highbd(CONVERT_TO_SHORTPTR(dgd->y_buffer), width, height,
918 dgd_stride);
919 else
920#endif
921 extend_frame(dgd->y_buffer, width, height, dgd_stride);
922
Yaowu Xuc27fc142016-08-22 16:08:15 -0700923 // Compute best Wiener filters for each tile
924 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700925 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
926 tile_height, width, height, 0, 0, &h_start, &h_end,
927 &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +0000928 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -0800929 h_end - h_start, v_start, v_end - v_start, 1);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700930 // #bits when a tile is not restored
931 bits = av1_cost_bit(RESTORE_NONE_WIENER_PROB, 0);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700932 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700933 best_tile_cost[tile_idx] = DBL_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700934
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700935 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
David Barker33f3bfd2017-01-06 15:34:50 +0000936 tile_height, width, height, 0, 0, &h_start, &h_end,
937 &v_start, &v_end);
Yaowu Xuf883b422016-08-30 14:01:10 -0700938#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700939 if (cm->use_highbitdepth)
940 compute_stats_highbd(dgd->y_buffer, src->y_buffer, h_start, h_end,
941 v_start, v_end, dgd_stride, src_stride, M, H);
942 else
Yaowu Xuf883b422016-08-30 14:01:10 -0700943#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700944 compute_stats(dgd->y_buffer, src->y_buffer, h_start, h_end, v_start,
945 v_end, dgd_stride, src_stride, M, H);
946
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800947 type[tile_idx] = RESTORE_WIENER;
948
Yaowu Xuc27fc142016-08-22 16:08:15 -0700949 if (!wiener_decompose_sep_sym(M, H, vfilterd, hfilterd)) {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800950 type[tile_idx] = RESTORE_NONE;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700951 continue;
952 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800953 quantize_sym_filter(vfilterd, rsi->wiener_info[tile_idx].vfilter);
954 quantize_sym_filter(hfilterd, rsi->wiener_info[tile_idx].hfilter);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700955
956 // Filter score computes the value of the function x'*A*x - x'*b for the
957 // learned filter and compares it against identity filer. If there is no
958 // reduction in the function, the filter is reverted back to identity
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800959 score = compute_score(M, H, rsi->wiener_info[tile_idx].vfilter,
960 rsi->wiener_info[tile_idx].hfilter);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700961 if (score > 0.0) {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800962 type[tile_idx] = RESTORE_NONE;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700963 continue;
964 }
965
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800966 rsi->restoration_type[tile_idx] = RESTORE_WIENER;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800967 err = try_restoration_tile(src, cpi, rsi, 1, partial_frame, tile_idx, 0, 0,
David Barker9666e752016-12-08 11:25:47 +0000968 dst_frame);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700969 bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT;
970 bits += av1_cost_bit(RESTORE_NONE_WIENER_PROB, 1);
971 cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700972 if (cost_wiener >= cost_norestore) {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800973 type[tile_idx] = RESTORE_NONE;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700974 } else {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800975 type[tile_idx] = RESTORE_WIENER;
976 memcpy(&wiener_info[tile_idx], &rsi->wiener_info[tile_idx],
977 sizeof(wiener_info[tile_idx]));
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700978 bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT;
979 best_tile_cost[tile_idx] = RDCOST_DBL(
980 x->rdmult, x->rddiv,
981 (bits + cpi->switchable_restore_cost[RESTORE_WIENER]) >> 4, err);
982 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800983 rsi->restoration_type[tile_idx] = RESTORE_NONE;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700984 }
985 // Cost for Wiener filtering
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800986 bits = frame_level_restore_bits[rsi->frame_restoration_type]
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700987 << AV1_PROB_COST_SHIFT;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700988 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800989 bits +=
990 av1_cost_bit(RESTORE_NONE_WIENER_PROB, type[tile_idx] != RESTORE_NONE);
991 memcpy(&rsi->wiener_info[tile_idx], &wiener_info[tile_idx],
992 sizeof(wiener_info[tile_idx]));
993 if (type[tile_idx] == RESTORE_WIENER) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700994 bits += (WIENER_FILT_BITS << AV1_PROB_COST_SHIFT);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700995 }
Debargha Mukherjee994ccd72017-01-06 11:18:23 -0800996 rsi->restoration_type[tile_idx] = type[tile_idx];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700997 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800998 err = try_restoration_frame(src, cpi, rsi, 1, partial_frame, dst_frame);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -0700999 cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001000
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001001 return cost_wiener;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001002}
1003
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001004static double search_norestore(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001005 int partial_frame, RestorationInfo *info,
1006 RestorationType *type, double *best_tile_cost,
David Barker9666e752016-12-08 11:25:47 +00001007 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001008 double err, cost_norestore;
1009 int bits;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001010 MACROBLOCK *x = &cpi->td.mb;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001011 AV1_COMMON *const cm = &cpi->common;
1012 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001013 int h_start, h_end, v_start, v_end;
Debargha Mukherjee1008c1e2017-03-06 19:18:43 -08001014 const int ntiles = av1_get_rest_ntiles(
1015 cm->width, cm->height, cm->rst_info[0].restoration_tilesize, &tile_width,
1016 &tile_height, &nhtiles, &nvtiles);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001017 (void)info;
David Barker9666e752016-12-08 11:25:47 +00001018 (void)dst_frame;
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001019 (void)partial_frame;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001020
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001021 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
1022 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
1023 tile_height, cm->width, cm->height, 0, 0, &h_start,
1024 &h_end, &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +00001025 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -08001026 h_end - h_start, v_start, v_end - v_start, 1);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001027 best_tile_cost[tile_idx] =
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001028 RDCOST_DBL(x->rdmult, x->rddiv,
1029 (cpi->switchable_restore_cost[RESTORE_NONE] >> 4), err);
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001030 type[tile_idx] = RESTORE_NONE;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001031 }
1032 // RD cost associated with no restoration
David Barker9666e752016-12-08 11:25:47 +00001033 err = sse_restoration_tile(src, cm->frame_to_show, cm, 0, cm->width, 0,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -08001034 cm->height, 1);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001035 bits = frame_level_restore_bits[RESTORE_NONE] << AV1_PROB_COST_SHIFT;
1036 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001037 return cost_norestore;
1038}
1039
1040static double search_switchable_restoration(
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001041 AV1_COMP *cpi, int partial_frame, RestorationInfo *rsi,
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001042 double *tile_cost[RESTORE_SWITCHABLE_TYPES]) {
1043 AV1_COMMON *const cm = &cpi->common;
1044 MACROBLOCK *x = &cpi->td.mb;
1045 double cost_switchable = 0;
1046 int r, bits, tile_idx;
Debargha Mukherjee1008c1e2017-03-06 19:18:43 -08001047 const int ntiles = av1_get_rest_ntiles(cm->width, cm->height,
1048 cm->rst_info[0].restoration_tilesize,
1049 NULL, NULL, NULL, NULL);
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001050 (void)partial_frame;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001051
1052 rsi->frame_restoration_type = RESTORE_SWITCHABLE;
1053 bits = frame_level_restore_bits[rsi->frame_restoration_type]
1054 << AV1_PROB_COST_SHIFT;
1055 cost_switchable = RDCOST_DBL(x->rdmult, x->rddiv, bits >> 4, 0);
1056 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
1057 double best_cost = tile_cost[RESTORE_NONE][tile_idx];
1058 rsi->restoration_type[tile_idx] = RESTORE_NONE;
1059 for (r = 1; r < RESTORE_SWITCHABLE_TYPES; r++) {
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -07001060#if FORCE_RESTORE_WIENER_ONLY
1061 if (r != RESTORE_WIENER) continue;
1062#endif // FORCE_RESTORE_WIENER_ONLY
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001063 if (tile_cost[r][tile_idx] < best_cost) {
1064 rsi->restoration_type[tile_idx] = r;
1065 best_cost = tile_cost[r][tile_idx];
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001066 }
1067 }
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -07001068#if FORCE_RESTORE_WIENER_ONLY
1069 assert(rsi->restoration_type[tile_idx] == RESTORE_WIENER ||
1070 rsi->restoration_type[tile_idx] == RESTORE_NONE);
1071#endif // FORCE_RESTORE_WIENER_ONLY
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001072 cost_switchable += best_cost;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001073 }
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001074 return cost_switchable;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001075}
1076
1077void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Yaowu Xuf883b422016-08-30 14:01:10 -07001078 LPF_PICK_METHOD method) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001079 static search_restore_type search_restore_fun[RESTORE_SWITCHABLE_TYPES] = {
Debargha Mukherjee4bfd72e2017-03-08 22:20:31 -08001080 search_norestore, search_wiener, search_sgrproj,
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001081 };
Yaowu Xuf883b422016-08-30 14:01:10 -07001082 AV1_COMMON *const cm = &cpi->common;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001083 double cost_restore[RESTORE_TYPES];
1084 double *tile_cost[RESTORE_SWITCHABLE_TYPES];
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001085 RestorationType *restore_types[RESTORE_SWITCHABLE_TYPES];
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001086 double best_cost_restore;
1087 RestorationType r, best_restore;
1088
Debargha Mukherjee1008c1e2017-03-06 19:18:43 -08001089 const int ntiles = av1_get_rest_ntiles(cm->width, cm->height,
1090 cm->rst_info[0].restoration_tilesize,
1091 NULL, NULL, NULL, NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001092
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001093 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001094 tile_cost[r] = (double *)aom_malloc(sizeof(*tile_cost[0]) * ntiles);
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001095 restore_types[r] =
1096 (RestorationType *)aom_malloc(sizeof(*restore_types[0]) * ntiles);
1097 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001098
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001099 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; ++r) {
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -07001100#if FORCE_RESTORE_WIENER_ONLY
1101 if (r != RESTORE_NONE && r != RESTORE_WIENER) continue;
1102#endif // FORCE_RESTORE_WIENER_ONLY
David Barker9666e752016-12-08 11:25:47 +00001103 cost_restore[r] = search_restore_fun[r](
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001104 src, cpi, method == LPF_PICK_FROM_SUBIMAGE, &cm->rst_info[0],
1105 restore_types[r], tile_cost[r], &cpi->trial_frame_rst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001106 }
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001107 cost_restore[RESTORE_SWITCHABLE] = search_switchable_restoration(
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001108 cpi, method == LPF_PICK_FROM_SUBIMAGE, &cm->rst_info[0], tile_cost);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001109
1110 best_cost_restore = DBL_MAX;
1111 best_restore = 0;
1112 for (r = 0; r < RESTORE_TYPES; ++r) {
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -07001113#if FORCE_RESTORE_WIENER_ONLY
1114 if (r != RESTORE_NONE && r != RESTORE_WIENER) continue;
1115#endif // FORCE_RESTORE_WIENER_ONLY
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001116 if (cost_restore[r] < best_cost_restore) {
1117 best_restore = r;
1118 best_cost_restore = cost_restore[r];
1119 }
1120 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001121 cm->rst_info[0].frame_restoration_type = best_restore;
Debargha Mukherjee1b3dbf02017-03-13 14:47:21 -07001122#if FORCE_RESTORE_WIENER_ONLY
1123 assert(best_restore == RESTORE_WIENER || best_restore == RESTORE_NONE);
1124#endif // FORCE_RESTORE_WIENER_ONLY
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001125 if (best_restore != RESTORE_SWITCHABLE) {
1126 memcpy(cm->rst_info[0].restoration_type, restore_types[best_restore],
1127 ntiles * sizeof(restore_types[best_restore][0]));
1128 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001129
1130 // Color components
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001131 search_wiener_uv(src, cpi, method == LPF_PICK_FROM_SUBIMAGE, AOM_PLANE_U,
1132 &cm->rst_info[AOM_PLANE_U],
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001133 cm->rst_info[AOM_PLANE_U].restoration_type,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001134 &cpi->trial_frame_rst);
Debargha Mukherjee00c54332017-03-03 15:44:17 -08001135 search_wiener_uv(src, cpi, method == LPF_PICK_FROM_SUBIMAGE, AOM_PLANE_V,
1136 &cm->rst_info[AOM_PLANE_V],
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001137 cm->rst_info[AOM_PLANE_V].restoration_type,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001138 &cpi->trial_frame_rst);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001139 /*
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -08001140 printf("Frame %d/%d restore types: %d %d %d\n",
1141 cm->current_video_frame, cm->show_frame,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001142 cm->rst_info[0].frame_restoration_type,
1143 cm->rst_info[1].frame_restoration_type,
1144 cm->rst_info[2].frame_restoration_type);
Debargha Mukherjeeb3c43bc2017-02-01 13:09:03 -08001145 printf("Frame %d/%d frame_restore_type %d : %f %f %f %f\n",
1146 cm->current_video_frame, cm->show_frame,
1147 cm->rst_info[0].frame_restoration_type, cost_restore[0],
1148 cost_restore[1], cost_restore[2], cost_restore[3]);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001149 */
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001150
Debargha Mukherjee994ccd72017-01-06 11:18:23 -08001151 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) {
1152 aom_free(tile_cost[r]);
1153 aom_free(restore_types[r]);
1154 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001155}