/src/aom/av1/encoder/picklpf.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
10 | | */ |
11 | | |
12 | | #include <assert.h> |
13 | | #include <limits.h> |
14 | | |
15 | | #include "config/aom_scale_rtcd.h" |
16 | | |
17 | | #include "aom_dsp/aom_dsp_common.h" |
18 | | #include "aom_dsp/psnr.h" |
19 | | #include "aom_mem/aom_mem.h" |
20 | | #include "aom_ports/mem.h" |
21 | | |
22 | | #include "av1/common/av1_common_int.h" |
23 | | #include "av1/common/av1_loopfilter.h" |
24 | | #include "av1/common/quant_common.h" |
25 | | |
26 | | #include "av1/encoder/av1_quantize.h" |
27 | | #include "av1/encoder/encoder.h" |
28 | | #include "av1/encoder/picklpf.h" |
29 | | |
30 | | static void yv12_copy_plane(const YV12_BUFFER_CONFIG *src_bc, |
31 | 16.3k | YV12_BUFFER_CONFIG *dst_bc, int plane) { |
32 | 16.3k | switch (plane) { |
33 | 5.27k | case 0: aom_yv12_copy_y(src_bc, dst_bc); break; |
34 | 5.51k | case 1: aom_yv12_copy_u(src_bc, dst_bc); break; |
35 | 5.51k | case 2: aom_yv12_copy_v(src_bc, dst_bc); break; |
36 | 0 | default: assert(plane >= 0 && plane <= 2); break; |
37 | 16.3k | } |
38 | 16.3k | } |
39 | | |
40 | 3.11k | int av1_get_max_filter_level(const AV1_COMP *cpi) { |
41 | 3.11k | if (is_stat_consumption_stage_twopass(cpi)) { |
42 | 0 | return cpi->ppi->twopass.section_intra_rating > 8 ? MAX_LOOP_FILTER * 3 / 4 |
43 | 0 | : MAX_LOOP_FILTER; |
44 | 3.11k | } else { |
45 | 3.11k | return MAX_LOOP_FILTER; |
46 | 3.11k | } |
47 | 3.11k | } |
48 | | |
49 | | static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd, |
50 | | AV1_COMP *const cpi, int filt_level, |
51 | 13.1k | int partial_frame, int plane, int dir) { |
52 | 13.1k | MultiThreadInfo *const mt_info = &cpi->mt_info; |
53 | 13.1k | int num_workers = mt_info->num_mod_workers[MOD_LPF]; |
54 | 13.1k | AV1_COMMON *const cm = &cpi->common; |
55 | 13.1k | int64_t filt_err; |
56 | | |
57 | 13.1k | assert(plane >= 0 && plane <= 2); |
58 | 13.1k | int filter_level[2] = { filt_level, filt_level }; |
59 | 13.1k | if (plane == 0 && dir == 0) filter_level[1] = cm->lf.filter_level[1]; |
60 | 13.1k | if (plane == 0 && dir == 1) filter_level[0] = cm->lf.filter_level[0]; |
61 | | |
62 | | // set base filters for use of av1_get_filter_level when in DELTA_LF mode |
63 | 13.1k | switch (plane) { |
64 | 4.23k | case 0: |
65 | 4.23k | cm->lf.filter_level[0] = filter_level[0]; |
66 | 4.23k | cm->lf.filter_level[1] = filter_level[1]; |
67 | 4.23k | break; |
68 | 4.48k | case 1: cm->lf.filter_level_u = filter_level[0]; break; |
69 | 4.48k | case 2: cm->lf.filter_level_v = filter_level[0]; break; |
70 | 13.1k | } |
71 | | |
72 | 13.1k | av1_loop_filter_frame_mt(&cm->cur_frame->buf, cm, &cpi->td.mb.e_mbd, plane, |
73 | 13.1k | plane + 1, partial_frame, mt_info->workers, |
74 | 13.1k | num_workers, &mt_info->lf_row_sync, 0); |
75 | | |
76 | 13.1k | filt_err = aom_get_sse_plane(sd, &cm->cur_frame->buf, plane, |
77 | 13.1k | cm->seq_params->use_highbitdepth); |
78 | | |
79 | | // Re-instate the unfiltered frame |
80 | 13.1k | yv12_copy_plane(&cpi->last_frame_uf, &cm->cur_frame->buf, plane); |
81 | | |
82 | 13.1k | return filt_err; |
83 | 13.1k | } |
84 | | |
85 | | static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi, |
86 | | int partial_frame, |
87 | | const int *last_frame_filter_level, int plane, |
88 | 3.11k | int dir) { |
89 | 3.11k | const AV1_COMMON *const cm = &cpi->common; |
90 | 3.11k | const int min_filter_level = 0; |
91 | 3.11k | const int max_filter_level = av1_get_max_filter_level(cpi); |
92 | 3.11k | int filt_direction = 0; |
93 | 3.11k | int64_t best_err; |
94 | 3.11k | int filt_best; |
95 | | |
96 | | // Start the search at the previous frame filter level unless it is now out of |
97 | | // range. |
98 | 3.11k | int lvl; |
99 | 3.11k | switch (plane) { |
100 | 1.03k | case 0: |
101 | 1.03k | switch (dir) { |
102 | 1.03k | case 2: |
103 | 1.03k | lvl = (last_frame_filter_level[0] + last_frame_filter_level[1] + 1) >> |
104 | 1.03k | 1; |
105 | 1.03k | break; |
106 | 0 | case 0: |
107 | 0 | case 1: lvl = last_frame_filter_level[dir]; break; |
108 | 0 | default: assert(dir >= 0 && dir <= 2); return 0; |
109 | 1.03k | } |
110 | 1.03k | break; |
111 | 1.03k | case 1: lvl = last_frame_filter_level[2]; break; |
112 | 1.03k | case 2: lvl = last_frame_filter_level[3]; break; |
113 | 0 | default: assert(plane >= 0 && plane <= 2); return 0; |
114 | 3.11k | } |
115 | 3.11k | int filt_mid = clamp(lvl, min_filter_level, max_filter_level); |
116 | 3.11k | int filter_step = filt_mid < 16 ? 4 : filt_mid / 4; |
117 | | // Sum squared error at each filter level |
118 | 3.11k | int64_t ss_err[MAX_LOOP_FILTER + 1]; |
119 | | |
120 | 3.11k | const int use_coarse_search = cpi->sf.lpf_sf.use_coarse_filter_level_search; |
121 | 3.11k | assert(use_coarse_search <= 1); |
122 | 3.11k | static const int min_filter_step_lookup[2] = { 0, 2 }; |
123 | | // min_filter_step_thesh determines the stopping criteria for the search. |
124 | | // The search is terminated when filter_step equals min_filter_step_thesh. |
125 | 3.11k | const int min_filter_step_thesh = min_filter_step_lookup[use_coarse_search]; |
126 | | |
127 | | // Set each entry to -1 |
128 | 3.11k | memset(ss_err, 0xFF, sizeof(ss_err)); |
129 | 3.11k | yv12_copy_plane(&cm->cur_frame->buf, &cpi->last_frame_uf, plane); |
130 | 3.11k | best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame, plane, dir); |
131 | 3.11k | filt_best = filt_mid; |
132 | 3.11k | ss_err[filt_mid] = best_err; |
133 | | |
134 | 12.6k | while (filter_step > min_filter_step_thesh) { |
135 | 9.58k | const int filt_high = AOMMIN(filt_mid + filter_step, max_filter_level); |
136 | 9.58k | const int filt_low = AOMMAX(filt_mid - filter_step, min_filter_level); |
137 | | |
138 | | // Bias against raising loop filter in favor of lowering it. |
139 | 9.58k | int64_t bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; |
140 | | |
141 | 9.58k | if ((is_stat_consumption_stage_twopass(cpi)) && |
142 | 9.58k | (cpi->ppi->twopass.section_intra_rating < 20)) |
143 | 0 | bias = (bias * cpi->ppi->twopass.section_intra_rating) / 20; |
144 | | |
145 | | // yx, bias less for large block size |
146 | 9.58k | if (cm->features.tx_mode != ONLY_4X4) bias >>= 1; |
147 | | |
148 | 9.58k | if (filt_direction <= 0 && filt_low != filt_mid) { |
149 | | // Get Low filter error score |
150 | 502 | if (ss_err[filt_low] < 0) { |
151 | 502 | ss_err[filt_low] = |
152 | 502 | try_filter_frame(sd, cpi, filt_low, partial_frame, plane, dir); |
153 | 502 | } |
154 | | // If value is close to the best so far then bias towards a lower loop |
155 | | // filter value. |
156 | 502 | if (ss_err[filt_low] < (best_err + bias)) { |
157 | | // Was it actually better than the previous best? |
158 | 0 | if (ss_err[filt_low] < best_err) { |
159 | 0 | best_err = ss_err[filt_low]; |
160 | 0 | } |
161 | 0 | filt_best = filt_low; |
162 | 0 | } |
163 | 502 | } |
164 | | |
165 | | // Now look at filt_high |
166 | 9.58k | if (filt_direction >= 0 && filt_high != filt_mid) { |
167 | 9.58k | if (ss_err[filt_high] < 0) { |
168 | 9.58k | ss_err[filt_high] = |
169 | 9.58k | try_filter_frame(sd, cpi, filt_high, partial_frame, plane, dir); |
170 | 9.58k | } |
171 | | // If value is significantly better than previous best, bias added against |
172 | | // raising filter value |
173 | 9.58k | if (ss_err[filt_high] < (best_err - bias)) { |
174 | 251 | best_err = ss_err[filt_high]; |
175 | 251 | filt_best = filt_high; |
176 | 251 | } |
177 | 9.58k | } |
178 | | |
179 | | // Half the step distance if the best filter value was the same as last time |
180 | 9.58k | if (filt_best == filt_mid) { |
181 | 9.33k | filter_step /= 2; |
182 | 9.33k | filt_direction = 0; |
183 | 9.33k | } else { |
184 | 251 | filt_direction = (filt_best < filt_mid) ? -1 : 1; |
185 | 251 | filt_mid = filt_best; |
186 | 251 | } |
187 | 9.58k | } |
188 | | |
189 | 3.11k | return filt_best; |
190 | 3.11k | } |
191 | | |
192 | | void av1_pick_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi, |
193 | 1.03k | LPF_PICK_METHOD method) { |
194 | 1.03k | AV1_COMMON *const cm = &cpi->common; |
195 | 1.03k | const SequenceHeader *const seq_params = cm->seq_params; |
196 | 1.03k | const int num_planes = av1_num_planes(cm); |
197 | 1.03k | struct loopfilter *const lf = &cm->lf; |
198 | 1.03k | (void)sd; |
199 | | |
200 | 1.03k | lf->sharpness_level = 0; |
201 | 1.03k | cpi->td.mb.rdmult = cpi->rd.RDMULT; |
202 | | |
203 | 1.03k | if (cpi->oxcf.algo_cfg.loopfilter_control == LOOPFILTER_NONE || |
204 | 1.03k | (cpi->oxcf.algo_cfg.loopfilter_control == LOOPFILTER_REFERENCE && |
205 | 1.03k | cpi->svc.non_reference_frame)) { |
206 | 0 | lf->filter_level[0] = 0; |
207 | 0 | lf->filter_level[1] = 0; |
208 | 0 | return; |
209 | 0 | } |
210 | | |
211 | 1.03k | if (method == LPF_PICK_MINIMAL_LPF) { |
212 | 0 | lf->filter_level[0] = 0; |
213 | 0 | lf->filter_level[1] = 0; |
214 | 1.03k | } else if (method >= LPF_PICK_FROM_Q) { |
215 | 0 | const int min_filter_level = 0; |
216 | 0 | const int max_filter_level = av1_get_max_filter_level(cpi); |
217 | 0 | const int q = av1_ac_quant_QTX(cm->quant_params.base_qindex, 0, |
218 | 0 | seq_params->bit_depth); |
219 | | // based on tests result for rtc test set |
220 | | // 0.04590 boosted or 0.02295 non-booseted in 18-bit fixed point |
221 | 0 | const int strength_boost_q_treshold = 0; |
222 | 0 | int inter_frame_multiplier = |
223 | 0 | (q > strength_boost_q_treshold || |
224 | 0 | (cpi->sf.rt_sf.use_nonrd_pick_mode && |
225 | 0 | cpi->common.width * cpi->common.height > 352 * 288)) |
226 | 0 | ? 12034 |
227 | 0 | : 6017; |
228 | | // These values were determined by linear fitting the result of the |
229 | | // searched level for 8 bit depth: |
230 | | // Keyframes: filt_guess = q * 0.06699 - 1.60817 |
231 | | // Other frames: filt_guess = q * inter_frame_multiplier + 2.48225 |
232 | | // |
233 | | // And high bit depth separately: |
234 | | // filt_guess = q * 0.316206 + 3.87252 |
235 | 0 | int filt_guess; |
236 | 0 | switch (seq_params->bit_depth) { |
237 | 0 | case AOM_BITS_8: |
238 | 0 | filt_guess = |
239 | 0 | (cm->current_frame.frame_type == KEY_FRAME) |
240 | 0 | ? ROUND_POWER_OF_TWO(q * 17563 - 421574, 18) |
241 | 0 | : ROUND_POWER_OF_TWO(q * inter_frame_multiplier + 650707, 18); |
242 | 0 | break; |
243 | 0 | case AOM_BITS_10: |
244 | 0 | filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 4060632, 20); |
245 | 0 | break; |
246 | 0 | case AOM_BITS_12: |
247 | 0 | filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 16242526, 22); |
248 | 0 | break; |
249 | 0 | default: |
250 | 0 | assert(0 && |
251 | 0 | "bit_depth should be AOM_BITS_8, AOM_BITS_10 " |
252 | 0 | "or AOM_BITS_12"); |
253 | 0 | return; |
254 | 0 | } |
255 | 0 | if (seq_params->bit_depth != AOM_BITS_8 && |
256 | 0 | cm->current_frame.frame_type == KEY_FRAME) |
257 | 0 | filt_guess -= 4; |
258 | | // TODO(chengchen): retrain the model for Y, U, V filter levels |
259 | 0 | lf->filter_level[0] = clamp(filt_guess, min_filter_level, max_filter_level); |
260 | 0 | lf->filter_level[1] = clamp(filt_guess, min_filter_level, max_filter_level); |
261 | 0 | lf->filter_level_u = clamp(filt_guess, min_filter_level, max_filter_level); |
262 | 0 | lf->filter_level_v = clamp(filt_guess, min_filter_level, max_filter_level); |
263 | 0 | if (cpi->oxcf.algo_cfg.loopfilter_control == LOOPFILTER_SELECTIVELY && |
264 | 0 | !frame_is_intra_only(cm)) { |
265 | 0 | const int num4x4 = (cm->width >> 2) * (cm->height >> 2); |
266 | 0 | const int newmv_thresh = 7; |
267 | 0 | const int distance_since_key_thresh = 5; |
268 | 0 | if ((cpi->td.rd_counts.newmv_or_intra_blocks * 100 / num4x4) < |
269 | 0 | newmv_thresh && |
270 | 0 | cpi->rc.frames_since_key > distance_since_key_thresh) { |
271 | 0 | lf->filter_level[0] = 0; |
272 | 0 | lf->filter_level[1] = 0; |
273 | 0 | } |
274 | 0 | } |
275 | 1.03k | } else { |
276 | 1.03k | int last_frame_filter_level[4] = { 0 }; |
277 | 1.03k | if (!frame_is_intra_only(cm)) { |
278 | | #if CONFIG_FRAME_PARALLEL_ENCODE |
279 | | last_frame_filter_level[0] = cpi->ppi->filter_level[0]; |
280 | | last_frame_filter_level[1] = cpi->ppi->filter_level[1]; |
281 | | last_frame_filter_level[2] = cpi->ppi->filter_level_u; |
282 | | last_frame_filter_level[3] = cpi->ppi->filter_level_v; |
283 | | #else |
284 | 0 | last_frame_filter_level[0] = lf->filter_level[0]; |
285 | 0 | last_frame_filter_level[1] = lf->filter_level[1]; |
286 | 0 | last_frame_filter_level[2] = lf->filter_level_u; |
287 | 0 | last_frame_filter_level[3] = lf->filter_level_v; |
288 | 0 | #endif |
289 | 0 | } |
290 | | // The frame buffer last_frame_uf is used to store the non-loop filtered |
291 | | // reconstructed frame in search_filter_level(). |
292 | 1.03k | if (aom_realloc_frame_buffer( |
293 | 1.03k | &cpi->last_frame_uf, cm->width, cm->height, |
294 | 1.03k | seq_params->subsampling_x, seq_params->subsampling_y, |
295 | 1.03k | seq_params->use_highbitdepth, cpi->oxcf.border_in_pixels, |
296 | 1.03k | cm->features.byte_alignment, NULL, NULL, NULL, 0)) |
297 | 0 | aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR, |
298 | 0 | "Failed to allocate last frame buffer"); |
299 | | |
300 | 1.03k | lf->filter_level[0] = lf->filter_level[1] = |
301 | 1.03k | search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, |
302 | 1.03k | last_frame_filter_level, 0, 2); |
303 | 1.03k | if (method != LPF_PICK_FROM_FULL_IMAGE_NON_DUAL) { |
304 | 0 | lf->filter_level[0] = |
305 | 0 | search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, |
306 | 0 | last_frame_filter_level, 0, 0); |
307 | 0 | lf->filter_level[1] = |
308 | 0 | search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, |
309 | 0 | last_frame_filter_level, 0, 1); |
310 | 0 | } |
311 | | |
312 | 1.03k | if (num_planes > 1) { |
313 | 1.03k | lf->filter_level_u = |
314 | 1.03k | search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, |
315 | 1.03k | last_frame_filter_level, 1, 0); |
316 | 1.03k | lf->filter_level_v = |
317 | 1.03k | search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, |
318 | 1.03k | last_frame_filter_level, 2, 0); |
319 | 1.03k | } |
320 | 1.03k | } |
321 | 1.03k | } |