blob: 12f07de69414298766ce5f32902a1b1006b3a737 [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xu9c01aa12016-09-01 14:32:49 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xu9c01aa12016-09-01 14:32:49 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Yaowu Xuc27fc142016-08-22 16:08:15 -070010 */
11
12#include <assert.h>
13#include <limits.h>
14
Yaowu Xuf883b422016-08-30 14:01:10 -070015#include "./aom_scale_rtcd.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070016
Yaowu Xuf883b422016-08-30 14:01:10 -070017#include "aom_dsp/aom_dsp_common.h"
Cheng Chenf572cd32017-08-25 18:34:51 -070018#include "aom_dsp/psnr.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070019#include "aom_mem/aom_mem.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070020#include "aom_ports/mem.h"
21
Tom Finegan17ce8b12017-02-08 12:46:31 -080022#include "av1/common/av1_loopfilter.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070023#include "av1/common/onyxc_int.h"
24#include "av1/common/quant_common.h"
25
Tom Finegan17ce8b12017-02-08 12:46:31 -080026#include "av1/encoder/av1_quantize.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070027#include "av1/encoder/encoder.h"
28#include "av1/encoder/picklpf.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070029
Cheng Chen765e34e2017-12-11 11:43:35 -080030#if CONFIG_LPF_SB && !CONFIG_LOOPFILTER_LEVEL
Cheng Chenf572cd32017-08-25 18:34:51 -070031#if CONFIG_HIGHBITDEPTH
Cheng Chenf89ca3e2017-09-07 14:47:47 -070032static int compute_sb_y_sse_highbd(const YV12_BUFFER_CONFIG *src,
33 const YV12_BUFFER_CONFIG *frame,
34 AV1_COMMON *const cm, int mi_row,
35 int mi_col) {
36 int sse = 0;
Cheng Chen5589d712017-09-05 12:03:25 -070037 const int mi_row_start = AOMMAX(0, mi_row - FILT_BOUNDARY_MI_OFFSET);
38 const int mi_col_start = AOMMAX(0, mi_col - FILT_BOUNDARY_MI_OFFSET);
39 const int mi_row_range = mi_row - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
40 const int mi_col_range = mi_col - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
41 const int mi_row_end = AOMMIN(mi_row_range, cm->mi_rows);
42 const int mi_col_end = AOMMIN(mi_col_range, cm->mi_cols);
43
44 const int row = mi_row_start * MI_SIZE;
45 const int col = mi_col_start * MI_SIZE;
Cheng Chenf572cd32017-08-25 18:34:51 -070046 const uint16_t *src_y =
47 CONVERT_TO_SHORTPTR(src->y_buffer) + row * src->y_stride + col;
48 const uint16_t *frame_y =
49 CONVERT_TO_SHORTPTR(frame->y_buffer) + row * frame->y_stride + col;
Cheng Chen5589d712017-09-05 12:03:25 -070050 const int row_end = (mi_row_end - mi_row_start) * MI_SIZE;
51 const int col_end = (mi_col_end - mi_col_start) * MI_SIZE;
52
Cheng Chenf572cd32017-08-25 18:34:51 -070053 int x, y;
Cheng Chen5589d712017-09-05 12:03:25 -070054 for (y = 0; y < row_end; ++y) {
55 for (x = 0; x < col_end; ++x) {
Cheng Chenf572cd32017-08-25 18:34:51 -070056 const int diff = src_y[x] - frame_y[x];
57 sse += diff * diff;
58 }
59 src_y += src->y_stride;
60 frame_y += frame->y_stride;
61 }
62 return sse;
63}
64#endif
65
Cheng Chenf89ca3e2017-09-07 14:47:47 -070066static int compute_sb_y_sse(const YV12_BUFFER_CONFIG *src,
67 const YV12_BUFFER_CONFIG *frame,
68 AV1_COMMON *const cm, int mi_row, int mi_col) {
69 int sse = 0;
Cheng Chen5589d712017-09-05 12:03:25 -070070 const int mi_row_start = AOMMAX(0, mi_row - FILT_BOUNDARY_MI_OFFSET);
71 const int mi_col_start = AOMMAX(0, mi_col - FILT_BOUNDARY_MI_OFFSET);
72 const int mi_row_range = mi_row - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
73 const int mi_col_range = mi_col - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
74 const int mi_row_end = AOMMIN(mi_row_range, cm->mi_rows);
75 const int mi_col_end = AOMMIN(mi_col_range, cm->mi_cols);
76
77 const int row = mi_row_start * MI_SIZE;
78 const int col = mi_col_start * MI_SIZE;
Cheng Chenf572cd32017-08-25 18:34:51 -070079 const uint8_t *src_y = src->y_buffer + row * src->y_stride + col;
80 const uint8_t *frame_y = frame->y_buffer + row * frame->y_stride + col;
Cheng Chen5589d712017-09-05 12:03:25 -070081 const int row_end = (mi_row_end - mi_row_start) * MI_SIZE;
82 const int col_end = (mi_col_end - mi_col_start) * MI_SIZE;
83
Cheng Chenf572cd32017-08-25 18:34:51 -070084 int x, y;
Cheng Chen5589d712017-09-05 12:03:25 -070085 for (y = 0; y < row_end; ++y) {
86 for (x = 0; x < col_end; ++x) {
Cheng Chenf572cd32017-08-25 18:34:51 -070087 const int diff = src_y[x] - frame_y[x];
88 sse += diff * diff;
89 }
90 src_y += src->y_stride;
91 frame_y += frame->y_stride;
92 }
93 return sse;
94}
95#endif // CONFIG_LPF_SB
96
97#if !CONFIG_LPF_SB
Cheng Chen9efbaf92017-07-27 14:09:59 -070098static void yv12_copy_plane(const YV12_BUFFER_CONFIG *src_bc,
99 YV12_BUFFER_CONFIG *dst_bc, int plane) {
100 switch (plane) {
101 case 0: aom_yv12_copy_y(src_bc, dst_bc); break;
102 case 1: aom_yv12_copy_u(src_bc, dst_bc); break;
103 case 2: aom_yv12_copy_v(src_bc, dst_bc); break;
104 default: assert(plane >= 0 && plane <= 2); break;
105 }
106}
Cheng Chenf572cd32017-08-25 18:34:51 -0700107#endif // CONFIG_LPF_SB
Cheng Chen9efbaf92017-07-27 14:09:59 -0700108
Yaowu Xuf883b422016-08-30 14:01:10 -0700109int av1_get_max_filter_level(const AV1_COMP *cpi) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700110 if (cpi->oxcf.pass == 2) {
111 return cpi->twopass.section_intra_rating > 8 ? MAX_LOOP_FILTER * 3 / 4
112 : MAX_LOOP_FILTER;
113 } else {
114 return MAX_LOOP_FILTER;
115 }
116}
117
Cheng Chen765e34e2017-12-11 11:43:35 -0800118#if CONFIG_LPF_SB && !CONFIG_LOOPFILTER_LEVEL
Cheng Chenf572cd32017-08-25 18:34:51 -0700119// TODO(chengchen): reduce memory usage by copy superblock instead of frame
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700120static int try_filter_superblock(const YV12_BUFFER_CONFIG *sd,
121 AV1_COMP *const cpi, int filt_level,
122 int partial_frame, int mi_row, int mi_col) {
Cheng Chenf572cd32017-08-25 18:34:51 -0700123 AV1_COMMON *const cm = &cpi->common;
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700124 int filt_err;
Cheng Chenf572cd32017-08-25 18:34:51 -0700125
Cheng Chenf572cd32017-08-25 18:34:51 -0700126 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level, 1,
127 partial_frame, mi_row, mi_col);
Cheng Chenf572cd32017-08-25 18:34:51 -0700128
129#if CONFIG_HIGHBITDEPTH
130 if (cm->use_highbitdepth) {
Cheng Chen5589d712017-09-05 12:03:25 -0700131 filt_err =
132 compute_sb_y_sse_highbd(sd, cm->frame_to_show, cm, mi_row, mi_col);
Cheng Chenf572cd32017-08-25 18:34:51 -0700133 } else {
Cheng Chen5589d712017-09-05 12:03:25 -0700134 filt_err = compute_sb_y_sse(sd, cm->frame_to_show, cm, mi_row, mi_col);
Cheng Chenf572cd32017-08-25 18:34:51 -0700135 }
136#else
Cheng Chen5589d712017-09-05 12:03:25 -0700137 filt_err = compute_sb_y_sse(sd, cm->frame_to_show, cm, mi_row, mi_col);
Cheng Chenf572cd32017-08-25 18:34:51 -0700138#endif // CONFIG_HIGHBITDEPTH
139
Cheng Chenc7855b12017-09-05 10:49:08 -0700140 // TODO(chengchen): Copy the superblock only
Cheng Chenf572cd32017-08-25 18:34:51 -0700141 // Re-instate the unfiltered frame
142 aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
143
144 return filt_err;
145}
146
Cheng Chenebcee0b2017-12-05 12:36:01 -0800147int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
148 int partial_frame, double *best_cost_ret,
149 int mi_row, int mi_col, int last_lvl) {
Cheng Chen5589d712017-09-05 12:03:25 -0700150 assert(partial_frame == 1);
151 assert(last_lvl >= 0);
152
Cheng Chenf572cd32017-08-25 18:34:51 -0700153 const AV1_COMMON *const cm = &cpi->common;
Cheng Chenf572cd32017-08-25 18:34:51 -0700154 MACROBLOCK *x = &cpi->td.mb;
155
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700156 int min_filter_level = AOMMAX(0, last_lvl - MAX_LPF_OFFSET);
157 int max_filter_level =
158 AOMMIN(av1_get_max_filter_level(cpi), last_lvl + MAX_LPF_OFFSET);
159
160 // search a larger range for the start superblock
161 if (mi_row == 0 && mi_col == 0) {
162 min_filter_level = 0;
163 max_filter_level = av1_get_max_filter_level(cpi);
164 }
165
Cheng Chen5589d712017-09-05 12:03:25 -0700166 // TODO(chengchen): Copy for superblock only
Cheng Chenc7855b12017-09-05 10:49:08 -0700167 // Make a copy of the unfiltered / processed recon buffer
Cheng Chenf572cd32017-08-25 18:34:51 -0700168 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
169
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700170 int estimate_err =
Cheng Chen5589d712017-09-05 12:03:25 -0700171 try_filter_superblock(sd, cpi, last_lvl, partial_frame, mi_row, mi_col);
Cheng Chenc7855b12017-09-05 10:49:08 -0700172
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700173 int best_err = estimate_err;
174 int filt_best = last_lvl;
175
Cheng Chena4b27de2017-08-31 16:05:19 -0700176 int i;
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700177 for (i = min_filter_level; i <= max_filter_level; i += LPF_STEP) {
Cheng Chenc7855b12017-09-05 10:49:08 -0700178 if (i == last_lvl) continue;
179
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700180 int filt_err =
Cheng Chen5589d712017-09-05 12:03:25 -0700181 try_filter_superblock(sd, cpi, i, partial_frame, mi_row, mi_col);
182
Cheng Chena4b27de2017-08-31 16:05:19 -0700183 if (filt_err < best_err) {
184 best_err = filt_err;
185 filt_best = i;
Cheng Chenf572cd32017-08-25 18:34:51 -0700186 }
187 }
188
Cheng Chenc7855b12017-09-05 10:49:08 -0700189 // If previous sb filter level has similar filtering performance as current
190 // best filter level, use previous level such that we can only send one bit
191 // to indicate current filter level is the same as the previous.
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700192 int threshold = 400;
Cheng Chen5589d712017-09-05 12:03:25 -0700193
194 // ratio = the filtering area / a superblock size
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700195 int ratio = 1;
Cheng Chen5589d712017-09-05 12:03:25 -0700196 if (mi_row + MAX_MIB_SIZE > cm->mi_rows) {
197 ratio *= (cm->mi_rows - mi_row);
198 } else {
199 if (mi_row == 0) {
200 ratio *= (MAX_MIB_SIZE - FILT_BOUNDARY_MI_OFFSET);
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700201 } else {
202 ratio *= MAX_MIB_SIZE;
Cheng Chen5589d712017-09-05 12:03:25 -0700203 }
204 }
205 if (mi_col + MAX_MIB_SIZE > cm->mi_cols) {
206 ratio *= (cm->mi_cols - mi_col);
207 } else {
208 if (mi_col == 0) {
209 ratio *= (MAX_MIB_SIZE - FILT_BOUNDARY_MI_OFFSET);
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700210 } else {
211 ratio *= MAX_MIB_SIZE;
Cheng Chen5589d712017-09-05 12:03:25 -0700212 }
213 }
214 threshold = threshold * ratio / (MAX_MIB_SIZE * MAX_MIB_SIZE);
215
Cheng Chenf89ca3e2017-09-07 14:47:47 -0700216 const int diff = abs(estimate_err - best_err);
217
218 const int percent_thresh = (int)((double)estimate_err * 0.01);
219 threshold = AOMMAX(threshold, percent_thresh);
220 if (diff < threshold) {
Cheng Chenc7855b12017-09-05 10:49:08 -0700221 best_err = estimate_err;
222 filt_best = last_lvl;
223 }
224
Cheng Chen15f6b862017-09-08 16:56:07 -0700225 // Compute rdcost to determine whether to reuse previous filter lvl
226 if (filt_best != last_lvl) {
227 }
228
Cheng Chenf572cd32017-08-25 18:34:51 -0700229 if (best_cost_ret) *best_cost_ret = RDCOST_DBL(x->rdmult, 0, best_err);
230 return filt_best;
231}
232
Cheng Chen765e34e2017-12-11 11:43:35 -0800233#elif !CONFIG_LPF_SB // CONFIG_LPF_SB
Yaowu Xuc27fc142016-08-22 16:08:15 -0700234static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
Yaowu Xuf883b422016-08-30 14:01:10 -0700235 AV1_COMP *const cpi, int filt_level,
Cheng Chene94df5c2017-07-19 17:25:33 -0700236 int partial_frame
Cheng Chen13fc8192017-08-19 11:49:28 -0700237#if CONFIG_LOOPFILTER_LEVEL
Cheng Chene94df5c2017-07-19 17:25:33 -0700238 ,
Cheng Chen179479f2017-08-04 10:56:39 -0700239 int plane, int dir
Cheng Chene94df5c2017-07-19 17:25:33 -0700240#endif
241 ) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700242 AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700243 int64_t filt_err;
244
Cheng Chen13fc8192017-08-19 11:49:28 -0700245#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen9efbaf92017-07-27 14:09:59 -0700246 assert(plane >= 0 && plane <= 2);
Cheng Chen179479f2017-08-04 10:56:39 -0700247 int filter_level[2] = { filt_level, filt_level };
248 if (plane == 0 && dir == 0) filter_level[1] = cm->lf.filter_level[1];
249 if (plane == 0 && dir == 1) filter_level[0] = cm->lf.filter_level[0];
250
251 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd,
252 filter_level[0], filter_level[1], plane, partial_frame);
Cheng Chene94df5c2017-07-19 17:25:33 -0700253#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700254 av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level, 1,
255 partial_frame);
Cheng Chen13fc8192017-08-19 11:49:28 -0700256#endif // CONFIG_LOOPFILTER_LEVEL
Yaowu Xuc27fc142016-08-22 16:08:15 -0700257
Cheng Chen9efbaf92017-07-27 14:09:59 -0700258 int highbd = 0;
259#if CONFIG_HIGHBITDEPTH
260 highbd = cm->use_highbitdepth;
261#endif // CONFIG_HIGHBITDEPTH
262
Cheng Chen13fc8192017-08-19 11:49:28 -0700263#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen9efbaf92017-07-27 14:09:59 -0700264 filt_err = aom_get_sse_plane(sd, cm->frame_to_show, plane, highbd);
Cheng Chene94df5c2017-07-19 17:25:33 -0700265
266 // Re-instate the unfiltered frame
Cheng Chen9efbaf92017-07-27 14:09:59 -0700267 yv12_copy_plane(&cpi->last_frame_uf, cm->frame_to_show, plane);
Cheng Chene94df5c2017-07-19 17:25:33 -0700268#else
Cheng Chen9efbaf92017-07-27 14:09:59 -0700269 filt_err = aom_get_sse_plane(sd, cm->frame_to_show, 0, highbd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700270
271 // Re-instate the unfiltered frame
Cheng Chen9efbaf92017-07-27 14:09:59 -0700272 yv12_copy_plane(&cpi->last_frame_uf, cm->frame_to_show, 0);
Cheng Chen13fc8192017-08-19 11:49:28 -0700273#endif // CONFIG_LOOPFILTER_LEVEL
Yaowu Xuc27fc142016-08-22 16:08:15 -0700274
275 return filt_err;
276}
277
Cheng Chen1545bdb2017-09-05 16:32:12 -0700278static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
279 int partial_frame, double *best_cost_ret
Cheng Chen13fc8192017-08-19 11:49:28 -0700280#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen1545bdb2017-09-05 16:32:12 -0700281 ,
282 int plane, int dir
Cheng Chene94df5c2017-07-19 17:25:33 -0700283#endif
Cheng Chen1545bdb2017-09-05 16:32:12 -0700284 ) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700285 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700286 const struct loopfilter *const lf = &cm->lf;
287 const int min_filter_level = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -0700288 const int max_filter_level = av1_get_max_filter_level(cpi);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700289 int filt_direction = 0;
290 int64_t best_err;
291 int filt_best;
292 MACROBLOCK *x = &cpi->td.mb;
293
Cheng Chene94df5c2017-07-19 17:25:33 -0700294// Start the search at the previous frame filter level unless it is now out of
295// range.
Cheng Chen13fc8192017-08-19 11:49:28 -0700296#if CONFIG_LOOPFILTER_LEVEL
Cheng Chene94df5c2017-07-19 17:25:33 -0700297 int lvl;
298 switch (plane) {
Cheng Chen179479f2017-08-04 10:56:39 -0700299 case 0: lvl = (dir == 1) ? lf->filter_level[1] : lf->filter_level[0]; break;
Cheng Chene94df5c2017-07-19 17:25:33 -0700300 case 1: lvl = lf->filter_level_u; break;
301 case 2: lvl = lf->filter_level_v; break;
Cheng Chen9efbaf92017-07-27 14:09:59 -0700302 default: assert(plane >= 0 && plane <= 2); return 0;
Cheng Chene94df5c2017-07-19 17:25:33 -0700303 }
304 int filt_mid = clamp(lvl, min_filter_level, max_filter_level);
305#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700306 int filt_mid = clamp(lf->filter_level, min_filter_level, max_filter_level);
Cheng Chen13fc8192017-08-19 11:49:28 -0700307#endif // CONFIG_LOOPFILTER_LEVEL
Yaowu Xuc27fc142016-08-22 16:08:15 -0700308 int filter_step = filt_mid < 16 ? 4 : filt_mid / 4;
309 // Sum squared error at each filter level
310 int64_t ss_err[MAX_LOOP_FILTER + 1];
311
312 // Set each entry to -1
313 memset(ss_err, 0xFF, sizeof(ss_err));
314
Cheng Chen13fc8192017-08-19 11:49:28 -0700315#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen9efbaf92017-07-27 14:09:59 -0700316 yv12_copy_plane(cm->frame_to_show, &cpi->last_frame_uf, plane);
Cheng Chene94df5c2017-07-19 17:25:33 -0700317#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700318 // Make a copy of the unfiltered / processed recon buffer
Yaowu Xuf883b422016-08-30 14:01:10 -0700319 aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
Cheng Chen13fc8192017-08-19 11:49:28 -0700320#endif // CONFIG_LOOPFILTER_LEVEL
Yaowu Xuc27fc142016-08-22 16:08:15 -0700321
Cheng Chen13fc8192017-08-19 11:49:28 -0700322#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen179479f2017-08-04 10:56:39 -0700323 best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame, plane, dir);
Cheng Chene94df5c2017-07-19 17:25:33 -0700324#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700325 best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame);
Cheng Chen13fc8192017-08-19 11:49:28 -0700326#endif // CONFIG_LOOPFILTER_LEVEL
Yaowu Xuc27fc142016-08-22 16:08:15 -0700327 filt_best = filt_mid;
328 ss_err[filt_mid] = best_err;
329
330 while (filter_step > 0) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700331 const int filt_high = AOMMIN(filt_mid + filter_step, max_filter_level);
332 const int filt_low = AOMMAX(filt_mid - filter_step, min_filter_level);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700333
334 // Bias against raising loop filter in favor of lowering it.
335 int64_t bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
336
337 if ((cpi->oxcf.pass == 2) && (cpi->twopass.section_intra_rating < 20))
338 bias = (bias * cpi->twopass.section_intra_rating) / 20;
339
340 // yx, bias less for large block size
341 if (cm->tx_mode != ONLY_4X4) bias >>= 1;
342
343 if (filt_direction <= 0 && filt_low != filt_mid) {
344 // Get Low filter error score
345 if (ss_err[filt_low] < 0) {
Cheng Chen13fc8192017-08-19 11:49:28 -0700346#if CONFIG_LOOPFILTER_LEVEL
Cheng Chene94df5c2017-07-19 17:25:33 -0700347 ss_err[filt_low] =
Cheng Chen179479f2017-08-04 10:56:39 -0700348 try_filter_frame(sd, cpi, filt_low, partial_frame, plane, dir);
Cheng Chene94df5c2017-07-19 17:25:33 -0700349#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700350 ss_err[filt_low] = try_filter_frame(sd, cpi, filt_low, partial_frame);
Cheng Chen13fc8192017-08-19 11:49:28 -0700351#endif // CONFIG_LOOPFILTER_LEVEL
Yaowu Xuc27fc142016-08-22 16:08:15 -0700352 }
353 // If value is close to the best so far then bias towards a lower loop
354 // filter value.
355 if (ss_err[filt_low] < (best_err + bias)) {
356 // Was it actually better than the previous best?
357 if (ss_err[filt_low] < best_err) {
358 best_err = ss_err[filt_low];
359 }
360 filt_best = filt_low;
361 }
362 }
363
364 // Now look at filt_high
365 if (filt_direction >= 0 && filt_high != filt_mid) {
366 if (ss_err[filt_high] < 0) {
Cheng Chen13fc8192017-08-19 11:49:28 -0700367#if CONFIG_LOOPFILTER_LEVEL
Cheng Chene94df5c2017-07-19 17:25:33 -0700368 ss_err[filt_high] =
Cheng Chen179479f2017-08-04 10:56:39 -0700369 try_filter_frame(sd, cpi, filt_high, partial_frame, plane, dir);
Cheng Chene94df5c2017-07-19 17:25:33 -0700370#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700371 ss_err[filt_high] = try_filter_frame(sd, cpi, filt_high, partial_frame);
Cheng Chen13fc8192017-08-19 11:49:28 -0700372#endif // CONFIG_LOOPFILTER_LEVEL
Yaowu Xuc27fc142016-08-22 16:08:15 -0700373 }
374 // If value is significantly better than previous best, bias added against
375 // raising filter value
376 if (ss_err[filt_high] < (best_err - bias)) {
377 best_err = ss_err[filt_high];
378 filt_best = filt_high;
379 }
380 }
381
382 // Half the step distance if the best filter value was the same as last time
383 if (filt_best == filt_mid) {
384 filter_step /= 2;
385 filt_direction = 0;
386 } else {
387 filt_direction = (filt_best < filt_mid) ? -1 : 1;
388 filt_mid = filt_best;
389 }
390 }
391
392 // Update best error
393 best_err = ss_err[filt_best];
394
Urvang Joshi70006e42017-06-14 16:08:55 -0700395 if (best_cost_ret) *best_cost_ret = RDCOST_DBL(x->rdmult, 0, best_err);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700396 return filt_best;
397}
Cheng Chenf572cd32017-08-25 18:34:51 -0700398#endif // CONFIG_LPF_SB
Yaowu Xuc27fc142016-08-22 16:08:15 -0700399
Yaowu Xuf883b422016-08-30 14:01:10 -0700400void av1_pick_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
401 LPF_PICK_METHOD method) {
402 AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700403 struct loopfilter *const lf = &cm->lf;
Cheng Chen765e34e2017-12-11 11:43:35 -0800404 (void)sd;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700405
406 lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness;
407
Cheng Chen179479f2017-08-04 10:56:39 -0700408 if (method == LPF_PICK_MINIMAL_LPF) {
Cheng Chen13fc8192017-08-19 11:49:28 -0700409#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen179479f2017-08-04 10:56:39 -0700410 lf->filter_level[0] = 0;
411 lf->filter_level[1] = 0;
412#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700413 lf->filter_level = 0;
Cheng Chen179479f2017-08-04 10:56:39 -0700414#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700415 } else if (method >= LPF_PICK_FROM_Q) {
416 const int min_filter_level = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -0700417 const int max_filter_level = av1_get_max_filter_level(cpi);
Monty Montgomery60f2a222017-11-01 19:48:38 -0400418 const int q = av1_ac_quant_Q3(cm->base_qindex, 0, cm->bit_depth);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700419// These values were determined by linear fitting the result of the
Alexander Bokovac504f72017-10-10 13:15:13 -0700420// searched level for 8 bit depth:
421// Keyframes: filt_guess = q * 0.06699 - 1.60817
422// Other frames: filt_guess = q * 0.02295 + 2.48225
423//
424// And high bit depth separately:
425// filt_guess = q * 0.316206 + 3.87252
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200426#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700427 int filt_guess;
428 switch (cm->bit_depth) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700429 case AOM_BITS_8:
Alexander Bokovac504f72017-10-10 13:15:13 -0700430 filt_guess = (cm->frame_type == KEY_FRAME)
431 ? ROUND_POWER_OF_TWO(q * 17563 - 421574, 18)
432 : ROUND_POWER_OF_TWO(q * 6017 + 650707, 18);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700433 break;
Yaowu Xuf883b422016-08-30 14:01:10 -0700434 case AOM_BITS_10:
Yaowu Xuc27fc142016-08-22 16:08:15 -0700435 filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 4060632, 20);
436 break;
Yaowu Xuf883b422016-08-30 14:01:10 -0700437 case AOM_BITS_12:
Yaowu Xuc27fc142016-08-22 16:08:15 -0700438 filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 16242526, 22);
439 break;
440 default:
441 assert(0 &&
Yaowu Xuf883b422016-08-30 14:01:10 -0700442 "bit_depth should be AOM_BITS_8, AOM_BITS_10 "
443 "or AOM_BITS_12");
Yaowu Xuc27fc142016-08-22 16:08:15 -0700444 return;
445 }
446#else
Alexander Bokovac504f72017-10-10 13:15:13 -0700447 int filt_guess = (cm->frame_type == KEY_FRAME)
448 ? ROUND_POWER_OF_TWO(q * 17563 - 421574, 18)
449 : ROUND_POWER_OF_TWO(q * 6017 + 650707, 18);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200450#endif // CONFIG_HIGHBITDEPTH
Alexander Bokovac504f72017-10-10 13:15:13 -0700451 if (cm->bit_depth != AOM_BITS_8 && cm->frame_type == KEY_FRAME)
452 filt_guess -= 4;
Cheng Chen13fc8192017-08-19 11:49:28 -0700453#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen765e34e2017-12-11 11:43:35 -0800454 // TODO(chengchen): retrain the model for Y, U, V filter levels
Cheng Chen179479f2017-08-04 10:56:39 -0700455 lf->filter_level[0] = clamp(filt_guess, min_filter_level, max_filter_level);
456 lf->filter_level[1] = clamp(filt_guess, min_filter_level, max_filter_level);
Cheng Chen765e34e2017-12-11 11:43:35 -0800457 lf->filter_level_u = clamp(filt_guess, min_filter_level, max_filter_level);
458 lf->filter_level_v = clamp(filt_guess, min_filter_level, max_filter_level);
Cheng Chen179479f2017-08-04 10:56:39 -0700459#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700460 lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level);
Cheng Chen179479f2017-08-04 10:56:39 -0700461#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700462 } else {
Cheng Chen765e34e2017-12-11 11:43:35 -0800463#if CONFIG_LPF_SB && !CONFIG_LOOPFILTER_LEVEL
Cheng Chenf572cd32017-08-25 18:34:51 -0700464 int mi_row, mi_col;
Cheng Chen5589d712017-09-05 12:03:25 -0700465 // TODO(chengchen): init last_lvl using previous frame's info?
Cheng Chenf572cd32017-08-25 18:34:51 -0700466 int last_lvl = 0;
Cheng Chen5589d712017-09-05 12:03:25 -0700467 // TODO(chengchen): if the frame size makes the last superblock very small,
468 // consider merge it to the previous superblock to save bits.
469 // Example, if frame size 1080x720, then in the last row of superblock,
470 // there're (FILT_BOUNDAR_OFFSET + 16) pixels.
Cheng Chenf572cd32017-08-25 18:34:51 -0700471 for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MAX_MIB_SIZE) {
472 for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
Cheng Chenebcee0b2017-12-05 12:36:01 -0800473#if CONFIG_LPF_SB
474 int lvl =
475 av1_search_filter_level(sd, cpi, 1, NULL, mi_row, mi_col, last_lvl);
476#else
Cheng Chenf572cd32017-08-25 18:34:51 -0700477 int lvl =
478 search_filter_level(sd, cpi, 1, NULL, mi_row, mi_col, last_lvl);
Cheng Chenebcee0b2017-12-05 12:36:01 -0800479#endif
Cheng Chen5589d712017-09-05 12:03:25 -0700480
481 av1_loop_filter_sb_level_init(cm, mi_row, mi_col, lvl);
Cheng Chena4b27de2017-08-31 16:05:19 -0700482
483 // For the superblock at row start, its previous filter level should be
484 // the one above it, not the one at the end of last row
485 if (mi_col + MAX_MIB_SIZE >= cm->mi_cols) {
486 last_lvl = cm->mi_grid_visible[mi_row * cm->mi_stride]->mbmi.filt_lvl;
487 } else {
488 last_lvl = lvl;
489 }
Cheng Chenf572cd32017-08-25 18:34:51 -0700490 }
491 }
Cheng Chen765e34e2017-12-11 11:43:35 -0800492#elif !CONFIG_LPF_SB // !CONFIG_LPF_SB
Cheng Chen13fc8192017-08-19 11:49:28 -0700493#if CONFIG_LOOPFILTER_LEVEL
Cheng Chen1545bdb2017-09-05 16:32:12 -0700494 lf->filter_level[0] = lf->filter_level[1] = search_filter_level(
Cheng Chen179479f2017-08-04 10:56:39 -0700495 sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 2);
Cheng Chen1545bdb2017-09-05 16:32:12 -0700496 lf->filter_level[0] = search_filter_level(
Cheng Chen179479f2017-08-04 10:56:39 -0700497 sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 0);
Cheng Chen1545bdb2017-09-05 16:32:12 -0700498 lf->filter_level[1] = search_filter_level(
Cheng Chen179479f2017-08-04 10:56:39 -0700499 sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 1);
500
Cheng Chen1545bdb2017-09-05 16:32:12 -0700501 lf->filter_level_u = search_filter_level(
Cheng Chen179479f2017-08-04 10:56:39 -0700502 sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 1, 0);
Cheng Chen1545bdb2017-09-05 16:32:12 -0700503 lf->filter_level_v = search_filter_level(
Cheng Chen179479f2017-08-04 10:56:39 -0700504 sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 2, 0);
Cheng Chene94df5c2017-07-19 17:25:33 -0700505#else
Cheng Chen1545bdb2017-09-05 16:32:12 -0700506 lf->filter_level =
507 search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL);
Cheng Chen13fc8192017-08-19 11:49:28 -0700508#endif // CONFIG_LOOPFILTER_LEVEL
Cheng Chenf572cd32017-08-25 18:34:51 -0700509#endif // CONFIG_LPF_SB
Yaowu Xuc27fc142016-08-22 16:08:15 -0700510 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700511}