blob: 1aa0ecfa24f17b0969225ca3fb090dd4cfae95f0 [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
28#include "av1/encoder/encoder.h"
29#include "av1/encoder/picklpf.h"
30#include "av1/encoder/pickrst.h"
31#include "av1/encoder/quantize.h"
32
Debargha Mukherjee5d89a632016-09-17 13:16:58 -070033typedef double (*search_restore_type)(const YV12_BUFFER_CONFIG *src,
34 AV1_COMP *cpi, int filter_level,
35 int partial_frame, RestorationInfo *info,
David Barker9666e752016-12-08 11:25:47 +000036 double *best_tile_cost,
37 YV12_BUFFER_CONFIG *dst_frame);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -070038
Debargha Mukherjee0e67b252016-12-08 09:22:44 -080039const int frame_level_restore_bits[RESTORE_TYPES] = { 2, 2, 3, 3, 2 };
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070040
41static int64_t sse_restoration_tile(const YV12_BUFFER_CONFIG *src,
David Barker9666e752016-12-08 11:25:47 +000042 const YV12_BUFFER_CONFIG *dst,
43 const AV1_COMMON *cm, int h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080044 int width, int v_start, int height,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080045 int components_pattern) {
46 int64_t filt_err = 0;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070047#if CONFIG_AOM_HIGHBITDEPTH
48 if (cm->use_highbitdepth) {
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080049 if ((components_pattern >> AOM_PLANE_Y) & 1) {
50 filt_err +=
51 aom_highbd_get_y_sse_part(src, dst, h_start, width, v_start, height);
52 }
53 if ((components_pattern >> AOM_PLANE_U) & 1) {
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080054 filt_err += aom_highbd_get_u_sse_part(
55 src, dst, h_start >> cm->subsampling_x, width >> cm->subsampling_x,
56 v_start >> cm->subsampling_y, height >> cm->subsampling_y);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080057 }
58 if ((components_pattern >> AOM_PLANE_V) & 1) {
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080059 filt_err += aom_highbd_get_v_sse_part(
60 src, dst, h_start >> cm->subsampling_x, width >> cm->subsampling_x,
61 v_start >> cm->subsampling_y, height >> cm->subsampling_y);
62 }
63 return filt_err;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070064 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070065#endif // CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080066 if ((components_pattern >> AOM_PLANE_Y) & 1) {
67 filt_err += aom_get_y_sse_part(src, dst, h_start, width, v_start, height);
68 }
69 if ((components_pattern >> AOM_PLANE_U) & 1) {
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080070 filt_err += aom_get_u_sse_part(
71 src, dst, h_start >> cm->subsampling_x, width >> cm->subsampling_x,
72 v_start >> cm->subsampling_y, height >> cm->subsampling_y);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080073 }
74 if ((components_pattern >> AOM_PLANE_V) & 1) {
Debargha Mukherjee874d36d2016-12-14 16:53:17 -080075 filt_err += aom_get_u_sse_part(
76 src, dst, h_start >> cm->subsampling_x, width >> cm->subsampling_x,
77 v_start >> cm->subsampling_y, height >> cm->subsampling_y);
78 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -070079 return filt_err;
80}
81
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -080082static int64_t sse_restoration_frame(const YV12_BUFFER_CONFIG *src,
83 const YV12_BUFFER_CONFIG *dst,
84 int components_pattern) {
85 int64_t filt_err = 0;
86#if CONFIG_AOM_HIGHBITDEPTH
87 if (cm->use_highbitdepth) {
88 if ((components_pattern >> AOM_PLANE_Y) & 1) {
89 filt_err += aom_highbd_get_y_sse(src, dst);
90 }
91 if ((components_pattern >> AOM_PLANE_U) & 1) {
92 filt_err += aom_highbd_get_u_sse(src, dst);
93 }
94 if ((components_pattern >> AOM_PLANE_V) & 1) {
95 filt_err += aom_highbd_get_v_sse(src, dst);
96 }
97 return filt_err;
98 }
99#endif // CONFIG_AOM_HIGHBITDEPTH
100 if ((components_pattern >> AOM_PLANE_Y) & 1) {
101 filt_err = aom_get_y_sse(src, dst);
102 }
103 if ((components_pattern >> AOM_PLANE_U) & 1) {
104 filt_err += aom_get_u_sse(src, dst);
105 }
106 if ((components_pattern >> AOM_PLANE_V) & 1) {
107 filt_err += aom_get_v_sse(src, dst);
108 }
109 return filt_err;
110}
111
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700112static int64_t try_restoration_tile(const YV12_BUFFER_CONFIG *src,
113 AV1_COMP *const cpi, RestorationInfo *rsi,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800114 int components_pattern, int partial_frame,
115 int tile_idx, int subtile_idx,
116 int subtile_bits,
David Barker9666e752016-12-08 11:25:47 +0000117 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700118 AV1_COMMON *const cm = &cpi->common;
119 int64_t filt_err;
120 int tile_width, tile_height, nhtiles, nvtiles;
121 int h_start, h_end, v_start, v_end;
122 const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
123 &tile_height, &nhtiles, &nvtiles);
124 (void)ntiles;
125
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800126 av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
127 partial_frame, dst_frame);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700128 av1_get_rest_tile_limits(tile_idx, subtile_idx, subtile_bits, nhtiles,
129 nvtiles, tile_width, tile_height, cm->width,
130 cm->height, 0, 0, &h_start, &h_end, &v_start,
131 &v_end);
David Barker9666e752016-12-08 11:25:47 +0000132 filt_err = sse_restoration_tile(src, dst_frame, cm, h_start, h_end - h_start,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800133 v_start, v_end - v_start, components_pattern);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700134
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -0700135 return filt_err;
136}
137
138static int64_t try_restoration_frame(const YV12_BUFFER_CONFIG *src,
Yaowu Xuf883b422016-08-30 14:01:10 -0700139 AV1_COMP *const cpi, RestorationInfo *rsi,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800140 int components_pattern, int partial_frame,
David Barker9666e752016-12-08 11:25:47 +0000141 YV12_BUFFER_CONFIG *dst_frame) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700142 AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700143 int64_t filt_err;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800144 av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
145 partial_frame, dst_frame);
146 filt_err = sse_restoration_frame(src, dst_frame, components_pattern);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700147 return filt_err;
148}
149
David Barker3a0df182016-12-21 10:44:52 +0000150static int64_t get_pixel_proj_error(uint8_t *src8, int width, int height,
151 int src_stride, uint8_t *dat8,
152 int dat_stride, int bit_depth,
153 int32_t *flt1, int flt1_stride,
154 int32_t *flt2, int flt2_stride, int *xqd) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700155 int i, j;
156 int64_t err = 0;
157 int xq[2];
158 decode_xq(xqd, xq);
David Barker3a0df182016-12-21 10:44:52 +0000159 if (bit_depth == 8) {
160 const uint8_t *src = src8;
161 const uint8_t *dat = dat8;
162 for (i = 0; i < height; ++i) {
163 for (j = 0; j < width; ++j) {
164 const int32_t u =
165 (int32_t)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
166 const int32_t f1 = (int32_t)flt1[i * flt1_stride + j] - u;
167 const int32_t f2 = (int32_t)flt2[i * flt2_stride + j] - u;
168 const int64_t v = xq[0] * f1 + xq[1] * f2 + (u << SGRPROJ_PRJ_BITS);
169 const int32_t e =
170 ROUND_POWER_OF_TWO(v, SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS) -
171 src[i * src_stride + j];
172 err += e * e;
173 }
174 }
175 } else {
176 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
177 const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
178 for (i = 0; i < height; ++i) {
179 for (j = 0; j < width; ++j) {
180 const int32_t u =
181 (int32_t)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
182 const int32_t f1 = (int32_t)flt1[i * flt1_stride + j] - u;
183 const int32_t f2 = (int32_t)flt2[i * flt2_stride + j] - u;
184 const int64_t v = xq[0] * f1 + xq[1] * f2 + (u << SGRPROJ_PRJ_BITS);
185 const int32_t e =
186 ROUND_POWER_OF_TWO(v, SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS) -
187 src[i * src_stride + j];
188 err += e * e;
189 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700190 }
191 }
192 return err;
193}
194
David Barker3a0df182016-12-21 10:44:52 +0000195static void get_proj_subspace(uint8_t *src8, int width, int height,
196 int src_stride, uint8_t *dat8, int dat_stride,
197 int bit_depth, int32_t *flt1, int flt1_stride,
198 int32_t *flt2, int flt2_stride, int *xq) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700199 int i, j;
200 double H[2][2] = { { 0, 0 }, { 0, 0 } };
201 double C[2] = { 0, 0 };
202 double Det;
203 double x[2];
204 const int size = width * height;
205
206 xq[0] = -(1 << SGRPROJ_PRJ_BITS) / 4;
207 xq[1] = (1 << SGRPROJ_PRJ_BITS) - xq[0];
David Barker3a0df182016-12-21 10:44:52 +0000208 if (bit_depth == 8) {
209 const uint8_t *src = src8;
210 const uint8_t *dat = dat8;
211 for (i = 0; i < height; ++i) {
212 for (j = 0; j < width; ++j) {
213 const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
214 const double s =
215 (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
216 const double f1 = (double)flt1[i * flt1_stride + j] - u;
217 const double f2 = (double)flt2[i * flt2_stride + j] - u;
218 H[0][0] += f1 * f1;
219 H[1][1] += f2 * f2;
220 H[0][1] += f1 * f2;
221 C[0] += f1 * s;
222 C[1] += f2 * s;
223 }
224 }
225 } else {
226 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
227 const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
228 for (i = 0; i < height; ++i) {
229 for (j = 0; j < width; ++j) {
230 const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
231 const double s =
232 (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
233 const double f1 = (double)flt1[i * flt1_stride + j] - u;
234 const double f2 = (double)flt2[i * flt2_stride + j] - u;
235 H[0][0] += f1 * f1;
236 H[1][1] += f2 * f2;
237 H[0][1] += f1 * f2;
238 C[0] += f1 * s;
239 C[1] += f2 * s;
240 }
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700241 }
242 }
243 H[0][0] /= size;
244 H[0][1] /= size;
245 H[1][1] /= size;
246 H[1][0] = H[0][1];
247 C[0] /= size;
248 C[1] /= size;
249 Det = (H[0][0] * H[1][1] - H[0][1] * H[1][0]);
250 if (Det < 1e-8) return; // ill-posed, return default values
251 x[0] = (H[1][1] * C[0] - H[0][1] * C[1]) / Det;
252 x[1] = (H[0][0] * C[1] - H[1][0] * C[0]) / Det;
253 xq[0] = (int)rint(x[0] * (1 << SGRPROJ_PRJ_BITS));
254 xq[1] = (int)rint(x[1] * (1 << SGRPROJ_PRJ_BITS));
255}
256
257void encode_xq(int *xq, int *xqd) {
258 xqd[0] = -xq[0];
259 xqd[0] = clamp(xqd[0], SGRPROJ_PRJ_MIN0, SGRPROJ_PRJ_MAX0);
260 xqd[1] = (1 << SGRPROJ_PRJ_BITS) + xqd[0] - xq[1];
261 xqd[1] = clamp(xqd[1], SGRPROJ_PRJ_MIN1, SGRPROJ_PRJ_MAX1);
262}
263
264static void search_selfguided_restoration(uint8_t *dat8, int width, int height,
265 int dat_stride, uint8_t *src8,
266 int src_stride, int bit_depth,
David Barker3a0df182016-12-21 10:44:52 +0000267 int *eps, int *xqd, int32_t *rstbuf) {
268 int32_t *flt1 = rstbuf;
Debargha Mukherjee519dbcf2016-12-16 03:13:02 -0800269 int32_t *flt2 = flt1 + RESTORATION_TILEPELS_MAX;
David Barker3a0df182016-12-21 10:44:52 +0000270 int32_t *tmpbuf2 = flt2 + RESTORATION_TILEPELS_MAX;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700271 int i, j, ep, bestep = 0;
272 int64_t err, besterr = -1;
273 int exqd[2], bestxqd[2] = { 0, 0 };
David Barker3a0df182016-12-21 10:44:52 +0000274
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700275 for (ep = 0; ep < SGRPROJ_PARAMS; ep++) {
276 int exq[2];
277 if (bit_depth > 8) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700278 uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
279 for (i = 0; i < height; ++i) {
280 for (j = 0; j < width; ++j) {
Debargha Mukherjee519dbcf2016-12-16 03:13:02 -0800281 flt1[i * width + j] = (int32_t)dat[i * dat_stride + j];
282 flt2[i * width + j] = (int32_t)dat[i * dat_stride + j];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700283 }
284 }
285 } else {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700286 uint8_t *dat = dat8;
287 for (i = 0; i < height; ++i) {
288 for (j = 0; j < width; ++j) {
289 const int k = i * width + j;
290 const int l = i * dat_stride + j;
Debargha Mukherjee519dbcf2016-12-16 03:13:02 -0800291 flt1[k] = (int32_t)dat[l];
292 flt2[k] = (int32_t)dat[l];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700293 }
294 }
295 }
296 av1_selfguided_restoration(flt1, width, height, width, bit_depth,
297 sgr_params[ep].r1, sgr_params[ep].e1, tmpbuf2);
298 av1_selfguided_restoration(flt2, width, height, width, bit_depth,
299 sgr_params[ep].r2, sgr_params[ep].e2, tmpbuf2);
David Barker3a0df182016-12-21 10:44:52 +0000300 get_proj_subspace(src8, width, height, src_stride, dat8, dat_stride,
301 bit_depth, flt1, width, flt2, width, exq);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700302 encode_xq(exq, exqd);
David Barker3a0df182016-12-21 10:44:52 +0000303 err =
304 get_pixel_proj_error(src8, width, height, src_stride, dat8, dat_stride,
305 bit_depth, flt1, width, flt2, width, exqd);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700306 if (besterr == -1 || err < besterr) {
307 bestep = ep;
308 besterr = err;
309 bestxqd[0] = exqd[0];
310 bestxqd[1] = exqd[1];
311 }
312 }
313 *eps = bestep;
314 xqd[0] = bestxqd[0];
315 xqd[1] = bestxqd[1];
316}
317
318static double search_sgrproj(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
319 int filter_level, int partial_frame,
David Barker9666e752016-12-08 11:25:47 +0000320 RestorationInfo *info, double *best_tile_cost,
321 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700322 SgrprojInfo *sgrproj_info = info->sgrproj_info;
323 double err, cost_norestore, cost_sgrproj;
324 int bits;
325 MACROBLOCK *x = &cpi->td.mb;
326 AV1_COMMON *const cm = &cpi->common;
327 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800328 RestorationInfo *rsi = &cpi->rst_search[0];
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700329 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
330 int h_start, h_end, v_start, v_end;
Debargha Mukherjee874d36d2016-12-14 16:53:17 -0800331 // Allocate for the src buffer at high precision
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700332 const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
333 &tile_height, &nhtiles, &nvtiles);
334 // Make a copy of the unfiltered / processed recon buffer
335 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
336 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
337 1, partial_frame);
338 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
339
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800340 rsi->frame_restoration_type = RESTORE_SGRPROJ;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700341
342 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx)
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800343 rsi->sgrproj_info[tile_idx].level = 0;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700344 // Compute best Sgrproj filters for each tile
345 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
346 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
347 tile_height, cm->width, cm->height, 0, 0, &h_start,
348 &h_end, &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +0000349 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -0800350 h_end - h_start, v_start, v_end - v_start, 1);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700351 // #bits when a tile is not restored
352 bits = av1_cost_bit(RESTORE_NONE_SGRPROJ_PROB, 0);
353 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
354 best_tile_cost[tile_idx] = DBL_MAX;
355 search_selfguided_restoration(
356 dgd->y_buffer + v_start * dgd->y_stride + h_start, h_end - h_start,
357 v_end - v_start, dgd->y_stride,
358 src->y_buffer + v_start * src->y_stride + h_start, src->y_stride,
359#if CONFIG_AOM_HIGHBITDEPTH
360 cm->bit_depth,
361#else
362 8,
363#endif // CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800364 &rsi->sgrproj_info[tile_idx].ep, rsi->sgrproj_info[tile_idx].xqd,
David Barker3a0df182016-12-21 10:44:52 +0000365 cm->rst_internal.tmpbuf);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800366 rsi->sgrproj_info[tile_idx].level = 1;
367 err = try_restoration_tile(src, cpi, rsi, 1, partial_frame, tile_idx, 0, 0,
David Barker9666e752016-12-08 11:25:47 +0000368 dst_frame);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700369 bits = SGRPROJ_BITS << AV1_PROB_COST_SHIFT;
370 bits += av1_cost_bit(RESTORE_NONE_SGRPROJ_PROB, 1);
371 cost_sgrproj = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
372 if (cost_sgrproj >= cost_norestore) {
373 sgrproj_info[tile_idx].level = 0;
374 } else {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800375 memcpy(&sgrproj_info[tile_idx], &rsi->sgrproj_info[tile_idx],
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700376 sizeof(sgrproj_info[tile_idx]));
377 bits = SGRPROJ_BITS << AV1_PROB_COST_SHIFT;
378 best_tile_cost[tile_idx] = RDCOST_DBL(
379 x->rdmult, x->rddiv,
380 (bits + cpi->switchable_restore_cost[RESTORE_SGRPROJ]) >> 4, err);
381 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800382 rsi->sgrproj_info[tile_idx].level = 0;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700383 }
384 // Cost for Sgrproj filtering
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800385 bits = frame_level_restore_bits[rsi->frame_restoration_type]
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700386 << AV1_PROB_COST_SHIFT;
387 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
388 bits +=
389 av1_cost_bit(RESTORE_NONE_SGRPROJ_PROB, sgrproj_info[tile_idx].level);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800390 memcpy(&rsi->sgrproj_info[tile_idx], &sgrproj_info[tile_idx],
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700391 sizeof(sgrproj_info[tile_idx]));
392 if (sgrproj_info[tile_idx].level) {
393 bits += (SGRPROJ_BITS << AV1_PROB_COST_SHIFT);
394 }
395 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800396 err = try_restoration_frame(src, cpi, rsi, 1, partial_frame, dst_frame);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700397 cost_sgrproj = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
398
Debargha Mukherjee8f209a82016-10-12 10:47:01 -0700399 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
400 return cost_sgrproj;
401}
402
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800403static int64_t compute_sse(uint8_t *dgd, int width, int height, int dgd_stride,
404 uint8_t *src, int src_stride) {
405 int64_t sse = 0;
406 int i, j;
407 for (i = 0; i < height; ++i) {
408 for (j = 0; j < width; ++j) {
409 const int diff =
410 (int)dgd[i * dgd_stride + j] - (int)src[i * src_stride + j];
411 sse += diff * diff;
412 }
413 }
414 return sse;
415}
416
417#if CONFIG_AOM_HIGHBITDEPTH
418static int64_t compute_sse_highbd(uint16_t *dgd, int width, int height,
419 int dgd_stride, uint16_t *src,
420 int src_stride) {
421 int64_t sse = 0;
422 int i, j;
423 for (i = 0; i < height; ++i) {
424 for (j = 0; j < width; ++j) {
425 const int diff =
426 (int)dgd[i * dgd_stride + j] - (int)src[i * src_stride + j];
427 sse += diff * diff;
428 }
429 }
430 return sse;
431}
432#endif // CONFIG_AOM_HIGHBITDEPTH
433
434static void search_domaintxfmrf_restoration(uint8_t *dgd8, int width,
435 int height, int dgd_stride,
436 uint8_t *src8, int src_stride,
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800437 int bit_depth, int *sigma_r,
David Barker3a0df182016-12-21 10:44:52 +0000438 uint8_t *fltbuf, int32_t *tmpbuf) {
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800439 const int first_p_step = 8;
440 const int second_p_range = first_p_step >> 1;
441 const int second_p_step = 2;
442 const int third_p_range = second_p_step >> 1;
443 const int third_p_step = 1;
David Barker9666e752016-12-08 11:25:47 +0000444 int p, best_p0, best_p = -1;
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800445 int64_t best_sse = INT64_MAX, sse;
446 if (bit_depth == 8) {
David Barker3a0df182016-12-21 10:44:52 +0000447 uint8_t *flt = fltbuf;
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800448 uint8_t *dgd = dgd8;
449 uint8_t *src = src8;
450 // First phase
451 for (p = first_p_step / 2; p < DOMAINTXFMRF_PARAMS; p += first_p_step) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800452 av1_domaintxfmrf_restoration(dgd, width, height, dgd_stride, p, flt,
Yaowu Xubf1d62d2016-12-14 19:20:46 -0800453 width, tmpbuf);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800454 sse = compute_sse(flt, width, height, width, src, src_stride);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800455 if (sse < best_sse || best_p == -1) {
456 best_p = p;
457 best_sse = sse;
458 }
459 }
460 // Second Phase
461 best_p0 = best_p;
462 for (p = best_p0 - second_p_range; p <= best_p0 + second_p_range;
463 p += second_p_step) {
464 if (p < 0 || p == best_p || p >= DOMAINTXFMRF_PARAMS) continue;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800465 av1_domaintxfmrf_restoration(dgd, width, height, dgd_stride, p, flt,
Yaowu Xubf1d62d2016-12-14 19:20:46 -0800466 width, tmpbuf);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800467 sse = compute_sse(flt, width, height, width, src, src_stride);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800468 if (sse < best_sse) {
469 best_p = p;
470 best_sse = sse;
471 }
472 }
473 // Third Phase
474 best_p0 = best_p;
475 for (p = best_p0 - third_p_range; p <= best_p0 + third_p_range;
476 p += third_p_step) {
477 if (p < 0 || p == best_p || p >= DOMAINTXFMRF_PARAMS) continue;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800478 av1_domaintxfmrf_restoration(dgd, width, height, dgd_stride, p, flt,
Yaowu Xubf1d62d2016-12-14 19:20:46 -0800479 width, tmpbuf);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800480 sse = compute_sse(flt, width, height, width, src, src_stride);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800481 if (sse < best_sse) {
482 best_p = p;
483 best_sse = sse;
484 }
485 }
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800486 } else {
487#if CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800488 uint16_t *flt = (uint16_t *)fltbuf;
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800489 uint16_t *dgd = CONVERT_TO_SHORTPTR(dgd8);
490 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
491 // First phase
492 for (p = first_p_step / 2; p < DOMAINTXFMRF_PARAMS; p += first_p_step) {
David Barker9666e752016-12-08 11:25:47 +0000493 av1_domaintxfmrf_restoration_highbd(dgd, width, height, dgd_stride, p,
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800494 bit_depth, flt, width, tmpbuf);
495 sse = compute_sse_highbd(flt, width, height, width, src, src_stride);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800496 if (sse < best_sse || best_p == -1) {
497 best_p = p;
498 best_sse = sse;
499 }
500 }
501 // Second Phase
502 best_p0 = best_p;
503 for (p = best_p0 - second_p_range; p <= best_p0 + second_p_range;
504 p += second_p_step) {
505 if (p < 0 || p == best_p || p >= DOMAINTXFMRF_PARAMS) continue;
David Barker9666e752016-12-08 11:25:47 +0000506 av1_domaintxfmrf_restoration_highbd(dgd, width, height, dgd_stride, p,
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800507 bit_depth, flt, width, tmpbuf);
508 sse = compute_sse_highbd(flt, width, height, width, src, src_stride);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800509 if (sse < best_sse) {
510 best_p = p;
511 best_sse = sse;
512 }
513 }
514 // Third Phase
515 best_p0 = best_p;
516 for (p = best_p0 - third_p_range; p <= best_p0 + third_p_range;
517 p += third_p_step) {
518 if (p < 0 || p == best_p || p >= DOMAINTXFMRF_PARAMS) continue;
David Barker9666e752016-12-08 11:25:47 +0000519 av1_domaintxfmrf_restoration_highbd(dgd, width, height, dgd_stride, p,
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800520 bit_depth, flt, width, tmpbuf);
521 sse = compute_sse_highbd(flt, width, height, width, src, src_stride);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800522 if (sse < best_sse) {
523 best_p = p;
524 best_sse = sse;
525 }
526 }
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800527#else
528 assert(0);
529#endif // CONFIG_AOM_HIGHBITDEPTH
530 }
531 *sigma_r = best_p;
532}
533
534static double search_domaintxfmrf(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
535 int filter_level, int partial_frame,
David Barker9666e752016-12-08 11:25:47 +0000536 RestorationInfo *info, double *best_tile_cost,
537 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800538 DomaintxfmrfInfo *domaintxfmrf_info = info->domaintxfmrf_info;
Debargha Mukherjee0e67b252016-12-08 09:22:44 -0800539 double cost_norestore, cost_domaintxfmrf;
540 int64_t err;
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800541 int bits;
542 MACROBLOCK *x = &cpi->td.mb;
543 AV1_COMMON *const cm = &cpi->common;
544 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800545 RestorationInfo *rsi = &cpi->rst_search[0];
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800546 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
547 int h_start, h_end, v_start, v_end;
548 const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
549 &tile_height, &nhtiles, &nvtiles);
550 // Make a copy of the unfiltered / processed recon buffer
551 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
552 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
553 1, partial_frame);
554 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
555
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800556 rsi->frame_restoration_type = RESTORE_DOMAINTXFMRF;
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800557
558 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx)
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800559 rsi->domaintxfmrf_info[tile_idx].level = 0;
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800560 // Compute best Domaintxfm filters for each tile
561 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
562 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
563 tile_height, cm->width, cm->height, 0, 0, &h_start,
564 &h_end, &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +0000565 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -0800566 h_end - h_start, v_start, v_end - v_start, 1);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800567 // #bits when a tile is not restored
568 bits = av1_cost_bit(RESTORE_NONE_DOMAINTXFMRF_PROB, 0);
569 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
570 best_tile_cost[tile_idx] = DBL_MAX;
571
572 search_domaintxfmrf_restoration(
573 dgd->y_buffer + v_start * dgd->y_stride + h_start, h_end - h_start,
574 v_end - v_start, dgd->y_stride,
575 src->y_buffer + v_start * src->y_stride + h_start, src->y_stride,
576#if CONFIG_AOM_HIGHBITDEPTH
577 cm->bit_depth,
578#else
579 8,
580#endif // CONFIG_AOM_HIGHBITDEPTH
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800581 &rsi->domaintxfmrf_info[tile_idx].sigma_r, cpi->extra_rstbuf,
582 cm->rst_internal.tmpbuf);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800583
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800584 rsi->domaintxfmrf_info[tile_idx].level = 1;
585 err = try_restoration_tile(src, cpi, rsi, 1, partial_frame, tile_idx, 0, 0,
David Barker9666e752016-12-08 11:25:47 +0000586 dst_frame);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800587 bits = DOMAINTXFMRF_PARAMS_BITS << AV1_PROB_COST_SHIFT;
588 bits += av1_cost_bit(RESTORE_NONE_DOMAINTXFMRF_PROB, 1);
589 cost_domaintxfmrf = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
590 if (cost_domaintxfmrf >= cost_norestore) {
591 domaintxfmrf_info[tile_idx].level = 0;
592 } else {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800593 memcpy(&domaintxfmrf_info[tile_idx], &rsi->domaintxfmrf_info[tile_idx],
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800594 sizeof(domaintxfmrf_info[tile_idx]));
595 bits = DOMAINTXFMRF_PARAMS_BITS << AV1_PROB_COST_SHIFT;
596 best_tile_cost[tile_idx] = RDCOST_DBL(
597 x->rdmult, x->rddiv,
598 (bits + cpi->switchable_restore_cost[RESTORE_DOMAINTXFMRF]) >> 4,
599 err);
600 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800601 rsi->domaintxfmrf_info[tile_idx].level = 0;
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800602 }
603 // Cost for Domaintxfmrf filtering
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800604 bits = frame_level_restore_bits[rsi->frame_restoration_type]
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800605 << AV1_PROB_COST_SHIFT;
606 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
607 bits += av1_cost_bit(RESTORE_NONE_DOMAINTXFMRF_PROB,
608 domaintxfmrf_info[tile_idx].level);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800609 memcpy(&rsi->domaintxfmrf_info[tile_idx], &domaintxfmrf_info[tile_idx],
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800610 sizeof(domaintxfmrf_info[tile_idx]));
611 if (domaintxfmrf_info[tile_idx].level) {
612 bits += (DOMAINTXFMRF_PARAMS_BITS << AV1_PROB_COST_SHIFT);
613 }
614 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800615 err = try_restoration_frame(src, cpi, rsi, 1, partial_frame, dst_frame);
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800616 cost_domaintxfmrf = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
617
Debargha Mukherjee3981be92016-11-21 09:35:44 -0800618 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
619 return cost_domaintxfmrf;
620}
621
Yaowu Xuc27fc142016-08-22 16:08:15 -0700622static double find_average(uint8_t *src, int h_start, int h_end, int v_start,
623 int v_end, int stride) {
624 uint64_t sum = 0;
625 double avg = 0;
626 int i, j;
627 for (i = v_start; i < v_end; i++)
628 for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
629 avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
630 return avg;
631}
632
633static void compute_stats(uint8_t *dgd, uint8_t *src, int h_start, int h_end,
634 int v_start, int v_end, int dgd_stride,
635 int src_stride, double *M, double *H) {
636 int i, j, k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800637 double Y[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700638 const double avg =
639 find_average(dgd, h_start, h_end, v_start, v_end, dgd_stride);
640
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800641 memset(M, 0, sizeof(*M) * WIENER_WIN2);
642 memset(H, 0, sizeof(*H) * WIENER_WIN2 * WIENER_WIN2);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700643 for (i = v_start; i < v_end; i++) {
644 for (j = h_start; j < h_end; j++) {
645 const double X = (double)src[i * src_stride + j] - avg;
646 int idx = 0;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800647 for (k = -WIENER_HALFWIN; k <= WIENER_HALFWIN; k++) {
648 for (l = -WIENER_HALFWIN; l <= WIENER_HALFWIN; l++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700649 Y[idx] = (double)dgd[(i + l) * dgd_stride + (j + k)] - avg;
650 idx++;
651 }
652 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800653 for (k = 0; k < WIENER_WIN2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700654 M[k] += Y[k] * X;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800655 H[k * WIENER_WIN2 + k] += Y[k] * Y[k];
656 for (l = k + 1; l < WIENER_WIN2; ++l) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700657 double value = Y[k] * Y[l];
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800658 H[k * WIENER_WIN2 + l] += value;
659 H[l * WIENER_WIN2 + k] += value;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700660 }
661 }
662 }
663 }
664}
665
Yaowu Xuf883b422016-08-30 14:01:10 -0700666#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700667static double find_average_highbd(uint16_t *src, int h_start, int h_end,
668 int v_start, int v_end, int stride) {
669 uint64_t sum = 0;
670 double avg = 0;
671 int i, j;
672 for (i = v_start; i < v_end; i++)
673 for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
674 avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
675 return avg;
676}
677
678static void compute_stats_highbd(uint8_t *dgd8, uint8_t *src8, int h_start,
679 int h_end, int v_start, int v_end,
680 int dgd_stride, int src_stride, double *M,
681 double *H) {
682 int i, j, k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800683 double Y[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700684 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
685 uint16_t *dgd = CONVERT_TO_SHORTPTR(dgd8);
686 const double avg =
687 find_average_highbd(dgd, h_start, h_end, v_start, v_end, dgd_stride);
688
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800689 memset(M, 0, sizeof(*M) * WIENER_WIN2);
690 memset(H, 0, sizeof(*H) * WIENER_WIN2 * WIENER_WIN2);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700691 for (i = v_start; i < v_end; i++) {
692 for (j = h_start; j < h_end; j++) {
693 const double X = (double)src[i * src_stride + j] - avg;
694 int idx = 0;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800695 for (k = -WIENER_HALFWIN; k <= WIENER_HALFWIN; k++) {
696 for (l = -WIENER_HALFWIN; l <= WIENER_HALFWIN; l++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700697 Y[idx] = (double)dgd[(i + l) * dgd_stride + (j + k)] - avg;
698 idx++;
699 }
700 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800701 for (k = 0; k < WIENER_WIN2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700702 M[k] += Y[k] * X;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800703 H[k * WIENER_WIN2 + k] += Y[k] * Y[k];
704 for (l = k + 1; l < WIENER_WIN2; ++l) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700705 double value = Y[k] * Y[l];
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800706 H[k * WIENER_WIN2 + l] += value;
707 H[l * WIENER_WIN2 + k] += value;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700708 }
709 }
710 }
711 }
712}
Yaowu Xuf883b422016-08-30 14:01:10 -0700713#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700714
715// Solves Ax = b, where x and b are column vectors
716static int linsolve(int n, double *A, int stride, double *b, double *x) {
717 int i, j, k;
718 double c;
719 // Partial pivoting
720 for (i = n - 1; i > 0; i--) {
721 if (A[(i - 1) * stride] < A[i * stride]) {
722 for (j = 0; j < n; j++) {
723 c = A[i * stride + j];
724 A[i * stride + j] = A[(i - 1) * stride + j];
725 A[(i - 1) * stride + j] = c;
726 }
727 c = b[i];
728 b[i] = b[i - 1];
729 b[i - 1] = c;
730 }
731 }
732 // Forward elimination
733 for (k = 0; k < n - 1; k++) {
734 for (i = k; i < n - 1; i++) {
735 c = A[(i + 1) * stride + k] / A[k * stride + k];
736 for (j = 0; j < n; j++) A[(i + 1) * stride + j] -= c * A[k * stride + j];
737 b[i + 1] -= c * b[k];
738 }
739 }
740 // Backward substitution
741 for (i = n - 1; i >= 0; i--) {
742 if (fabs(A[i * stride + i]) < 1e-10) return 0;
743 c = 0;
744 for (j = i + 1; j <= n - 1; j++) c += A[i * stride + j] * x[j];
745 x[i] = (b[i] - c) / A[i * stride + i];
746 }
747 return 1;
748}
749
750static INLINE int wrap_index(int i) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800751 return (i >= WIENER_HALFWIN1 ? WIENER_WIN - 1 - i : i);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700752}
753
754// Fix vector b, update vector a
755static void update_a_sep_sym(double **Mc, double **Hc, double *a, double *b) {
756 int i, j;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800757 double S[WIENER_WIN];
758 double A[WIENER_WIN], B[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700759 int w, w2;
760 memset(A, 0, sizeof(A));
761 memset(B, 0, sizeof(B));
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800762 for (i = 0; i < WIENER_WIN; i++) {
763 for (j = 0; j < WIENER_WIN; ++j) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700764 const int jj = wrap_index(j);
765 A[jj] += Mc[i][j] * b[i];
766 }
767 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800768 for (i = 0; i < WIENER_WIN; i++) {
769 for (j = 0; j < WIENER_WIN; j++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700770 int k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800771 for (k = 0; k < WIENER_WIN; ++k)
772 for (l = 0; l < WIENER_WIN; ++l) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700773 const int kk = wrap_index(k);
774 const int ll = wrap_index(l);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800775 B[ll * WIENER_HALFWIN1 + kk] +=
776 Hc[j * WIENER_WIN + i][k * WIENER_WIN2 + l] * b[i] * b[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700777 }
778 }
779 }
780 // Normalization enforcement in the system of equations itself
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800781 w = WIENER_WIN;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700782 w2 = (w >> 1) + 1;
783 for (i = 0; i < w2 - 1; ++i)
784 A[i] -=
785 A[w2 - 1] * 2 + B[i * w2 + w2 - 1] - 2 * B[(w2 - 1) * w2 + (w2 - 1)];
786 for (i = 0; i < w2 - 1; ++i)
787 for (j = 0; j < w2 - 1; ++j)
788 B[i * w2 + j] -= 2 * (B[i * w2 + (w2 - 1)] + B[(w2 - 1) * w2 + j] -
789 2 * B[(w2 - 1) * w2 + (w2 - 1)]);
790 if (linsolve(w2 - 1, B, w2, A, S)) {
791 S[w2 - 1] = 1.0;
792 for (i = w2; i < w; ++i) {
793 S[i] = S[w - 1 - i];
794 S[w2 - 1] -= 2 * S[i];
795 }
796 memcpy(a, S, w * sizeof(*a));
797 }
798}
799
800// Fix vector a, update vector b
801static void update_b_sep_sym(double **Mc, double **Hc, double *a, double *b) {
802 int i, j;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800803 double S[WIENER_WIN];
804 double A[WIENER_WIN], B[WIENER_WIN2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700805 int w, w2;
806 memset(A, 0, sizeof(A));
807 memset(B, 0, sizeof(B));
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800808 for (i = 0; i < WIENER_WIN; i++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700809 const int ii = wrap_index(i);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800810 for (j = 0; j < WIENER_WIN; j++) A[ii] += Mc[i][j] * a[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700811 }
812
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800813 for (i = 0; i < WIENER_WIN; i++) {
814 for (j = 0; j < WIENER_WIN; j++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700815 const int ii = wrap_index(i);
816 const int jj = wrap_index(j);
817 int k, l;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800818 for (k = 0; k < WIENER_WIN; ++k)
819 for (l = 0; l < WIENER_WIN; ++l)
820 B[jj * WIENER_HALFWIN1 + ii] +=
821 Hc[i * WIENER_WIN + j][k * WIENER_WIN2 + l] * a[k] * a[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700822 }
823 }
824 // Normalization enforcement in the system of equations itself
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800825 w = WIENER_WIN;
826 w2 = WIENER_HALFWIN1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700827 for (i = 0; i < w2 - 1; ++i)
828 A[i] -=
829 A[w2 - 1] * 2 + B[i * w2 + w2 - 1] - 2 * B[(w2 - 1) * w2 + (w2 - 1)];
830 for (i = 0; i < w2 - 1; ++i)
831 for (j = 0; j < w2 - 1; ++j)
832 B[i * w2 + j] -= 2 * (B[i * w2 + (w2 - 1)] + B[(w2 - 1) * w2 + j] -
833 2 * B[(w2 - 1) * w2 + (w2 - 1)]);
834 if (linsolve(w2 - 1, B, w2, A, S)) {
835 S[w2 - 1] = 1.0;
836 for (i = w2; i < w; ++i) {
837 S[i] = S[w - 1 - i];
838 S[w2 - 1] -= 2 * S[i];
839 }
840 memcpy(b, S, w * sizeof(*b));
841 }
842}
843
844static int wiener_decompose_sep_sym(double *M, double *H, double *a,
845 double *b) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800846 static const double init_filt[WIENER_WIN] = {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700847 0.035623, -0.127154, 0.211436, 0.760190, 0.211436, -0.127154, 0.035623,
848 };
849 int i, j, iter;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800850 double *Hc[WIENER_WIN2];
851 double *Mc[WIENER_WIN];
852 for (i = 0; i < WIENER_WIN; i++) {
853 Mc[i] = M + i * WIENER_WIN;
854 for (j = 0; j < WIENER_WIN; j++) {
855 Hc[i * WIENER_WIN + j] =
856 H + i * WIENER_WIN * WIENER_WIN2 + j * WIENER_WIN;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700857 }
858 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800859 memcpy(a, init_filt, sizeof(*a) * WIENER_WIN);
860 memcpy(b, init_filt, sizeof(*b) * WIENER_WIN);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700861
862 iter = 1;
863 while (iter < 10) {
864 update_a_sep_sym(Mc, Hc, a, b);
865 update_b_sep_sym(Mc, Hc, a, b);
866 iter++;
867 }
868 return 1;
869}
870
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800871// Computes the function x'*H*x - x'*M for the learned 2D filter x, and compares
Yaowu Xuc27fc142016-08-22 16:08:15 -0700872// against identity filters; Final score is defined as the difference between
873// the function values
874static double compute_score(double *M, double *H, int *vfilt, int *hfilt) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800875 double ab[WIENER_WIN * WIENER_WIN];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700876 int i, k, l;
877 double P = 0, Q = 0;
878 double iP = 0, iQ = 0;
879 double Score, iScore;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800880 double a[WIENER_WIN], b[WIENER_WIN];
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800881 a[WIENER_HALFWIN] = b[WIENER_HALFWIN] = 1.0;
882 for (i = 0; i < WIENER_HALFWIN; ++i) {
883 a[i] = a[WIENER_WIN - i - 1] = (double)vfilt[i] / WIENER_FILT_STEP;
884 b[i] = b[WIENER_WIN - i - 1] = (double)hfilt[i] / WIENER_FILT_STEP;
885 a[WIENER_HALFWIN] -= 2 * a[i];
886 b[WIENER_HALFWIN] -= 2 * b[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700887 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800888 for (k = 0; k < WIENER_WIN; ++k) {
889 for (l = 0; l < WIENER_WIN; ++l) ab[k * WIENER_WIN + l] = a[l] * b[k];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700890 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800891 for (k = 0; k < WIENER_WIN2; ++k) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700892 P += ab[k] * M[k];
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800893 for (l = 0; l < WIENER_WIN2; ++l)
894 Q += ab[k] * H[k * WIENER_WIN2 + l] * ab[l];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700895 }
896 Score = Q - 2 * P;
897
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800898 iP = M[WIENER_WIN2 >> 1];
899 iQ = H[(WIENER_WIN2 >> 1) * WIENER_WIN2 + (WIENER_WIN2 >> 1)];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700900 iScore = iQ - 2 * iP;
901
902 return Score - iScore;
903}
904
Yaowu Xuc27fc142016-08-22 16:08:15 -0700905static void quantize_sym_filter(double *f, int *fi) {
906 int i;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -0800907 for (i = 0; i < WIENER_HALFWIN; ++i) {
908 fi[i] = RINT(f[i] * WIENER_FILT_STEP);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700909 }
910 // Specialize for 7-tap filter
911 fi[0] = CLIP(fi[0], WIENER_FILT_TAP0_MINV, WIENER_FILT_TAP0_MAXV);
912 fi[1] = CLIP(fi[1], WIENER_FILT_TAP1_MINV, WIENER_FILT_TAP1_MAXV);
913 fi[2] = CLIP(fi[2], WIENER_FILT_TAP2_MINV, WIENER_FILT_TAP2_MAXV);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800914 // Satisfy filter constraints
915 fi[WIENER_WIN - 1] = fi[0];
916 fi[WIENER_WIN - 2] = fi[1];
917 fi[WIENER_WIN - 3] = fi[2];
918 fi[3] = WIENER_FILT_STEP - 2 * (fi[0] + fi[1] + fi[2]);
919}
920
921static double search_wiener_uv(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
922 int filter_level, int partial_frame, int plane,
923 RestorationInfo *info,
924 YV12_BUFFER_CONFIG *dst_frame) {
925 WienerInfo *wiener_info = info->wiener_info;
926 AV1_COMMON *const cm = &cpi->common;
927 RestorationInfo *rsi = cpi->rst_search;
928 int64_t err;
929 int bits;
930 double cost_wiener = 0, cost_norestore = 0;
931 MACROBLOCK *x = &cpi->td.mb;
932 double M[WIENER_WIN2];
933 double H[WIENER_WIN2 * WIENER_WIN2];
934 double vfilterd[WIENER_WIN], hfilterd[WIENER_WIN];
935 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
936 const int width = src->uv_crop_width;
937 const int height = src->uv_crop_height;
938 const int src_stride = src->uv_stride;
939 const int dgd_stride = dgd->uv_stride;
940 double score;
941 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
942 int h_start, h_end, v_start, v_end;
943 const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
944 &tile_height, &nhtiles, &nvtiles);
945
946 assert(width == dgd->uv_crop_width);
947 assert(height == dgd->uv_crop_height);
948
949 // Make a copy of the unfiltered / processed recon buffer
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -0800950 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
951 aom_yv12_copy_u(cm->frame_to_show, &cpi->last_frame_uf);
952 aom_yv12_copy_v(cm->frame_to_show, &cpi->last_frame_uf);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800953 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
954 0, partial_frame);
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -0800955 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
956 aom_yv12_copy_u(cm->frame_to_show, &cpi->last_frame_db);
957 aom_yv12_copy_v(cm->frame_to_show, &cpi->last_frame_db);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800958
959 rsi[plane].frame_restoration_type = RESTORE_NONE;
960
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -0800961 err = sse_restoration_frame(src, cm->frame_to_show, (1 << plane));
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800962 bits = 0;
963 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
964
965 rsi[plane].frame_restoration_type = RESTORE_WIENER;
966 h_start = v_start = WIENER_HALFWIN;
967 h_end = width - WIENER_HALFWIN;
968 v_end = height - WIENER_HALFWIN;
969 if (plane == AOM_PLANE_U) {
970#if CONFIG_AOM_HIGHBITDEPTH
971 if (cm->use_highbitdepth)
972 compute_stats_highbd(dgd->u_buffer, src->u_buffer, h_start, h_end,
973 v_start, v_end, dgd_stride, src_stride, M, H);
974 else
975#endif // CONFIG_AOM_HIGHBITDEPTH
976 compute_stats(dgd->u_buffer, src->u_buffer, h_start, h_end, v_start,
977 v_end, dgd_stride, src_stride, M, H);
978 } else if (plane == AOM_PLANE_V) {
979#if CONFIG_AOM_HIGHBITDEPTH
980 if (cm->use_highbitdepth)
981 compute_stats_highbd(dgd->v_buffer, src->v_buffer, h_start, h_end,
982 v_start, v_end, dgd_stride, src_stride, M, H);
983 else
984#endif // CONFIG_AOM_HIGHBITDEPTH
985 compute_stats(dgd->v_buffer, src->v_buffer, h_start, h_end, v_start,
986 v_end, dgd_stride, src_stride, M, H);
987 } else {
988 assert(0);
989 }
990 if (!wiener_decompose_sep_sym(M, H, vfilterd, hfilterd)) {
991 info->frame_restoration_type = RESTORE_NONE;
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -0800992 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
993 aom_yv12_copy_u(&cpi->last_frame_uf, cm->frame_to_show);
994 aom_yv12_copy_v(&cpi->last_frame_uf, cm->frame_to_show);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -0800995 return cost_norestore;
996 }
997 quantize_sym_filter(vfilterd, rsi[plane].wiener_info[0].vfilter);
998 quantize_sym_filter(hfilterd, rsi[plane].wiener_info[0].hfilter);
999
1000 // Filter score computes the value of the function x'*A*x - x'*b for the
1001 // learned filter and compares it against identity filer. If there is no
1002 // reduction in the function, the filter is reverted back to identity
1003 score = compute_score(M, H, rsi[plane].wiener_info[0].vfilter,
1004 rsi[plane].wiener_info[0].hfilter);
1005 if (score > 0.0) {
1006 info->frame_restoration_type = RESTORE_NONE;
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -08001007 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
1008 aom_yv12_copy_u(&cpi->last_frame_uf, cm->frame_to_show);
1009 aom_yv12_copy_v(&cpi->last_frame_uf, cm->frame_to_show);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001010 return cost_norestore;
1011 }
1012
1013 info->frame_restoration_type = RESTORE_WIENER;
1014 rsi[plane].restoration_type[0] = info->restoration_type[0] = RESTORE_WIENER;
1015 rsi[plane].wiener_info[0].level = 1;
1016 memcpy(&wiener_info[0], &rsi[plane].wiener_info[0], sizeof(wiener_info[0]));
1017 for (tile_idx = 1; tile_idx < ntiles; ++tile_idx) {
1018 info->restoration_type[tile_idx] = RESTORE_WIENER;
1019 memcpy(&rsi[plane].wiener_info[tile_idx], &rsi[plane].wiener_info[0],
1020 sizeof(rsi[plane].wiener_info[0]));
1021 memcpy(&wiener_info[tile_idx], &rsi[plane].wiener_info[0],
1022 sizeof(rsi[plane].wiener_info[0]));
1023 }
1024 err = try_restoration_frame(src, cpi, rsi, (1 << plane), partial_frame,
1025 dst_frame);
1026 bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT;
1027 cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
1028 if (cost_wiener > cost_norestore) {
1029 info->frame_restoration_type = RESTORE_NONE;
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -08001030 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
1031 aom_yv12_copy_u(&cpi->last_frame_uf, cm->frame_to_show);
1032 aom_yv12_copy_v(&cpi->last_frame_uf, cm->frame_to_show);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001033 return cost_norestore;
1034 }
1035
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -08001036 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
1037 aom_yv12_copy_u(&cpi->last_frame_uf, cm->frame_to_show);
1038 aom_yv12_copy_v(&cpi->last_frame_uf, cm->frame_to_show);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001039 return cost_wiener;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001040}
1041
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001042static double search_wiener(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
1043 int filter_level, int partial_frame,
David Barker9666e752016-12-08 11:25:47 +00001044 RestorationInfo *info, double *best_tile_cost,
1045 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001046 WienerInfo *wiener_info = info->wiener_info;
Yaowu Xuf883b422016-08-30 14:01:10 -07001047 AV1_COMMON *const cm = &cpi->common;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001048 RestorationInfo *rsi = cpi->rst_search;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001049 int64_t err;
1050 int bits;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001051 double cost_wiener, cost_norestore;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001052 MACROBLOCK *x = &cpi->td.mb;
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001053 double M[WIENER_WIN2];
1054 double H[WIENER_WIN2 * WIENER_WIN2];
1055 double vfilterd[WIENER_WIN], hfilterd[WIENER_WIN];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001056 const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
1057 const int width = cm->width;
1058 const int height = cm->height;
1059 const int src_stride = src->y_stride;
1060 const int dgd_stride = dgd->y_stride;
1061 double score;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001062 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001063 int h_start, h_end, v_start, v_end;
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001064 int i;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001065 const int ntiles = av1_get_rest_ntiles(width, height, &tile_width,
1066 &tile_height, &nhtiles, &nvtiles);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001067 assert(width == dgd->y_crop_width);
1068 assert(height == dgd->y_crop_height);
1069 assert(width == src->y_crop_width);
1070 assert(height == src->y_crop_height);
1071
Yaowu Xuc27fc142016-08-22 16:08:15 -07001072 // Make a copy of the unfiltered / processed recon buffer
Yaowu Xuf883b422016-08-30 14:01:10 -07001073 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
1074 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
1075 1, partial_frame);
1076 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001077
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001078 rsi->frame_restoration_type = RESTORE_WIENER;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001079
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001080 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx)
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001081 rsi->wiener_info[tile_idx].level = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001082
1083 // Compute best Wiener filters for each tile
1084 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001085 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
1086 tile_height, width, height, 0, 0, &h_start, &h_end,
1087 &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +00001088 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -08001089 h_end - h_start, v_start, v_end - v_start, 1);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001090 // #bits when a tile is not restored
1091 bits = av1_cost_bit(RESTORE_NONE_WIENER_PROB, 0);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001092 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001093 best_tile_cost[tile_idx] = DBL_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001094
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001095 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001096 tile_height, width, height, WIENER_HALFWIN,
1097 WIENER_HALFWIN, &h_start, &h_end, &v_start,
1098 &v_end);
Yaowu Xuf883b422016-08-30 14:01:10 -07001099#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001100 if (cm->use_highbitdepth)
1101 compute_stats_highbd(dgd->y_buffer, src->y_buffer, h_start, h_end,
1102 v_start, v_end, dgd_stride, src_stride, M, H);
1103 else
Yaowu Xuf883b422016-08-30 14:01:10 -07001104#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001105 compute_stats(dgd->y_buffer, src->y_buffer, h_start, h_end, v_start,
1106 v_end, dgd_stride, src_stride, M, H);
1107
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001108 wiener_info[tile_idx].level = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001109 if (!wiener_decompose_sep_sym(M, H, vfilterd, hfilterd)) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001110 wiener_info[tile_idx].level = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001111 continue;
1112 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001113 quantize_sym_filter(vfilterd, rsi->wiener_info[tile_idx].vfilter);
1114 quantize_sym_filter(hfilterd, rsi->wiener_info[tile_idx].hfilter);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001115
1116 // Filter score computes the value of the function x'*A*x - x'*b for the
1117 // learned filter and compares it against identity filer. If there is no
1118 // reduction in the function, the filter is reverted back to identity
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001119 score = compute_score(M, H, rsi->wiener_info[tile_idx].vfilter,
1120 rsi->wiener_info[tile_idx].hfilter);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001121 if (score > 0.0) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001122 wiener_info[tile_idx].level = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001123 continue;
1124 }
1125
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001126 rsi->wiener_info[tile_idx].level = 1;
1127 err = try_restoration_tile(src, cpi, rsi, 1, partial_frame, tile_idx, 0, 0,
David Barker9666e752016-12-08 11:25:47 +00001128 dst_frame);
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001129 bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT;
1130 bits += av1_cost_bit(RESTORE_NONE_WIENER_PROB, 1);
1131 cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001132 if (cost_wiener >= cost_norestore) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001133 wiener_info[tile_idx].level = 0;
1134 } else {
1135 wiener_info[tile_idx].level = 1;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001136 for (i = 0; i < WIENER_WIN; ++i) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001137 wiener_info[tile_idx].vfilter[i] =
1138 rsi->wiener_info[tile_idx].vfilter[i];
1139 wiener_info[tile_idx].hfilter[i] =
1140 rsi->wiener_info[tile_idx].hfilter[i];
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001141 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001142 bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT;
1143 best_tile_cost[tile_idx] = RDCOST_DBL(
1144 x->rdmult, x->rddiv,
1145 (bits + cpi->switchable_restore_cost[RESTORE_WIENER]) >> 4, err);
1146 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001147 rsi->wiener_info[tile_idx].level = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001148 }
1149 // Cost for Wiener filtering
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001150 bits = frame_level_restore_bits[rsi->frame_restoration_type]
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001151 << AV1_PROB_COST_SHIFT;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001152 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001153 bits += av1_cost_bit(RESTORE_NONE_WIENER_PROB, wiener_info[tile_idx].level);
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001154 rsi->wiener_info[tile_idx].level = wiener_info[tile_idx].level;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001155 if (wiener_info[tile_idx].level) {
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001156 bits += (WIENER_FILT_BITS << AV1_PROB_COST_SHIFT);
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001157 for (i = 0; i < WIENER_WIN; ++i) {
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001158 rsi->wiener_info[tile_idx].vfilter[i] =
1159 wiener_info[tile_idx].vfilter[i];
1160 rsi->wiener_info[tile_idx].hfilter[i] =
1161 wiener_info[tile_idx].hfilter[i];
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001162 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001163 }
1164 }
Debargha Mukherjee999d2f62016-12-15 13:23:21 -08001165 err = try_restoration_frame(src, cpi, rsi, 1, partial_frame, dst_frame);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001166 cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
Debargha Mukherjee8f209a82016-10-12 10:47:01 -07001167
Yaowu Xuf883b422016-08-30 14:01:10 -07001168 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001169 return cost_wiener;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001170}
1171
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001172static double search_norestore(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
1173 int filter_level, int partial_frame,
David Barker9666e752016-12-08 11:25:47 +00001174 RestorationInfo *info, double *best_tile_cost,
1175 YV12_BUFFER_CONFIG *dst_frame) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001176 double err, cost_norestore;
1177 int bits;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001178 MACROBLOCK *x = &cpi->td.mb;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001179 AV1_COMMON *const cm = &cpi->common;
1180 int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001181 int h_start, h_end, v_start, v_end;
1182 const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
1183 &tile_height, &nhtiles, &nvtiles);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001184 (void)info;
David Barker9666e752016-12-08 11:25:47 +00001185 (void)dst_frame;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001186
1187 // Make a copy of the unfiltered / processed recon buffer
1188 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
1189 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
1190 1, partial_frame);
1191 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
1192
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001193 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
1194 av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width,
1195 tile_height, cm->width, cm->height, 0, 0, &h_start,
1196 &h_end, &v_start, &v_end);
David Barker9666e752016-12-08 11:25:47 +00001197 err = sse_restoration_tile(src, cm->frame_to_show, cm, h_start,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -08001198 h_end - h_start, v_start, v_end - v_start, 1);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001199 best_tile_cost[tile_idx] =
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001200 RDCOST_DBL(x->rdmult, x->rddiv,
1201 (cpi->switchable_restore_cost[RESTORE_NONE] >> 4), err);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001202 }
1203 // RD cost associated with no restoration
David Barker9666e752016-12-08 11:25:47 +00001204 err = sse_restoration_tile(src, cm->frame_to_show, cm, 0, cm->width, 0,
Debargha Mukherjee874d36d2016-12-14 16:53:17 -08001205 cm->height, 1);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001206 bits = frame_level_restore_bits[RESTORE_NONE] << AV1_PROB_COST_SHIFT;
1207 cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err);
1208 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
1209 return cost_norestore;
1210}
1211
1212static double search_switchable_restoration(
1213 AV1_COMP *cpi, int filter_level, int partial_frame, RestorationInfo *rsi,
1214 double *tile_cost[RESTORE_SWITCHABLE_TYPES]) {
1215 AV1_COMMON *const cm = &cpi->common;
1216 MACROBLOCK *x = &cpi->td.mb;
1217 double cost_switchable = 0;
1218 int r, bits, tile_idx;
1219 const int ntiles =
1220 av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL);
1221
1222 // Make a copy of the unfiltered / processed recon buffer
1223 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
1224 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
1225 1, partial_frame);
1226 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
1227
1228 rsi->frame_restoration_type = RESTORE_SWITCHABLE;
1229 bits = frame_level_restore_bits[rsi->frame_restoration_type]
1230 << AV1_PROB_COST_SHIFT;
1231 cost_switchable = RDCOST_DBL(x->rdmult, x->rddiv, bits >> 4, 0);
1232 for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
1233 double best_cost = tile_cost[RESTORE_NONE][tile_idx];
1234 rsi->restoration_type[tile_idx] = RESTORE_NONE;
1235 for (r = 1; r < RESTORE_SWITCHABLE_TYPES; r++) {
1236 if (tile_cost[r][tile_idx] < best_cost) {
1237 rsi->restoration_type[tile_idx] = r;
1238 best_cost = tile_cost[r][tile_idx];
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001239 }
1240 }
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001241 cost_switchable += best_cost;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001242 }
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001243 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001244 return cost_switchable;
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001245}
1246
1247void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
Yaowu Xuf883b422016-08-30 14:01:10 -07001248 LPF_PICK_METHOD method) {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001249 static search_restore_type search_restore_fun[RESTORE_SWITCHABLE_TYPES] = {
Debargha Mukherjee0e67b252016-12-08 09:22:44 -08001250 search_norestore, search_wiener, search_sgrproj, search_domaintxfmrf,
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001251 };
Yaowu Xuf883b422016-08-30 14:01:10 -07001252 AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001253 struct loopfilter *const lf = &cm->lf;
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001254 double cost_restore[RESTORE_TYPES];
1255 double *tile_cost[RESTORE_SWITCHABLE_TYPES];
1256 double best_cost_restore;
1257 RestorationType r, best_restore;
1258
Debargha Mukherjee5cd2ab92016-09-08 15:15:17 -07001259 const int ntiles =
1260 av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001261
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001262 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++)
1263 tile_cost[r] = (double *)aom_malloc(sizeof(*tile_cost[0]) * ntiles);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001264
1265 lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness;
1266
1267 if (method == LPF_PICK_MINIMAL_LPF && lf->filter_level) {
1268 lf->filter_level = 0;
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001269 cm->rst_info[0].frame_restoration_type = RESTORE_NONE;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001270 } else if (method >= LPF_PICK_FROM_Q) {
1271 const int min_filter_level = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -07001272 const int max_filter_level = av1_get_max_filter_level(cpi);
1273 const int q = av1_ac_quant(cm->base_qindex, 0, cm->bit_depth);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001274// These values were determined by linear fitting the result of the
1275// searched level, filt_guess = q * 0.316206 + 3.87252
Yaowu Xuf883b422016-08-30 14:01:10 -07001276#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001277 int filt_guess;
1278 switch (cm->bit_depth) {
Yaowu Xuf883b422016-08-30 14:01:10 -07001279 case AOM_BITS_8:
Yaowu Xuc27fc142016-08-22 16:08:15 -07001280 filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 1015158, 18);
1281 break;
Yaowu Xuf883b422016-08-30 14:01:10 -07001282 case AOM_BITS_10:
Yaowu Xuc27fc142016-08-22 16:08:15 -07001283 filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 4060632, 20);
1284 break;
Yaowu Xuf883b422016-08-30 14:01:10 -07001285 case AOM_BITS_12:
Yaowu Xuc27fc142016-08-22 16:08:15 -07001286 filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 16242526, 22);
1287 break;
1288 default:
1289 assert(0 &&
Yaowu Xuf883b422016-08-30 14:01:10 -07001290 "bit_depth should be AOM_BITS_8, AOM_BITS_10 "
1291 "or AOM_BITS_12");
Yaowu Xuc27fc142016-08-22 16:08:15 -07001292 return;
1293 }
1294#else
1295 int filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 1015158, 18);
Yaowu Xuf883b422016-08-30 14:01:10 -07001296#endif // CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001297 if (cm->frame_type == KEY_FRAME) filt_guess -= 4;
1298 lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001299 } else {
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001300 lf->filter_level =
1301 av1_search_filter_level(src, cpi, method == LPF_PICK_FROM_SUBIMAGE,
1302 &cost_restore[RESTORE_NONE]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001303 }
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001304 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; ++r) {
David Barker9666e752016-12-08 11:25:47 +00001305 cost_restore[r] = search_restore_fun[r](
1306 src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001307 &cm->rst_info[0], tile_cost[r], &cpi->trial_frame_rst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001308 }
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001309 cost_restore[RESTORE_SWITCHABLE] = search_switchable_restoration(
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001310 cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, &cm->rst_info[0],
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001311 tile_cost);
1312
1313 best_cost_restore = DBL_MAX;
1314 best_restore = 0;
1315 for (r = 0; r < RESTORE_TYPES; ++r) {
1316 if (cost_restore[r] < best_cost_restore) {
1317 best_restore = r;
1318 best_cost_restore = cost_restore[r];
1319 }
1320 }
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001321 cm->rst_info[0].frame_restoration_type = best_restore;
1322
1323 // Color components
1324 search_wiener_uv(src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE,
1325 AOM_PLANE_U, &cm->rst_info[AOM_PLANE_U],
1326 &cpi->trial_frame_rst);
1327 search_wiener_uv(src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE,
1328 AOM_PLANE_V, &cm->rst_info[AOM_PLANE_V],
1329 &cpi->trial_frame_rst);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001330 /*
Debargha Mukherjee09ad6d82017-01-06 13:02:57 -08001331 printf("Frame %d/%d restore types: %d %d %d\n",
1332 cm->current_video_frame, cm->show_frame,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001333 cm->rst_info[0].frame_restoration_type,
1334 cm->rst_info[1].frame_restoration_type,
1335 cm->rst_info[2].frame_restoration_type);
Debargha Mukherjee0e67b252016-12-08 09:22:44 -08001336 printf("Frame %d/%d frame_restore_type %d : %f %f %f %f %f\n",
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001337 cm->current_video_frame, cm->show_frame,
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001338 cm->rst_info[0].frame_restoration_type, cost_restore[0],
1339 cost_restore[1],
Debargha Mukherjee0e67b252016-12-08 09:22:44 -08001340 cost_restore[2], cost_restore[3], cost_restore[4]);
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001341 */
Debargha Mukherjeea43a2d92017-01-03 15:14:57 -08001342
Debargha Mukherjee5d89a632016-09-17 13:16:58 -07001343 for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) aom_free(tile_cost[r]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001344}