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 <math.h>
14 #include <stdbool.h>
15
16 #include "config/aom_config.h"
17 #include "config/aom_dsp_rtcd.h"
18 #include "config/av1_rtcd.h"
19
20 #include "aom_dsp/aom_dsp_common.h"
21 #include "aom_dsp/blend.h"
22 #include "aom_mem/aom_mem.h"
23 #include "aom_ports/aom_timer.h"
24 #include "aom_ports/mem.h"
25 #include "aom_ports/system_state.h"
26
27 #include "av1/common/cfl.h"
28 #include "av1/common/common.h"
29 #include "av1/common/common_data.h"
30 #include "av1/common/entropy.h"
31 #include "av1/common/entropymode.h"
32 #include "av1/common/idct.h"
33 #include "av1/common/mvref_common.h"
34 #include "av1/common/obmc.h"
35 #include "av1/common/onyxc_int.h"
36 #include "av1/common/pred_common.h"
37 #include "av1/common/quant_common.h"
38 #include "av1/common/reconinter.h"
39 #include "av1/common/reconintra.h"
40 #include "av1/common/scan.h"
41 #include "av1/common/seg_common.h"
42 #include "av1/common/txb_common.h"
43 #include "av1/common/warped_motion.h"
44
45 #include "av1/encoder/aq_variance.h"
46 #include "av1/encoder/av1_quantize.h"
47 #include "av1/encoder/cost.h"
48 #include "av1/encoder/compound_type.h"
49 #include "av1/encoder/encodemb.h"
50 #include "av1/encoder/encodemv.h"
51 #include "av1/encoder/encoder.h"
52 #include "av1/encoder/encodetxb.h"
53 #include "av1/encoder/hybrid_fwd_txfm.h"
54 #include "av1/encoder/interp_search.h"
55 #include "av1/encoder/intra_mode_search.h"
56 #include "av1/encoder/mcomp.h"
57 #include "av1/encoder/ml.h"
58 #include "av1/encoder/mode_prune_model_weights.h"
59 #include "av1/encoder/model_rd.h"
60 #include "av1/encoder/motion_search_facade.h"
61 #include "av1/encoder/palette.h"
62 #include "av1/encoder/pustats.h"
63 #include "av1/encoder/random.h"
64 #include "av1/encoder/ratectrl.h"
65 #include "av1/encoder/rd.h"
66 #include "av1/encoder/rdopt.h"
67 #include "av1/encoder/reconinter_enc.h"
68 #include "av1/encoder/tokenize.h"
69 #include "av1/encoder/tpl_model.h"
70 #include "av1/encoder/tx_search.h"
71
72 #define LAST_NEW_MV_INDEX 6
73
74 // Mode_threshold multiplication factor table for prune_inter_modes_if_skippable
75 // The values are kept in Q12 format and equation used to derive is
76 // (2.5 - ((float)x->qindex / MAXQ) * 1.5)
77 #define MODE_THRESH_QBITS 12
78 static const int mode_threshold_mul_factor[QINDEX_RANGE] = {
79 10240, 10216, 10192, 10168, 10144, 10120, 10095, 10071, 10047, 10023, 9999,
80 9975, 9951, 9927, 9903, 9879, 9854, 9830, 9806, 9782, 9758, 9734,
81 9710, 9686, 9662, 9638, 9614, 9589, 9565, 9541, 9517, 9493, 9469,
82 9445, 9421, 9397, 9373, 9349, 9324, 9300, 9276, 9252, 9228, 9204,
83 9180, 9156, 9132, 9108, 9083, 9059, 9035, 9011, 8987, 8963, 8939,
84 8915, 8891, 8867, 8843, 8818, 8794, 8770, 8746, 8722, 8698, 8674,
85 8650, 8626, 8602, 8578, 8553, 8529, 8505, 8481, 8457, 8433, 8409,
86 8385, 8361, 8337, 8312, 8288, 8264, 8240, 8216, 8192, 8168, 8144,
87 8120, 8096, 8072, 8047, 8023, 7999, 7975, 7951, 7927, 7903, 7879,
88 7855, 7831, 7806, 7782, 7758, 7734, 7710, 7686, 7662, 7638, 7614,
89 7590, 7566, 7541, 7517, 7493, 7469, 7445, 7421, 7397, 7373, 7349,
90 7325, 7301, 7276, 7252, 7228, 7204, 7180, 7156, 7132, 7108, 7084,
91 7060, 7035, 7011, 6987, 6963, 6939, 6915, 6891, 6867, 6843, 6819,
92 6795, 6770, 6746, 6722, 6698, 6674, 6650, 6626, 6602, 6578, 6554,
93 6530, 6505, 6481, 6457, 6433, 6409, 6385, 6361, 6337, 6313, 6289,
94 6264, 6240, 6216, 6192, 6168, 6144, 6120, 6096, 6072, 6048, 6024,
95 5999, 5975, 5951, 5927, 5903, 5879, 5855, 5831, 5807, 5783, 5758,
96 5734, 5710, 5686, 5662, 5638, 5614, 5590, 5566, 5542, 5518, 5493,
97 5469, 5445, 5421, 5397, 5373, 5349, 5325, 5301, 5277, 5253, 5228,
98 5204, 5180, 5156, 5132, 5108, 5084, 5060, 5036, 5012, 4987, 4963,
99 4939, 4915, 4891, 4867, 4843, 4819, 4795, 4771, 4747, 4722, 4698,
100 4674, 4650, 4626, 4602, 4578, 4554, 4530, 4506, 4482, 4457, 4433,
101 4409, 4385, 4361, 4337, 4313, 4289, 4265, 4241, 4216, 4192, 4168,
102 4144, 4120, 4096
103 };
104
105 static const THR_MODES av1_default_mode_order[MAX_MODES] = {
106 THR_NEARESTMV,
107 THR_NEARESTL2,
108 THR_NEARESTL3,
109 THR_NEARESTB,
110 THR_NEARESTA2,
111 THR_NEARESTA,
112 THR_NEARESTG,
113
114 THR_NEWMV,
115 THR_NEWL2,
116 THR_NEWL3,
117 THR_NEWB,
118 THR_NEWA2,
119 THR_NEWA,
120 THR_NEWG,
121
122 THR_NEARMV,
123 THR_NEARL2,
124 THR_NEARL3,
125 THR_NEARB,
126 THR_NEARA2,
127 THR_NEARA,
128 THR_NEARG,
129
130 THR_GLOBALMV,
131 THR_GLOBALL2,
132 THR_GLOBALL3,
133 THR_GLOBALB,
134 THR_GLOBALA2,
135 THR_GLOBALA,
136 THR_GLOBALG,
137
138 THR_COMP_NEAREST_NEARESTLA,
139 THR_COMP_NEAREST_NEARESTL2A,
140 THR_COMP_NEAREST_NEARESTL3A,
141 THR_COMP_NEAREST_NEARESTGA,
142 THR_COMP_NEAREST_NEARESTLB,
143 THR_COMP_NEAREST_NEARESTL2B,
144 THR_COMP_NEAREST_NEARESTL3B,
145 THR_COMP_NEAREST_NEARESTGB,
146 THR_COMP_NEAREST_NEARESTLA2,
147 THR_COMP_NEAREST_NEARESTL2A2,
148 THR_COMP_NEAREST_NEARESTL3A2,
149 THR_COMP_NEAREST_NEARESTGA2,
150 THR_COMP_NEAREST_NEARESTLL2,
151 THR_COMP_NEAREST_NEARESTLL3,
152 THR_COMP_NEAREST_NEARESTLG,
153 THR_COMP_NEAREST_NEARESTBA,
154
155 THR_COMP_NEAR_NEARLA,
156 THR_COMP_NEW_NEARESTLA,
157 THR_COMP_NEAREST_NEWLA,
158 THR_COMP_NEW_NEARLA,
159 THR_COMP_NEAR_NEWLA,
160 THR_COMP_NEW_NEWLA,
161 THR_COMP_GLOBAL_GLOBALLA,
162
163 THR_COMP_NEAR_NEARL2A,
164 THR_COMP_NEW_NEARESTL2A,
165 THR_COMP_NEAREST_NEWL2A,
166 THR_COMP_NEW_NEARL2A,
167 THR_COMP_NEAR_NEWL2A,
168 THR_COMP_NEW_NEWL2A,
169 THR_COMP_GLOBAL_GLOBALL2A,
170
171 THR_COMP_NEAR_NEARL3A,
172 THR_COMP_NEW_NEARESTL3A,
173 THR_COMP_NEAREST_NEWL3A,
174 THR_COMP_NEW_NEARL3A,
175 THR_COMP_NEAR_NEWL3A,
176 THR_COMP_NEW_NEWL3A,
177 THR_COMP_GLOBAL_GLOBALL3A,
178
179 THR_COMP_NEAR_NEARGA,
180 THR_COMP_NEW_NEARESTGA,
181 THR_COMP_NEAREST_NEWGA,
182 THR_COMP_NEW_NEARGA,
183 THR_COMP_NEAR_NEWGA,
184 THR_COMP_NEW_NEWGA,
185 THR_COMP_GLOBAL_GLOBALGA,
186
187 THR_COMP_NEAR_NEARLB,
188 THR_COMP_NEW_NEARESTLB,
189 THR_COMP_NEAREST_NEWLB,
190 THR_COMP_NEW_NEARLB,
191 THR_COMP_NEAR_NEWLB,
192 THR_COMP_NEW_NEWLB,
193 THR_COMP_GLOBAL_GLOBALLB,
194
195 THR_COMP_NEAR_NEARL2B,
196 THR_COMP_NEW_NEARESTL2B,
197 THR_COMP_NEAREST_NEWL2B,
198 THR_COMP_NEW_NEARL2B,
199 THR_COMP_NEAR_NEWL2B,
200 THR_COMP_NEW_NEWL2B,
201 THR_COMP_GLOBAL_GLOBALL2B,
202
203 THR_COMP_NEAR_NEARL3B,
204 THR_COMP_NEW_NEARESTL3B,
205 THR_COMP_NEAREST_NEWL3B,
206 THR_COMP_NEW_NEARL3B,
207 THR_COMP_NEAR_NEWL3B,
208 THR_COMP_NEW_NEWL3B,
209 THR_COMP_GLOBAL_GLOBALL3B,
210
211 THR_COMP_NEAR_NEARGB,
212 THR_COMP_NEW_NEARESTGB,
213 THR_COMP_NEAREST_NEWGB,
214 THR_COMP_NEW_NEARGB,
215 THR_COMP_NEAR_NEWGB,
216 THR_COMP_NEW_NEWGB,
217 THR_COMP_GLOBAL_GLOBALGB,
218
219 THR_COMP_NEAR_NEARLA2,
220 THR_COMP_NEW_NEARESTLA2,
221 THR_COMP_NEAREST_NEWLA2,
222 THR_COMP_NEW_NEARLA2,
223 THR_COMP_NEAR_NEWLA2,
224 THR_COMP_NEW_NEWLA2,
225 THR_COMP_GLOBAL_GLOBALLA2,
226
227 THR_COMP_NEAR_NEARL2A2,
228 THR_COMP_NEW_NEARESTL2A2,
229 THR_COMP_NEAREST_NEWL2A2,
230 THR_COMP_NEW_NEARL2A2,
231 THR_COMP_NEAR_NEWL2A2,
232 THR_COMP_NEW_NEWL2A2,
233 THR_COMP_GLOBAL_GLOBALL2A2,
234
235 THR_COMP_NEAR_NEARL3A2,
236 THR_COMP_NEW_NEARESTL3A2,
237 THR_COMP_NEAREST_NEWL3A2,
238 THR_COMP_NEW_NEARL3A2,
239 THR_COMP_NEAR_NEWL3A2,
240 THR_COMP_NEW_NEWL3A2,
241 THR_COMP_GLOBAL_GLOBALL3A2,
242
243 THR_COMP_NEAR_NEARGA2,
244 THR_COMP_NEW_NEARESTGA2,
245 THR_COMP_NEAREST_NEWGA2,
246 THR_COMP_NEW_NEARGA2,
247 THR_COMP_NEAR_NEWGA2,
248 THR_COMP_NEW_NEWGA2,
249 THR_COMP_GLOBAL_GLOBALGA2,
250
251 THR_COMP_NEAR_NEARLL2,
252 THR_COMP_NEW_NEARESTLL2,
253 THR_COMP_NEAREST_NEWLL2,
254 THR_COMP_NEW_NEARLL2,
255 THR_COMP_NEAR_NEWLL2,
256 THR_COMP_NEW_NEWLL2,
257 THR_COMP_GLOBAL_GLOBALLL2,
258
259 THR_COMP_NEAR_NEARLL3,
260 THR_COMP_NEW_NEARESTLL3,
261 THR_COMP_NEAREST_NEWLL3,
262 THR_COMP_NEW_NEARLL3,
263 THR_COMP_NEAR_NEWLL3,
264 THR_COMP_NEW_NEWLL3,
265 THR_COMP_GLOBAL_GLOBALLL3,
266
267 THR_COMP_NEAR_NEARLG,
268 THR_COMP_NEW_NEARESTLG,
269 THR_COMP_NEAREST_NEWLG,
270 THR_COMP_NEW_NEARLG,
271 THR_COMP_NEAR_NEWLG,
272 THR_COMP_NEW_NEWLG,
273 THR_COMP_GLOBAL_GLOBALLG,
274
275 THR_COMP_NEAR_NEARBA,
276 THR_COMP_NEW_NEARESTBA,
277 THR_COMP_NEAREST_NEWBA,
278 THR_COMP_NEW_NEARBA,
279 THR_COMP_NEAR_NEWBA,
280 THR_COMP_NEW_NEWBA,
281 THR_COMP_GLOBAL_GLOBALBA,
282
283 THR_DC,
284 THR_PAETH,
285 THR_SMOOTH,
286 THR_SMOOTH_V,
287 THR_SMOOTH_H,
288 THR_H_PRED,
289 THR_V_PRED,
290 THR_D135_PRED,
291 THR_D203_PRED,
292 THR_D157_PRED,
293 THR_D67_PRED,
294 THR_D113_PRED,
295 THR_D45_PRED,
296 };
297
find_last_single_ref_mode_idx(const THR_MODES * mode_order)298 static int find_last_single_ref_mode_idx(const THR_MODES *mode_order) {
299 uint8_t mode_found[NUM_SINGLE_REF_MODES];
300 av1_zero(mode_found);
301 int num_single_ref_modes_left = NUM_SINGLE_REF_MODES;
302
303 for (int idx = 0; idx < MAX_MODES; idx++) {
304 const THR_MODES curr_mode = mode_order[idx];
305 if (curr_mode < SINGLE_REF_MODE_END) {
306 num_single_ref_modes_left--;
307 }
308 if (!num_single_ref_modes_left) {
309 return idx;
310 }
311 }
312 return -1;
313 }
314
315 typedef struct SingleInterModeState {
316 int64_t rd;
317 MV_REFERENCE_FRAME ref_frame;
318 int valid;
319 } SingleInterModeState;
320
321 typedef struct InterModeSearchState {
322 int64_t best_rd;
323 int64_t best_skip_rd[2];
324 MB_MODE_INFO best_mbmode;
325 int best_rate_y;
326 int best_rate_uv;
327 int best_mode_skippable;
328 int best_skip2;
329 THR_MODES best_mode_index;
330 int num_available_refs;
331 int64_t dist_refs[REF_FRAMES];
332 int dist_order_refs[REF_FRAMES];
333 int64_t mode_threshold[MAX_MODES];
334 int64_t best_intra_rd;
335 unsigned int best_pred_sse;
336 int64_t best_pred_diff[REFERENCE_MODES];
337 // Save a set of single_newmv for each checked ref_mv.
338 int_mv single_newmv[MAX_REF_MV_SEARCH][REF_FRAMES];
339 int single_newmv_rate[MAX_REF_MV_SEARCH][REF_FRAMES];
340 int single_newmv_valid[MAX_REF_MV_SEARCH][REF_FRAMES];
341 int64_t modelled_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES];
342 // The rd of simple translation in single inter modes
343 int64_t simple_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES];
344
345 // Single search results by [directions][modes][reference frames]
346 SingleInterModeState single_state[2][SINGLE_INTER_MODE_NUM][FWD_REFS];
347 int single_state_cnt[2][SINGLE_INTER_MODE_NUM];
348 SingleInterModeState single_state_modelled[2][SINGLE_INTER_MODE_NUM]
349 [FWD_REFS];
350 int single_state_modelled_cnt[2][SINGLE_INTER_MODE_NUM];
351 MV_REFERENCE_FRAME single_rd_order[2][SINGLE_INTER_MODE_NUM][FWD_REFS];
352 IntraModeSearchState intra_search_state;
353 } InterModeSearchState;
354
av1_inter_mode_data_init(TileDataEnc * tile_data)355 void av1_inter_mode_data_init(TileDataEnc *tile_data) {
356 for (int i = 0; i < BLOCK_SIZES_ALL; ++i) {
357 InterModeRdModel *md = &tile_data->inter_mode_rd_models[i];
358 md->ready = 0;
359 md->num = 0;
360 md->dist_sum = 0;
361 md->ld_sum = 0;
362 md->sse_sum = 0;
363 md->sse_sse_sum = 0;
364 md->sse_ld_sum = 0;
365 }
366 }
367
get_est_rate_dist(const TileDataEnc * tile_data,BLOCK_SIZE bsize,int64_t sse,int * est_residue_cost,int64_t * est_dist)368 static int get_est_rate_dist(const TileDataEnc *tile_data, BLOCK_SIZE bsize,
369 int64_t sse, int *est_residue_cost,
370 int64_t *est_dist) {
371 aom_clear_system_state();
372 const InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
373 if (md->ready) {
374 if (sse < md->dist_mean) {
375 *est_residue_cost = 0;
376 *est_dist = sse;
377 } else {
378 *est_dist = (int64_t)round(md->dist_mean);
379 const double est_ld = md->a * sse + md->b;
380 // Clamp estimated rate cost by INT_MAX / 2.
381 // TODO(angiebird@google.com): find better solution than clamping.
382 if (fabs(est_ld) < 1e-2) {
383 *est_residue_cost = INT_MAX / 2;
384 } else {
385 double est_residue_cost_dbl = ((sse - md->dist_mean) / est_ld);
386 if (est_residue_cost_dbl < 0) {
387 *est_residue_cost = 0;
388 } else {
389 *est_residue_cost =
390 (int)AOMMIN((int64_t)round(est_residue_cost_dbl), INT_MAX / 2);
391 }
392 }
393 if (*est_residue_cost <= 0) {
394 *est_residue_cost = 0;
395 *est_dist = sse;
396 }
397 }
398 return 1;
399 }
400 return 0;
401 }
402
av1_inter_mode_data_fit(TileDataEnc * tile_data,int rdmult)403 void av1_inter_mode_data_fit(TileDataEnc *tile_data, int rdmult) {
404 aom_clear_system_state();
405 for (int bsize = 0; bsize < BLOCK_SIZES_ALL; ++bsize) {
406 const int block_idx = inter_mode_data_block_idx(bsize);
407 InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
408 if (block_idx == -1) continue;
409 if ((md->ready == 0 && md->num < 200) || (md->ready == 1 && md->num < 64)) {
410 continue;
411 } else {
412 if (md->ready == 0) {
413 md->dist_mean = md->dist_sum / md->num;
414 md->ld_mean = md->ld_sum / md->num;
415 md->sse_mean = md->sse_sum / md->num;
416 md->sse_sse_mean = md->sse_sse_sum / md->num;
417 md->sse_ld_mean = md->sse_ld_sum / md->num;
418 } else {
419 const double factor = 3;
420 md->dist_mean =
421 (md->dist_mean * factor + (md->dist_sum / md->num)) / (factor + 1);
422 md->ld_mean =
423 (md->ld_mean * factor + (md->ld_sum / md->num)) / (factor + 1);
424 md->sse_mean =
425 (md->sse_mean * factor + (md->sse_sum / md->num)) / (factor + 1);
426 md->sse_sse_mean =
427 (md->sse_sse_mean * factor + (md->sse_sse_sum / md->num)) /
428 (factor + 1);
429 md->sse_ld_mean =
430 (md->sse_ld_mean * factor + (md->sse_ld_sum / md->num)) /
431 (factor + 1);
432 }
433
434 const double my = md->ld_mean;
435 const double mx = md->sse_mean;
436 const double dx = sqrt(md->sse_sse_mean);
437 const double dxy = md->sse_ld_mean;
438
439 md->a = (dxy - mx * my) / (dx * dx - mx * mx);
440 md->b = my - md->a * mx;
441 md->ready = 1;
442
443 md->num = 0;
444 md->dist_sum = 0;
445 md->ld_sum = 0;
446 md->sse_sum = 0;
447 md->sse_sse_sum = 0;
448 md->sse_ld_sum = 0;
449 }
450 (void)rdmult;
451 }
452 }
453
inter_mode_data_push(TileDataEnc * tile_data,BLOCK_SIZE bsize,int64_t sse,int64_t dist,int residue_cost)454 static AOM_INLINE void inter_mode_data_push(TileDataEnc *tile_data,
455 BLOCK_SIZE bsize, int64_t sse,
456 int64_t dist, int residue_cost) {
457 if (residue_cost == 0 || sse == dist) return;
458 const int block_idx = inter_mode_data_block_idx(bsize);
459 if (block_idx == -1) return;
460 InterModeRdModel *rd_model = &tile_data->inter_mode_rd_models[bsize];
461 if (rd_model->num < INTER_MODE_RD_DATA_OVERALL_SIZE) {
462 aom_clear_system_state();
463 const double ld = (sse - dist) * 1. / residue_cost;
464 ++rd_model->num;
465 rd_model->dist_sum += dist;
466 rd_model->ld_sum += ld;
467 rd_model->sse_sum += sse;
468 rd_model->sse_sse_sum += (double)sse * (double)sse;
469 rd_model->sse_ld_sum += sse * ld;
470 }
471 }
472
inter_modes_info_push(InterModesInfo * inter_modes_info,int mode_rate,int64_t sse,int64_t rd,RD_STATS * rd_cost,RD_STATS * rd_cost_y,RD_STATS * rd_cost_uv,const MB_MODE_INFO * mbmi)473 static AOM_INLINE void inter_modes_info_push(InterModesInfo *inter_modes_info,
474 int mode_rate, int64_t sse,
475 int64_t rd, RD_STATS *rd_cost,
476 RD_STATS *rd_cost_y,
477 RD_STATS *rd_cost_uv,
478 const MB_MODE_INFO *mbmi) {
479 const int num = inter_modes_info->num;
480 assert(num < MAX_INTER_MODES);
481 inter_modes_info->mbmi_arr[num] = *mbmi;
482 inter_modes_info->mode_rate_arr[num] = mode_rate;
483 inter_modes_info->sse_arr[num] = sse;
484 inter_modes_info->est_rd_arr[num] = rd;
485 inter_modes_info->rd_cost_arr[num] = *rd_cost;
486 inter_modes_info->rd_cost_y_arr[num] = *rd_cost_y;
487 inter_modes_info->rd_cost_uv_arr[num] = *rd_cost_uv;
488 ++inter_modes_info->num;
489 }
490
compare_rd_idx_pair(const void * a,const void * b)491 static int compare_rd_idx_pair(const void *a, const void *b) {
492 if (((RdIdxPair *)a)->rd == ((RdIdxPair *)b)->rd) {
493 return 0;
494 } else if (((const RdIdxPair *)a)->rd > ((const RdIdxPair *)b)->rd) {
495 return 1;
496 } else {
497 return -1;
498 }
499 }
500
inter_modes_info_sort(const InterModesInfo * inter_modes_info,RdIdxPair * rd_idx_pair_arr)501 static AOM_INLINE void inter_modes_info_sort(
502 const InterModesInfo *inter_modes_info, RdIdxPair *rd_idx_pair_arr) {
503 if (inter_modes_info->num == 0) {
504 return;
505 }
506 for (int i = 0; i < inter_modes_info->num; ++i) {
507 rd_idx_pair_arr[i].idx = i;
508 rd_idx_pair_arr[i].rd = inter_modes_info->est_rd_arr[i];
509 }
510 qsort(rd_idx_pair_arr, inter_modes_info->num, sizeof(rd_idx_pair_arr[0]),
511 compare_rd_idx_pair);
512 }
513
514 // Similar to get_horver_correlation, but also takes into account first
515 // row/column, when computing horizontal/vertical correlation.
av1_get_horver_correlation_full_c(const int16_t * diff,int stride,int width,int height,float * hcorr,float * vcorr)516 void av1_get_horver_correlation_full_c(const int16_t *diff, int stride,
517 int width, int height, float *hcorr,
518 float *vcorr) {
519 // The following notation is used:
520 // x - current pixel
521 // y - left neighbor pixel
522 // z - top neighbor pixel
523 int64_t x_sum = 0, x2_sum = 0, xy_sum = 0, xz_sum = 0;
524 int64_t x_firstrow = 0, x_finalrow = 0, x_firstcol = 0, x_finalcol = 0;
525 int64_t x2_firstrow = 0, x2_finalrow = 0, x2_firstcol = 0, x2_finalcol = 0;
526
527 // First, process horizontal correlation on just the first row
528 x_sum += diff[0];
529 x2_sum += diff[0] * diff[0];
530 x_firstrow += diff[0];
531 x2_firstrow += diff[0] * diff[0];
532 for (int j = 1; j < width; ++j) {
533 const int16_t x = diff[j];
534 const int16_t y = diff[j - 1];
535 x_sum += x;
536 x_firstrow += x;
537 x2_sum += x * x;
538 x2_firstrow += x * x;
539 xy_sum += x * y;
540 }
541
542 // Process vertical correlation in the first column
543 x_firstcol += diff[0];
544 x2_firstcol += diff[0] * diff[0];
545 for (int i = 1; i < height; ++i) {
546 const int16_t x = diff[i * stride];
547 const int16_t z = diff[(i - 1) * stride];
548 x_sum += x;
549 x_firstcol += x;
550 x2_sum += x * x;
551 x2_firstcol += x * x;
552 xz_sum += x * z;
553 }
554
555 // Now process horiz and vert correlation through the rest unit
556 for (int i = 1; i < height; ++i) {
557 for (int j = 1; j < width; ++j) {
558 const int16_t x = diff[i * stride + j];
559 const int16_t y = diff[i * stride + j - 1];
560 const int16_t z = diff[(i - 1) * stride + j];
561 x_sum += x;
562 x2_sum += x * x;
563 xy_sum += x * y;
564 xz_sum += x * z;
565 }
566 }
567
568 for (int j = 0; j < width; ++j) {
569 x_finalrow += diff[(height - 1) * stride + j];
570 x2_finalrow +=
571 diff[(height - 1) * stride + j] * diff[(height - 1) * stride + j];
572 }
573 for (int i = 0; i < height; ++i) {
574 x_finalcol += diff[i * stride + width - 1];
575 x2_finalcol += diff[i * stride + width - 1] * diff[i * stride + width - 1];
576 }
577
578 int64_t xhor_sum = x_sum - x_finalcol;
579 int64_t xver_sum = x_sum - x_finalrow;
580 int64_t y_sum = x_sum - x_firstcol;
581 int64_t z_sum = x_sum - x_firstrow;
582 int64_t x2hor_sum = x2_sum - x2_finalcol;
583 int64_t x2ver_sum = x2_sum - x2_finalrow;
584 int64_t y2_sum = x2_sum - x2_firstcol;
585 int64_t z2_sum = x2_sum - x2_firstrow;
586
587 const float num_hor = (float)(height * (width - 1));
588 const float num_ver = (float)((height - 1) * width);
589
590 const float xhor_var_n = x2hor_sum - (xhor_sum * xhor_sum) / num_hor;
591 const float xver_var_n = x2ver_sum - (xver_sum * xver_sum) / num_ver;
592
593 const float y_var_n = y2_sum - (y_sum * y_sum) / num_hor;
594 const float z_var_n = z2_sum - (z_sum * z_sum) / num_ver;
595
596 const float xy_var_n = xy_sum - (xhor_sum * y_sum) / num_hor;
597 const float xz_var_n = xz_sum - (xver_sum * z_sum) / num_ver;
598
599 if (xhor_var_n > 0 && y_var_n > 0) {
600 *hcorr = xy_var_n / sqrtf(xhor_var_n * y_var_n);
601 *hcorr = *hcorr < 0 ? 0 : *hcorr;
602 } else {
603 *hcorr = 1.0;
604 }
605 if (xver_var_n > 0 && z_var_n > 0) {
606 *vcorr = xz_var_n / sqrtf(xver_var_n * z_var_n);
607 *vcorr = *vcorr < 0 ? 0 : *vcorr;
608 } else {
609 *vcorr = 1.0;
610 }
611 }
612
get_sse(const AV1_COMP * cpi,const MACROBLOCK * x,int64_t * sse_y)613 static int64_t get_sse(const AV1_COMP *cpi, const MACROBLOCK *x,
614 int64_t *sse_y) {
615 const AV1_COMMON *cm = &cpi->common;
616 const int num_planes = av1_num_planes(cm);
617 const MACROBLOCKD *xd = &x->e_mbd;
618 const MB_MODE_INFO *mbmi = xd->mi[0];
619 int64_t total_sse = 0;
620 for (int plane = 0; plane < num_planes; ++plane) {
621 if (plane && !xd->is_chroma_ref) break;
622 const struct macroblock_plane *const p = &x->plane[plane];
623 const struct macroblockd_plane *const pd = &xd->plane[plane];
624 const BLOCK_SIZE bs = get_plane_block_size(mbmi->sb_type, pd->subsampling_x,
625 pd->subsampling_y);
626 unsigned int sse;
627
628 cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride, pd->dst.buf, pd->dst.stride,
629 &sse);
630 total_sse += sse;
631 if (!plane && sse_y) *sse_y = sse;
632 }
633 total_sse <<= 4;
634 return total_sse;
635 }
636
av1_block_error_c(const tran_low_t * coeff,const tran_low_t * dqcoeff,intptr_t block_size,int64_t * ssz)637 int64_t av1_block_error_c(const tran_low_t *coeff, const tran_low_t *dqcoeff,
638 intptr_t block_size, int64_t *ssz) {
639 int i;
640 int64_t error = 0, sqcoeff = 0;
641
642 for (i = 0; i < block_size; i++) {
643 const int diff = coeff[i] - dqcoeff[i];
644 error += diff * diff;
645 sqcoeff += coeff[i] * coeff[i];
646 }
647
648 *ssz = sqcoeff;
649 return error;
650 }
651
av1_block_error_lp_c(const int16_t * coeff,const int16_t * dqcoeff,intptr_t block_size)652 int64_t av1_block_error_lp_c(const int16_t *coeff, const int16_t *dqcoeff,
653 intptr_t block_size) {
654 int64_t error = 0;
655
656 for (int i = 0; i < block_size; i++) {
657 const int diff = coeff[i] - dqcoeff[i];
658 error += diff * diff;
659 }
660
661 return error;
662 }
663
664 #if CONFIG_AV1_HIGHBITDEPTH
av1_highbd_block_error_c(const tran_low_t * coeff,const tran_low_t * dqcoeff,intptr_t block_size,int64_t * ssz,int bd)665 int64_t av1_highbd_block_error_c(const tran_low_t *coeff,
666 const tran_low_t *dqcoeff, intptr_t block_size,
667 int64_t *ssz, int bd) {
668 int i;
669 int64_t error = 0, sqcoeff = 0;
670 int shift = 2 * (bd - 8);
671 int rounding = shift > 0 ? 1 << (shift - 1) : 0;
672
673 for (i = 0; i < block_size; i++) {
674 const int64_t diff = coeff[i] - dqcoeff[i];
675 error += diff * diff;
676 sqcoeff += (int64_t)coeff[i] * (int64_t)coeff[i];
677 }
678 assert(error >= 0 && sqcoeff >= 0);
679 error = (error + rounding) >> shift;
680 sqcoeff = (sqcoeff + rounding) >> shift;
681
682 *ssz = sqcoeff;
683 return error;
684 }
685 #endif
686
conditional_skipintra(PREDICTION_MODE mode,PREDICTION_MODE best_intra_mode)687 static int conditional_skipintra(PREDICTION_MODE mode,
688 PREDICTION_MODE best_intra_mode) {
689 if (mode == D113_PRED && best_intra_mode != V_PRED &&
690 best_intra_mode != D135_PRED)
691 return 1;
692 if (mode == D67_PRED && best_intra_mode != V_PRED &&
693 best_intra_mode != D45_PRED)
694 return 1;
695 if (mode == D203_PRED && best_intra_mode != H_PRED &&
696 best_intra_mode != D45_PRED)
697 return 1;
698 if (mode == D157_PRED && best_intra_mode != H_PRED &&
699 best_intra_mode != D135_PRED)
700 return 1;
701 return 0;
702 }
703
cost_mv_ref(const MACROBLOCK * const x,PREDICTION_MODE mode,int16_t mode_context)704 static int cost_mv_ref(const MACROBLOCK *const x, PREDICTION_MODE mode,
705 int16_t mode_context) {
706 if (is_inter_compound_mode(mode)) {
707 return x
708 ->inter_compound_mode_cost[mode_context][INTER_COMPOUND_OFFSET(mode)];
709 }
710
711 int mode_cost = 0;
712 int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
713
714 assert(is_inter_mode(mode));
715
716 if (mode == NEWMV) {
717 mode_cost = x->newmv_mode_cost[mode_ctx][0];
718 return mode_cost;
719 } else {
720 mode_cost = x->newmv_mode_cost[mode_ctx][1];
721 mode_ctx = (mode_context >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
722
723 if (mode == GLOBALMV) {
724 mode_cost += x->zeromv_mode_cost[mode_ctx][0];
725 return mode_cost;
726 } else {
727 mode_cost += x->zeromv_mode_cost[mode_ctx][1];
728 mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
729 mode_cost += x->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
730 return mode_cost;
731 }
732 }
733 }
734
get_single_mode(PREDICTION_MODE this_mode,int ref_idx)735 static INLINE PREDICTION_MODE get_single_mode(PREDICTION_MODE this_mode,
736 int ref_idx) {
737 return ref_idx ? compound_ref1_mode(this_mode)
738 : compound_ref0_mode(this_mode);
739 }
740
estimate_ref_frame_costs(const AV1_COMMON * cm,const MACROBLOCKD * xd,const MACROBLOCK * x,int segment_id,unsigned int * ref_costs_single,unsigned int (* ref_costs_comp)[REF_FRAMES])741 static AOM_INLINE void estimate_ref_frame_costs(
742 const AV1_COMMON *cm, const MACROBLOCKD *xd, const MACROBLOCK *x,
743 int segment_id, unsigned int *ref_costs_single,
744 unsigned int (*ref_costs_comp)[REF_FRAMES]) {
745 int seg_ref_active =
746 segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
747 if (seg_ref_active) {
748 memset(ref_costs_single, 0, REF_FRAMES * sizeof(*ref_costs_single));
749 int ref_frame;
750 for (ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame)
751 memset(ref_costs_comp[ref_frame], 0,
752 REF_FRAMES * sizeof((*ref_costs_comp)[0]));
753 } else {
754 int intra_inter_ctx = av1_get_intra_inter_context(xd);
755 ref_costs_single[INTRA_FRAME] = x->intra_inter_cost[intra_inter_ctx][0];
756 unsigned int base_cost = x->intra_inter_cost[intra_inter_ctx][1];
757
758 for (int i = LAST_FRAME; i <= ALTREF_FRAME; ++i)
759 ref_costs_single[i] = base_cost;
760
761 const int ctx_p1 = av1_get_pred_context_single_ref_p1(xd);
762 const int ctx_p2 = av1_get_pred_context_single_ref_p2(xd);
763 const int ctx_p3 = av1_get_pred_context_single_ref_p3(xd);
764 const int ctx_p4 = av1_get_pred_context_single_ref_p4(xd);
765 const int ctx_p5 = av1_get_pred_context_single_ref_p5(xd);
766 const int ctx_p6 = av1_get_pred_context_single_ref_p6(xd);
767
768 // Determine cost of a single ref frame, where frame types are represented
769 // by a tree:
770 // Level 0: add cost whether this ref is a forward or backward ref
771 ref_costs_single[LAST_FRAME] += x->single_ref_cost[ctx_p1][0][0];
772 ref_costs_single[LAST2_FRAME] += x->single_ref_cost[ctx_p1][0][0];
773 ref_costs_single[LAST3_FRAME] += x->single_ref_cost[ctx_p1][0][0];
774 ref_costs_single[GOLDEN_FRAME] += x->single_ref_cost[ctx_p1][0][0];
775 ref_costs_single[BWDREF_FRAME] += x->single_ref_cost[ctx_p1][0][1];
776 ref_costs_single[ALTREF2_FRAME] += x->single_ref_cost[ctx_p1][0][1];
777 ref_costs_single[ALTREF_FRAME] += x->single_ref_cost[ctx_p1][0][1];
778
779 // Level 1: if this ref is forward ref,
780 // add cost whether it is last/last2 or last3/golden
781 ref_costs_single[LAST_FRAME] += x->single_ref_cost[ctx_p3][2][0];
782 ref_costs_single[LAST2_FRAME] += x->single_ref_cost[ctx_p3][2][0];
783 ref_costs_single[LAST3_FRAME] += x->single_ref_cost[ctx_p3][2][1];
784 ref_costs_single[GOLDEN_FRAME] += x->single_ref_cost[ctx_p3][2][1];
785
786 // Level 1: if this ref is backward ref
787 // then add cost whether this ref is altref or backward ref
788 ref_costs_single[BWDREF_FRAME] += x->single_ref_cost[ctx_p2][1][0];
789 ref_costs_single[ALTREF2_FRAME] += x->single_ref_cost[ctx_p2][1][0];
790 ref_costs_single[ALTREF_FRAME] += x->single_ref_cost[ctx_p2][1][1];
791
792 // Level 2: further add cost whether this ref is last or last2
793 ref_costs_single[LAST_FRAME] += x->single_ref_cost[ctx_p4][3][0];
794 ref_costs_single[LAST2_FRAME] += x->single_ref_cost[ctx_p4][3][1];
795
796 // Level 2: last3 or golden
797 ref_costs_single[LAST3_FRAME] += x->single_ref_cost[ctx_p5][4][0];
798 ref_costs_single[GOLDEN_FRAME] += x->single_ref_cost[ctx_p5][4][1];
799
800 // Level 2: bwdref or altref2
801 ref_costs_single[BWDREF_FRAME] += x->single_ref_cost[ctx_p6][5][0];
802 ref_costs_single[ALTREF2_FRAME] += x->single_ref_cost[ctx_p6][5][1];
803
804 if (cm->current_frame.reference_mode != SINGLE_REFERENCE) {
805 // Similar to single ref, determine cost of compound ref frames.
806 // cost_compound_refs = cost_first_ref + cost_second_ref
807 const int bwdref_comp_ctx_p = av1_get_pred_context_comp_bwdref_p(xd);
808 const int bwdref_comp_ctx_p1 = av1_get_pred_context_comp_bwdref_p1(xd);
809 const int ref_comp_ctx_p = av1_get_pred_context_comp_ref_p(xd);
810 const int ref_comp_ctx_p1 = av1_get_pred_context_comp_ref_p1(xd);
811 const int ref_comp_ctx_p2 = av1_get_pred_context_comp_ref_p2(xd);
812
813 const int comp_ref_type_ctx = av1_get_comp_reference_type_context(xd);
814 unsigned int ref_bicomp_costs[REF_FRAMES] = { 0 };
815
816 ref_bicomp_costs[LAST_FRAME] = ref_bicomp_costs[LAST2_FRAME] =
817 ref_bicomp_costs[LAST3_FRAME] = ref_bicomp_costs[GOLDEN_FRAME] =
818 base_cost + x->comp_ref_type_cost[comp_ref_type_ctx][1];
819 ref_bicomp_costs[BWDREF_FRAME] = ref_bicomp_costs[ALTREF2_FRAME] = 0;
820 ref_bicomp_costs[ALTREF_FRAME] = 0;
821
822 // cost of first ref frame
823 ref_bicomp_costs[LAST_FRAME] += x->comp_ref_cost[ref_comp_ctx_p][0][0];
824 ref_bicomp_costs[LAST2_FRAME] += x->comp_ref_cost[ref_comp_ctx_p][0][0];
825 ref_bicomp_costs[LAST3_FRAME] += x->comp_ref_cost[ref_comp_ctx_p][0][1];
826 ref_bicomp_costs[GOLDEN_FRAME] += x->comp_ref_cost[ref_comp_ctx_p][0][1];
827
828 ref_bicomp_costs[LAST_FRAME] += x->comp_ref_cost[ref_comp_ctx_p1][1][0];
829 ref_bicomp_costs[LAST2_FRAME] += x->comp_ref_cost[ref_comp_ctx_p1][1][1];
830
831 ref_bicomp_costs[LAST3_FRAME] += x->comp_ref_cost[ref_comp_ctx_p2][2][0];
832 ref_bicomp_costs[GOLDEN_FRAME] += x->comp_ref_cost[ref_comp_ctx_p2][2][1];
833
834 // cost of second ref frame
835 ref_bicomp_costs[BWDREF_FRAME] +=
836 x->comp_bwdref_cost[bwdref_comp_ctx_p][0][0];
837 ref_bicomp_costs[ALTREF2_FRAME] +=
838 x->comp_bwdref_cost[bwdref_comp_ctx_p][0][0];
839 ref_bicomp_costs[ALTREF_FRAME] +=
840 x->comp_bwdref_cost[bwdref_comp_ctx_p][0][1];
841
842 ref_bicomp_costs[BWDREF_FRAME] +=
843 x->comp_bwdref_cost[bwdref_comp_ctx_p1][1][0];
844 ref_bicomp_costs[ALTREF2_FRAME] +=
845 x->comp_bwdref_cost[bwdref_comp_ctx_p1][1][1];
846
847 // cost: if one ref frame is forward ref, the other ref is backward ref
848 int ref0, ref1;
849 for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
850 for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1) {
851 ref_costs_comp[ref0][ref1] =
852 ref_bicomp_costs[ref0] + ref_bicomp_costs[ref1];
853 }
854 }
855
856 // cost: if both ref frames are the same side.
857 const int uni_comp_ref_ctx_p = av1_get_pred_context_uni_comp_ref_p(xd);
858 const int uni_comp_ref_ctx_p1 = av1_get_pred_context_uni_comp_ref_p1(xd);
859 const int uni_comp_ref_ctx_p2 = av1_get_pred_context_uni_comp_ref_p2(xd);
860 ref_costs_comp[LAST_FRAME][LAST2_FRAME] =
861 base_cost + x->comp_ref_type_cost[comp_ref_type_ctx][0] +
862 x->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
863 x->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][0];
864 ref_costs_comp[LAST_FRAME][LAST3_FRAME] =
865 base_cost + x->comp_ref_type_cost[comp_ref_type_ctx][0] +
866 x->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
867 x->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][1] +
868 x->uni_comp_ref_cost[uni_comp_ref_ctx_p2][2][0];
869 ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] =
870 base_cost + x->comp_ref_type_cost[comp_ref_type_ctx][0] +
871 x->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
872 x->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][1] +
873 x->uni_comp_ref_cost[uni_comp_ref_ctx_p2][2][1];
874 ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] =
875 base_cost + x->comp_ref_type_cost[comp_ref_type_ctx][0] +
876 x->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][1];
877 } else {
878 int ref0, ref1;
879 for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
880 for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1)
881 ref_costs_comp[ref0][ref1] = 512;
882 }
883 ref_costs_comp[LAST_FRAME][LAST2_FRAME] = 512;
884 ref_costs_comp[LAST_FRAME][LAST3_FRAME] = 512;
885 ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] = 512;
886 ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] = 512;
887 }
888 }
889 }
890
store_coding_context(MACROBLOCK * x,PICK_MODE_CONTEXT * ctx,int mode_index,int64_t comp_pred_diff[REFERENCE_MODES],int skippable)891 static AOM_INLINE void store_coding_context(
892 #if CONFIG_INTERNAL_STATS
893 MACROBLOCK *x, PICK_MODE_CONTEXT *ctx, int mode_index,
894 #else
895 MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
896 #endif // CONFIG_INTERNAL_STATS
897 int64_t comp_pred_diff[REFERENCE_MODES], int skippable) {
898 MACROBLOCKD *const xd = &x->e_mbd;
899
900 // Take a snapshot of the coding context so it can be
901 // restored if we decide to encode this way
902 ctx->rd_stats.skip = x->force_skip;
903 ctx->skippable = skippable;
904 #if CONFIG_INTERNAL_STATS
905 ctx->best_mode_index = mode_index;
906 #endif // CONFIG_INTERNAL_STATS
907 ctx->mic = *xd->mi[0];
908 ctx->mbmi_ext = *x->mbmi_ext;
909 ctx->single_pred_diff = (int)comp_pred_diff[SINGLE_REFERENCE];
910 ctx->comp_pred_diff = (int)comp_pred_diff[COMPOUND_REFERENCE];
911 ctx->hybrid_pred_diff = (int)comp_pred_diff[REFERENCE_MODE_SELECT];
912 }
913
setup_buffer_ref_mvs_inter(const AV1_COMP * const cpi,MACROBLOCK * x,MV_REFERENCE_FRAME ref_frame,BLOCK_SIZE block_size,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE])914 static AOM_INLINE void setup_buffer_ref_mvs_inter(
915 const AV1_COMP *const cpi, MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame,
916 BLOCK_SIZE block_size, struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
917 const AV1_COMMON *cm = &cpi->common;
918 const int num_planes = av1_num_planes(cm);
919 const YV12_BUFFER_CONFIG *scaled_ref_frame =
920 av1_get_scaled_ref_frame(cpi, ref_frame);
921 MACROBLOCKD *const xd = &x->e_mbd;
922 MB_MODE_INFO *const mbmi = xd->mi[0];
923 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
924 const struct scale_factors *const sf =
925 get_ref_scale_factors_const(cm, ref_frame);
926 const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_yv12_buf(cm, ref_frame);
927 assert(yv12 != NULL);
928
929 if (scaled_ref_frame) {
930 // Setup pred block based on scaled reference, because av1_mv_pred() doesn't
931 // support scaling.
932 av1_setup_pred_block(xd, yv12_mb[ref_frame], scaled_ref_frame, NULL, NULL,
933 num_planes);
934 } else {
935 av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
936 }
937
938 // Gets an initial list of candidate vectors from neighbours and orders them
939 av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
940 xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
941 mbmi_ext->mode_context);
942 // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
943 // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
944 av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
945 // Further refinement that is encode side only to test the top few candidates
946 // in full and choose the best as the center point for subsequent searches.
947 // The current implementation doesn't support scaling.
948 av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12_mb[ref_frame][0].stride,
949 ref_frame, block_size);
950
951 // Go back to unscaled reference.
952 if (scaled_ref_frame) {
953 // We had temporarily setup pred block based on scaled reference above. Go
954 // back to unscaled reference now, for subsequent use.
955 av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
956 }
957 }
958
959 #define LEFT_TOP_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
960 #define RIGHT_BOTTOM_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
961
962 // TODO(jingning): this mv clamping function should be block size dependent.
clamp_mv2(MV * mv,const MACROBLOCKD * xd)963 static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
964 const SubpelMvLimits mv_limits = { xd->mb_to_left_edge - LEFT_TOP_MARGIN,
965 xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
966 xd->mb_to_top_edge - LEFT_TOP_MARGIN,
967 xd->mb_to_bottom_edge +
968 RIGHT_BOTTOM_MARGIN };
969 clamp_mv(mv, &mv_limits);
970 }
971
972 /* If the current mode shares the same mv with other modes with higher cost,
973 * skip this mode. */
skip_repeated_mv(const AV1_COMMON * const cm,const MACROBLOCK * const x,PREDICTION_MODE this_mode,const MV_REFERENCE_FRAME ref_frames[2],InterModeSearchState * search_state)974 static int skip_repeated_mv(const AV1_COMMON *const cm,
975 const MACROBLOCK *const x,
976 PREDICTION_MODE this_mode,
977 const MV_REFERENCE_FRAME ref_frames[2],
978 InterModeSearchState *search_state) {
979 const int is_comp_pred = ref_frames[1] > INTRA_FRAME;
980 const uint8_t ref_frame_type = av1_ref_frame_type(ref_frames);
981 const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
982 const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
983 PREDICTION_MODE compare_mode = MB_MODE_COUNT;
984 if (!is_comp_pred) {
985 if (this_mode == NEARMV) {
986 if (ref_mv_count == 0) {
987 // NEARMV has the same motion vector as NEARESTMV
988 compare_mode = NEARESTMV;
989 }
990 if (ref_mv_count == 1 &&
991 cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) {
992 // NEARMV has the same motion vector as GLOBALMV
993 compare_mode = GLOBALMV;
994 }
995 }
996 if (this_mode == GLOBALMV) {
997 if (ref_mv_count == 0 &&
998 cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) {
999 // GLOBALMV has the same motion vector as NEARESTMV
1000 compare_mode = NEARESTMV;
1001 }
1002 if (ref_mv_count == 1) {
1003 // GLOBALMV has the same motion vector as NEARMV
1004 compare_mode = NEARMV;
1005 }
1006 }
1007
1008 if (compare_mode != MB_MODE_COUNT) {
1009 // Use modelled_rd to check whether compare mode was searched
1010 if (search_state->modelled_rd[compare_mode][0][ref_frames[0]] !=
1011 INT64_MAX) {
1012 const int16_t mode_ctx =
1013 av1_mode_context_analyzer(mbmi_ext->mode_context, ref_frames);
1014 const int compare_cost = cost_mv_ref(x, compare_mode, mode_ctx);
1015 const int this_cost = cost_mv_ref(x, this_mode, mode_ctx);
1016
1017 // Only skip if the mode cost is larger than compare mode cost
1018 if (this_cost > compare_cost) {
1019 search_state->modelled_rd[this_mode][0][ref_frames[0]] =
1020 search_state->modelled_rd[compare_mode][0][ref_frames[0]];
1021 return 1;
1022 }
1023 }
1024 }
1025 }
1026 return 0;
1027 }
1028
clamp_and_check_mv(int_mv * out_mv,int_mv in_mv,const AV1_COMMON * cm,const MACROBLOCK * x)1029 static INLINE int clamp_and_check_mv(int_mv *out_mv, int_mv in_mv,
1030 const AV1_COMMON *cm,
1031 const MACROBLOCK *x) {
1032 const MACROBLOCKD *const xd = &x->e_mbd;
1033 *out_mv = in_mv;
1034 lower_mv_precision(&out_mv->as_mv, cm->allow_high_precision_mv,
1035 cm->cur_frame_force_integer_mv);
1036 clamp_mv2(&out_mv->as_mv, xd);
1037 return av1_is_fullmv_in_range(&x->mv_limits,
1038 get_fullmv_from_mv(&out_mv->as_mv));
1039 }
1040
1041 // To use single newmv directly for compound modes, need to clamp the mv to the
1042 // valid mv range. Without this, encoder would generate out of range mv, and
1043 // this is seen in 8k encoding.
clamp_mv_in_range(MACROBLOCK * const x,int_mv * mv,int ref_idx)1044 static INLINE void clamp_mv_in_range(MACROBLOCK *const x, int_mv *mv,
1045 int ref_idx) {
1046 const int_mv ref_mv = av1_get_ref_mv(x, ref_idx);
1047 SubpelMvLimits mv_limits;
1048
1049 av1_set_subpel_mv_search_range(&mv_limits, &x->mv_limits, &ref_mv.as_mv);
1050 clamp_mv(&mv->as_mv, &mv_limits);
1051 }
1052
handle_newmv(const AV1_COMP * const cpi,MACROBLOCK * const x,const BLOCK_SIZE bsize,int_mv * cur_mv,int * const rate_mv,HandleInterModeArgs * const args,inter_mode_info * mode_info)1053 static int64_t handle_newmv(const AV1_COMP *const cpi, MACROBLOCK *const x,
1054 const BLOCK_SIZE bsize, int_mv *cur_mv,
1055 int *const rate_mv, HandleInterModeArgs *const args,
1056 inter_mode_info *mode_info) {
1057 const MACROBLOCKD *const xd = &x->e_mbd;
1058 const MB_MODE_INFO *const mbmi = xd->mi[0];
1059 const int is_comp_pred = has_second_ref(mbmi);
1060 const PREDICTION_MODE this_mode = mbmi->mode;
1061 const int refs[2] = { mbmi->ref_frame[0],
1062 mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
1063 const int ref_mv_idx = mbmi->ref_mv_idx;
1064
1065 if (is_comp_pred) {
1066 const int valid_mv0 = args->single_newmv_valid[ref_mv_idx][refs[0]];
1067 const int valid_mv1 = args->single_newmv_valid[ref_mv_idx][refs[1]];
1068
1069 if (this_mode == NEW_NEWMV) {
1070 if (valid_mv0) {
1071 cur_mv[0].as_int = args->single_newmv[ref_mv_idx][refs[0]].as_int;
1072 clamp_mv_in_range(x, &cur_mv[0], 0);
1073 }
1074 if (valid_mv1) {
1075 cur_mv[1].as_int = args->single_newmv[ref_mv_idx][refs[1]].as_int;
1076 clamp_mv_in_range(x, &cur_mv[1], 1);
1077 }
1078
1079 // aomenc1
1080 if (cpi->sf.inter_sf.comp_inter_joint_search_thresh <= bsize ||
1081 !valid_mv0 || !valid_mv1) {
1082 av1_joint_motion_search(cpi, x, bsize, cur_mv, NULL, 0, rate_mv);
1083 } else {
1084 *rate_mv = 0;
1085 for (int i = 0; i < 2; ++i) {
1086 const int_mv ref_mv = av1_get_ref_mv(x, i);
1087 *rate_mv +=
1088 av1_mv_bit_cost(&cur_mv[i].as_mv, &ref_mv.as_mv, x->nmv_vec_cost,
1089 x->mv_cost_stack, MV_COST_WEIGHT);
1090 }
1091 }
1092 } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
1093 if (valid_mv1) {
1094 cur_mv[1].as_int = args->single_newmv[ref_mv_idx][refs[1]].as_int;
1095 clamp_mv_in_range(x, &cur_mv[1], 1);
1096 }
1097
1098 // aomenc2
1099 if (cpi->sf.inter_sf.comp_inter_joint_search_thresh <= bsize ||
1100 !valid_mv1) {
1101 av1_compound_single_motion_search_interinter(cpi, x, bsize, cur_mv,
1102 NULL, 0, rate_mv, 1);
1103 } else {
1104 const int_mv ref_mv = av1_get_ref_mv(x, 1);
1105 *rate_mv =
1106 av1_mv_bit_cost(&cur_mv[1].as_mv, &ref_mv.as_mv, x->nmv_vec_cost,
1107 x->mv_cost_stack, MV_COST_WEIGHT);
1108 }
1109 } else {
1110 assert(this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV);
1111 if (valid_mv0) {
1112 cur_mv[0].as_int = args->single_newmv[ref_mv_idx][refs[0]].as_int;
1113 clamp_mv_in_range(x, &cur_mv[0], 0);
1114 }
1115
1116 // aomenc3
1117 if (cpi->sf.inter_sf.comp_inter_joint_search_thresh <= bsize ||
1118 !valid_mv0) {
1119 av1_compound_single_motion_search_interinter(cpi, x, bsize, cur_mv,
1120 NULL, 0, rate_mv, 0);
1121 } else {
1122 const int_mv ref_mv = av1_get_ref_mv(x, 0);
1123 *rate_mv =
1124 av1_mv_bit_cost(&cur_mv[0].as_mv, &ref_mv.as_mv, x->nmv_vec_cost,
1125 x->mv_cost_stack, MV_COST_WEIGHT);
1126 }
1127 }
1128 } else {
1129 // Single ref case.
1130 const int ref_idx = 0;
1131 int search_range = INT_MAX;
1132
1133 if (cpi->sf.mv_sf.reduce_search_range && mbmi->ref_mv_idx > 0) {
1134 const MV ref_mv = av1_get_ref_mv(x, ref_idx).as_mv;
1135 int min_mv_diff = INT_MAX;
1136 int best_match = -1;
1137 MV prev_ref_mv[2] = { { 0 } };
1138 for (int idx = 0; idx < mbmi->ref_mv_idx; ++idx) {
1139 prev_ref_mv[idx] = av1_get_ref_mv_from_stack(ref_idx, mbmi->ref_frame,
1140 idx, x->mbmi_ext)
1141 .as_mv;
1142 const int ref_mv_diff = AOMMAX(abs(ref_mv.row - prev_ref_mv[idx].row),
1143 abs(ref_mv.col - prev_ref_mv[idx].col));
1144
1145 if (min_mv_diff > ref_mv_diff) {
1146 min_mv_diff = ref_mv_diff;
1147 best_match = idx;
1148 }
1149 }
1150
1151 if (min_mv_diff < (16 << 3)) {
1152 if (args->single_newmv_valid[best_match][refs[0]]) {
1153 search_range = min_mv_diff;
1154 search_range +=
1155 AOMMAX(abs(args->single_newmv[best_match][refs[0]].as_mv.row -
1156 prev_ref_mv[best_match].row),
1157 abs(args->single_newmv[best_match][refs[0]].as_mv.col -
1158 prev_ref_mv[best_match].col));
1159 // Get full pixel search range.
1160 search_range = (search_range + 4) >> 3;
1161 }
1162 }
1163 }
1164
1165 av1_single_motion_search(cpi, x, bsize, ref_idx, rate_mv, search_range,
1166 mode_info);
1167 if (x->best_mv.as_int == INVALID_MV) return INT64_MAX;
1168
1169 args->single_newmv[ref_mv_idx][refs[0]] = x->best_mv;
1170 args->single_newmv_rate[ref_mv_idx][refs[0]] = *rate_mv;
1171 args->single_newmv_valid[ref_mv_idx][refs[0]] = 1;
1172
1173 cur_mv[0].as_int = x->best_mv.as_int;
1174 }
1175
1176 return 0;
1177 }
1178
1179 // If number of valid neighbours is 1,
1180 // 1) ROTZOOM parameters can be obtained reliably (2 parameters from
1181 // one neighbouring MV)
1182 // 2) For IDENTITY/TRANSLATION cases, warp can perform better due to
1183 // a different interpolation filter being used. However the quality
1184 // gains (due to the same) may not be much
1185 // For above 2 cases warp evaluation is skipped
1186
check_if_optimal_warp(const AV1_COMP * cpi,WarpedMotionParams * wm_params,int num_proj_ref)1187 static int check_if_optimal_warp(const AV1_COMP *cpi,
1188 WarpedMotionParams *wm_params,
1189 int num_proj_ref) {
1190 int is_valid_warp = 1;
1191 if (cpi->sf.inter_sf.prune_warp_using_wmtype) {
1192 TransformationType wmtype = get_wmtype(wm_params);
1193 if (num_proj_ref == 1) {
1194 if (wmtype != ROTZOOM) is_valid_warp = 0;
1195 } else {
1196 if (wmtype < ROTZOOM) is_valid_warp = 0;
1197 }
1198 }
1199 return is_valid_warp;
1200 }
1201
update_mode_start_end_index(const AV1_COMP * const cpi,int * mode_index_start,int * mode_index_end,int last_motion_mode_allowed,int interintra_allowed,int eval_motion_mode)1202 static INLINE void update_mode_start_end_index(const AV1_COMP *const cpi,
1203 int *mode_index_start,
1204 int *mode_index_end,
1205 int last_motion_mode_allowed,
1206 int interintra_allowed,
1207 int eval_motion_mode) {
1208 *mode_index_start = (int)SIMPLE_TRANSLATION;
1209 *mode_index_end = (int)last_motion_mode_allowed + interintra_allowed;
1210 if (cpi->sf.winner_mode_sf.motion_mode_for_winner_cand) {
1211 if (!eval_motion_mode) {
1212 *mode_index_end = (int)SIMPLE_TRANSLATION;
1213 } else {
1214 // Set the start index appropriately to process motion modes other than
1215 // simple translation
1216 *mode_index_start = 1;
1217 }
1218 }
1219 }
1220
1221 // TODO(afergs): Refactor the MBMI references in here - there's four
1222 // TODO(afergs): Refactor optional args - add them to a struct or remove
motion_mode_rd(const AV1_COMP * const cpi,TileDataEnc * tile_data,MACROBLOCK * const x,BLOCK_SIZE bsize,RD_STATS * rd_stats,RD_STATS * rd_stats_y,RD_STATS * rd_stats_uv,int * disable_skip,HandleInterModeArgs * const args,int64_t ref_best_rd,int64_t * ref_skip_rd,int * rate_mv,const BUFFER_SET * orig_dst,int64_t * best_est_rd,int do_tx_search,InterModesInfo * inter_modes_info,int eval_motion_mode)1223 static int64_t motion_mode_rd(
1224 const AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *const x,
1225 BLOCK_SIZE bsize, RD_STATS *rd_stats, RD_STATS *rd_stats_y,
1226 RD_STATS *rd_stats_uv, int *disable_skip, HandleInterModeArgs *const args,
1227 int64_t ref_best_rd, int64_t *ref_skip_rd, int *rate_mv,
1228 const BUFFER_SET *orig_dst, int64_t *best_est_rd, int do_tx_search,
1229 InterModesInfo *inter_modes_info, int eval_motion_mode) {
1230 const AV1_COMMON *const cm = &cpi->common;
1231 const int num_planes = av1_num_planes(cm);
1232 MACROBLOCKD *xd = &x->e_mbd;
1233 MB_MODE_INFO *mbmi = xd->mi[0];
1234 const int is_comp_pred = has_second_ref(mbmi);
1235 const PREDICTION_MODE this_mode = mbmi->mode;
1236 const int rate2_nocoeff = rd_stats->rate;
1237 int best_xskip = 0, best_disable_skip = 0;
1238 RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
1239 uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
1240 uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
1241 const int rate_mv0 = *rate_mv;
1242 const int interintra_allowed = cm->seq_params.enable_interintra_compound &&
1243 is_interintra_allowed(mbmi) &&
1244 mbmi->compound_idx;
1245 int pts0[SAMPLES_ARRAY_SIZE], pts_inref0[SAMPLES_ARRAY_SIZE];
1246
1247 assert(mbmi->ref_frame[1] != INTRA_FRAME);
1248 const MV_REFERENCE_FRAME ref_frame_1 = mbmi->ref_frame[1];
1249 (void)tile_data;
1250 av1_invalid_rd_stats(&best_rd_stats);
1251 aom_clear_system_state();
1252 mbmi->num_proj_ref = 1; // assume num_proj_ref >=1
1253 MOTION_MODE last_motion_mode_allowed = SIMPLE_TRANSLATION;
1254 if (cm->switchable_motion_mode) {
1255 last_motion_mode_allowed = motion_mode_allowed(xd->global_motion, xd, mbmi,
1256 cm->allow_warped_motion);
1257 }
1258
1259 if (last_motion_mode_allowed == WARPED_CAUSAL) {
1260 mbmi->num_proj_ref = av1_findSamples(cm, xd, pts0, pts_inref0);
1261 }
1262 const int total_samples = mbmi->num_proj_ref;
1263 if (total_samples == 0) {
1264 last_motion_mode_allowed = OBMC_CAUSAL;
1265 }
1266
1267 const MB_MODE_INFO base_mbmi = *mbmi;
1268 MB_MODE_INFO best_mbmi;
1269 SimpleRDState *const simple_states = &args->simple_rd_state[mbmi->ref_mv_idx];
1270 const int switchable_rate =
1271 av1_is_interp_needed(xd) ? av1_get_switchable_rate(cm, x, xd) : 0;
1272 int64_t best_rd = INT64_MAX;
1273 int best_rate_mv = rate_mv0;
1274 const int mi_row = xd->mi_row;
1275 const int mi_col = xd->mi_col;
1276 int mode_index_start, mode_index_end;
1277 update_mode_start_end_index(cpi, &mode_index_start, &mode_index_end,
1278 last_motion_mode_allowed, interintra_allowed,
1279 eval_motion_mode);
1280 for (int mode_index = mode_index_start; mode_index <= mode_index_end;
1281 mode_index++) {
1282 if (args->skip_motion_mode && mode_index) continue;
1283 if (cpi->sf.inter_sf.prune_single_motion_modes_by_simple_trans &&
1284 args->single_ref_first_pass && mode_index)
1285 break;
1286 int tmp_rate2 = rate2_nocoeff;
1287 const int is_interintra_mode = mode_index > (int)last_motion_mode_allowed;
1288 int tmp_rate_mv = rate_mv0;
1289
1290 *mbmi = base_mbmi;
1291 if (is_interintra_mode) {
1292 mbmi->motion_mode = SIMPLE_TRANSLATION;
1293 } else {
1294 mbmi->motion_mode = (MOTION_MODE)mode_index;
1295 assert(mbmi->ref_frame[1] != INTRA_FRAME);
1296 }
1297
1298 const FRAME_UPDATE_TYPE update_type = get_frame_update_type(&cpi->gf_group);
1299 const int prune_obmc = cpi->obmc_probs[update_type][bsize] <
1300 cpi->sf.inter_sf.prune_obmc_prob_thresh;
1301 if ((cpi->oxcf.enable_obmc == 0 || cpi->sf.inter_sf.disable_obmc ||
1302 cpi->sf.rt_sf.use_nonrd_pick_mode || prune_obmc) &&
1303 mbmi->motion_mode == OBMC_CAUSAL)
1304 continue;
1305
1306 if (mbmi->motion_mode == SIMPLE_TRANSLATION && !is_interintra_mode) {
1307 // SIMPLE_TRANSLATION mode: no need to recalculate.
1308 // The prediction is calculated before motion_mode_rd() is called in
1309 // handle_inter_mode()
1310 if (cpi->sf.inter_sf.prune_single_motion_modes_by_simple_trans &&
1311 !is_comp_pred) {
1312 if (args->single_ref_first_pass == 0) {
1313 if (simple_states->early_skipped) {
1314 assert(simple_states->rd_stats.rdcost == INT64_MAX);
1315 return INT64_MAX;
1316 }
1317 if (simple_states->rd_stats.rdcost != INT64_MAX) {
1318 best_rd = simple_states->rd_stats.rdcost;
1319 best_rd_stats = simple_states->rd_stats;
1320 best_rd_stats_y = simple_states->rd_stats_y;
1321 best_rd_stats_uv = simple_states->rd_stats_uv;
1322 memcpy(best_blk_skip, simple_states->blk_skip,
1323 sizeof(x->blk_skip[0]) * xd->n4_h * xd->n4_w);
1324 av1_copy_array(best_tx_type_map, simple_states->tx_type_map,
1325 xd->n4_h * xd->n4_w);
1326 best_xskip = simple_states->skip;
1327 best_disable_skip = simple_states->disable_skip;
1328 best_mbmi = *mbmi;
1329 }
1330 continue;
1331 }
1332 simple_states->early_skipped = 0;
1333 }
1334 } else if (mbmi->motion_mode == OBMC_CAUSAL) {
1335 const uint32_t cur_mv = mbmi->mv[0].as_int;
1336 assert(!is_comp_pred);
1337 if (have_newmv_in_inter_mode(this_mode)) {
1338 av1_single_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, INT_MAX, NULL);
1339 mbmi->mv[0].as_int = x->best_mv.as_int;
1340 tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
1341 }
1342 if ((mbmi->mv[0].as_int != cur_mv) || eval_motion_mode) {
1343 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
1344 0, av1_num_planes(cm) - 1);
1345 }
1346 av1_build_obmc_inter_prediction(
1347 cm, xd, args->above_pred_buf, args->above_pred_stride,
1348 args->left_pred_buf, args->left_pred_stride);
1349 } else if (mbmi->motion_mode == WARPED_CAUSAL) {
1350 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
1351 mbmi->motion_mode = WARPED_CAUSAL;
1352 mbmi->wm_params.wmtype = DEFAULT_WMTYPE;
1353 mbmi->interp_filters = av1_broadcast_interp_filter(
1354 av1_unswitchable_filter(cm->interp_filter));
1355
1356 memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
1357 memcpy(pts_inref, pts_inref0, total_samples * 2 * sizeof(*pts_inref0));
1358 // Select the samples according to motion vector difference
1359 if (mbmi->num_proj_ref > 1) {
1360 mbmi->num_proj_ref = av1_selectSamples(
1361 &mbmi->mv[0].as_mv, pts, pts_inref, mbmi->num_proj_ref, bsize);
1362 }
1363
1364 if (!av1_find_projection(mbmi->num_proj_ref, pts, pts_inref, bsize,
1365 mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
1366 &mbmi->wm_params, mi_row, mi_col)) {
1367 // Refine MV for NEWMV mode
1368 assert(!is_comp_pred);
1369 if (have_newmv_in_inter_mode(this_mode)) {
1370 const int_mv mv0 = mbmi->mv[0];
1371 const WarpedMotionParams wm_params0 = mbmi->wm_params;
1372 const int num_proj_ref0 = mbmi->num_proj_ref;
1373
1374 if (cpi->sf.inter_sf.prune_warp_using_wmtype) {
1375 TransformationType wmtype = get_wmtype(&mbmi->wm_params);
1376 if (wmtype < ROTZOOM) continue;
1377 }
1378
1379 // Refine MV in a small range.
1380 av1_refine_warped_mv(cpi, x, bsize, pts0, pts_inref0, total_samples);
1381
1382 // Keep the refined MV and WM parameters.
1383 if (mv0.as_int != mbmi->mv[0].as_int) {
1384 const int_mv ref_mv = av1_get_ref_mv(x, 0);
1385 tmp_rate_mv = av1_mv_bit_cost(&mbmi->mv[0].as_mv, &ref_mv.as_mv,
1386 x->nmv_vec_cost, x->mv_cost_stack,
1387 MV_COST_WEIGHT);
1388 if (cpi->sf.mv_sf.adaptive_motion_search) {
1389 x->pred_mv[mbmi->ref_frame[0]] = mbmi->mv[0].as_mv;
1390 }
1391 tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
1392 } else {
1393 // Restore the old MV and WM parameters.
1394 mbmi->mv[0] = mv0;
1395 mbmi->wm_params = wm_params0;
1396 mbmi->num_proj_ref = num_proj_ref0;
1397 }
1398 } else {
1399 if (!check_if_optimal_warp(cpi, &mbmi->wm_params, mbmi->num_proj_ref))
1400 continue;
1401 }
1402
1403 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
1404 av1_num_planes(cm) - 1);
1405 } else {
1406 continue;
1407 }
1408 } else if (is_interintra_mode) {
1409 const int ret =
1410 av1_handle_inter_intra_mode(cpi, x, bsize, mbmi, args, ref_best_rd,
1411 &tmp_rate_mv, &tmp_rate2, orig_dst);
1412 if (ret < 0) continue;
1413 }
1414
1415 // If we are searching newmv and the mv is the same as refmv, skip the
1416 // current mode
1417 if (this_mode == NEW_NEWMV) {
1418 const int_mv ref_mv_0 = av1_get_ref_mv(x, 0);
1419 const int_mv ref_mv_1 = av1_get_ref_mv(x, 1);
1420 if (mbmi->mv[0].as_int == ref_mv_0.as_int ||
1421 mbmi->mv[1].as_int == ref_mv_1.as_int) {
1422 continue;
1423 }
1424 } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
1425 const int_mv ref_mv_1 = av1_get_ref_mv(x, 1);
1426 if (mbmi->mv[1].as_int == ref_mv_1.as_int) {
1427 continue;
1428 }
1429 } else if (this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV) {
1430 const int_mv ref_mv_0 = av1_get_ref_mv(x, 0);
1431 if (mbmi->mv[0].as_int == ref_mv_0.as_int) {
1432 continue;
1433 }
1434 } else if (this_mode == NEWMV) {
1435 const int_mv ref_mv_0 = av1_get_ref_mv(x, 0);
1436 if (mbmi->mv[0].as_int == ref_mv_0.as_int) {
1437 continue;
1438 }
1439 }
1440
1441 x->force_skip = 0;
1442 rd_stats->dist = 0;
1443 rd_stats->sse = 0;
1444 rd_stats->skip = 1;
1445 rd_stats->rate = tmp_rate2;
1446 if (mbmi->motion_mode != WARPED_CAUSAL) rd_stats->rate += switchable_rate;
1447 if (interintra_allowed) {
1448 rd_stats->rate += x->interintra_cost[size_group_lookup[bsize]]
1449 [mbmi->ref_frame[1] == INTRA_FRAME];
1450 if (mbmi->ref_frame[1] == INTRA_FRAME) {
1451 rd_stats->rate += x->interintra_mode_cost[size_group_lookup[bsize]]
1452 [mbmi->interintra_mode];
1453 if (av1_is_wedge_used(bsize)) {
1454 rd_stats->rate +=
1455 x->wedge_interintra_cost[bsize][mbmi->use_wedge_interintra];
1456 if (mbmi->use_wedge_interintra) {
1457 rd_stats->rate +=
1458 x->wedge_idx_cost[bsize][mbmi->interintra_wedge_index];
1459 }
1460 }
1461 }
1462 }
1463 if ((last_motion_mode_allowed > SIMPLE_TRANSLATION) &&
1464 (mbmi->ref_frame[1] != INTRA_FRAME)) {
1465 if (last_motion_mode_allowed == WARPED_CAUSAL) {
1466 rd_stats->rate += x->motion_mode_cost[bsize][mbmi->motion_mode];
1467 } else {
1468 rd_stats->rate += x->motion_mode_cost1[bsize][mbmi->motion_mode];
1469 }
1470 }
1471
1472 if (!do_tx_search) {
1473 int64_t curr_sse = -1;
1474 int64_t sse_y = -1;
1475 int est_residue_cost = 0;
1476 int64_t est_dist = 0;
1477 int64_t est_rd = 0;
1478 if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
1479 curr_sse = get_sse(cpi, x, &sse_y);
1480 // Scale luma SSE as per bit depth so as to be consistent with
1481 // model_rd_sb_fn and compound type rd
1482 sse_y = ROUND_POWER_OF_TWO(sse_y, (xd->bd - 8) * 2);
1483 const int has_est_rd = get_est_rate_dist(tile_data, bsize, curr_sse,
1484 &est_residue_cost, &est_dist);
1485 (void)has_est_rd;
1486 assert(has_est_rd);
1487 } else if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 2 ||
1488 cpi->sf.rt_sf.use_nonrd_pick_mode) {
1489 model_rd_sb_fn[MODELRD_TYPE_MOTION_MODE_RD](
1490 cpi, bsize, x, xd, 0, num_planes - 1, &est_residue_cost, &est_dist,
1491 NULL, &curr_sse, NULL, NULL, NULL);
1492 sse_y = x->pred_sse[xd->mi[0]->ref_frame[0]];
1493 }
1494 est_rd = RDCOST(x->rdmult, rd_stats->rate + est_residue_cost, est_dist);
1495 if (est_rd * 0.80 > *best_est_rd) {
1496 mbmi->ref_frame[1] = ref_frame_1;
1497 continue;
1498 }
1499 const int mode_rate = rd_stats->rate;
1500 rd_stats->rate += est_residue_cost;
1501 rd_stats->dist = est_dist;
1502 rd_stats->rdcost = est_rd;
1503 if (rd_stats->rdcost < *best_est_rd) {
1504 *best_est_rd = rd_stats->rdcost;
1505 assert(sse_y >= 0);
1506 ref_skip_rd[1] = cpi->sf.inter_sf.txfm_rd_gate_level
1507 ? RDCOST(x->rdmult, mode_rate, (sse_y << 4))
1508 : INT64_MAX;
1509 }
1510 if (cm->current_frame.reference_mode == SINGLE_REFERENCE) {
1511 if (!is_comp_pred) {
1512 assert(curr_sse >= 0);
1513 inter_modes_info_push(inter_modes_info, mode_rate, curr_sse,
1514 rd_stats->rdcost, rd_stats, rd_stats_y,
1515 rd_stats_uv, mbmi);
1516 }
1517 } else {
1518 assert(curr_sse >= 0);
1519 inter_modes_info_push(inter_modes_info, mode_rate, curr_sse,
1520 rd_stats->rdcost, rd_stats, rd_stats_y,
1521 rd_stats_uv, mbmi);
1522 }
1523 mbmi->skip = 0;
1524 } else {
1525 int64_t skip_rd = INT64_MAX;
1526 int64_t skip_rdy = INT64_MAX;
1527 if (cpi->sf.inter_sf.txfm_rd_gate_level) {
1528 // Check if the mode is good enough based on skip RD
1529 int64_t sse_y = INT64_MAX;
1530 int64_t curr_sse = get_sse(cpi, x, &sse_y);
1531 // Scale luma SSE as per bit depth so as to be consistent with
1532 // model_rd_sb_fn and compound type rd
1533 sse_y = ROUND_POWER_OF_TWO(sse_y, (xd->bd - 8) * 2);
1534 skip_rd = RDCOST(x->rdmult, rd_stats->rate, curr_sse);
1535 skip_rdy = RDCOST(x->rdmult, rd_stats->rate, (sse_y << 4));
1536 int eval_txfm = check_txfm_eval(x, bsize, ref_skip_rd[0], skip_rd,
1537 cpi->sf.inter_sf.txfm_rd_gate_level, 0);
1538 if (!eval_txfm) continue;
1539 }
1540
1541 if (!av1_txfm_search(cpi, tile_data, x, bsize, rd_stats, rd_stats_y,
1542 rd_stats_uv, rd_stats->rate, ref_best_rd)) {
1543 if (rd_stats_y->rate == INT_MAX && mode_index == 0) {
1544 if (cpi->sf.inter_sf.prune_single_motion_modes_by_simple_trans &&
1545 !is_comp_pred) {
1546 simple_states->early_skipped = 1;
1547 }
1548 return INT64_MAX;
1549 }
1550 continue;
1551 }
1552
1553 const int64_t curr_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
1554 if (curr_rd < ref_best_rd) {
1555 ref_best_rd = curr_rd;
1556 ref_skip_rd[0] = skip_rd;
1557 ref_skip_rd[1] = skip_rdy;
1558 }
1559 *disable_skip = 0;
1560 if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
1561 const int skip_ctx = av1_get_skip_context(xd);
1562 inter_mode_data_push(tile_data, mbmi->sb_type, rd_stats->sse,
1563 rd_stats->dist,
1564 rd_stats_y->rate + rd_stats_uv->rate +
1565 x->skip_cost[skip_ctx][mbmi->skip]);
1566 }
1567 }
1568
1569 if (this_mode == GLOBALMV || this_mode == GLOBAL_GLOBALMV) {
1570 if (is_nontrans_global_motion(xd, xd->mi[0])) {
1571 mbmi->interp_filters = av1_broadcast_interp_filter(
1572 av1_unswitchable_filter(cm->interp_filter));
1573 }
1574 }
1575
1576 const int64_t tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
1577 if (mode_index == 0) {
1578 args->simple_rd[this_mode][mbmi->ref_mv_idx][mbmi->ref_frame[0]] = tmp_rd;
1579 if (!is_comp_pred) {
1580 simple_states->rd_stats = *rd_stats;
1581 simple_states->rd_stats.rdcost = tmp_rd;
1582 simple_states->rd_stats_y = *rd_stats_y;
1583 simple_states->rd_stats_uv = *rd_stats_uv;
1584 memcpy(simple_states->blk_skip, x->blk_skip,
1585 sizeof(x->blk_skip[0]) * xd->n4_h * xd->n4_w);
1586 av1_copy_array(simple_states->tx_type_map, xd->tx_type_map,
1587 xd->n4_h * xd->n4_w);
1588 simple_states->skip = mbmi->skip;
1589 simple_states->disable_skip = *disable_skip;
1590 }
1591 }
1592 if (mode_index == 0 || tmp_rd < best_rd) {
1593 best_mbmi = *mbmi;
1594 best_rd = tmp_rd;
1595 best_rd_stats = *rd_stats;
1596 best_rd_stats_y = *rd_stats_y;
1597 best_rate_mv = tmp_rate_mv;
1598 if (num_planes > 1) best_rd_stats_uv = *rd_stats_uv;
1599 memcpy(best_blk_skip, x->blk_skip,
1600 sizeof(x->blk_skip[0]) * xd->n4_h * xd->n4_w);
1601 av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->n4_h * xd->n4_w);
1602 best_xskip = mbmi->skip;
1603 best_disable_skip = *disable_skip;
1604 // TODO(anyone): evaluate the quality and speed trade-off of the early
1605 // termination logic below.
1606 // if (best_xskip) break;
1607 }
1608 }
1609 mbmi->ref_frame[1] = ref_frame_1;
1610 *rate_mv = best_rate_mv;
1611 if (best_rd == INT64_MAX) {
1612 av1_invalid_rd_stats(rd_stats);
1613 restore_dst_buf(xd, *orig_dst, num_planes);
1614 return INT64_MAX;
1615 }
1616 *mbmi = best_mbmi;
1617 *rd_stats = best_rd_stats;
1618 *rd_stats_y = best_rd_stats_y;
1619 if (num_planes > 1) *rd_stats_uv = best_rd_stats_uv;
1620 memcpy(x->blk_skip, best_blk_skip,
1621 sizeof(x->blk_skip[0]) * xd->n4_h * xd->n4_w);
1622 av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->n4_h * xd->n4_w);
1623 x->force_skip = best_xskip;
1624 *disable_skip = best_disable_skip;
1625
1626 restore_dst_buf(xd, *orig_dst, num_planes);
1627 return 0;
1628 }
1629
skip_mode_rd(RD_STATS * rd_stats,const AV1_COMP * const cpi,MACROBLOCK * const x,BLOCK_SIZE bsize,const BUFFER_SET * const orig_dst)1630 static int64_t skip_mode_rd(RD_STATS *rd_stats, const AV1_COMP *const cpi,
1631 MACROBLOCK *const x, BLOCK_SIZE bsize,
1632 const BUFFER_SET *const orig_dst) {
1633 assert(bsize < BLOCK_SIZES_ALL);
1634 const AV1_COMMON *cm = &cpi->common;
1635 const int num_planes = av1_num_planes(cm);
1636 MACROBLOCKD *const xd = &x->e_mbd;
1637 const int mi_row = xd->mi_row;
1638 const int mi_col = xd->mi_col;
1639 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize, 0,
1640 av1_num_planes(cm) - 1);
1641
1642 int64_t total_sse = 0;
1643 for (int plane = 0; plane < num_planes; ++plane) {
1644 const struct macroblock_plane *const p = &x->plane[plane];
1645 const struct macroblockd_plane *const pd = &xd->plane[plane];
1646 const BLOCK_SIZE plane_bsize =
1647 get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
1648 const int bw = block_size_wide[plane_bsize];
1649 const int bh = block_size_high[plane_bsize];
1650
1651 av1_subtract_plane(x, plane_bsize, plane);
1652 int64_t sse = aom_sum_squares_2d_i16(p->src_diff, bw, bw, bh) << 4;
1653 total_sse += sse;
1654 }
1655 const int skip_mode_ctx = av1_get_skip_mode_context(xd);
1656 rd_stats->dist = rd_stats->sse = total_sse;
1657 rd_stats->rate = x->skip_mode_cost[skip_mode_ctx][1];
1658 rd_stats->rdcost = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
1659
1660 restore_dst_buf(xd, *orig_dst, num_planes);
1661 return 0;
1662 }
1663
1664 // Check NEARESTMV, NEARMV, GLOBALMV ref mvs for duplicate and skip the relevant
1665 // mode
check_repeat_ref_mv(const MB_MODE_INFO_EXT * mbmi_ext,int ref_idx,const MV_REFERENCE_FRAME * ref_frame,PREDICTION_MODE single_mode)1666 static INLINE int check_repeat_ref_mv(const MB_MODE_INFO_EXT *mbmi_ext,
1667 int ref_idx,
1668 const MV_REFERENCE_FRAME *ref_frame,
1669 PREDICTION_MODE single_mode) {
1670 const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
1671 const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
1672 assert(single_mode != NEWMV);
1673 if (single_mode == NEARESTMV) {
1674 return 0;
1675 } else if (single_mode == NEARMV) {
1676 // when ref_mv_count = 0, NEARESTMV and NEARMV are same as GLOBALMV
1677 // when ref_mv_count = 1, NEARMV is same as GLOBALMV
1678 if (ref_mv_count < 2) return 1;
1679 } else if (single_mode == GLOBALMV) {
1680 // when ref_mv_count == 0, GLOBALMV is same as NEARESTMV
1681 if (ref_mv_count == 0) return 1;
1682 // when ref_mv_count == 1, NEARMV is same as GLOBALMV
1683 else if (ref_mv_count == 1)
1684 return 0;
1685
1686 int stack_size = AOMMIN(USABLE_REF_MV_STACK_SIZE, ref_mv_count);
1687 // Check GLOBALMV is matching with any mv in ref_mv_stack
1688 for (int ref_mv_idx = 0; ref_mv_idx < stack_size; ref_mv_idx++) {
1689 int_mv this_mv;
1690
1691 if (ref_idx == 0)
1692 this_mv = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
1693 else
1694 this_mv = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
1695
1696 if (this_mv.as_int == mbmi_ext->global_mvs[ref_frame[ref_idx]].as_int)
1697 return 1;
1698 }
1699 }
1700 return 0;
1701 }
1702
get_this_mv(int_mv * this_mv,PREDICTION_MODE this_mode,int ref_idx,int ref_mv_idx,int skip_repeated_ref_mv,const MV_REFERENCE_FRAME * ref_frame,const MB_MODE_INFO_EXT * mbmi_ext)1703 static INLINE int get_this_mv(int_mv *this_mv, PREDICTION_MODE this_mode,
1704 int ref_idx, int ref_mv_idx,
1705 int skip_repeated_ref_mv,
1706 const MV_REFERENCE_FRAME *ref_frame,
1707 const MB_MODE_INFO_EXT *mbmi_ext) {
1708 const PREDICTION_MODE single_mode = get_single_mode(this_mode, ref_idx);
1709 assert(is_inter_singleref_mode(single_mode));
1710 if (single_mode == NEWMV) {
1711 this_mv->as_int = INVALID_MV;
1712 } else if (single_mode == GLOBALMV) {
1713 if (skip_repeated_ref_mv &&
1714 check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
1715 return 0;
1716 *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
1717 } else {
1718 assert(single_mode == NEARMV || single_mode == NEARESTMV);
1719 const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
1720 const int ref_mv_offset = single_mode == NEARESTMV ? 0 : ref_mv_idx + 1;
1721 if (ref_mv_offset < mbmi_ext->ref_mv_count[ref_frame_type]) {
1722 assert(ref_mv_offset >= 0);
1723 if (ref_idx == 0) {
1724 *this_mv =
1725 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_offset].this_mv;
1726 } else {
1727 *this_mv =
1728 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_offset].comp_mv;
1729 }
1730 } else {
1731 if (skip_repeated_ref_mv &&
1732 check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
1733 return 0;
1734 *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
1735 }
1736 }
1737 return 1;
1738 }
1739
1740 // This function update the non-new mv for the current prediction mode
build_cur_mv(int_mv * cur_mv,PREDICTION_MODE this_mode,const AV1_COMMON * cm,const MACROBLOCK * x,int skip_repeated_ref_mv)1741 static INLINE int build_cur_mv(int_mv *cur_mv, PREDICTION_MODE this_mode,
1742 const AV1_COMMON *cm, const MACROBLOCK *x,
1743 int skip_repeated_ref_mv) {
1744 const MACROBLOCKD *xd = &x->e_mbd;
1745 const MB_MODE_INFO *mbmi = xd->mi[0];
1746 const int is_comp_pred = has_second_ref(mbmi);
1747
1748 int ret = 1;
1749 for (int i = 0; i < is_comp_pred + 1; ++i) {
1750 int_mv this_mv;
1751 this_mv.as_int = INVALID_MV;
1752 ret = get_this_mv(&this_mv, this_mode, i, mbmi->ref_mv_idx,
1753 skip_repeated_ref_mv, mbmi->ref_frame, x->mbmi_ext);
1754 if (!ret) return 0;
1755 const PREDICTION_MODE single_mode = get_single_mode(this_mode, i);
1756 if (single_mode == NEWMV) {
1757 const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
1758 cur_mv[i] =
1759 (i == 0) ? x->mbmi_ext->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
1760 .this_mv
1761 : x->mbmi_ext->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
1762 .comp_mv;
1763 } else {
1764 ret &= clamp_and_check_mv(cur_mv + i, this_mv, cm, x);
1765 }
1766 }
1767 return ret;
1768 }
1769
get_drl_cost(const MB_MODE_INFO * mbmi,const MB_MODE_INFO_EXT * mbmi_ext,const int (* const drl_mode_cost0)[2],int8_t ref_frame_type)1770 static INLINE int get_drl_cost(const MB_MODE_INFO *mbmi,
1771 const MB_MODE_INFO_EXT *mbmi_ext,
1772 const int (*const drl_mode_cost0)[2],
1773 int8_t ref_frame_type) {
1774 int cost = 0;
1775 if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
1776 for (int idx = 0; idx < 2; ++idx) {
1777 if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
1778 uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
1779 cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != idx];
1780 if (mbmi->ref_mv_idx == idx) return cost;
1781 }
1782 }
1783 return cost;
1784 }
1785
1786 if (have_nearmv_in_inter_mode(mbmi->mode)) {
1787 for (int idx = 1; idx < 3; ++idx) {
1788 if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
1789 uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
1790 cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != (idx - 1)];
1791 if (mbmi->ref_mv_idx == (idx - 1)) return cost;
1792 }
1793 }
1794 return cost;
1795 }
1796 return cost;
1797 }
1798
is_single_newmv_valid(const HandleInterModeArgs * const args,const MB_MODE_INFO * const mbmi,PREDICTION_MODE this_mode)1799 static INLINE int is_single_newmv_valid(const HandleInterModeArgs *const args,
1800 const MB_MODE_INFO *const mbmi,
1801 PREDICTION_MODE this_mode) {
1802 for (int ref_idx = 0; ref_idx < 2; ++ref_idx) {
1803 const PREDICTION_MODE single_mode = get_single_mode(this_mode, ref_idx);
1804 const MV_REFERENCE_FRAME ref = mbmi->ref_frame[ref_idx];
1805 if (single_mode == NEWMV &&
1806 args->single_newmv_valid[mbmi->ref_mv_idx][ref] == 0) {
1807 return 0;
1808 }
1809 }
1810 return 1;
1811 }
1812
get_drl_refmv_count(const MACROBLOCK * const x,const MV_REFERENCE_FRAME * ref_frame,PREDICTION_MODE mode)1813 static int get_drl_refmv_count(const MACROBLOCK *const x,
1814 const MV_REFERENCE_FRAME *ref_frame,
1815 PREDICTION_MODE mode) {
1816 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
1817 const int8_t ref_frame_type = av1_ref_frame_type(ref_frame);
1818 const int has_nearmv = have_nearmv_in_inter_mode(mode) ? 1 : 0;
1819 const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
1820 const int only_newmv = (mode == NEWMV || mode == NEW_NEWMV);
1821 const int has_drl =
1822 (has_nearmv && ref_mv_count > 2) || (only_newmv && ref_mv_count > 1);
1823 const int ref_set =
1824 has_drl ? AOMMIN(MAX_REF_MV_SEARCH, ref_mv_count - has_nearmv) : 1;
1825
1826 return ref_set;
1827 }
1828
1829 // Whether this reference motion vector can be skipped, based on initial
1830 // heuristics.
ref_mv_idx_early_breakout(const AV1_COMP * const cpi,MACROBLOCK * x,const HandleInterModeArgs * const args,int64_t ref_best_rd,int ref_mv_idx)1831 static bool ref_mv_idx_early_breakout(const AV1_COMP *const cpi, MACROBLOCK *x,
1832 const HandleInterModeArgs *const args,
1833 int64_t ref_best_rd, int ref_mv_idx) {
1834 const SPEED_FEATURES *const sf = &cpi->sf;
1835 MACROBLOCKD *xd = &x->e_mbd;
1836 MB_MODE_INFO *mbmi = xd->mi[0];
1837 const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
1838 const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
1839 const int is_comp_pred = has_second_ref(mbmi);
1840 if (sf->inter_sf.reduce_inter_modes && ref_mv_idx > 0) {
1841 if (mbmi->ref_frame[0] == LAST2_FRAME ||
1842 mbmi->ref_frame[0] == LAST3_FRAME ||
1843 mbmi->ref_frame[1] == LAST2_FRAME ||
1844 mbmi->ref_frame[1] == LAST3_FRAME) {
1845 const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
1846 if (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
1847 REF_CAT_LEVEL) {
1848 return true;
1849 }
1850 }
1851 // TODO(any): Experiment with reduce_inter_modes for compound prediction
1852 if (sf->inter_sf.reduce_inter_modes >= 2 && !is_comp_pred &&
1853 have_newmv_in_inter_mode(mbmi->mode)) {
1854 if (mbmi->ref_frame[0] != cpi->nearest_past_ref &&
1855 mbmi->ref_frame[0] != cpi->nearest_future_ref) {
1856 const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
1857 if (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
1858 REF_CAT_LEVEL) {
1859 return true;
1860 }
1861 }
1862 }
1863 }
1864 if (sf->inter_sf.prune_single_motion_modes_by_simple_trans && !is_comp_pred &&
1865 args->single_ref_first_pass == 0) {
1866 if (args->simple_rd_state[ref_mv_idx].early_skipped) {
1867 return true;
1868 }
1869 }
1870 mbmi->ref_mv_idx = ref_mv_idx;
1871 if (is_comp_pred && (!is_single_newmv_valid(args, mbmi, mbmi->mode))) {
1872 return true;
1873 }
1874 size_t est_rd_rate = args->ref_frame_cost + args->single_comp_cost;
1875 const int drl_cost =
1876 get_drl_cost(mbmi, mbmi_ext, x->drl_mode_cost0, ref_frame_type);
1877 est_rd_rate += drl_cost;
1878 if (RDCOST(x->rdmult, est_rd_rate, 0) > ref_best_rd &&
1879 mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
1880 return true;
1881 }
1882 return false;
1883 }
1884
1885 // Compute the estimated RD cost for the motion vector with simple translation.
simple_translation_pred_rd(AV1_COMP * const cpi,MACROBLOCK * x,RD_STATS * rd_stats,HandleInterModeArgs * args,int ref_mv_idx,inter_mode_info * mode_info,int64_t ref_best_rd,BLOCK_SIZE bsize)1886 static int64_t simple_translation_pred_rd(
1887 AV1_COMP *const cpi, MACROBLOCK *x, RD_STATS *rd_stats,
1888 HandleInterModeArgs *args, int ref_mv_idx, inter_mode_info *mode_info,
1889 int64_t ref_best_rd, BLOCK_SIZE bsize) {
1890 MACROBLOCKD *xd = &x->e_mbd;
1891 MB_MODE_INFO *mbmi = xd->mi[0];
1892 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
1893 const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
1894 const AV1_COMMON *cm = &cpi->common;
1895 const int is_comp_pred = has_second_ref(mbmi);
1896
1897 struct macroblockd_plane *p = xd->plane;
1898 const BUFFER_SET orig_dst = {
1899 { p[0].dst.buf, p[1].dst.buf, p[2].dst.buf },
1900 { p[0].dst.stride, p[1].dst.stride, p[2].dst.stride },
1901 };
1902 av1_init_rd_stats(rd_stats);
1903
1904 mbmi->interinter_comp.type = COMPOUND_AVERAGE;
1905 mbmi->comp_group_idx = 0;
1906 mbmi->compound_idx = 1;
1907 if (mbmi->ref_frame[1] == INTRA_FRAME) {
1908 mbmi->ref_frame[1] = NONE_FRAME;
1909 }
1910 int16_t mode_ctx =
1911 av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame);
1912
1913 mbmi->num_proj_ref = 0;
1914 mbmi->motion_mode = SIMPLE_TRANSLATION;
1915 mbmi->ref_mv_idx = ref_mv_idx;
1916
1917 rd_stats->rate += args->ref_frame_cost + args->single_comp_cost;
1918 const int drl_cost =
1919 get_drl_cost(mbmi, mbmi_ext, x->drl_mode_cost0, ref_frame_type);
1920 rd_stats->rate += drl_cost;
1921 mode_info[ref_mv_idx].drl_cost = drl_cost;
1922
1923 int_mv cur_mv[2];
1924 if (!build_cur_mv(cur_mv, mbmi->mode, cm, x, 0)) {
1925 return INT64_MAX;
1926 }
1927 assert(have_nearmv_in_inter_mode(mbmi->mode));
1928 for (int i = 0; i < is_comp_pred + 1; ++i) {
1929 mbmi->mv[i].as_int = cur_mv[i].as_int;
1930 }
1931 const int ref_mv_cost = cost_mv_ref(x, mbmi->mode, mode_ctx);
1932 rd_stats->rate += ref_mv_cost;
1933
1934 if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd) {
1935 return INT64_MAX;
1936 }
1937
1938 mbmi->motion_mode = SIMPLE_TRANSLATION;
1939 mbmi->num_proj_ref = 0;
1940 if (is_comp_pred) {
1941 // Only compound_average
1942 mbmi->interinter_comp.type = COMPOUND_AVERAGE;
1943 mbmi->comp_group_idx = 0;
1944 mbmi->compound_idx = 1;
1945 }
1946 set_default_interp_filters(mbmi, cm->interp_filter);
1947
1948 const int mi_row = xd->mi_row;
1949 const int mi_col = xd->mi_col;
1950 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize,
1951 AOM_PLANE_Y, AOM_PLANE_Y);
1952 int est_rate;
1953 int64_t est_dist;
1954 model_rd_sb_fn[MODELRD_CURVFIT](cpi, bsize, x, xd, 0, 0, &est_rate, &est_dist,
1955 NULL, NULL, NULL, NULL, NULL);
1956 return RDCOST(x->rdmult, rd_stats->rate + est_rate, est_dist);
1957 }
1958
1959 // Represents a set of integers, from 0 to sizeof(int) * 8, as bits in
1960 // an integer. 0 for the i-th bit means that integer is excluded, 1 means
1961 // it is included.
mask_set_bit(int * mask,int index)1962 static INLINE void mask_set_bit(int *mask, int index) { *mask |= (1 << index); }
1963
mask_check_bit(int mask,int index)1964 static INLINE bool mask_check_bit(int mask, int index) {
1965 return (mask >> index) & 0x1;
1966 }
1967
1968 // Before performing the full MV search in handle_inter_mode, do a simple
1969 // translation search and see if we can eliminate any motion vectors.
1970 // Returns an integer where, if the i-th bit is set, it means that the i-th
1971 // motion vector should be searched. This is only set for NEAR_MV.
ref_mv_idx_to_search(AV1_COMP * const cpi,MACROBLOCK * x,RD_STATS * rd_stats,HandleInterModeArgs * const args,int64_t ref_best_rd,inter_mode_info * mode_info,BLOCK_SIZE bsize,const int ref_set)1972 static int ref_mv_idx_to_search(AV1_COMP *const cpi, MACROBLOCK *x,
1973 RD_STATS *rd_stats,
1974 HandleInterModeArgs *const args,
1975 int64_t ref_best_rd, inter_mode_info *mode_info,
1976 BLOCK_SIZE bsize, const int ref_set) {
1977 AV1_COMMON *const cm = &cpi->common;
1978 const MACROBLOCKD *const xd = &x->e_mbd;
1979 const MB_MODE_INFO *const mbmi = xd->mi[0];
1980 const PREDICTION_MODE this_mode = mbmi->mode;
1981
1982 // Only search indices if they have some chance of being good.
1983 int good_indices = 0;
1984 for (int i = 0; i < ref_set; ++i) {
1985 if (ref_mv_idx_early_breakout(cpi, x, args, ref_best_rd, i)) {
1986 continue;
1987 }
1988 mask_set_bit(&good_indices, i);
1989 }
1990
1991 // Only prune in NEARMV mode, if the speed feature is set, and the block size
1992 // is large enough. If these conditions are not met, return all good indices
1993 // found so far.
1994 if (!cpi->sf.inter_sf.prune_mode_search_simple_translation)
1995 return good_indices;
1996 if (!have_nearmv_in_inter_mode(this_mode)) return good_indices;
1997 if (num_pels_log2_lookup[bsize] <= 6) return good_indices;
1998 // Do not prune when there is internal resizing. TODO(elliottk) fix this
1999 // so b/2384 can be resolved.
2000 if (av1_is_scaled(get_ref_scale_factors(cm, mbmi->ref_frame[0])) ||
2001 (mbmi->ref_frame[1] > 0 &&
2002 av1_is_scaled(get_ref_scale_factors(cm, mbmi->ref_frame[1])))) {
2003 return good_indices;
2004 }
2005
2006 // Calculate the RD cost for the motion vectors using simple translation.
2007 int64_t idx_rdcost[] = { INT64_MAX, INT64_MAX, INT64_MAX };
2008 for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ++ref_mv_idx) {
2009 // If this index is bad, ignore it.
2010 if (!mask_check_bit(good_indices, ref_mv_idx)) {
2011 continue;
2012 }
2013 idx_rdcost[ref_mv_idx] = simple_translation_pred_rd(
2014 cpi, x, rd_stats, args, ref_mv_idx, mode_info, ref_best_rd, bsize);
2015 }
2016 // Find the index with the best RD cost.
2017 int best_idx = 0;
2018 for (int i = 1; i < MAX_REF_MV_SEARCH; ++i) {
2019 if (idx_rdcost[i] < idx_rdcost[best_idx]) {
2020 best_idx = i;
2021 }
2022 }
2023 // Only include indices that are good and within a % of the best.
2024 const double dth = has_second_ref(mbmi) ? 1.05 : 1.001;
2025 // If the simple translation cost is not within this multiple of the
2026 // best RD, skip it. Note that the cutoff is derived experimentally.
2027 const double ref_dth = 5;
2028 int result = 0;
2029 for (int i = 0; i < ref_set; ++i) {
2030 if (mask_check_bit(good_indices, i) &&
2031 (1.0 * idx_rdcost[i]) / idx_rdcost[best_idx] < dth &&
2032 (1.0 * idx_rdcost[i]) / ref_best_rd < ref_dth) {
2033 mask_set_bit(&result, i);
2034 }
2035 }
2036 return result;
2037 }
2038
2039 typedef struct motion_mode_candidate {
2040 MB_MODE_INFO mbmi;
2041 int rate_mv;
2042 int rate2_nocoeff;
2043 int skip_motion_mode;
2044 int64_t rd_cost;
2045 } motion_mode_candidate;
2046
2047 typedef struct motion_mode_best_st_candidate {
2048 motion_mode_candidate motion_mode_cand[MAX_WINNER_MOTION_MODES];
2049 int num_motion_mode_cand;
2050 } motion_mode_best_st_candidate;
2051
2052 // Checks if the current reference frame matches with neighbouring block's
2053 // (top/left) reference frames
ref_match_found_in_nb_blocks(MB_MODE_INFO * cur_mbmi,MB_MODE_INFO * nb_mbmi)2054 static AOM_INLINE int ref_match_found_in_nb_blocks(MB_MODE_INFO *cur_mbmi,
2055 MB_MODE_INFO *nb_mbmi) {
2056 MV_REFERENCE_FRAME nb_ref_frames[2] = { nb_mbmi->ref_frame[0],
2057 nb_mbmi->ref_frame[1] };
2058 MV_REFERENCE_FRAME cur_ref_frames[2] = { cur_mbmi->ref_frame[0],
2059 cur_mbmi->ref_frame[1] };
2060 const int is_cur_comp_pred = has_second_ref(cur_mbmi);
2061 int match_found = 0;
2062
2063 for (int i = 0; i < (is_cur_comp_pred + 1); i++) {
2064 if ((cur_ref_frames[i] == nb_ref_frames[0]) ||
2065 (cur_ref_frames[i] == nb_ref_frames[1]))
2066 match_found = 1;
2067 }
2068 return match_found;
2069 }
2070
find_ref_match_in_above_nbs(const int total_mi_cols,MACROBLOCKD * xd)2071 static AOM_INLINE int find_ref_match_in_above_nbs(const int total_mi_cols,
2072 MACROBLOCKD *xd) {
2073 if (!xd->up_available) return 0;
2074 const int mi_col = xd->mi_col;
2075 MB_MODE_INFO **cur_mbmi = xd->mi;
2076 // prev_row_mi points into the mi array, starting at the beginning of the
2077 // previous row.
2078 MB_MODE_INFO **prev_row_mi = xd->mi - mi_col - 1 * xd->mi_stride;
2079 const int end_col = AOMMIN(mi_col + xd->n4_w, total_mi_cols);
2080 uint8_t mi_step;
2081 for (int above_mi_col = mi_col; above_mi_col < end_col;
2082 above_mi_col += mi_step) {
2083 MB_MODE_INFO **above_mi = prev_row_mi + above_mi_col;
2084 mi_step = mi_size_wide[above_mi[0]->sb_type];
2085 int match_found = 0;
2086 if (is_inter_block(*above_mi))
2087 match_found = ref_match_found_in_nb_blocks(*cur_mbmi, *above_mi);
2088 if (match_found) return 1;
2089 }
2090 return 0;
2091 }
2092
find_ref_match_in_left_nbs(const int total_mi_rows,MACROBLOCKD * xd)2093 static AOM_INLINE int find_ref_match_in_left_nbs(const int total_mi_rows,
2094 MACROBLOCKD *xd) {
2095 if (!xd->left_available) return 0;
2096 const int mi_row = xd->mi_row;
2097 MB_MODE_INFO **cur_mbmi = xd->mi;
2098 // prev_col_mi points into the mi array, starting at the top of the
2099 // previous column
2100 MB_MODE_INFO **prev_col_mi = xd->mi - 1 - mi_row * xd->mi_stride;
2101 const int end_row = AOMMIN(mi_row + xd->n4_h, total_mi_rows);
2102 uint8_t mi_step;
2103 for (int left_mi_row = mi_row; left_mi_row < end_row;
2104 left_mi_row += mi_step) {
2105 MB_MODE_INFO **left_mi = prev_col_mi + left_mi_row * xd->mi_stride;
2106 mi_step = mi_size_high[left_mi[0]->sb_type];
2107 int match_found = 0;
2108 if (is_inter_block(*left_mi))
2109 match_found = ref_match_found_in_nb_blocks(*cur_mbmi, *left_mi);
2110 if (match_found) return 1;
2111 }
2112 return 0;
2113 }
2114
2115 typedef struct {
2116 int64_t best_inter_cost;
2117 int64_t ref_inter_cost[INTER_REFS_PER_FRAME];
2118 } PruneInfoFromTpl;
2119
2120 #if !CONFIG_REALTIME_ONLY
2121 // TODO(Remya): Check if get_tpl_stats_b() can be reused
get_block_level_tpl_stats(AV1_COMP * cpi,BLOCK_SIZE bsize,int mi_row,int mi_col,int * valid_refs,PruneInfoFromTpl * inter_cost_info_from_tpl)2122 static AOM_INLINE void get_block_level_tpl_stats(
2123 AV1_COMP *cpi, BLOCK_SIZE bsize, int mi_row, int mi_col, int *valid_refs,
2124 PruneInfoFromTpl *inter_cost_info_from_tpl) {
2125 const GF_GROUP *const gf_group = &cpi->gf_group;
2126 AV1_COMMON *const cm = &cpi->common;
2127
2128 assert(IMPLIES(gf_group->size > 0, gf_group->index < gf_group->size));
2129 const int tpl_idx = gf_group->index;
2130 TplDepFrame *tpl_frame = &cpi->tpl_frame[tpl_idx];
2131 TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
2132
2133 const int mi_wide = mi_size_wide[bsize];
2134 const int mi_high = mi_size_high[bsize];
2135 if (tpl_frame->is_valid) {
2136 int64_t best_inter_cost = INT64_MAX;
2137 int tpl_stride = tpl_frame->stride;
2138 const int step = 1 << cpi->tpl_stats_block_mis_log2;
2139 const int mi_col_sr =
2140 coded_to_superres_mi(mi_col, cm->superres_scale_denominator);
2141 const int mi_col_end_sr =
2142 coded_to_superres_mi(mi_col + mi_wide, cm->superres_scale_denominator);
2143 const int mi_cols_sr = av1_pixels_to_mi(cm->superres_upscaled_width);
2144
2145 for (int row = mi_row; row < mi_row + mi_high; row += step) {
2146 for (int col = mi_col_sr; col < mi_col_end_sr; col += step) {
2147 if (row >= cm->mi_rows || col >= mi_cols_sr) continue;
2148 TplDepStats *this_stats =
2149 &tpl_stats[av1_tpl_ptr_pos(cpi, row, col, tpl_stride)];
2150
2151 // Sums up the inter cost of corresponding ref frames
2152 for (int ref_idx = 0; ref_idx < INTER_REFS_PER_FRAME; ref_idx++) {
2153 inter_cost_info_from_tpl->ref_inter_cost[ref_idx] +=
2154 this_stats->pred_error[ref_idx];
2155 }
2156 }
2157 }
2158
2159 // Computes the best inter cost (minimum inter_cost)
2160 for (int ref_idx = 0; ref_idx < INTER_REFS_PER_FRAME; ref_idx++) {
2161 int64_t cur_inter_cost =
2162 inter_cost_info_from_tpl->ref_inter_cost[ref_idx];
2163 // For invalid ref frames, cur_inter_cost = 0 and has to be handled while
2164 // calculating the minimum inter_cost
2165 if (cur_inter_cost != 0 && (cur_inter_cost < best_inter_cost) &&
2166 (valid_refs[ref_idx]))
2167 best_inter_cost = cur_inter_cost;
2168 }
2169 inter_cost_info_from_tpl->best_inter_cost = best_inter_cost;
2170 }
2171 }
2172 #endif
2173
prune_modes_based_on_tpl_stats(PruneInfoFromTpl * inter_cost_info_from_tpl,const int * refs,int ref_mv_idx,const PREDICTION_MODE this_mode,int prune_mode_level)2174 static AOM_INLINE int prune_modes_based_on_tpl_stats(
2175 PruneInfoFromTpl *inter_cost_info_from_tpl, const int *refs, int ref_mv_idx,
2176 const PREDICTION_MODE this_mode, int prune_mode_level) {
2177 int have_newmv = have_newmv_in_inter_mode(this_mode);
2178 if ((prune_mode_level < 3) && have_newmv) return 0;
2179
2180 const int prune_level_idx[3] = { 0, 1, 1 };
2181 int prune_level = prune_level_idx[prune_mode_level - 1];
2182 int64_t cur_inter_cost;
2183
2184 int is_globalmv = (this_mode == GLOBALMV) || (this_mode == GLOBAL_GLOBALMV);
2185 int prune_index = is_globalmv ? MAX_REF_MV_SEARCH : ref_mv_idx;
2186
2187 // Thresholds used for pruning:
2188 // Lower value indicates aggressive pruning and higher value indicates
2189 // conservative pruning which is set based on ref_mv_idx and speed feature.
2190 // 'prune_index' 0, 1, 2 corresponds to ref_mv indices 0, 1 and 2. prune_index
2191 // 3 corresponds to GLOBALMV/GLOBAL_GLOBALMV
2192 const int tpl_inter_mode_prune_mul_factor[2][MAX_REF_MV_SEARCH + 1] = {
2193 { 3, 3, 3, 2 }, { 3, 2, 2, 2 }
2194 };
2195
2196 int is_comp_pred = (refs[1] > INTRA_FRAME);
2197
2198 if (!is_comp_pred) {
2199 cur_inter_cost = inter_cost_info_from_tpl->ref_inter_cost[refs[0] - 1];
2200 } else {
2201 int64_t inter_cost_ref0 =
2202 inter_cost_info_from_tpl->ref_inter_cost[refs[0] - 1];
2203 int64_t inter_cost_ref1 =
2204 inter_cost_info_from_tpl->ref_inter_cost[refs[1] - 1];
2205 // Choose maximum inter_cost among inter_cost_ref0 and inter_cost_ref1 for
2206 // more aggressive pruning
2207 cur_inter_cost = AOMMAX(inter_cost_ref0, inter_cost_ref1);
2208 }
2209
2210 // Prune the mode if cur_inter_cost is greater than threshold times
2211 // best_inter_cost
2212 int64_t best_inter_cost = inter_cost_info_from_tpl->best_inter_cost;
2213 if (cur_inter_cost >
2214 ((tpl_inter_mode_prune_mul_factor[prune_level][prune_index] *
2215 best_inter_cost) >>
2216 1))
2217 return 1;
2218 return 0;
2219 }
2220
handle_inter_mode(AV1_COMP * const cpi,TileDataEnc * tile_data,MACROBLOCK * x,BLOCK_SIZE bsize,RD_STATS * rd_stats,RD_STATS * rd_stats_y,RD_STATS * rd_stats_uv,int * disable_skip,HandleInterModeArgs * args,int64_t ref_best_rd,uint8_t * const tmp_buf,const CompoundTypeRdBuffers * rd_buffers,int64_t * best_est_rd,const int do_tx_search,InterModesInfo * inter_modes_info,motion_mode_candidate * motion_mode_cand,int64_t * skip_rd,PruneInfoFromTpl * inter_cost_info_from_tpl)2221 static int64_t handle_inter_mode(
2222 AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *x,
2223 BLOCK_SIZE bsize, RD_STATS *rd_stats, RD_STATS *rd_stats_y,
2224 RD_STATS *rd_stats_uv, int *disable_skip, HandleInterModeArgs *args,
2225 int64_t ref_best_rd, uint8_t *const tmp_buf,
2226 const CompoundTypeRdBuffers *rd_buffers, int64_t *best_est_rd,
2227 const int do_tx_search, InterModesInfo *inter_modes_info,
2228 motion_mode_candidate *motion_mode_cand, int64_t *skip_rd,
2229 PruneInfoFromTpl *inter_cost_info_from_tpl) {
2230 const AV1_COMMON *cm = &cpi->common;
2231 const int num_planes = av1_num_planes(cm);
2232 MACROBLOCKD *xd = &x->e_mbd;
2233 MB_MODE_INFO *mbmi = xd->mi[0];
2234 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
2235 const int is_comp_pred = has_second_ref(mbmi);
2236 const PREDICTION_MODE this_mode = mbmi->mode;
2237
2238 const GF_GROUP *const gf_group = &cpi->gf_group;
2239 const int tpl_idx = gf_group->index;
2240 TplDepFrame *tpl_frame = &cpi->tpl_frame[tpl_idx];
2241 int prune_modes_based_on_tpl =
2242 cpi->sf.inter_sf.prune_inter_modes_based_on_tpl && tpl_frame->is_valid;
2243 int i;
2244 const int refs[2] = { mbmi->ref_frame[0],
2245 (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
2246 int rate_mv = 0;
2247 int64_t rd = INT64_MAX;
2248 // do first prediction into the destination buffer. Do the next
2249 // prediction into a temporary buffer. Then keep track of which one
2250 // of these currently holds the best predictor, and use the other
2251 // one for future predictions. In the end, copy from tmp_buf to
2252 // dst if necessary.
2253 struct macroblockd_plane *p = xd->plane;
2254 const BUFFER_SET orig_dst = {
2255 { p[0].dst.buf, p[1].dst.buf, p[2].dst.buf },
2256 { p[0].dst.stride, p[1].dst.stride, p[2].dst.stride },
2257 };
2258 const BUFFER_SET tmp_dst = { { tmp_buf, tmp_buf + 1 * MAX_SB_SQUARE,
2259 tmp_buf + 2 * MAX_SB_SQUARE },
2260 { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE } };
2261
2262 const int masked_compound_used = is_any_masked_compound_used(bsize) &&
2263 cm->seq_params.enable_masked_compound;
2264 int64_t ret_val = INT64_MAX;
2265 const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
2266 RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
2267 int64_t best_rd = INT64_MAX;
2268 uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
2269 uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
2270 MB_MODE_INFO best_mbmi = *mbmi;
2271 int best_disable_skip = 0;
2272 int best_xskip = 0;
2273 int64_t newmv_ret_val = INT64_MAX;
2274 inter_mode_info mode_info[MAX_REF_MV_SEARCH];
2275
2276 int mode_search_mask = (1 << COMPOUND_AVERAGE) | (1 << COMPOUND_DISTWTD) |
2277 (1 << COMPOUND_WEDGE) | (1 << COMPOUND_DIFFWTD);
2278
2279 // Do not prune the mode based on inter cost from tpl if the current ref frame
2280 // is the winner ref in neighbouring blocks.
2281 int ref_match_found_in_above_nb = 0;
2282 int ref_match_found_in_left_nb = 0;
2283 if (prune_modes_based_on_tpl) {
2284 const int total_mi_cols = cm->mi_cols;
2285 ref_match_found_in_above_nb =
2286 find_ref_match_in_above_nbs(total_mi_cols, xd);
2287 const int total_mi_rows = cm->mi_rows;
2288 ref_match_found_in_left_nb = find_ref_match_in_left_nbs(total_mi_rows, xd);
2289 }
2290
2291 // First, perform a simple translation search for each of the indices. If
2292 // an index performs well, it will be fully searched here.
2293 const int ref_set = get_drl_refmv_count(x, mbmi->ref_frame, this_mode);
2294 // Save MV results from first 2 ref_mv_idx.
2295 int_mv save_mv[MAX_REF_MV_SEARCH - 1][2] = { { { 0 } } };
2296 int best_ref_mv_idx = -1;
2297 const int idx_mask = ref_mv_idx_to_search(cpi, x, rd_stats, args, ref_best_rd,
2298 mode_info, bsize, ref_set);
2299 const int16_t mode_ctx =
2300 av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame);
2301 const int ref_mv_cost = cost_mv_ref(x, this_mode, mode_ctx);
2302 const int base_rate =
2303 args->ref_frame_cost + args->single_comp_cost + ref_mv_cost;
2304 for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ++ref_mv_idx) {
2305 mode_info[ref_mv_idx].full_search_mv.as_int = INVALID_MV;
2306 mode_info[ref_mv_idx].mv.as_int = INVALID_MV;
2307 mode_info[ref_mv_idx].rd = INT64_MAX;
2308 if (!mask_check_bit(idx_mask, ref_mv_idx)) {
2309 // MV did not perform well in simple translation search. Skip it.
2310 continue;
2311 }
2312 if (prune_modes_based_on_tpl && !ref_match_found_in_above_nb &&
2313 !ref_match_found_in_left_nb && (ref_best_rd != INT64_MAX)) {
2314 if (prune_modes_based_on_tpl_stats(
2315 inter_cost_info_from_tpl, refs, ref_mv_idx, this_mode,
2316 cpi->sf.inter_sf.prune_inter_modes_based_on_tpl))
2317 continue;
2318 }
2319 av1_init_rd_stats(rd_stats);
2320
2321 mbmi->interinter_comp.type = COMPOUND_AVERAGE;
2322 mbmi->comp_group_idx = 0;
2323 mbmi->compound_idx = 1;
2324 if (mbmi->ref_frame[1] == INTRA_FRAME) mbmi->ref_frame[1] = NONE_FRAME;
2325
2326 mbmi->num_proj_ref = 0;
2327 mbmi->motion_mode = SIMPLE_TRANSLATION;
2328 mbmi->ref_mv_idx = ref_mv_idx;
2329
2330 rd_stats->rate = base_rate;
2331 const int drl_cost =
2332 get_drl_cost(mbmi, mbmi_ext, x->drl_mode_cost0, ref_frame_type);
2333 rd_stats->rate += drl_cost;
2334 mode_info[ref_mv_idx].drl_cost = drl_cost;
2335
2336 int rs = 0;
2337 int compmode_interinter_cost = 0;
2338
2339 int_mv cur_mv[2];
2340
2341 // TODO(Cherma): Extend this speed feature to support compound mode
2342 int skip_repeated_ref_mv =
2343 is_comp_pred ? 0 : cpi->sf.inter_sf.skip_repeated_ref_mv;
2344 if (!build_cur_mv(cur_mv, this_mode, cm, x, skip_repeated_ref_mv)) {
2345 continue;
2346 }
2347
2348 if (have_newmv_in_inter_mode(this_mode)) {
2349 #if CONFIG_COLLECT_COMPONENT_TIMING
2350 start_timing(cpi, handle_newmv_time);
2351 #endif
2352 if (cpi->sf.inter_sf.prune_single_motion_modes_by_simple_trans &&
2353 args->single_ref_first_pass == 0 && !is_comp_pred) {
2354 const int ref0 = mbmi->ref_frame[0];
2355 newmv_ret_val = args->single_newmv_valid[ref_mv_idx][ref0] ? 0 : 1;
2356 cur_mv[0] = args->single_newmv[ref_mv_idx][ref0];
2357 rate_mv = args->single_newmv_rate[ref_mv_idx][ref0];
2358 } else {
2359 newmv_ret_val =
2360 handle_newmv(cpi, x, bsize, cur_mv, &rate_mv, args, mode_info);
2361 }
2362 #if CONFIG_COLLECT_COMPONENT_TIMING
2363 end_timing(cpi, handle_newmv_time);
2364 #endif
2365
2366 if (newmv_ret_val != 0) continue;
2367
2368 rd_stats->rate += rate_mv;
2369
2370 if (cpi->sf.inter_sf.skip_repeated_newmv) {
2371 if (!is_comp_pred && this_mode == NEWMV && ref_mv_idx > 0) {
2372 int skip = 0;
2373 int this_rate_mv = 0;
2374 for (i = 0; i < ref_mv_idx; ++i) {
2375 // Check if the motion search result same as previous results
2376 if (cur_mv[0].as_int == args->single_newmv[i][refs[0]].as_int &&
2377 args->single_newmv_valid[i][refs[0]]) {
2378 // If the compared mode has no valid rd, it is unlikely this
2379 // mode will be the best mode
2380 if (mode_info[i].rd == INT64_MAX) {
2381 skip = 1;
2382 break;
2383 }
2384 // Compare the cost difference including drl cost and mv cost
2385 if (mode_info[i].mv.as_int != INVALID_MV) {
2386 const int compare_cost =
2387 mode_info[i].rate_mv + mode_info[i].drl_cost;
2388 const int_mv ref_mv = av1_get_ref_mv(x, 0);
2389 this_rate_mv = av1_mv_bit_cost(
2390 &mode_info[i].mv.as_mv, &ref_mv.as_mv, x->nmv_vec_cost,
2391 x->mv_cost_stack, MV_COST_WEIGHT);
2392 const int this_cost = this_rate_mv + drl_cost;
2393
2394 if (compare_cost <= this_cost) {
2395 skip = 1;
2396 break;
2397 } else {
2398 // If the cost is less than current best result, make this
2399 // the best and update corresponding variables unless the
2400 // best_mv is the same as ref_mv. In this case we skip and
2401 // rely on NEAR(EST)MV instead
2402 if (best_mbmi.ref_mv_idx == i &&
2403 mode_info[i].mv.as_int != ref_mv.as_int) {
2404 assert(best_rd != INT64_MAX);
2405 best_mbmi.ref_mv_idx = ref_mv_idx;
2406 motion_mode_cand->rate_mv = this_rate_mv;
2407 best_rd_stats.rate += this_cost - compare_cost;
2408 best_rd = RDCOST(x->rdmult, best_rd_stats.rate,
2409 best_rd_stats.dist);
2410 if (best_rd < ref_best_rd) ref_best_rd = best_rd;
2411 skip = 1;
2412 break;
2413 }
2414 }
2415 }
2416 }
2417 }
2418 if (skip) {
2419 const THR_MODES mode_enum = get_prediction_mode_idx(
2420 best_mbmi.mode, best_mbmi.ref_frame[0], best_mbmi.ref_frame[1]);
2421 // Collect mode stats for multiwinner mode processing
2422 store_winner_mode_stats(
2423 &cpi->common, x, &best_mbmi, &best_rd_stats, &best_rd_stats_y,
2424 &best_rd_stats_uv, mode_enum, NULL, bsize, best_rd,
2425 cpi->sf.winner_mode_sf.enable_multiwinner_mode_process,
2426 do_tx_search);
2427 args->modelled_rd[this_mode][ref_mv_idx][refs[0]] =
2428 args->modelled_rd[this_mode][i][refs[0]];
2429 args->simple_rd[this_mode][ref_mv_idx][refs[0]] =
2430 args->simple_rd[this_mode][i][refs[0]];
2431 mode_info[ref_mv_idx].rd = mode_info[i].rd;
2432 mode_info[ref_mv_idx].rate_mv = this_rate_mv;
2433 mode_info[ref_mv_idx].mv.as_int = mode_info[i].mv.as_int;
2434
2435 restore_dst_buf(xd, orig_dst, num_planes);
2436 continue;
2437 }
2438 }
2439 }
2440 }
2441 for (i = 0; i < is_comp_pred + 1; ++i) {
2442 mbmi->mv[i].as_int = cur_mv[i].as_int;
2443 }
2444
2445 if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd &&
2446 mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
2447 continue;
2448 }
2449
2450 if (cpi->sf.inter_sf.prune_ref_mv_idx_search && is_comp_pred) {
2451 // TODO(yunqing): Move this part to a separate function when it is done.
2452 // Store MV result.
2453 if (ref_mv_idx < MAX_REF_MV_SEARCH - 1) {
2454 for (i = 0; i < is_comp_pred + 1; ++i)
2455 save_mv[ref_mv_idx][i].as_int = mbmi->mv[i].as_int;
2456 }
2457 // Skip the evaluation if an MV match is found.
2458 if (ref_mv_idx > 0) {
2459 int match = 0;
2460 for (int idx = 0; idx < ref_mv_idx; ++idx) {
2461 int mv_diff = 0;
2462 for (i = 0; i < 1 + is_comp_pred; ++i) {
2463 mv_diff += abs(save_mv[idx][i].as_mv.row - mbmi->mv[i].as_mv.row) +
2464 abs(save_mv[idx][i].as_mv.col - mbmi->mv[i].as_mv.col);
2465 }
2466
2467 // If this mode is not the best one, and current MV is similar to
2468 // previous stored MV, terminate this ref_mv_idx evaluation.
2469 if (best_ref_mv_idx == -1 && mv_diff < 1) {
2470 match = 1;
2471 break;
2472 }
2473 }
2474 if (match == 1) continue;
2475 }
2476 }
2477
2478 #if CONFIG_COLLECT_COMPONENT_TIMING
2479 start_timing(cpi, compound_type_rd_time);
2480 #endif
2481 int skip_build_pred = 0;
2482 const int mi_row = xd->mi_row;
2483 const int mi_col = xd->mi_col;
2484 if (is_comp_pred) {
2485 // Find matching interp filter or set to default interp filter
2486 const int need_search = av1_is_interp_needed(xd);
2487 const InterpFilter assign_filter = cm->interp_filter;
2488 int is_luma_interp_done = 0;
2489 av1_find_interp_filter_match(mbmi, cpi, assign_filter, need_search,
2490 args->interp_filter_stats,
2491 args->interp_filter_stats_idx);
2492
2493 int64_t best_rd_compound;
2494 int64_t rd_thresh;
2495 const int comp_type_rd_shift = COMP_TYPE_RD_THRESH_SHIFT;
2496 const int comp_type_rd_scale = COMP_TYPE_RD_THRESH_SCALE;
2497 rd_thresh = get_rd_thresh_from_best_rd(
2498 ref_best_rd, (1 << comp_type_rd_shift), comp_type_rd_scale);
2499 compmode_interinter_cost = av1_compound_type_rd(
2500 cpi, x, bsize, cur_mv, mode_search_mask, masked_compound_used,
2501 &orig_dst, &tmp_dst, rd_buffers, &rate_mv, &best_rd_compound,
2502 rd_stats, ref_best_rd, skip_rd[1], &is_luma_interp_done, rd_thresh);
2503 if (ref_best_rd < INT64_MAX &&
2504 (best_rd_compound >> comp_type_rd_shift) * comp_type_rd_scale >
2505 ref_best_rd) {
2506 restore_dst_buf(xd, orig_dst, num_planes);
2507 continue;
2508 }
2509 // No need to call av1_enc_build_inter_predictor for luma if
2510 // COMPOUND_AVERAGE is selected because it is the first
2511 // candidate in av1_compound_type_rd, and the following
2512 // compound types searching uses tmp_dst buffer
2513
2514 if (mbmi->interinter_comp.type == COMPOUND_AVERAGE &&
2515 is_luma_interp_done) {
2516 if (num_planes > 1) {
2517 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst,
2518 bsize, AOM_PLANE_U, num_planes - 1);
2519 }
2520 skip_build_pred = 1;
2521 }
2522 }
2523
2524 #if CONFIG_COLLECT_COMPONENT_TIMING
2525 end_timing(cpi, compound_type_rd_time);
2526 #endif
2527
2528 #if CONFIG_COLLECT_COMPONENT_TIMING
2529 start_timing(cpi, interpolation_filter_search_time);
2530 #endif
2531 ret_val = av1_interpolation_filter_search(
2532 x, cpi, tile_data, bsize, &tmp_dst, &orig_dst, &rd, &rs,
2533 &skip_build_pred, args, ref_best_rd);
2534 #if CONFIG_COLLECT_COMPONENT_TIMING
2535 end_timing(cpi, interpolation_filter_search_time);
2536 #endif
2537 if (args->modelled_rd != NULL && !is_comp_pred) {
2538 args->modelled_rd[this_mode][ref_mv_idx][refs[0]] = rd;
2539 }
2540 if (ret_val != 0) {
2541 restore_dst_buf(xd, orig_dst, num_planes);
2542 continue;
2543 } else if (cpi->sf.inter_sf.model_based_post_interp_filter_breakout &&
2544 ref_best_rd != INT64_MAX && (rd >> 3) * 3 > ref_best_rd) {
2545 restore_dst_buf(xd, orig_dst, num_planes);
2546 continue;
2547 }
2548
2549 if (args->modelled_rd != NULL) {
2550 if (is_comp_pred) {
2551 const int mode0 = compound_ref0_mode(this_mode);
2552 const int mode1 = compound_ref1_mode(this_mode);
2553 const int64_t mrd =
2554 AOMMIN(args->modelled_rd[mode0][ref_mv_idx][refs[0]],
2555 args->modelled_rd[mode1][ref_mv_idx][refs[1]]);
2556 if ((rd >> 3) * 6 > mrd && ref_best_rd < INT64_MAX) {
2557 restore_dst_buf(xd, orig_dst, num_planes);
2558 continue;
2559 }
2560 }
2561 }
2562 rd_stats->rate += compmode_interinter_cost;
2563 if (skip_build_pred != 1) {
2564 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize, 0,
2565 av1_num_planes(cm) - 1);
2566 }
2567
2568 #if CONFIG_COLLECT_COMPONENT_TIMING
2569 start_timing(cpi, motion_mode_rd_time);
2570 #endif
2571 int rate2_nocoeff = rd_stats->rate;
2572 ret_val = motion_mode_rd(cpi, tile_data, x, bsize, rd_stats, rd_stats_y,
2573 rd_stats_uv, disable_skip, args, ref_best_rd,
2574 skip_rd, &rate_mv, &orig_dst, best_est_rd,
2575 do_tx_search, inter_modes_info, 0);
2576 #if CONFIG_COLLECT_COMPONENT_TIMING
2577 end_timing(cpi, motion_mode_rd_time);
2578 #endif
2579
2580 mode_info[ref_mv_idx].mv.as_int = mbmi->mv[0].as_int;
2581 mode_info[ref_mv_idx].rate_mv = rate_mv;
2582 if (ret_val != INT64_MAX) {
2583 int64_t tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
2584 mode_info[ref_mv_idx].rd = tmp_rd;
2585 const THR_MODES mode_enum = get_prediction_mode_idx(
2586 mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
2587 // Collect mode stats for multiwinner mode processing
2588 store_winner_mode_stats(
2589 &cpi->common, x, mbmi, rd_stats, rd_stats_y, rd_stats_uv, mode_enum,
2590 NULL, bsize, tmp_rd,
2591 cpi->sf.winner_mode_sf.enable_multiwinner_mode_process, do_tx_search);
2592 if (tmp_rd < best_rd) {
2593 best_rd_stats = *rd_stats;
2594 best_rd_stats_y = *rd_stats_y;
2595 best_rd_stats_uv = *rd_stats_uv;
2596 best_rd = tmp_rd;
2597 best_mbmi = *mbmi;
2598 best_disable_skip = *disable_skip;
2599 best_xskip = x->force_skip;
2600 memcpy(best_blk_skip, x->blk_skip,
2601 sizeof(best_blk_skip[0]) * xd->n4_h * xd->n4_w);
2602 av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->n4_h * xd->n4_w);
2603 motion_mode_cand->rate_mv = rate_mv;
2604 motion_mode_cand->rate2_nocoeff = rate2_nocoeff;
2605 }
2606
2607 if (tmp_rd < ref_best_rd) {
2608 ref_best_rd = tmp_rd;
2609 best_ref_mv_idx = ref_mv_idx;
2610 }
2611 }
2612 restore_dst_buf(xd, orig_dst, num_planes);
2613 }
2614
2615 if (best_rd == INT64_MAX) return INT64_MAX;
2616
2617 // re-instate status of the best choice
2618 *rd_stats = best_rd_stats;
2619 *rd_stats_y = best_rd_stats_y;
2620 *rd_stats_uv = best_rd_stats_uv;
2621 *mbmi = best_mbmi;
2622 *disable_skip = best_disable_skip;
2623 x->force_skip = best_xskip;
2624 assert(IMPLIES(mbmi->comp_group_idx == 1,
2625 mbmi->interinter_comp.type != COMPOUND_AVERAGE));
2626 memcpy(x->blk_skip, best_blk_skip,
2627 sizeof(best_blk_skip[0]) * xd->n4_h * xd->n4_w);
2628 av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->n4_h * xd->n4_w);
2629
2630 rd_stats->rdcost = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
2631
2632 return rd_stats->rdcost;
2633 }
2634
rd_pick_intrabc_mode_sb(const AV1_COMP * cpi,MACROBLOCK * x,PICK_MODE_CONTEXT * ctx,RD_STATS * rd_stats,BLOCK_SIZE bsize,int64_t best_rd)2635 static int64_t rd_pick_intrabc_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
2636 PICK_MODE_CONTEXT *ctx,
2637 RD_STATS *rd_stats, BLOCK_SIZE bsize,
2638 int64_t best_rd) {
2639 const AV1_COMMON *const cm = &cpi->common;
2640 if (!av1_allow_intrabc(cm) || !cpi->oxcf.enable_intrabc) return INT64_MAX;
2641 const int num_planes = av1_num_planes(cm);
2642
2643 MACROBLOCKD *const xd = &x->e_mbd;
2644 const TileInfo *tile = &xd->tile;
2645 MB_MODE_INFO *mbmi = xd->mi[0];
2646 const int mi_row = xd->mi_row;
2647 const int mi_col = xd->mi_col;
2648 const int w = block_size_wide[bsize];
2649 const int h = block_size_high[bsize];
2650 const int sb_row = mi_row >> cm->seq_params.mib_size_log2;
2651 const int sb_col = mi_col >> cm->seq_params.mib_size_log2;
2652
2653 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
2654 MV_REFERENCE_FRAME ref_frame = INTRA_FRAME;
2655 av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
2656 xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
2657 mbmi_ext->mode_context);
2658 // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
2659 // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
2660 av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
2661 int_mv nearestmv, nearmv;
2662 av1_find_best_ref_mvs_from_stack(0, mbmi_ext, ref_frame, &nearestmv, &nearmv,
2663 0);
2664
2665 if (nearestmv.as_int == INVALID_MV) {
2666 nearestmv.as_int = 0;
2667 }
2668 if (nearmv.as_int == INVALID_MV) {
2669 nearmv.as_int = 0;
2670 }
2671
2672 int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
2673 if (dv_ref.as_int == 0) {
2674 av1_find_ref_dv(&dv_ref, tile, cm->seq_params.mib_size, mi_row);
2675 }
2676 // Ref DV should not have sub-pel.
2677 assert((dv_ref.as_mv.col & 7) == 0);
2678 assert((dv_ref.as_mv.row & 7) == 0);
2679 mbmi_ext->ref_mv_stack[INTRA_FRAME][0].this_mv = dv_ref;
2680
2681 struct buf_2d yv12_mb[MAX_MB_PLANE];
2682 av1_setup_pred_block(xd, yv12_mb, xd->cur_buf, NULL, NULL, num_planes);
2683 for (int i = 0; i < num_planes; ++i) {
2684 xd->plane[i].pre[0] = yv12_mb[i];
2685 }
2686
2687 enum IntrabcMotionDirection {
2688 IBC_MOTION_ABOVE,
2689 IBC_MOTION_LEFT,
2690 IBC_MOTION_DIRECTIONS
2691 };
2692
2693 MB_MODE_INFO best_mbmi = *mbmi;
2694 RD_STATS best_rdstats = *rd_stats;
2695 uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE] = { 0 };
2696 uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
2697 av1_copy_array(best_tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
2698
2699 for (enum IntrabcMotionDirection dir = IBC_MOTION_ABOVE;
2700 dir < IBC_MOTION_DIRECTIONS; ++dir) {
2701 const FullMvLimits tmp_mv_limits = x->mv_limits;
2702 switch (dir) {
2703 case IBC_MOTION_ABOVE:
2704 x->mv_limits.col_min = (tile->mi_col_start - mi_col) * MI_SIZE;
2705 x->mv_limits.col_max = (tile->mi_col_end - mi_col) * MI_SIZE - w;
2706 x->mv_limits.row_min = (tile->mi_row_start - mi_row) * MI_SIZE;
2707 x->mv_limits.row_max =
2708 (sb_row * cm->seq_params.mib_size - mi_row) * MI_SIZE - h;
2709 break;
2710 case IBC_MOTION_LEFT:
2711 x->mv_limits.col_min = (tile->mi_col_start - mi_col) * MI_SIZE;
2712 x->mv_limits.col_max =
2713 (sb_col * cm->seq_params.mib_size - mi_col) * MI_SIZE - w;
2714 // TODO(aconverse@google.com): Minimize the overlap between above and
2715 // left areas.
2716 x->mv_limits.row_min = (tile->mi_row_start - mi_row) * MI_SIZE;
2717 int bottom_coded_mi_edge =
2718 AOMMIN((sb_row + 1) * cm->seq_params.mib_size, tile->mi_row_end);
2719 x->mv_limits.row_max = (bottom_coded_mi_edge - mi_row) * MI_SIZE - h;
2720 break;
2721 default: assert(0);
2722 }
2723 assert(x->mv_limits.col_min >= tmp_mv_limits.col_min);
2724 assert(x->mv_limits.col_max <= tmp_mv_limits.col_max);
2725 assert(x->mv_limits.row_min >= tmp_mv_limits.row_min);
2726 assert(x->mv_limits.row_max <= tmp_mv_limits.row_max);
2727 av1_set_mv_search_range(&x->mv_limits, &dv_ref.as_mv);
2728
2729 if (x->mv_limits.col_max < x->mv_limits.col_min ||
2730 x->mv_limits.row_max < x->mv_limits.row_min) {
2731 x->mv_limits = tmp_mv_limits;
2732 continue;
2733 }
2734
2735 int step_param = cpi->mv_step_param;
2736 FULLPEL_MV start_mv = get_fullmv_from_mv(&dv_ref.as_mv);
2737 const int sadpb = x->sadperbit16;
2738 int cost_list[5];
2739 int bestsme = av1_full_pixel_search(
2740 cpi, x, bsize, start_mv, step_param, cpi->sf.mv_sf.search_method, 0,
2741 sadpb, cond_cost_list(cpi, cost_list), &dv_ref.as_mv, 1,
2742 &cpi->ss_cfg[SS_CFG_LOOKAHEAD], &x->best_mv.as_fullmv, NULL);
2743 av1_intrabc_hash_search(cpi, x, bsize, &dv_ref.as_mv, &bestsme,
2744 &x->best_mv.as_fullmv);
2745
2746 x->mv_limits = tmp_mv_limits;
2747 if (bestsme == INT_MAX) continue;
2748 const MV dv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
2749 if (!av1_is_fullmv_in_range(&x->mv_limits, get_fullmv_from_mv(&dv)))
2750 continue;
2751 if (!av1_is_dv_valid(dv, cm, xd, mi_row, mi_col, bsize,
2752 cm->seq_params.mib_size_log2))
2753 continue;
2754
2755 // DV should not have sub-pel.
2756 assert((dv.col & 7) == 0);
2757 assert((dv.row & 7) == 0);
2758 memset(&mbmi->palette_mode_info, 0, sizeof(mbmi->palette_mode_info));
2759 mbmi->filter_intra_mode_info.use_filter_intra = 0;
2760 mbmi->use_intrabc = 1;
2761 mbmi->mode = DC_PRED;
2762 mbmi->uv_mode = UV_DC_PRED;
2763 mbmi->motion_mode = SIMPLE_TRANSLATION;
2764 mbmi->mv[0].as_mv = dv;
2765 mbmi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
2766 mbmi->skip = 0;
2767 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
2768 av1_num_planes(cm) - 1);
2769
2770 int *dvcost[2] = { (int *)&cpi->dv_cost[0][MV_MAX],
2771 (int *)&cpi->dv_cost[1][MV_MAX] };
2772 // TODO(aconverse@google.com): The full motion field defining discount
2773 // in MV_COST_WEIGHT is too large. Explore other values.
2774 const int rate_mv = av1_mv_bit_cost(&dv, &dv_ref.as_mv, cpi->dv_joint_cost,
2775 dvcost, MV_COST_WEIGHT_SUB);
2776 const int rate_mode = x->intrabc_cost[1];
2777 RD_STATS rd_stats_yuv, rd_stats_y, rd_stats_uv;
2778 if (!av1_txfm_search(cpi, NULL, x, bsize, &rd_stats_yuv, &rd_stats_y,
2779 &rd_stats_uv, rate_mode + rate_mv, INT64_MAX))
2780 continue;
2781 rd_stats_yuv.rdcost =
2782 RDCOST(x->rdmult, rd_stats_yuv.rate, rd_stats_yuv.dist);
2783 if (rd_stats_yuv.rdcost < best_rd) {
2784 best_rd = rd_stats_yuv.rdcost;
2785 best_mbmi = *mbmi;
2786 best_rdstats = rd_stats_yuv;
2787 memcpy(best_blk_skip, x->blk_skip,
2788 sizeof(x->blk_skip[0]) * xd->n4_h * xd->n4_w);
2789 av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->n4_h * xd->n4_w);
2790 }
2791 }
2792 *mbmi = best_mbmi;
2793 *rd_stats = best_rdstats;
2794 memcpy(x->blk_skip, best_blk_skip,
2795 sizeof(x->blk_skip[0]) * xd->n4_h * xd->n4_w);
2796 av1_copy_array(xd->tx_type_map, best_tx_type_map, ctx->num_4x4_blk);
2797 #if CONFIG_RD_DEBUG
2798 mbmi->rd_stats = *rd_stats;
2799 #endif
2800 return best_rd;
2801 }
2802
av1_rd_pick_intra_mode_sb(const AV1_COMP * cpi,MACROBLOCK * x,RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,int64_t best_rd)2803 void av1_rd_pick_intra_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
2804 RD_STATS *rd_cost, BLOCK_SIZE bsize,
2805 PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
2806 const AV1_COMMON *const cm = &cpi->common;
2807 MACROBLOCKD *const xd = &x->e_mbd;
2808 MB_MODE_INFO *const mbmi = xd->mi[0];
2809 const int num_planes = av1_num_planes(cm);
2810 int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
2811 int y_skip = 0, uv_skip = 0;
2812 int64_t dist_y = 0, dist_uv = 0;
2813
2814 ctx->rd_stats.skip = 0;
2815 mbmi->ref_frame[0] = INTRA_FRAME;
2816 mbmi->ref_frame[1] = NONE_FRAME;
2817 mbmi->use_intrabc = 0;
2818 mbmi->mv[0].as_int = 0;
2819 mbmi->skip_mode = 0;
2820
2821 const int64_t intra_yrd =
2822 av1_rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly, &dist_y,
2823 &y_skip, bsize, best_rd, ctx);
2824
2825 // Initialize default mode evaluation params
2826 set_mode_eval_params(cpi, x, DEFAULT_EVAL);
2827
2828 if (intra_yrd < best_rd) {
2829 // Only store reconstructed luma when there's chroma RDO. When there's no
2830 // chroma RDO, the reconstructed luma will be stored in encode_superblock().
2831 xd->cfl.store_y = store_cfl_required_rdo(cm, x);
2832 if (xd->cfl.store_y) {
2833 // Restore reconstructed luma values.
2834 memcpy(x->blk_skip, ctx->blk_skip,
2835 sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
2836 av1_copy_array(xd->tx_type_map, ctx->tx_type_map, ctx->num_4x4_blk);
2837 av1_encode_intra_block_plane(cpi, x, bsize, AOM_PLANE_Y,
2838 cpi->optimize_seg_arr[mbmi->segment_id]);
2839 av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
2840 xd->cfl.store_y = 0;
2841 }
2842 if (num_planes > 1) {
2843 init_sbuv_mode(mbmi);
2844 if (xd->is_chroma_ref) {
2845 const TX_SIZE max_uv_tx_size = av1_get_tx_size(AOM_PLANE_U, xd);
2846 av1_rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
2847 &dist_uv, &uv_skip, bsize, max_uv_tx_size);
2848 }
2849 }
2850
2851 // Intra block is always coded as non-skip
2852 rd_cost->rate =
2853 rate_y + rate_uv + x->skip_cost[av1_get_skip_context(xd)][0];
2854 rd_cost->dist = dist_y + dist_uv;
2855 rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
2856 rd_cost->skip = 0;
2857 } else {
2858 rd_cost->rate = INT_MAX;
2859 }
2860
2861 if (rd_cost->rate != INT_MAX && rd_cost->rdcost < best_rd)
2862 best_rd = rd_cost->rdcost;
2863 if (rd_pick_intrabc_mode_sb(cpi, x, ctx, rd_cost, bsize, best_rd) < best_rd) {
2864 ctx->rd_stats.skip = mbmi->skip;
2865 memcpy(ctx->blk_skip, x->blk_skip,
2866 sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
2867 assert(rd_cost->rate != INT_MAX);
2868 }
2869 if (rd_cost->rate == INT_MAX) return;
2870
2871 ctx->mic = *xd->mi[0];
2872 ctx->mbmi_ext = *x->mbmi_ext;
2873 av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
2874 }
2875
2876 static AOM_INLINE void calc_target_weighted_pred(
2877 const AV1_COMMON *cm, const MACROBLOCK *x, const MACROBLOCKD *xd,
2878 const uint8_t *above, int above_stride, const uint8_t *left,
2879 int left_stride);
2880
rd_pick_skip_mode(RD_STATS * rd_cost,InterModeSearchState * search_state,const AV1_COMP * const cpi,MACROBLOCK * const x,BLOCK_SIZE bsize,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE])2881 static AOM_INLINE void rd_pick_skip_mode(
2882 RD_STATS *rd_cost, InterModeSearchState *search_state,
2883 const AV1_COMP *const cpi, MACROBLOCK *const x, BLOCK_SIZE bsize,
2884 struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
2885 const AV1_COMMON *const cm = &cpi->common;
2886 const SkipModeInfo *const skip_mode_info = &cm->current_frame.skip_mode_info;
2887 const int num_planes = av1_num_planes(cm);
2888 MACROBLOCKD *const xd = &x->e_mbd;
2889 MB_MODE_INFO *const mbmi = xd->mi[0];
2890
2891 x->compound_idx = 1; // COMPOUND_AVERAGE
2892 RD_STATS skip_mode_rd_stats;
2893 av1_invalid_rd_stats(&skip_mode_rd_stats);
2894
2895 if (skip_mode_info->ref_frame_idx_0 == INVALID_IDX ||
2896 skip_mode_info->ref_frame_idx_1 == INVALID_IDX) {
2897 return;
2898 }
2899
2900 const MV_REFERENCE_FRAME ref_frame =
2901 LAST_FRAME + skip_mode_info->ref_frame_idx_0;
2902 const MV_REFERENCE_FRAME second_ref_frame =
2903 LAST_FRAME + skip_mode_info->ref_frame_idx_1;
2904 const PREDICTION_MODE this_mode = NEAREST_NEARESTMV;
2905 const THR_MODES mode_index =
2906 get_prediction_mode_idx(this_mode, ref_frame, second_ref_frame);
2907
2908 if (mode_index == THR_INVALID) {
2909 return;
2910 }
2911
2912 if ((!cpi->oxcf.enable_onesided_comp ||
2913 cpi->sf.inter_sf.disable_onesided_comp) &&
2914 cpi->all_one_sided_refs) {
2915 return;
2916 }
2917
2918 mbmi->mode = this_mode;
2919 mbmi->uv_mode = UV_DC_PRED;
2920 mbmi->ref_frame[0] = ref_frame;
2921 mbmi->ref_frame[1] = second_ref_frame;
2922 const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
2923 if (x->mbmi_ext->ref_mv_count[ref_frame_type] == UINT8_MAX) {
2924 if (x->mbmi_ext->ref_mv_count[ref_frame] == UINT8_MAX ||
2925 x->mbmi_ext->ref_mv_count[second_ref_frame] == UINT8_MAX) {
2926 return;
2927 }
2928 MB_MODE_INFO_EXT *mbmi_ext = x->mbmi_ext;
2929 av1_find_mv_refs(cm, xd, mbmi, ref_frame_type, mbmi_ext->ref_mv_count,
2930 xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
2931 mbmi_ext->mode_context);
2932 // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
2933 // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
2934 av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame_type);
2935 }
2936
2937 assert(this_mode == NEAREST_NEARESTMV);
2938 if (!build_cur_mv(mbmi->mv, this_mode, cm, x, 0)) {
2939 return;
2940 }
2941
2942 mbmi->filter_intra_mode_info.use_filter_intra = 0;
2943 mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
2944 mbmi->comp_group_idx = 0;
2945 mbmi->compound_idx = x->compound_idx;
2946 mbmi->interinter_comp.type = COMPOUND_AVERAGE;
2947 mbmi->motion_mode = SIMPLE_TRANSLATION;
2948 mbmi->ref_mv_idx = 0;
2949 mbmi->skip_mode = mbmi->skip = 1;
2950
2951 set_default_interp_filters(mbmi, cm->interp_filter);
2952
2953 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
2954 for (int i = 0; i < num_planes; i++) {
2955 xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
2956 xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
2957 }
2958
2959 BUFFER_SET orig_dst;
2960 for (int i = 0; i < num_planes; i++) {
2961 orig_dst.plane[i] = xd->plane[i].dst.buf;
2962 orig_dst.stride[i] = xd->plane[i].dst.stride;
2963 }
2964
2965 // Obtain the rdcost for skip_mode.
2966 skip_mode_rd(&skip_mode_rd_stats, cpi, x, bsize, &orig_dst);
2967
2968 // Compare the use of skip_mode with the best intra/inter mode obtained.
2969 const int skip_mode_ctx = av1_get_skip_mode_context(xd);
2970 int64_t best_intra_inter_mode_cost = INT64_MAX;
2971 if (rd_cost->dist < INT64_MAX && rd_cost->rate < INT32_MAX) {
2972 best_intra_inter_mode_cost =
2973 RDCOST(x->rdmult, rd_cost->rate + x->skip_mode_cost[skip_mode_ctx][0],
2974 rd_cost->dist);
2975 // Account for non-skip mode rate in total rd stats
2976 rd_cost->rate += x->skip_mode_cost[skip_mode_ctx][0];
2977 av1_rd_cost_update(x->rdmult, rd_cost);
2978 }
2979
2980 if (skip_mode_rd_stats.rdcost <= best_intra_inter_mode_cost &&
2981 (!xd->lossless[mbmi->segment_id] || skip_mode_rd_stats.dist == 0)) {
2982 assert(mode_index != THR_INVALID);
2983 search_state->best_mbmode.skip_mode = 1;
2984 search_state->best_mbmode = *mbmi;
2985
2986 search_state->best_mbmode.skip_mode = search_state->best_mbmode.skip = 1;
2987 search_state->best_mbmode.mode = NEAREST_NEARESTMV;
2988 search_state->best_mbmode.ref_frame[0] = mbmi->ref_frame[0];
2989 search_state->best_mbmode.ref_frame[1] = mbmi->ref_frame[1];
2990 search_state->best_mbmode.mv[0].as_int = mbmi->mv[0].as_int;
2991 search_state->best_mbmode.mv[1].as_int = mbmi->mv[1].as_int;
2992 search_state->best_mbmode.ref_mv_idx = 0;
2993
2994 // Set up tx_size related variables for skip-specific loop filtering.
2995 search_state->best_mbmode.tx_size =
2996 block_signals_txsize(bsize)
2997 ? tx_size_from_tx_mode(bsize, x->tx_mode_search_type)
2998 : max_txsize_rect_lookup[bsize];
2999 memset(search_state->best_mbmode.inter_tx_size,
3000 search_state->best_mbmode.tx_size,
3001 sizeof(search_state->best_mbmode.inter_tx_size));
3002 set_txfm_ctxs(search_state->best_mbmode.tx_size, xd->n4_w, xd->n4_h,
3003 search_state->best_mbmode.skip && is_inter_block(mbmi), xd);
3004
3005 // Set up color-related variables for skip mode.
3006 search_state->best_mbmode.uv_mode = UV_DC_PRED;
3007 search_state->best_mbmode.palette_mode_info.palette_size[0] = 0;
3008 search_state->best_mbmode.palette_mode_info.palette_size[1] = 0;
3009
3010 search_state->best_mbmode.comp_group_idx = 0;
3011 search_state->best_mbmode.compound_idx = x->compound_idx;
3012 search_state->best_mbmode.interinter_comp.type = COMPOUND_AVERAGE;
3013 search_state->best_mbmode.motion_mode = SIMPLE_TRANSLATION;
3014
3015 search_state->best_mbmode.interintra_mode =
3016 (INTERINTRA_MODE)(II_DC_PRED - 1);
3017 search_state->best_mbmode.filter_intra_mode_info.use_filter_intra = 0;
3018
3019 set_default_interp_filters(&search_state->best_mbmode, cm->interp_filter);
3020
3021 search_state->best_mode_index = mode_index;
3022
3023 // Update rd_cost
3024 rd_cost->rate = skip_mode_rd_stats.rate;
3025 rd_cost->dist = rd_cost->sse = skip_mode_rd_stats.dist;
3026 rd_cost->rdcost = skip_mode_rd_stats.rdcost;
3027
3028 search_state->best_rd = rd_cost->rdcost;
3029 search_state->best_skip2 = 1;
3030 search_state->best_mode_skippable = 1;
3031
3032 x->force_skip = 1;
3033 }
3034 }
3035
3036 // Get winner mode stats of given mode index
get_winner_mode_stats(MACROBLOCK * x,MB_MODE_INFO * best_mbmode,RD_STATS * best_rd_cost,int best_rate_y,int best_rate_uv,THR_MODES * best_mode_index,RD_STATS ** winner_rd_cost,int * winner_rate_y,int * winner_rate_uv,THR_MODES * winner_mode_index,int enable_multiwinner_mode_process,int mode_idx)3037 static AOM_INLINE MB_MODE_INFO *get_winner_mode_stats(
3038 MACROBLOCK *x, MB_MODE_INFO *best_mbmode, RD_STATS *best_rd_cost,
3039 int best_rate_y, int best_rate_uv, THR_MODES *best_mode_index,
3040 RD_STATS **winner_rd_cost, int *winner_rate_y, int *winner_rate_uv,
3041 THR_MODES *winner_mode_index, int enable_multiwinner_mode_process,
3042 int mode_idx) {
3043 MB_MODE_INFO *winner_mbmi;
3044 if (enable_multiwinner_mode_process) {
3045 assert(mode_idx >= 0 && mode_idx < x->winner_mode_count);
3046 WinnerModeStats *winner_mode_stat = &x->winner_mode_stats[mode_idx];
3047 winner_mbmi = &winner_mode_stat->mbmi;
3048
3049 *winner_rd_cost = &winner_mode_stat->rd_cost;
3050 *winner_rate_y = winner_mode_stat->rate_y;
3051 *winner_rate_uv = winner_mode_stat->rate_uv;
3052 *winner_mode_index = winner_mode_stat->mode_index;
3053 } else {
3054 winner_mbmi = best_mbmode;
3055 *winner_rd_cost = best_rd_cost;
3056 *winner_rate_y = best_rate_y;
3057 *winner_rate_uv = best_rate_uv;
3058 *winner_mode_index = *best_mode_index;
3059 }
3060 return winner_mbmi;
3061 }
3062
3063 // speed feature: fast intra/inter transform type search
3064 // Used for speed >= 2
3065 // When this speed feature is on, in rd mode search, only DCT is used.
3066 // After the mode is determined, this function is called, to select
3067 // transform types and get accurate rdcost.
refine_winner_mode_tx(const AV1_COMP * cpi,MACROBLOCK * x,RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,THR_MODES * best_mode_index,MB_MODE_INFO * best_mbmode,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],int best_rate_y,int best_rate_uv,int * best_skip2,int winner_mode_count)3068 static AOM_INLINE void refine_winner_mode_tx(
3069 const AV1_COMP *cpi, MACROBLOCK *x, RD_STATS *rd_cost, BLOCK_SIZE bsize,
3070 PICK_MODE_CONTEXT *ctx, THR_MODES *best_mode_index,
3071 MB_MODE_INFO *best_mbmode, struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],
3072 int best_rate_y, int best_rate_uv, int *best_skip2, int winner_mode_count) {
3073 const AV1_COMMON *const cm = &cpi->common;
3074 MACROBLOCKD *const xd = &x->e_mbd;
3075 MB_MODE_INFO *const mbmi = xd->mi[0];
3076 int64_t best_rd;
3077 const int num_planes = av1_num_planes(cm);
3078
3079 if (!is_winner_mode_processing_enabled(cpi, best_mbmode, best_mbmode->mode))
3080 return;
3081
3082 // Set params for winner mode evaluation
3083 set_mode_eval_params(cpi, x, WINNER_MODE_EVAL);
3084
3085 // No best mode identified so far
3086 if (*best_mode_index == THR_INVALID) return;
3087
3088 best_rd = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
3089 for (int mode_idx = 0; mode_idx < winner_mode_count; mode_idx++) {
3090 RD_STATS *winner_rd_stats = NULL;
3091 int winner_rate_y = 0, winner_rate_uv = 0;
3092 THR_MODES winner_mode_index = 0;
3093
3094 // TODO(any): Combine best mode and multi-winner mode processing paths
3095 // Get winner mode stats for current mode index
3096 MB_MODE_INFO *winner_mbmi = get_winner_mode_stats(
3097 x, best_mbmode, rd_cost, best_rate_y, best_rate_uv, best_mode_index,
3098 &winner_rd_stats, &winner_rate_y, &winner_rate_uv, &winner_mode_index,
3099 cpi->sf.winner_mode_sf.enable_multiwinner_mode_process, mode_idx);
3100
3101 if (xd->lossless[winner_mbmi->segment_id] == 0 &&
3102 winner_mode_index != THR_INVALID &&
3103 is_winner_mode_processing_enabled(cpi, winner_mbmi,
3104 winner_mbmi->mode)) {
3105 RD_STATS rd_stats = *winner_rd_stats;
3106 int skip_blk = 0;
3107 RD_STATS rd_stats_y, rd_stats_uv;
3108 const int skip_ctx = av1_get_skip_context(xd);
3109
3110 *mbmi = *winner_mbmi;
3111
3112 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
3113
3114 // Select prediction reference frames.
3115 for (int i = 0; i < num_planes; i++) {
3116 xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
3117 if (has_second_ref(mbmi))
3118 xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
3119 }
3120
3121 if (is_inter_mode(mbmi->mode)) {
3122 const int mi_row = xd->mi_row;
3123 const int mi_col = xd->mi_col;
3124 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
3125 av1_num_planes(cm) - 1);
3126 if (mbmi->motion_mode == OBMC_CAUSAL)
3127 av1_build_obmc_inter_predictors_sb(cm, xd);
3128
3129 av1_subtract_plane(x, bsize, 0);
3130 if (x->tx_mode_search_type == TX_MODE_SELECT &&
3131 !xd->lossless[mbmi->segment_id]) {
3132 av1_pick_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
3133 assert(rd_stats_y.rate != INT_MAX);
3134 } else {
3135 av1_super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
3136 memset(mbmi->inter_tx_size, mbmi->tx_size,
3137 sizeof(mbmi->inter_tx_size));
3138 for (int i = 0; i < xd->n4_h * xd->n4_w; ++i)
3139 set_blk_skip(x, 0, i, rd_stats_y.skip);
3140 }
3141 } else {
3142 av1_super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
3143 }
3144
3145 if (num_planes > 1) {
3146 av1_super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
3147 } else {
3148 av1_init_rd_stats(&rd_stats_uv);
3149 }
3150
3151 if (is_inter_mode(mbmi->mode) &&
3152 RDCOST(x->rdmult,
3153 x->skip_cost[skip_ctx][0] + rd_stats_y.rate + rd_stats_uv.rate,
3154 (rd_stats_y.dist + rd_stats_uv.dist)) >
3155 RDCOST(x->rdmult, x->skip_cost[skip_ctx][1],
3156 (rd_stats_y.sse + rd_stats_uv.sse))) {
3157 skip_blk = 1;
3158 rd_stats_y.rate = x->skip_cost[skip_ctx][1];
3159 rd_stats_uv.rate = 0;
3160 rd_stats_y.dist = rd_stats_y.sse;
3161 rd_stats_uv.dist = rd_stats_uv.sse;
3162 } else {
3163 skip_blk = 0;
3164 rd_stats_y.rate += x->skip_cost[skip_ctx][0];
3165 }
3166 int this_rate = rd_stats.rate + rd_stats_y.rate + rd_stats_uv.rate -
3167 winner_rate_y - winner_rate_uv;
3168 int64_t this_rd =
3169 RDCOST(x->rdmult, this_rate, (rd_stats_y.dist + rd_stats_uv.dist));
3170 if (best_rd > this_rd) {
3171 *best_mbmode = *mbmi;
3172 *best_mode_index = winner_mode_index;
3173 av1_copy_array(ctx->blk_skip, x->blk_skip, ctx->num_4x4_blk);
3174 av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
3175 rd_cost->rate = this_rate;
3176 rd_cost->dist = rd_stats_y.dist + rd_stats_uv.dist;
3177 rd_cost->sse = rd_stats_y.sse + rd_stats_uv.sse;
3178 rd_cost->rdcost = this_rd;
3179 best_rd = this_rd;
3180 *best_skip2 = skip_blk;
3181 }
3182 }
3183 }
3184 }
3185
3186 typedef struct {
3187 // Mask for each reference frame, specifying which prediction modes to NOT try
3188 // during search.
3189 uint32_t pred_modes[REF_FRAMES];
3190 // If ref_combo[i][j + 1] is true, do NOT try prediction using combination of
3191 // reference frames (i, j).
3192 // Note: indexing with 'j + 1' is due to the fact that 2nd reference can be -1
3193 // (NONE_FRAME).
3194 bool ref_combo[REF_FRAMES][REF_FRAMES + 1];
3195 } mode_skip_mask_t;
3196
3197 // Update 'ref_combo' mask to disable given 'ref' in single and compound modes.
disable_reference(MV_REFERENCE_FRAME ref,bool ref_combo[REF_FRAMES][REF_FRAMES+1])3198 static AOM_INLINE void disable_reference(
3199 MV_REFERENCE_FRAME ref, bool ref_combo[REF_FRAMES][REF_FRAMES + 1]) {
3200 for (MV_REFERENCE_FRAME ref2 = NONE_FRAME; ref2 < REF_FRAMES; ++ref2) {
3201 ref_combo[ref][ref2 + 1] = true;
3202 }
3203 }
3204
3205 // Update 'ref_combo' mask to disable all inter references except ALTREF.
disable_inter_references_except_altref(bool ref_combo[REF_FRAMES][REF_FRAMES+1])3206 static AOM_INLINE void disable_inter_references_except_altref(
3207 bool ref_combo[REF_FRAMES][REF_FRAMES + 1]) {
3208 disable_reference(LAST_FRAME, ref_combo);
3209 disable_reference(LAST2_FRAME, ref_combo);
3210 disable_reference(LAST3_FRAME, ref_combo);
3211 disable_reference(GOLDEN_FRAME, ref_combo);
3212 disable_reference(BWDREF_FRAME, ref_combo);
3213 disable_reference(ALTREF2_FRAME, ref_combo);
3214 }
3215
3216 static const MV_REFERENCE_FRAME reduced_ref_combos[][2] = {
3217 { LAST_FRAME, NONE_FRAME }, { ALTREF_FRAME, NONE_FRAME },
3218 { LAST_FRAME, ALTREF_FRAME }, { GOLDEN_FRAME, NONE_FRAME },
3219 { INTRA_FRAME, NONE_FRAME }, { GOLDEN_FRAME, ALTREF_FRAME },
3220 { LAST_FRAME, GOLDEN_FRAME }, { LAST_FRAME, INTRA_FRAME },
3221 { LAST_FRAME, BWDREF_FRAME }, { LAST_FRAME, LAST3_FRAME },
3222 { GOLDEN_FRAME, BWDREF_FRAME }, { GOLDEN_FRAME, INTRA_FRAME },
3223 { BWDREF_FRAME, NONE_FRAME }, { BWDREF_FRAME, ALTREF_FRAME },
3224 { ALTREF_FRAME, INTRA_FRAME }, { BWDREF_FRAME, INTRA_FRAME },
3225 };
3226
3227 static const MV_REFERENCE_FRAME real_time_ref_combos[][2] = {
3228 { LAST_FRAME, NONE_FRAME },
3229 { ALTREF_FRAME, NONE_FRAME },
3230 { GOLDEN_FRAME, NONE_FRAME },
3231 { INTRA_FRAME, NONE_FRAME }
3232 };
3233
3234 typedef enum { REF_SET_FULL, REF_SET_REDUCED, REF_SET_REALTIME } REF_SET;
3235
default_skip_mask(mode_skip_mask_t * mask,REF_SET ref_set)3236 static AOM_INLINE void default_skip_mask(mode_skip_mask_t *mask,
3237 REF_SET ref_set) {
3238 if (ref_set == REF_SET_FULL) {
3239 // Everything available by default.
3240 memset(mask, 0, sizeof(*mask));
3241 } else {
3242 // All modes available by default.
3243 memset(mask->pred_modes, 0, sizeof(mask->pred_modes));
3244 // All references disabled first.
3245 for (MV_REFERENCE_FRAME ref1 = INTRA_FRAME; ref1 < REF_FRAMES; ++ref1) {
3246 for (MV_REFERENCE_FRAME ref2 = NONE_FRAME; ref2 < REF_FRAMES; ++ref2) {
3247 mask->ref_combo[ref1][ref2 + 1] = true;
3248 }
3249 }
3250 const MV_REFERENCE_FRAME(*ref_set_combos)[2];
3251 int num_ref_combos;
3252
3253 // Then enable reduced set of references explicitly.
3254 switch (ref_set) {
3255 case REF_SET_REDUCED:
3256 ref_set_combos = reduced_ref_combos;
3257 num_ref_combos =
3258 (int)sizeof(reduced_ref_combos) / sizeof(reduced_ref_combos[0]);
3259 break;
3260 case REF_SET_REALTIME:
3261 ref_set_combos = real_time_ref_combos;
3262 num_ref_combos =
3263 (int)sizeof(real_time_ref_combos) / sizeof(real_time_ref_combos[0]);
3264 break;
3265 default: assert(0); num_ref_combos = 0;
3266 }
3267
3268 for (int i = 0; i < num_ref_combos; ++i) {
3269 const MV_REFERENCE_FRAME *const this_combo = ref_set_combos[i];
3270 mask->ref_combo[this_combo[0]][this_combo[1] + 1] = false;
3271 }
3272 }
3273 }
3274
init_mode_skip_mask(mode_skip_mask_t * mask,const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize)3275 static AOM_INLINE void init_mode_skip_mask(mode_skip_mask_t *mask,
3276 const AV1_COMP *cpi, MACROBLOCK *x,
3277 BLOCK_SIZE bsize) {
3278 const AV1_COMMON *const cm = &cpi->common;
3279 const struct segmentation *const seg = &cm->seg;
3280 MACROBLOCKD *const xd = &x->e_mbd;
3281 MB_MODE_INFO *const mbmi = xd->mi[0];
3282 unsigned char segment_id = mbmi->segment_id;
3283 const SPEED_FEATURES *const sf = &cpi->sf;
3284 REF_SET ref_set = REF_SET_FULL;
3285
3286 if (sf->rt_sf.use_real_time_ref_set)
3287 ref_set = REF_SET_REALTIME;
3288 else if (cpi->oxcf.enable_reduced_reference_set)
3289 ref_set = REF_SET_REDUCED;
3290
3291 default_skip_mask(mask, ref_set);
3292
3293 int min_pred_mv_sad = INT_MAX;
3294 MV_REFERENCE_FRAME ref_frame;
3295 if (ref_set == REF_SET_REALTIME) {
3296 // For real-time encoding, we only look at a subset of ref frames. So the
3297 // threshold for pruning should be computed from this subset as well.
3298 const int num_rt_refs =
3299 sizeof(real_time_ref_combos) / sizeof(*real_time_ref_combos);
3300 for (int r_idx = 0; r_idx < num_rt_refs; r_idx++) {
3301 const MV_REFERENCE_FRAME ref = real_time_ref_combos[r_idx][0];
3302 if (ref != INTRA_FRAME) {
3303 min_pred_mv_sad = AOMMIN(min_pred_mv_sad, x->pred_mv_sad[ref]);
3304 }
3305 }
3306 } else {
3307 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame)
3308 min_pred_mv_sad = AOMMIN(min_pred_mv_sad, x->pred_mv_sad[ref_frame]);
3309 }
3310
3311 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
3312 if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame])) {
3313 // Skip checking missing reference in both single and compound reference
3314 // modes.
3315 disable_reference(ref_frame, mask->ref_combo);
3316 } else {
3317 // Skip fixed mv modes for poor references
3318 if ((x->pred_mv_sad[ref_frame] >> 2) > min_pred_mv_sad) {
3319 mask->pred_modes[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
3320 }
3321 }
3322 if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
3323 get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
3324 // Reference not used for the segment.
3325 disable_reference(ref_frame, mask->ref_combo);
3326 }
3327 }
3328 // Note: We use the following drop-out only if the SEG_LVL_REF_FRAME feature
3329 // is disabled for this segment. This is to prevent the possibility that we
3330 // end up unable to pick any mode.
3331 if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
3332 // Only consider GLOBALMV/ALTREF_FRAME for alt ref frame,
3333 // unless ARNR filtering is enabled in which case we want
3334 // an unfiltered alternative. We allow near/nearest as well
3335 // because they may result in zero-zero MVs but be cheaper.
3336 if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
3337 disable_inter_references_except_altref(mask->ref_combo);
3338
3339 mask->pred_modes[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
3340 const MV_REFERENCE_FRAME tmp_ref_frames[2] = { ALTREF_FRAME, NONE_FRAME };
3341 int_mv near_mv, nearest_mv, global_mv;
3342 get_this_mv(&nearest_mv, NEARESTMV, 0, 0, 0, tmp_ref_frames, x->mbmi_ext);
3343 get_this_mv(&near_mv, NEARMV, 0, 0, 0, tmp_ref_frames, x->mbmi_ext);
3344 get_this_mv(&global_mv, GLOBALMV, 0, 0, 0, tmp_ref_frames, x->mbmi_ext);
3345
3346 if (near_mv.as_int != global_mv.as_int)
3347 mask->pred_modes[ALTREF_FRAME] |= (1 << NEARMV);
3348 if (nearest_mv.as_int != global_mv.as_int)
3349 mask->pred_modes[ALTREF_FRAME] |= (1 << NEARESTMV);
3350 }
3351 }
3352
3353 if (cpi->rc.is_src_frame_alt_ref) {
3354 if (sf->inter_sf.alt_ref_search_fp) {
3355 assert(cpi->ref_frame_flags & av1_ref_frame_flag_list[ALTREF_FRAME]);
3356 mask->pred_modes[ALTREF_FRAME] = 0;
3357 disable_inter_references_except_altref(mask->ref_combo);
3358 disable_reference(INTRA_FRAME, mask->ref_combo);
3359 }
3360 }
3361
3362 if (sf->inter_sf.alt_ref_search_fp) {
3363 if (!cm->show_frame && x->best_pred_mv_sad < INT_MAX) {
3364 int sad_thresh = x->best_pred_mv_sad + (x->best_pred_mv_sad >> 3);
3365 // Conservatively skip the modes w.r.t. BWDREF, ALTREF2 and ALTREF, if
3366 // those are past frames
3367 for (ref_frame = BWDREF_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
3368 if (cpi->ref_relative_dist[ref_frame - LAST_FRAME] < 0)
3369 if (x->pred_mv_sad[ref_frame] > sad_thresh)
3370 mask->pred_modes[ref_frame] |= INTER_ALL;
3371 }
3372 }
3373 }
3374
3375 if (sf->inter_sf.adaptive_mode_search) {
3376 if (cm->show_frame && !cpi->rc.is_src_frame_alt_ref &&
3377 cpi->rc.frames_since_golden >= 3)
3378 if ((x->pred_mv_sad[GOLDEN_FRAME] >> 1) > x->pred_mv_sad[LAST_FRAME])
3379 mask->pred_modes[GOLDEN_FRAME] |= INTER_ALL;
3380 }
3381
3382 if (bsize > sf->part_sf.max_intra_bsize) {
3383 disable_reference(INTRA_FRAME, mask->ref_combo);
3384 }
3385
3386 mask->pred_modes[INTRA_FRAME] |=
3387 ~(sf->intra_sf.intra_y_mode_mask[max_txsize_lookup[bsize]]);
3388 }
3389
init_pred_buf(const MACROBLOCK * const x,HandleInterModeArgs * const args)3390 static AOM_INLINE void init_pred_buf(const MACROBLOCK *const x,
3391 HandleInterModeArgs *const args) {
3392 const MACROBLOCKD *const xd = &x->e_mbd;
3393 if (is_cur_buf_hbd(xd)) {
3394 const int len = sizeof(uint16_t);
3395 args->above_pred_buf[0] = CONVERT_TO_BYTEPTR(x->above_pred_buf);
3396 args->above_pred_buf[1] =
3397 CONVERT_TO_BYTEPTR(x->above_pred_buf + (MAX_SB_SQUARE >> 1) * len);
3398 args->above_pred_buf[2] =
3399 CONVERT_TO_BYTEPTR(x->above_pred_buf + MAX_SB_SQUARE * len);
3400 args->left_pred_buf[0] = CONVERT_TO_BYTEPTR(x->left_pred_buf);
3401 args->left_pred_buf[1] =
3402 CONVERT_TO_BYTEPTR(x->left_pred_buf + (MAX_SB_SQUARE >> 1) * len);
3403 args->left_pred_buf[2] =
3404 CONVERT_TO_BYTEPTR(x->left_pred_buf + MAX_SB_SQUARE * len);
3405 } else {
3406 args->above_pred_buf[0] = x->above_pred_buf;
3407 args->above_pred_buf[1] = x->above_pred_buf + (MAX_SB_SQUARE >> 1);
3408 args->above_pred_buf[2] = x->above_pred_buf + MAX_SB_SQUARE;
3409 args->left_pred_buf[0] = x->left_pred_buf;
3410 args->left_pred_buf[1] = x->left_pred_buf + (MAX_SB_SQUARE >> 1);
3411 args->left_pred_buf[2] = x->left_pred_buf + MAX_SB_SQUARE;
3412 }
3413 }
3414
3415 // Please add/modify parameter setting in this function, making it consistent
3416 // and easy to read and maintain.
set_params_rd_pick_inter_mode(const AV1_COMP * cpi,MACROBLOCK * x,HandleInterModeArgs * args,BLOCK_SIZE bsize,mode_skip_mask_t * mode_skip_mask,int skip_ref_frame_mask,unsigned int * ref_costs_single,unsigned int (* ref_costs_comp)[REF_FRAMES],struct buf_2d (* yv12_mb)[MAX_MB_PLANE])3417 static AOM_INLINE void set_params_rd_pick_inter_mode(
3418 const AV1_COMP *cpi, MACROBLOCK *x, HandleInterModeArgs *args,
3419 BLOCK_SIZE bsize, mode_skip_mask_t *mode_skip_mask, int skip_ref_frame_mask,
3420 unsigned int *ref_costs_single, unsigned int (*ref_costs_comp)[REF_FRAMES],
3421 struct buf_2d (*yv12_mb)[MAX_MB_PLANE]) {
3422 const AV1_COMMON *const cm = &cpi->common;
3423 MACROBLOCKD *const xd = &x->e_mbd;
3424 MB_MODE_INFO *const mbmi = xd->mi[0];
3425 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
3426 unsigned char segment_id = mbmi->segment_id;
3427
3428 init_pred_buf(x, args);
3429 av1_collect_neighbors_ref_counts(xd);
3430 estimate_ref_frame_costs(cm, xd, x, segment_id, ref_costs_single,
3431 ref_costs_comp);
3432
3433 const int mi_row = xd->mi_row;
3434 const int mi_col = xd->mi_col;
3435 MV_REFERENCE_FRAME ref_frame;
3436 x->best_pred_mv_sad = INT_MAX;
3437 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
3438 x->pred_mv_sad[ref_frame] = INT_MAX;
3439 x->mbmi_ext->mode_context[ref_frame] = 0;
3440 mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
3441 if (cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
3442 if (mbmi->partition != PARTITION_NONE &&
3443 mbmi->partition != PARTITION_SPLIT) {
3444 if (skip_ref_frame_mask & (1 << ref_frame)) {
3445 int skip = 1;
3446 for (int r = ALTREF_FRAME + 1; r < MODE_CTX_REF_FRAMES; ++r) {
3447 if (!(skip_ref_frame_mask & (1 << r))) {
3448 const MV_REFERENCE_FRAME *rf = ref_frame_map[r - REF_FRAMES];
3449 if (rf[0] == ref_frame || rf[1] == ref_frame) {
3450 skip = 0;
3451 break;
3452 }
3453 }
3454 }
3455 if (skip) continue;
3456 }
3457 }
3458 assert(get_ref_frame_yv12_buf(cm, ref_frame) != NULL);
3459 setup_buffer_ref_mvs_inter(cpi, x, ref_frame, bsize, yv12_mb);
3460 }
3461 // Store the best pred_mv_sad across all past frames
3462 if (cpi->sf.inter_sf.alt_ref_search_fp &&
3463 cpi->ref_relative_dist[ref_frame - LAST_FRAME] < 0)
3464 x->best_pred_mv_sad =
3465 AOMMIN(x->best_pred_mv_sad, x->pred_mv_sad[ref_frame]);
3466 }
3467 // ref_frame = ALTREF_FRAME
3468 if (!cpi->sf.rt_sf.use_real_time_ref_set) {
3469 // No second reference on RT ref set, so no need to initialize
3470 for (; ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {
3471 x->mbmi_ext->mode_context[ref_frame] = 0;
3472 mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
3473 const MV_REFERENCE_FRAME *rf = ref_frame_map[ref_frame - REF_FRAMES];
3474 if (!((cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[0]]) &&
3475 (cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[1]]))) {
3476 continue;
3477 }
3478
3479 if (mbmi->partition != PARTITION_NONE &&
3480 mbmi->partition != PARTITION_SPLIT) {
3481 if (skip_ref_frame_mask & (1 << ref_frame)) {
3482 continue;
3483 }
3484 }
3485 av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
3486 xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
3487 mbmi_ext->mode_context);
3488 // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
3489 // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
3490 av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
3491 }
3492 }
3493
3494 av1_count_overlappable_neighbors(cm, xd);
3495 const FRAME_UPDATE_TYPE update_type = get_frame_update_type(&cpi->gf_group);
3496 const int prune_obmc = cpi->obmc_probs[update_type][bsize] <
3497 cpi->sf.inter_sf.prune_obmc_prob_thresh;
3498 if (cpi->oxcf.enable_obmc && !cpi->sf.inter_sf.disable_obmc && !prune_obmc) {
3499 if (check_num_overlappable_neighbors(mbmi) &&
3500 is_motion_variation_allowed_bsize(bsize)) {
3501 int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
3502 int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
3503 MAX_SB_SIZE >> 1 };
3504 int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
3505 MAX_SB_SIZE >> 1 };
3506 int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
3507 av1_build_prediction_by_above_preds(cm, xd, args->above_pred_buf,
3508 dst_width1, dst_height1,
3509 args->above_pred_stride);
3510 av1_build_prediction_by_left_preds(cm, xd, args->left_pred_buf,
3511 dst_width2, dst_height2,
3512 args->left_pred_stride);
3513 const int num_planes = av1_num_planes(cm);
3514 av1_setup_dst_planes(xd->plane, bsize, &cm->cur_frame->buf, mi_row,
3515 mi_col, 0, num_planes);
3516 calc_target_weighted_pred(
3517 cm, x, xd, args->above_pred_buf[0], args->above_pred_stride[0],
3518 args->left_pred_buf[0], args->left_pred_stride[0]);
3519 }
3520 }
3521
3522 init_mode_skip_mask(mode_skip_mask, cpi, x, bsize);
3523
3524 // Set params for mode evaluation
3525 set_mode_eval_params(cpi, x, MODE_EVAL);
3526
3527 x->comp_rd_stats_idx = 0;
3528 }
3529
init_intra_mode_search_state(IntraModeSearchState * intra_search_state)3530 static AOM_INLINE void init_intra_mode_search_state(
3531 IntraModeSearchState *intra_search_state) {
3532 intra_search_state->skip_intra_modes = 0;
3533 intra_search_state->best_intra_mode = DC_PRED;
3534 intra_search_state->angle_stats_ready = 0;
3535 av1_zero(intra_search_state->directional_mode_skip_mask);
3536 intra_search_state->rate_uv_intra = INT_MAX;
3537 av1_zero(intra_search_state->pmi_uv);
3538 for (int i = 0; i < REFERENCE_MODES; ++i)
3539 intra_search_state->best_pred_rd[i] = INT64_MAX;
3540 }
3541
init_inter_mode_search_state(InterModeSearchState * search_state,const AV1_COMP * cpi,const MACROBLOCK * x,BLOCK_SIZE bsize,int64_t best_rd_so_far)3542 static AOM_INLINE void init_inter_mode_search_state(
3543 InterModeSearchState *search_state, const AV1_COMP *cpi,
3544 const MACROBLOCK *x, BLOCK_SIZE bsize, int64_t best_rd_so_far) {
3545 init_intra_mode_search_state(&search_state->intra_search_state);
3546
3547 search_state->best_rd = best_rd_so_far;
3548 search_state->best_skip_rd[0] = INT64_MAX;
3549 search_state->best_skip_rd[1] = INT64_MAX;
3550
3551 av1_zero(search_state->best_mbmode);
3552
3553 search_state->best_rate_y = INT_MAX;
3554
3555 search_state->best_rate_uv = INT_MAX;
3556
3557 search_state->best_mode_skippable = 0;
3558
3559 search_state->best_skip2 = 0;
3560
3561 search_state->best_mode_index = THR_INVALID;
3562
3563 const MACROBLOCKD *const xd = &x->e_mbd;
3564 const MB_MODE_INFO *const mbmi = xd->mi[0];
3565 const unsigned char segment_id = mbmi->segment_id;
3566
3567 search_state->num_available_refs = 0;
3568 memset(search_state->dist_refs, -1, sizeof(search_state->dist_refs));
3569 memset(search_state->dist_order_refs, -1,
3570 sizeof(search_state->dist_order_refs));
3571
3572 for (int i = 0; i <= LAST_NEW_MV_INDEX; ++i)
3573 search_state->mode_threshold[i] = 0;
3574 const int *const rd_threshes = cpi->rd.threshes[segment_id][bsize];
3575 for (int i = LAST_NEW_MV_INDEX + 1; i < MAX_MODES; ++i)
3576 search_state->mode_threshold[i] =
3577 ((int64_t)rd_threshes[i] * x->thresh_freq_fact[bsize][i]) >>
3578 RD_THRESH_FAC_FRAC_BITS;
3579
3580 search_state->best_intra_rd = INT64_MAX;
3581
3582 search_state->best_pred_sse = UINT_MAX;
3583
3584 av1_zero(search_state->single_newmv);
3585 av1_zero(search_state->single_newmv_rate);
3586 av1_zero(search_state->single_newmv_valid);
3587 for (int i = 0; i < MB_MODE_COUNT; ++i) {
3588 for (int j = 0; j < MAX_REF_MV_SEARCH; ++j) {
3589 for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
3590 search_state->modelled_rd[i][j][ref_frame] = INT64_MAX;
3591 search_state->simple_rd[i][j][ref_frame] = INT64_MAX;
3592 }
3593 }
3594 }
3595
3596 for (int dir = 0; dir < 2; ++dir) {
3597 for (int mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
3598 for (int ref_frame = 0; ref_frame < FWD_REFS; ++ref_frame) {
3599 SingleInterModeState *state;
3600
3601 state = &search_state->single_state[dir][mode][ref_frame];
3602 state->ref_frame = NONE_FRAME;
3603 state->rd = INT64_MAX;
3604
3605 state = &search_state->single_state_modelled[dir][mode][ref_frame];
3606 state->ref_frame = NONE_FRAME;
3607 state->rd = INT64_MAX;
3608 }
3609 }
3610 }
3611 for (int dir = 0; dir < 2; ++dir) {
3612 for (int mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
3613 for (int ref_frame = 0; ref_frame < FWD_REFS; ++ref_frame) {
3614 search_state->single_rd_order[dir][mode][ref_frame] = NONE_FRAME;
3615 }
3616 }
3617 }
3618 av1_zero(search_state->single_state_cnt);
3619 av1_zero(search_state->single_state_modelled_cnt);
3620 }
3621
mask_says_skip(const mode_skip_mask_t * mode_skip_mask,const MV_REFERENCE_FRAME * ref_frame,const PREDICTION_MODE this_mode)3622 static bool mask_says_skip(const mode_skip_mask_t *mode_skip_mask,
3623 const MV_REFERENCE_FRAME *ref_frame,
3624 const PREDICTION_MODE this_mode) {
3625 if (mode_skip_mask->pred_modes[ref_frame[0]] & (1 << this_mode)) {
3626 return true;
3627 }
3628
3629 return mode_skip_mask->ref_combo[ref_frame[0]][ref_frame[1] + 1];
3630 }
3631
inter_mode_compatible_skip(const AV1_COMP * cpi,const MACROBLOCK * x,BLOCK_SIZE bsize,PREDICTION_MODE curr_mode,const MV_REFERENCE_FRAME * ref_frames)3632 static int inter_mode_compatible_skip(const AV1_COMP *cpi, const MACROBLOCK *x,
3633 BLOCK_SIZE bsize,
3634 PREDICTION_MODE curr_mode,
3635 const MV_REFERENCE_FRAME *ref_frames) {
3636 const int comp_pred = ref_frames[1] > INTRA_FRAME;
3637 if (comp_pred) {
3638 if (!is_comp_ref_allowed(bsize)) return 1;
3639 if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frames[1]])) {
3640 return 1;
3641 }
3642
3643 const AV1_COMMON *const cm = &cpi->common;
3644 if (frame_is_intra_only(cm)) return 1;
3645
3646 const CurrentFrame *const current_frame = &cm->current_frame;
3647 if (current_frame->reference_mode == SINGLE_REFERENCE) return 1;
3648
3649 const struct segmentation *const seg = &cm->seg;
3650 const unsigned char segment_id = x->e_mbd.mi[0]->segment_id;
3651 // Do not allow compound prediction if the segment level reference frame
3652 // feature is in use as in this case there can only be one reference.
3653 if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) return 1;
3654 }
3655
3656 if (ref_frames[0] > INTRA_FRAME && ref_frames[1] == INTRA_FRAME) {
3657 // Mode must be compatible
3658 if (!is_interintra_allowed_bsize(bsize)) return 1;
3659 if (!is_interintra_allowed_mode(curr_mode)) return 1;
3660 }
3661
3662 return 0;
3663 }
3664
fetch_picked_ref_frames_mask(const MACROBLOCK * const x,BLOCK_SIZE bsize,int mib_size)3665 static int fetch_picked_ref_frames_mask(const MACROBLOCK *const x,
3666 BLOCK_SIZE bsize, int mib_size) {
3667 const int sb_size_mask = mib_size - 1;
3668 const MACROBLOCKD *const xd = &x->e_mbd;
3669 const int mi_row = xd->mi_row;
3670 const int mi_col = xd->mi_col;
3671 const int mi_row_in_sb = mi_row & sb_size_mask;
3672 const int mi_col_in_sb = mi_col & sb_size_mask;
3673 const int mi_w = mi_size_wide[bsize];
3674 const int mi_h = mi_size_high[bsize];
3675 int picked_ref_frames_mask = 0;
3676 for (int i = mi_row_in_sb; i < mi_row_in_sb + mi_h; ++i) {
3677 for (int j = mi_col_in_sb; j < mi_col_in_sb + mi_w; ++j) {
3678 picked_ref_frames_mask |= x->picked_ref_frames_mask[i * 32 + j];
3679 }
3680 }
3681 return picked_ref_frames_mask;
3682 }
3683
3684 // Case 1: return 0, means don't skip this mode
3685 // Case 2: return 1, means skip this mode completely
3686 // Case 3: return 2, means skip compound only, but still try single motion modes
inter_mode_search_order_independent_skip(const AV1_COMP * cpi,const MACROBLOCK * x,mode_skip_mask_t * mode_skip_mask,InterModeSearchState * search_state,int skip_ref_frame_mask,PREDICTION_MODE mode,const MV_REFERENCE_FRAME * ref_frame)3687 static int inter_mode_search_order_independent_skip(
3688 const AV1_COMP *cpi, const MACROBLOCK *x, mode_skip_mask_t *mode_skip_mask,
3689 InterModeSearchState *search_state, int skip_ref_frame_mask,
3690 PREDICTION_MODE mode, const MV_REFERENCE_FRAME *ref_frame) {
3691 if (mask_says_skip(mode_skip_mask, ref_frame, mode)) {
3692 return 1;
3693 }
3694
3695 const int ref_type = av1_ref_frame_type(ref_frame);
3696 if ((cpi->prune_ref_frame_mask >> ref_type) & 1) return 1;
3697
3698 // This is only used in motion vector unit test.
3699 if (cpi->oxcf.motion_vector_unit_test && ref_frame[0] == INTRA_FRAME)
3700 return 1;
3701
3702 const AV1_COMMON *const cm = &cpi->common;
3703 if (skip_repeated_mv(cm, x, mode, ref_frame, search_state)) {
3704 return 1;
3705 }
3706
3707 const int comp_pred = ref_frame[1] > INTRA_FRAME;
3708 if ((!cpi->oxcf.enable_onesided_comp ||
3709 cpi->sf.inter_sf.disable_onesided_comp) &&
3710 comp_pred && cpi->all_one_sided_refs) {
3711 return 1;
3712 }
3713
3714 const MB_MODE_INFO *const mbmi = x->e_mbd.mi[0];
3715 // If no valid mode has been found so far in PARTITION_NONE when finding a
3716 // valid partition is required, do not skip mode.
3717 if (search_state->best_rd == INT64_MAX && mbmi->partition == PARTITION_NONE &&
3718 x->must_find_valid_partition)
3719 return 0;
3720
3721 int skip_motion_mode = 0;
3722 if (mbmi->partition != PARTITION_NONE && mbmi->partition != PARTITION_SPLIT) {
3723 int skip_ref = skip_ref_frame_mask & (1 << ref_type);
3724 if (ref_type <= ALTREF_FRAME && skip_ref) {
3725 // Since the compound ref modes depends on the motion estimation result of
3726 // two single ref modes( best mv of single ref modes as the start point )
3727 // If current single ref mode is marked skip, we need to check if it will
3728 // be used in compound ref modes.
3729 for (int r = ALTREF_FRAME + 1; r < MODE_CTX_REF_FRAMES; ++r) {
3730 if (skip_ref_frame_mask & (1 << r)) continue;
3731 const MV_REFERENCE_FRAME *rf = ref_frame_map[r - REF_FRAMES];
3732 if (rf[0] == ref_type || rf[1] == ref_type) {
3733 // Found a not skipped compound ref mode which contains current
3734 // single ref. So this single ref can't be skipped completly
3735 // Just skip it's motion mode search, still try it's simple
3736 // transition mode.
3737 skip_motion_mode = 1;
3738 skip_ref = 0;
3739 break;
3740 }
3741 }
3742 }
3743 if (skip_ref) return 1;
3744 }
3745
3746 const SPEED_FEATURES *const sf = &cpi->sf;
3747 if (ref_frame[0] == INTRA_FRAME) {
3748 if (mode != DC_PRED) {
3749 // Disable intra modes other than DC_PRED for blocks with low variance
3750 // Threshold for intra skipping based on source variance
3751 // TODO(debargha): Specialize the threshold for super block sizes
3752 const unsigned int skip_intra_var_thresh = 64;
3753 if ((sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
3754 x->source_variance < skip_intra_var_thresh)
3755 return 1;
3756 }
3757 }
3758
3759 if (prune_ref_by_selective_ref_frame(cpi, x, ref_frame,
3760 cm->cur_frame->ref_display_order_hint))
3761 return 1;
3762
3763 if (skip_motion_mode) return 2;
3764
3765 return 0;
3766 }
3767
init_mbmi(MB_MODE_INFO * mbmi,PREDICTION_MODE curr_mode,const MV_REFERENCE_FRAME * ref_frames,const AV1_COMMON * cm)3768 static INLINE void init_mbmi(MB_MODE_INFO *mbmi, PREDICTION_MODE curr_mode,
3769 const MV_REFERENCE_FRAME *ref_frames,
3770 const AV1_COMMON *cm) {
3771 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
3772 mbmi->ref_mv_idx = 0;
3773 mbmi->mode = curr_mode;
3774 mbmi->uv_mode = UV_DC_PRED;
3775 mbmi->ref_frame[0] = ref_frames[0];
3776 mbmi->ref_frame[1] = ref_frames[1];
3777 pmi->palette_size[0] = 0;
3778 pmi->palette_size[1] = 0;
3779 mbmi->filter_intra_mode_info.use_filter_intra = 0;
3780 mbmi->mv[0].as_int = mbmi->mv[1].as_int = 0;
3781 mbmi->motion_mode = SIMPLE_TRANSLATION;
3782 mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
3783 set_default_interp_filters(mbmi, cm->interp_filter);
3784 }
3785
collect_single_states(MACROBLOCK * x,InterModeSearchState * search_state,const MB_MODE_INFO * const mbmi)3786 static AOM_INLINE void collect_single_states(MACROBLOCK *x,
3787 InterModeSearchState *search_state,
3788 const MB_MODE_INFO *const mbmi) {
3789 int i, j;
3790 const MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame[0];
3791 const PREDICTION_MODE this_mode = mbmi->mode;
3792 const int dir = ref_frame <= GOLDEN_FRAME ? 0 : 1;
3793 const int mode_offset = INTER_OFFSET(this_mode);
3794 const int ref_set = get_drl_refmv_count(x, mbmi->ref_frame, this_mode);
3795
3796 // Simple rd
3797 int64_t simple_rd = search_state->simple_rd[this_mode][0][ref_frame];
3798 for (int ref_mv_idx = 1; ref_mv_idx < ref_set; ++ref_mv_idx) {
3799 const int64_t rd =
3800 search_state->simple_rd[this_mode][ref_mv_idx][ref_frame];
3801 if (rd < simple_rd) simple_rd = rd;
3802 }
3803
3804 // Insertion sort of single_state
3805 const SingleInterModeState this_state_s = { simple_rd, ref_frame, 1 };
3806 SingleInterModeState *state_s = search_state->single_state[dir][mode_offset];
3807 i = search_state->single_state_cnt[dir][mode_offset];
3808 for (j = i; j > 0 && state_s[j - 1].rd > this_state_s.rd; --j)
3809 state_s[j] = state_s[j - 1];
3810 state_s[j] = this_state_s;
3811 search_state->single_state_cnt[dir][mode_offset]++;
3812
3813 // Modelled rd
3814 int64_t modelled_rd = search_state->modelled_rd[this_mode][0][ref_frame];
3815 for (int ref_mv_idx = 1; ref_mv_idx < ref_set; ++ref_mv_idx) {
3816 const int64_t rd =
3817 search_state->modelled_rd[this_mode][ref_mv_idx][ref_frame];
3818 if (rd < modelled_rd) modelled_rd = rd;
3819 }
3820
3821 // Insertion sort of single_state_modelled
3822 const SingleInterModeState this_state_m = { modelled_rd, ref_frame, 1 };
3823 SingleInterModeState *state_m =
3824 search_state->single_state_modelled[dir][mode_offset];
3825 i = search_state->single_state_modelled_cnt[dir][mode_offset];
3826 for (j = i; j > 0 && state_m[j - 1].rd > this_state_m.rd; --j)
3827 state_m[j] = state_m[j - 1];
3828 state_m[j] = this_state_m;
3829 search_state->single_state_modelled_cnt[dir][mode_offset]++;
3830 }
3831
analyze_single_states(const AV1_COMP * cpi,InterModeSearchState * search_state)3832 static AOM_INLINE void analyze_single_states(
3833 const AV1_COMP *cpi, InterModeSearchState *search_state) {
3834 const int prune_level = cpi->sf.inter_sf.prune_comp_search_by_single_result;
3835 assert(prune_level >= 1);
3836 int i, j, dir, mode;
3837
3838 for (dir = 0; dir < 2; ++dir) {
3839 int64_t best_rd;
3840 SingleInterModeState(*state)[FWD_REFS];
3841 const int prune_factor = prune_level >= 2 ? 6 : 5;
3842
3843 // Use the best rd of GLOBALMV or NEWMV to prune the unlikely
3844 // reference frames for all the modes (NEARESTMV and NEARMV may not
3845 // have same motion vectors). Always keep the best of each mode
3846 // because it might form the best possible combination with other mode.
3847 state = search_state->single_state[dir];
3848 best_rd = AOMMIN(state[INTER_OFFSET(NEWMV)][0].rd,
3849 state[INTER_OFFSET(GLOBALMV)][0].rd);
3850 for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
3851 for (i = 1; i < search_state->single_state_cnt[dir][mode]; ++i) {
3852 if (state[mode][i].rd != INT64_MAX &&
3853 (state[mode][i].rd >> 3) * prune_factor > best_rd) {
3854 state[mode][i].valid = 0;
3855 }
3856 }
3857 }
3858
3859 state = search_state->single_state_modelled[dir];
3860 best_rd = AOMMIN(state[INTER_OFFSET(NEWMV)][0].rd,
3861 state[INTER_OFFSET(GLOBALMV)][0].rd);
3862 for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
3863 for (i = 1; i < search_state->single_state_modelled_cnt[dir][mode]; ++i) {
3864 if (state[mode][i].rd != INT64_MAX &&
3865 (state[mode][i].rd >> 3) * prune_factor > best_rd) {
3866 state[mode][i].valid = 0;
3867 }
3868 }
3869 }
3870 }
3871
3872 // Ordering by simple rd first, then by modelled rd
3873 for (dir = 0; dir < 2; ++dir) {
3874 for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
3875 const int state_cnt_s = search_state->single_state_cnt[dir][mode];
3876 const int state_cnt_m =
3877 search_state->single_state_modelled_cnt[dir][mode];
3878 SingleInterModeState *state_s = search_state->single_state[dir][mode];
3879 SingleInterModeState *state_m =
3880 search_state->single_state_modelled[dir][mode];
3881 int count = 0;
3882 const int max_candidates = AOMMAX(state_cnt_s, state_cnt_m);
3883 for (i = 0; i < state_cnt_s; ++i) {
3884 if (state_s[i].rd == INT64_MAX) break;
3885 if (state_s[i].valid) {
3886 search_state->single_rd_order[dir][mode][count++] =
3887 state_s[i].ref_frame;
3888 }
3889 }
3890 if (count >= max_candidates) continue;
3891
3892 for (i = 0; i < state_cnt_m && count < max_candidates; ++i) {
3893 if (state_m[i].rd == INT64_MAX) break;
3894 if (!state_m[i].valid) continue;
3895 const int ref_frame = state_m[i].ref_frame;
3896 int match = 0;
3897 // Check if existing already
3898 for (j = 0; j < count; ++j) {
3899 if (search_state->single_rd_order[dir][mode][j] == ref_frame) {
3900 match = 1;
3901 break;
3902 }
3903 }
3904 if (match) continue;
3905 // Check if this ref_frame is removed in simple rd
3906 int valid = 1;
3907 for (j = 0; j < state_cnt_s; ++j) {
3908 if (ref_frame == state_s[j].ref_frame) {
3909 valid = state_s[j].valid;
3910 break;
3911 }
3912 }
3913 if (valid) {
3914 search_state->single_rd_order[dir][mode][count++] = ref_frame;
3915 }
3916 }
3917 }
3918 }
3919 }
3920
compound_skip_get_candidates(const AV1_COMP * cpi,const InterModeSearchState * search_state,const int dir,const PREDICTION_MODE mode)3921 static int compound_skip_get_candidates(
3922 const AV1_COMP *cpi, const InterModeSearchState *search_state,
3923 const int dir, const PREDICTION_MODE mode) {
3924 const int mode_offset = INTER_OFFSET(mode);
3925 const SingleInterModeState *state =
3926 search_state->single_state[dir][mode_offset];
3927 const SingleInterModeState *state_modelled =
3928 search_state->single_state_modelled[dir][mode_offset];
3929
3930 int max_candidates = 0;
3931 for (int i = 0; i < FWD_REFS; ++i) {
3932 if (search_state->single_rd_order[dir][mode_offset][i] == NONE_FRAME) break;
3933 max_candidates++;
3934 }
3935
3936 int candidates = max_candidates;
3937 if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 2) {
3938 candidates = AOMMIN(2, max_candidates);
3939 }
3940 if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 3) {
3941 if (state[0].rd != INT64_MAX && state_modelled[0].rd != INT64_MAX &&
3942 state[0].ref_frame == state_modelled[0].ref_frame)
3943 candidates = 1;
3944 if (mode == NEARMV || mode == GLOBALMV) candidates = 1;
3945 }
3946
3947 if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 4) {
3948 // Limit the number of candidates to 1 in each direction for compound
3949 // prediction
3950 candidates = AOMMIN(1, candidates);
3951 }
3952 return candidates;
3953 }
3954
compound_skip_by_single_states(const AV1_COMP * cpi,const InterModeSearchState * search_state,const PREDICTION_MODE this_mode,const MV_REFERENCE_FRAME ref_frame,const MV_REFERENCE_FRAME second_ref_frame,const MACROBLOCK * x)3955 static int compound_skip_by_single_states(
3956 const AV1_COMP *cpi, const InterModeSearchState *search_state,
3957 const PREDICTION_MODE this_mode, const MV_REFERENCE_FRAME ref_frame,
3958 const MV_REFERENCE_FRAME second_ref_frame, const MACROBLOCK *x) {
3959 const MV_REFERENCE_FRAME refs[2] = { ref_frame, second_ref_frame };
3960 const int mode[2] = { compound_ref0_mode(this_mode),
3961 compound_ref1_mode(this_mode) };
3962 const int mode_offset[2] = { INTER_OFFSET(mode[0]), INTER_OFFSET(mode[1]) };
3963 const int mode_dir[2] = { refs[0] <= GOLDEN_FRAME ? 0 : 1,
3964 refs[1] <= GOLDEN_FRAME ? 0 : 1 };
3965 int ref_searched[2] = { 0, 0 };
3966 int ref_mv_match[2] = { 1, 1 };
3967 int i, j;
3968
3969 for (i = 0; i < 2; ++i) {
3970 const SingleInterModeState *state =
3971 search_state->single_state[mode_dir[i]][mode_offset[i]];
3972 const int state_cnt =
3973 search_state->single_state_cnt[mode_dir[i]][mode_offset[i]];
3974 for (j = 0; j < state_cnt; ++j) {
3975 if (state[j].ref_frame == refs[i]) {
3976 ref_searched[i] = 1;
3977 break;
3978 }
3979 }
3980 }
3981
3982 const int ref_set = get_drl_refmv_count(x, refs, this_mode);
3983 for (i = 0; i < 2; ++i) {
3984 if (!ref_searched[i] || (mode[i] != NEARESTMV && mode[i] != NEARMV)) {
3985 continue;
3986 }
3987 const MV_REFERENCE_FRAME single_refs[2] = { refs[i], NONE_FRAME };
3988 for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ref_mv_idx++) {
3989 int_mv single_mv;
3990 int_mv comp_mv;
3991 get_this_mv(&single_mv, mode[i], 0, ref_mv_idx, 0, single_refs,
3992 x->mbmi_ext);
3993 get_this_mv(&comp_mv, this_mode, i, ref_mv_idx, 0, refs, x->mbmi_ext);
3994 if (single_mv.as_int != comp_mv.as_int) {
3995 ref_mv_match[i] = 0;
3996 break;
3997 }
3998 }
3999 }
4000
4001 for (i = 0; i < 2; ++i) {
4002 if (!ref_searched[i] || !ref_mv_match[i]) continue;
4003 const int candidates =
4004 compound_skip_get_candidates(cpi, search_state, mode_dir[i], mode[i]);
4005 const MV_REFERENCE_FRAME *ref_order =
4006 search_state->single_rd_order[mode_dir[i]][mode_offset[i]];
4007 int match = 0;
4008 for (j = 0; j < candidates; ++j) {
4009 if (refs[i] == ref_order[j]) {
4010 match = 1;
4011 break;
4012 }
4013 }
4014 if (!match) return 1;
4015 }
4016
4017 return 0;
4018 }
4019
compare_int64(const void * a,const void * b)4020 static int compare_int64(const void *a, const void *b) {
4021 int64_t a64 = *((int64_t *)a);
4022 int64_t b64 = *((int64_t *)b);
4023 if (a64 < b64) {
4024 return -1;
4025 } else if (a64 == b64) {
4026 return 0;
4027 } else {
4028 return 1;
4029 }
4030 }
4031
update_search_state(InterModeSearchState * search_state,RD_STATS * best_rd_stats_dst,PICK_MODE_CONTEXT * ctx,const RD_STATS * new_best_rd_stats,const RD_STATS * new_best_rd_stats_y,const RD_STATS * new_best_rd_stats_uv,THR_MODES new_best_mode,const MACROBLOCK * x,int txfm_search_done)4032 static INLINE void update_search_state(
4033 InterModeSearchState *search_state, RD_STATS *best_rd_stats_dst,
4034 PICK_MODE_CONTEXT *ctx, const RD_STATS *new_best_rd_stats,
4035 const RD_STATS *new_best_rd_stats_y, const RD_STATS *new_best_rd_stats_uv,
4036 THR_MODES new_best_mode, const MACROBLOCK *x, int txfm_search_done) {
4037 const MACROBLOCKD *xd = &x->e_mbd;
4038 const MB_MODE_INFO *mbmi = xd->mi[0];
4039 const int skip_ctx = av1_get_skip_context(xd);
4040 const int mode_is_intra =
4041 (av1_mode_defs[new_best_mode].mode < INTRA_MODE_END);
4042 const int skip = mbmi->skip && !mode_is_intra;
4043
4044 search_state->best_rd = new_best_rd_stats->rdcost;
4045 search_state->best_mode_index = new_best_mode;
4046 *best_rd_stats_dst = *new_best_rd_stats;
4047 search_state->best_mbmode = *mbmi;
4048 search_state->best_skip2 = skip;
4049 search_state->best_mode_skippable = new_best_rd_stats->skip;
4050 // When !txfm_search_done, new_best_rd_stats won't provide correct rate_y and
4051 // rate_uv because av1_txfm_search process is replaced by rd estimation.
4052 // Therfore, we should avoid updating best_rate_y and best_rate_uv here.
4053 // These two values will be updated when av1_txfm_search is called.
4054 if (txfm_search_done) {
4055 search_state->best_rate_y =
4056 new_best_rd_stats_y->rate +
4057 x->skip_cost[skip_ctx][new_best_rd_stats->skip || skip];
4058 search_state->best_rate_uv = new_best_rd_stats_uv->rate;
4059 }
4060 memcpy(ctx->blk_skip, x->blk_skip, sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
4061 av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
4062 }
4063
4064 // Find the best RD for a reference frame (among single reference modes)
4065 // and store +10% of it in the 0-th element in ref_frame_rd.
find_top_ref(int64_t ref_frame_rd[REF_FRAMES])4066 static AOM_INLINE void find_top_ref(int64_t ref_frame_rd[REF_FRAMES]) {
4067 assert(ref_frame_rd[0] == INT64_MAX);
4068 int64_t ref_copy[REF_FRAMES - 1];
4069 memcpy(ref_copy, ref_frame_rd + 1,
4070 sizeof(ref_frame_rd[0]) * (REF_FRAMES - 1));
4071 qsort(ref_copy, REF_FRAMES - 1, sizeof(int64_t), compare_int64);
4072
4073 int64_t cutoff = ref_copy[0];
4074 // The cut-off is within 10% of the best.
4075 if (cutoff != INT64_MAX) {
4076 assert(cutoff < INT64_MAX / 200);
4077 cutoff = (110 * cutoff) / 100;
4078 }
4079 ref_frame_rd[0] = cutoff;
4080 }
4081
4082 // Check if either frame is within the cutoff.
in_single_ref_cutoff(int64_t ref_frame_rd[REF_FRAMES],MV_REFERENCE_FRAME frame1,MV_REFERENCE_FRAME frame2)4083 static INLINE bool in_single_ref_cutoff(int64_t ref_frame_rd[REF_FRAMES],
4084 MV_REFERENCE_FRAME frame1,
4085 MV_REFERENCE_FRAME frame2) {
4086 assert(frame2 > 0);
4087 return ref_frame_rd[frame1] <= ref_frame_rd[0] ||
4088 ref_frame_rd[frame2] <= ref_frame_rd[0];
4089 }
4090
evaluate_motion_mode_for_winner_candidates(const AV1_COMP * const cpi,MACROBLOCK * const x,RD_STATS * const rd_cost,HandleInterModeArgs * const args,TileDataEnc * const tile_data,PICK_MODE_CONTEXT * const ctx,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],const motion_mode_best_st_candidate * const best_motion_mode_cands,int do_tx_search,const BLOCK_SIZE bsize,int64_t * const best_est_rd,InterModeSearchState * const search_state)4091 static AOM_INLINE void evaluate_motion_mode_for_winner_candidates(
4092 const AV1_COMP *const cpi, MACROBLOCK *const x, RD_STATS *const rd_cost,
4093 HandleInterModeArgs *const args, TileDataEnc *const tile_data,
4094 PICK_MODE_CONTEXT *const ctx,
4095 struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],
4096 const motion_mode_best_st_candidate *const best_motion_mode_cands,
4097 int do_tx_search, const BLOCK_SIZE bsize, int64_t *const best_est_rd,
4098 InterModeSearchState *const search_state) {
4099 const AV1_COMMON *const cm = &cpi->common;
4100 const int num_planes = av1_num_planes(cm);
4101 MACROBLOCKD *const xd = &x->e_mbd;
4102 MB_MODE_INFO *const mbmi = xd->mi[0];
4103 InterModesInfo *const inter_modes_info = x->inter_modes_info;
4104 const int num_best_cand = best_motion_mode_cands->num_motion_mode_cand;
4105
4106 for (int cand = 0; cand < num_best_cand; cand++) {
4107 RD_STATS rd_stats;
4108 RD_STATS rd_stats_y;
4109 RD_STATS rd_stats_uv;
4110 av1_init_rd_stats(&rd_stats);
4111 av1_init_rd_stats(&rd_stats_y);
4112 av1_init_rd_stats(&rd_stats_uv);
4113 int disable_skip = 0, rate_mv;
4114
4115 rate_mv = best_motion_mode_cands->motion_mode_cand[cand].rate_mv;
4116 args->skip_motion_mode =
4117 best_motion_mode_cands->motion_mode_cand[cand].skip_motion_mode;
4118 *mbmi = best_motion_mode_cands->motion_mode_cand[cand].mbmi;
4119 rd_stats.rate =
4120 best_motion_mode_cands->motion_mode_cand[cand].rate2_nocoeff;
4121
4122 // Continue if the best candidate is compound.
4123 if (!is_inter_singleref_mode(mbmi->mode)) continue;
4124
4125 x->force_skip = 0;
4126 const int mode_index = get_prediction_mode_idx(
4127 mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4128 struct macroblockd_plane *p = xd->plane;
4129 const BUFFER_SET orig_dst = {
4130 { p[0].dst.buf, p[1].dst.buf, p[2].dst.buf },
4131 { p[0].dst.stride, p[1].dst.stride, p[2].dst.stride },
4132 };
4133
4134 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4135 args->simple_rd_state = x->simple_rd_state[mode_index];
4136 // Initialize motion mode to simple translation
4137 // Calculation of switchable rate depends on it.
4138 mbmi->motion_mode = 0;
4139 const int is_comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
4140 for (int i = 0; i < num_planes; i++) {
4141 xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
4142 if (is_comp_pred) xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
4143 }
4144
4145 int64_t skip_rd[2] = { search_state->best_skip_rd[0],
4146 search_state->best_skip_rd[1] };
4147 int64_t ret_value = motion_mode_rd(
4148 cpi, tile_data, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv,
4149 &disable_skip, args, search_state->best_rd, skip_rd, &rate_mv,
4150 &orig_dst, best_est_rd, do_tx_search, inter_modes_info, 1);
4151
4152 if (ret_value != INT64_MAX) {
4153 rd_stats.rdcost = RDCOST(x->rdmult, rd_stats.rate, rd_stats.dist);
4154 const THR_MODES mode_enum = get_prediction_mode_idx(
4155 mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4156 // Collect mode stats for multiwinner mode processing
4157 store_winner_mode_stats(
4158 &cpi->common, x, mbmi, &rd_stats, &rd_stats_y, &rd_stats_uv,
4159 mode_enum, NULL, bsize, rd_stats.rdcost,
4160 cpi->sf.winner_mode_sf.enable_multiwinner_mode_process, do_tx_search);
4161 if (rd_stats.rdcost < search_state->best_rd) {
4162 update_search_state(search_state, rd_cost, ctx, &rd_stats, &rd_stats_y,
4163 &rd_stats_uv, mode_enum, x, do_tx_search);
4164 if (do_tx_search) search_state->best_skip_rd[0] = skip_rd[0];
4165 }
4166 }
4167 }
4168 }
4169
av1_rd_pick_inter_mode_sb(AV1_COMP * cpi,TileDataEnc * tile_data,MACROBLOCK * x,RD_STATS * rd_cost,const BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,int64_t best_rd_so_far)4170 void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
4171 MACROBLOCK *x, RD_STATS *rd_cost,
4172 const BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
4173 int64_t best_rd_so_far) {
4174 AV1_COMMON *const cm = &cpi->common;
4175 const int num_planes = av1_num_planes(cm);
4176 const SPEED_FEATURES *const sf = &cpi->sf;
4177 MACROBLOCKD *const xd = &x->e_mbd;
4178 MB_MODE_INFO *const mbmi = xd->mi[0];
4179 int i;
4180 const int *comp_inter_cost =
4181 x->comp_inter_cost[av1_get_reference_mode_context(xd)];
4182
4183 InterModeSearchState search_state;
4184 init_inter_mode_search_state(&search_state, cpi, x, bsize, best_rd_so_far);
4185 INTERINTRA_MODE interintra_modes[REF_FRAMES] = {
4186 INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES,
4187 INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES
4188 };
4189 HandleInterModeArgs args = { { NULL },
4190 { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
4191 { NULL },
4192 { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
4193 MAX_SB_SIZE >> 1 },
4194 NULL,
4195 NULL,
4196 NULL,
4197 search_state.modelled_rd,
4198 INT_MAX,
4199 INT_MAX,
4200 search_state.simple_rd,
4201 0,
4202 interintra_modes,
4203 1,
4204 NULL,
4205 { { { 0 }, { { 0 } }, { 0 }, 0, 0, 0, 0 } },
4206 0 };
4207 const int max_winner_motion_mode_cand = cpi->num_winner_motion_modes;
4208 motion_mode_candidate motion_mode_cand;
4209 motion_mode_best_st_candidate best_motion_mode_cands;
4210 // Initializing the number of motion mode candidates to zero.
4211 best_motion_mode_cands.num_motion_mode_cand = 0;
4212 for (i = 0; i < MAX_WINNER_MOTION_MODES; ++i)
4213 best_motion_mode_cands.motion_mode_cand[i].rd_cost = INT64_MAX;
4214
4215 for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;
4216
4217 av1_invalid_rd_stats(rd_cost);
4218
4219 // Ref frames that are selected by square partition blocks.
4220 int picked_ref_frames_mask = 0;
4221 if (cpi->sf.inter_sf.prune_ref_frame_for_rect_partitions &&
4222 mbmi->partition != PARTITION_NONE && mbmi->partition != PARTITION_SPLIT) {
4223 // prune_ref_frame_for_rect_partitions = 1 implies prune only extended
4224 // partition blocks. prune_ref_frame_for_rect_partitions >=2
4225 // implies prune for vert, horiz and extended partition blocks.
4226 if ((mbmi->partition != PARTITION_VERT &&
4227 mbmi->partition != PARTITION_HORZ) ||
4228 cpi->sf.inter_sf.prune_ref_frame_for_rect_partitions >= 2) {
4229 picked_ref_frames_mask =
4230 fetch_picked_ref_frames_mask(x, bsize, cm->seq_params.mib_size);
4231 }
4232 }
4233
4234 // Skip ref frames that never selected by square blocks.
4235 const int skip_ref_frame_mask =
4236 picked_ref_frames_mask ? ~picked_ref_frames_mask : 0;
4237 mode_skip_mask_t mode_skip_mask;
4238 unsigned int ref_costs_single[REF_FRAMES];
4239 unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES];
4240 struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE];
4241 // init params, set frame modes, speed features
4242 set_params_rd_pick_inter_mode(cpi, x, &args, bsize, &mode_skip_mask,
4243 skip_ref_frame_mask, ref_costs_single,
4244 ref_costs_comp, yv12_mb);
4245
4246 int64_t best_est_rd = INT64_MAX;
4247 const InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
4248 // If do_tx_search is 0, only estimated RD should be computed.
4249 // If do_tx_search is 1, all modes have TX search performed.
4250 const int do_tx_search =
4251 !((cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1 && md->ready) ||
4252 (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 2 &&
4253 num_pels_log2_lookup[bsize] > 8) ||
4254 cpi->sf.rt_sf.force_tx_search_off);
4255 InterModesInfo *inter_modes_info = x->inter_modes_info;
4256 inter_modes_info->num = 0;
4257
4258 int intra_mode_num = 0;
4259 int intra_mode_idx_ls[INTRA_MODES];
4260 int reach_first_comp_mode = 0;
4261
4262 // Temporary buffers used by handle_inter_mode().
4263 uint8_t *const tmp_buf = get_buf_by_bd(xd, x->tmp_obmc_bufs[0]);
4264
4265 // The best RD found for the reference frame, among single reference modes.
4266 // Note that the 0-th element will contain a cut-off that is later used
4267 // to determine if we should skip a compound mode.
4268 int64_t ref_frame_rd[REF_FRAMES] = { INT64_MAX, INT64_MAX, INT64_MAX,
4269 INT64_MAX, INT64_MAX, INT64_MAX,
4270 INT64_MAX, INT64_MAX };
4271 const int skip_ctx = av1_get_skip_context(xd);
4272
4273 // Prepared stats used later to check if we could skip intra mode eval.
4274 int64_t inter_cost = -1;
4275 int64_t intra_cost = -1;
4276 // Need to tweak the threshold for hdres speed 0 & 1.
4277 const int mi_row = xd->mi_row;
4278 const int mi_col = xd->mi_col;
4279 // x->search_ref_frame[id] = 1 => no pruning in
4280 // prune_ref_by_selective_ref_frame()
4281 // x->search_ref_frame[id] = 0 => ref frame can be pruned in
4282 // prune_ref_by_selective_ref_frame()
4283 // Populating valid_refs[idx] = 1 ensures that
4284 // 'inter_cost_info_from_tpl.best_inter_cost' does not correspond to a pruned
4285 // ref frame
4286 int valid_refs[INTER_REFS_PER_FRAME];
4287 memset(valid_refs, 0, sizeof(valid_refs));
4288
4289 for (MV_REFERENCE_FRAME frame = LAST_FRAME; frame < REF_FRAMES; frame++) {
4290 MV_REFERENCE_FRAME refs[2] = { frame, NONE_FRAME };
4291 valid_refs[frame - 1] = x->search_ref_frame[frame];
4292 if (!valid_refs[frame - 1]) {
4293 valid_refs[frame - 1] = (!prune_ref_by_selective_ref_frame(
4294 cpi, x, refs, cm->cur_frame->ref_display_order_hint));
4295 }
4296 }
4297
4298 // Obtain the relevant tpl stats for pruning inter modes
4299 PruneInfoFromTpl inter_cost_info_from_tpl;
4300 inter_cost_info_from_tpl.best_inter_cost = 0;
4301 memset(inter_cost_info_from_tpl.ref_inter_cost, 0,
4302 sizeof(inter_cost_info_from_tpl.ref_inter_cost));
4303 #if !CONFIG_REALTIME_ONLY
4304 if (cpi->sf.inter_sf.prune_inter_modes_based_on_tpl) {
4305 get_block_level_tpl_stats(cpi, bsize, mi_row, mi_col, valid_refs,
4306 &inter_cost_info_from_tpl);
4307 }
4308 #endif
4309 const int do_pruning =
4310 (AOMMIN(cm->width, cm->height) > 480 && cpi->speed <= 1) ? 0 : 1;
4311 if (do_pruning && sf->intra_sf.skip_intra_in_interframe) {
4312 // Only consider full SB.
4313 int len = tpl_blocks_in_sb(cm->seq_params.sb_size);
4314 if (len == x->valid_cost_b) {
4315 const BLOCK_SIZE tpl_bsize = convert_length_to_bsize(MC_FLOW_BSIZE_1D);
4316 const int tplw = mi_size_wide[tpl_bsize];
4317 const int tplh = mi_size_high[tpl_bsize];
4318 const int nw = mi_size_wide[bsize] / tplw;
4319 const int nh = mi_size_high[bsize] / tplh;
4320 if (nw >= 1 && nh >= 1) {
4321 const int of_h = mi_row % mi_size_high[cm->seq_params.sb_size];
4322 const int of_w = mi_col % mi_size_wide[cm->seq_params.sb_size];
4323 const int start = of_h / tplh * x->cost_stride + of_w / tplw;
4324
4325 for (int k = 0; k < nh; k++) {
4326 for (int l = 0; l < nw; l++) {
4327 inter_cost += x->inter_cost_b[start + k * x->cost_stride + l];
4328 intra_cost += x->intra_cost_b[start + k * x->cost_stride + l];
4329 }
4330 }
4331 inter_cost /= nw * nh;
4332 intra_cost /= nw * nh;
4333 }
4334 }
4335 }
4336
4337 const int last_single_ref_mode_idx =
4338 find_last_single_ref_mode_idx(av1_default_mode_order);
4339 int prune_cpd_using_sr_stats_ready = 0;
4340
4341 // Initialize best mode stats for winner mode processing
4342 av1_zero(x->winner_mode_stats);
4343 x->winner_mode_count = 0;
4344 store_winner_mode_stats(
4345 &cpi->common, x, mbmi, NULL, NULL, NULL, THR_INVALID, NULL, bsize,
4346 best_rd_so_far, cpi->sf.winner_mode_sf.enable_multiwinner_mode_process,
4347 0);
4348
4349 int mode_thresh_mul_fact = (1 << MODE_THRESH_QBITS);
4350 if (sf->inter_sf.prune_inter_modes_if_skippable) {
4351 // Higher multiplication factor values for lower quantizers.
4352 mode_thresh_mul_fact = mode_threshold_mul_factor[x->qindex];
4353 }
4354
4355 // Here midx is just an iterator index that should not be used by itself
4356 // except to keep track of the number of modes searched. It should be used
4357 // with av1_default_mode_order to get the enum that defines the mode, which
4358 // can be used with av1_mode_defs to get the prediction mode and the ref
4359 // frames.
4360 for (THR_MODES midx = THR_MODE_START; midx < THR_MODE_END; ++midx) {
4361 // Get the actual prediction mode we are trying in this iteration
4362 const THR_MODES mode_enum = av1_default_mode_order[midx];
4363 const MODE_DEFINITION *mode_def = &av1_mode_defs[mode_enum];
4364 const PREDICTION_MODE this_mode = mode_def->mode;
4365 const MV_REFERENCE_FRAME *ref_frames = mode_def->ref_frame;
4366
4367 const MV_REFERENCE_FRAME ref_frame = ref_frames[0];
4368 const MV_REFERENCE_FRAME second_ref_frame = ref_frames[1];
4369 const int is_single_pred =
4370 ref_frame > INTRA_FRAME && second_ref_frame == NONE_FRAME;
4371 const int comp_pred = second_ref_frame > INTRA_FRAME;
4372
4373 // After we done with single reference modes, find the 2nd best RD
4374 // for a reference frame. Only search compound modes that have a reference
4375 // frame at least as good as the 2nd best.
4376 if (sf->inter_sf.prune_compound_using_single_ref &&
4377 midx == last_single_ref_mode_idx + 1) {
4378 find_top_ref(ref_frame_rd);
4379 prune_cpd_using_sr_stats_ready = 1;
4380 }
4381
4382 if (inter_mode_compatible_skip(cpi, x, bsize, this_mode, ref_frames))
4383 continue;
4384 const int ret = inter_mode_search_order_independent_skip(
4385 cpi, x, &mode_skip_mask, &search_state, skip_ref_frame_mask, this_mode,
4386 mode_def->ref_frame);
4387 if (ret == 1) continue;
4388 args.skip_motion_mode = (ret == 2);
4389
4390 if (sf->inter_sf.prune_compound_using_single_ref &&
4391 prune_cpd_using_sr_stats_ready && comp_pred &&
4392 !in_single_ref_cutoff(ref_frame_rd, ref_frame, second_ref_frame)) {
4393 continue;
4394 }
4395
4396 // Reach the first compound prediction mode
4397 if (sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred &&
4398 reach_first_comp_mode == 0) {
4399 analyze_single_states(cpi, &search_state);
4400 reach_first_comp_mode = 1;
4401 }
4402
4403 init_mbmi(mbmi, this_mode, ref_frames, cm);
4404
4405 x->force_skip = 0;
4406 set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
4407
4408 // Prune aggressively when best mode is skippable.
4409 int mul_fact = search_state.best_mode_skippable ? mode_thresh_mul_fact
4410 : (1 << MODE_THRESH_QBITS);
4411 int64_t mode_threshold =
4412 (search_state.mode_threshold[mode_enum] * mul_fact) >>
4413 MODE_THRESH_QBITS;
4414
4415 if (search_state.best_rd < mode_threshold) continue;
4416
4417 if (sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred) {
4418 if (compound_skip_by_single_states(cpi, &search_state, this_mode,
4419 ref_frame, second_ref_frame, x))
4420 continue;
4421 }
4422
4423 const int compmode_cost =
4424 is_comp_ref_allowed(mbmi->sb_type) ? comp_inter_cost[comp_pred] : 0;
4425 const int real_compmode_cost =
4426 cm->current_frame.reference_mode == REFERENCE_MODE_SELECT
4427 ? compmode_cost
4428 : 0;
4429
4430 if (ref_frame == INTRA_FRAME) {
4431 if ((!cpi->oxcf.enable_smooth_intra ||
4432 sf->intra_sf.disable_smooth_intra) &&
4433 (mbmi->mode == SMOOTH_PRED || mbmi->mode == SMOOTH_H_PRED ||
4434 mbmi->mode == SMOOTH_V_PRED))
4435 continue;
4436 if (!cpi->oxcf.enable_paeth_intra && mbmi->mode == PAETH_PRED) continue;
4437 if (sf->inter_sf.adaptive_mode_search > 1)
4438 if ((x->source_variance << num_pels_log2_lookup[bsize]) >
4439 search_state.best_pred_sse)
4440 continue;
4441
4442 // Intra modes will be handled in another loop later.
4443 assert(intra_mode_num < INTRA_MODES);
4444 intra_mode_idx_ls[intra_mode_num++] = mode_enum;
4445 continue;
4446 }
4447
4448 // Select prediction reference frames.
4449 for (i = 0; i < num_planes; i++) {
4450 xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
4451 if (comp_pred) xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
4452 }
4453
4454 mbmi->angle_delta[PLANE_TYPE_Y] = 0;
4455 mbmi->angle_delta[PLANE_TYPE_UV] = 0;
4456 mbmi->filter_intra_mode_info.use_filter_intra = 0;
4457 mbmi->ref_mv_idx = 0;
4458
4459 const int64_t ref_best_rd = search_state.best_rd;
4460 int disable_skip = 0;
4461 RD_STATS rd_stats, rd_stats_y, rd_stats_uv;
4462 av1_init_rd_stats(&rd_stats);
4463
4464 const int ref_frame_cost = comp_pred
4465 ? ref_costs_comp[ref_frame][second_ref_frame]
4466 : ref_costs_single[ref_frame];
4467 // Point to variables that are maintained between loop iterations
4468 args.single_newmv = search_state.single_newmv;
4469 args.single_newmv_rate = search_state.single_newmv_rate;
4470 args.single_newmv_valid = search_state.single_newmv_valid;
4471 args.single_comp_cost = real_compmode_cost;
4472 args.ref_frame_cost = ref_frame_cost;
4473 if (is_single_pred) {
4474 args.simple_rd_state = x->simple_rd_state[mode_enum];
4475 }
4476
4477 int64_t skip_rd[2] = { search_state.best_skip_rd[0],
4478 search_state.best_skip_rd[1] };
4479 int64_t this_rd = handle_inter_mode(
4480 cpi, tile_data, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv,
4481 &disable_skip, &args, ref_best_rd, tmp_buf, &x->comp_rd_buffer,
4482 &best_est_rd, do_tx_search, inter_modes_info, &motion_mode_cand,
4483 skip_rd, &inter_cost_info_from_tpl);
4484
4485 if (sf->inter_sf.prune_comp_search_by_single_result > 0 &&
4486 is_inter_singleref_mode(this_mode) && args.single_ref_first_pass) {
4487 collect_single_states(x, &search_state, mbmi);
4488 }
4489
4490 if (this_rd == INT64_MAX) continue;
4491
4492 if (mbmi->skip) {
4493 rd_stats_y.rate = 0;
4494 rd_stats_uv.rate = 0;
4495 }
4496
4497 if (sf->inter_sf.prune_compound_using_single_ref && is_single_pred &&
4498 this_rd < ref_frame_rd[ref_frame]) {
4499 ref_frame_rd[ref_frame] = this_rd;
4500 }
4501
4502 // Did this mode help, i.e., is it the new best mode
4503 if (this_rd < search_state.best_rd) {
4504 assert(IMPLIES(comp_pred,
4505 cm->current_frame.reference_mode != SINGLE_REFERENCE));
4506 search_state.best_pred_sse = x->pred_sse[ref_frame];
4507 update_search_state(&search_state, rd_cost, ctx, &rd_stats, &rd_stats_y,
4508 &rd_stats_uv, mode_enum, x, do_tx_search);
4509 if (do_tx_search) search_state.best_skip_rd[0] = skip_rd[0];
4510 search_state.best_skip_rd[1] = skip_rd[1];
4511 }
4512 if (cpi->sf.winner_mode_sf.motion_mode_for_winner_cand) {
4513 const int num_motion_mode_cand =
4514 best_motion_mode_cands.num_motion_mode_cand;
4515 int valid_motion_mode_cand_loc = num_motion_mode_cand;
4516
4517 // find the best location to insert new motion mode candidate
4518 for (int j = 0; j < num_motion_mode_cand; j++) {
4519 if (this_rd < best_motion_mode_cands.motion_mode_cand[j].rd_cost) {
4520 valid_motion_mode_cand_loc = j;
4521 break;
4522 }
4523 }
4524
4525 if (valid_motion_mode_cand_loc < max_winner_motion_mode_cand) {
4526 if (num_motion_mode_cand > 0 &&
4527 valid_motion_mode_cand_loc < max_winner_motion_mode_cand - 1)
4528 memmove(
4529 &best_motion_mode_cands
4530 .motion_mode_cand[valid_motion_mode_cand_loc + 1],
4531 &best_motion_mode_cands
4532 .motion_mode_cand[valid_motion_mode_cand_loc],
4533 (AOMMIN(num_motion_mode_cand, max_winner_motion_mode_cand - 1) -
4534 valid_motion_mode_cand_loc) *
4535 sizeof(best_motion_mode_cands.motion_mode_cand[0]));
4536 motion_mode_cand.mbmi = *mbmi;
4537 motion_mode_cand.rd_cost = this_rd;
4538 motion_mode_cand.skip_motion_mode = args.skip_motion_mode;
4539 best_motion_mode_cands.motion_mode_cand[valid_motion_mode_cand_loc] =
4540 motion_mode_cand;
4541 best_motion_mode_cands.num_motion_mode_cand =
4542 AOMMIN(max_winner_motion_mode_cand,
4543 best_motion_mode_cands.num_motion_mode_cand + 1);
4544 }
4545 }
4546
4547 /* keep record of best compound/single-only prediction */
4548 if (!disable_skip) {
4549 int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
4550
4551 if (cm->current_frame.reference_mode == REFERENCE_MODE_SELECT) {
4552 single_rate = rd_stats.rate - compmode_cost;
4553 hybrid_rate = rd_stats.rate;
4554 } else {
4555 single_rate = rd_stats.rate;
4556 hybrid_rate = rd_stats.rate + compmode_cost;
4557 }
4558
4559 single_rd = RDCOST(x->rdmult, single_rate, rd_stats.dist);
4560 hybrid_rd = RDCOST(x->rdmult, hybrid_rate, rd_stats.dist);
4561
4562 if (!comp_pred) {
4563 if (single_rd <
4564 search_state.intra_search_state.best_pred_rd[SINGLE_REFERENCE])
4565 search_state.intra_search_state.best_pred_rd[SINGLE_REFERENCE] =
4566 single_rd;
4567 } else {
4568 if (single_rd <
4569 search_state.intra_search_state.best_pred_rd[COMPOUND_REFERENCE])
4570 search_state.intra_search_state.best_pred_rd[COMPOUND_REFERENCE] =
4571 single_rd;
4572 }
4573 if (hybrid_rd <
4574 search_state.intra_search_state.best_pred_rd[REFERENCE_MODE_SELECT])
4575 search_state.intra_search_state.best_pred_rd[REFERENCE_MODE_SELECT] =
4576 hybrid_rd;
4577 }
4578 }
4579
4580 if (cpi->sf.winner_mode_sf.motion_mode_for_winner_cand) {
4581 // For the single ref winner candidates, evaluate other motion modes (non
4582 // simple translation).
4583 evaluate_motion_mode_for_winner_candidates(
4584 cpi, x, rd_cost, &args, tile_data, ctx, yv12_mb,
4585 &best_motion_mode_cands, do_tx_search, bsize, &best_est_rd,
4586 &search_state);
4587 }
4588
4589 #if CONFIG_COLLECT_COMPONENT_TIMING
4590 start_timing(cpi, do_tx_search_time);
4591 #endif
4592 if (do_tx_search != 1) {
4593 inter_modes_info_sort(inter_modes_info, inter_modes_info->rd_idx_pair_arr);
4594 search_state.best_rd = best_rd_so_far;
4595 search_state.best_mode_index = THR_INVALID;
4596 // Initialize best mode stats for winner mode processing
4597 x->winner_mode_count = 0;
4598 store_winner_mode_stats(
4599 &cpi->common, x, mbmi, NULL, NULL, NULL, THR_INVALID, NULL, bsize,
4600 best_rd_so_far, cpi->sf.winner_mode_sf.enable_multiwinner_mode_process,
4601 do_tx_search);
4602 inter_modes_info->num =
4603 inter_modes_info->num < cpi->sf.rt_sf.num_inter_modes_for_tx_search
4604 ? inter_modes_info->num
4605 : cpi->sf.rt_sf.num_inter_modes_for_tx_search;
4606 const int64_t top_est_rd =
4607 inter_modes_info->num > 0
4608 ? inter_modes_info
4609 ->est_rd_arr[inter_modes_info->rd_idx_pair_arr[0].idx]
4610 : INT64_MAX;
4611 for (int j = 0; j < inter_modes_info->num; ++j) {
4612 const int data_idx = inter_modes_info->rd_idx_pair_arr[j].idx;
4613 *mbmi = inter_modes_info->mbmi_arr[data_idx];
4614 int64_t curr_est_rd = inter_modes_info->est_rd_arr[data_idx];
4615 if (curr_est_rd * 0.80 > top_est_rd) break;
4616
4617 x->force_skip = 0;
4618 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4619
4620 // Select prediction reference frames.
4621 const int is_comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
4622 for (i = 0; i < num_planes; i++) {
4623 xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
4624 if (is_comp_pred) xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
4625 }
4626
4627 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
4628 av1_num_planes(cm) - 1);
4629 if (mbmi->motion_mode == OBMC_CAUSAL) {
4630 av1_build_obmc_inter_predictors_sb(cm, xd);
4631 }
4632
4633 RD_STATS rd_stats;
4634 RD_STATS rd_stats_y;
4635 RD_STATS rd_stats_uv;
4636 const int mode_rate = inter_modes_info->mode_rate_arr[data_idx];
4637 int64_t skip_rd = INT64_MAX;
4638 if (cpi->sf.inter_sf.txfm_rd_gate_level) {
4639 // Check if the mode is good enough based on skip RD
4640 int64_t curr_sse = inter_modes_info->sse_arr[data_idx];
4641 skip_rd = RDCOST(x->rdmult, mode_rate, curr_sse);
4642 int eval_txfm =
4643 check_txfm_eval(x, bsize, search_state.best_skip_rd[0], skip_rd,
4644 cpi->sf.inter_sf.txfm_rd_gate_level, 0);
4645 if (!eval_txfm) continue;
4646 }
4647
4648 if (!av1_txfm_search(cpi, tile_data, x, bsize, &rd_stats, &rd_stats_y,
4649 &rd_stats_uv, mode_rate, search_state.best_rd)) {
4650 continue;
4651 } else if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
4652 inter_mode_data_push(tile_data, mbmi->sb_type, rd_stats.sse,
4653 rd_stats.dist,
4654 rd_stats_y.rate + rd_stats_uv.rate +
4655 x->skip_cost[skip_ctx][mbmi->skip]);
4656 }
4657 rd_stats.rdcost = RDCOST(x->rdmult, rd_stats.rate, rd_stats.dist);
4658
4659 const THR_MODES mode_enum = get_prediction_mode_idx(
4660 mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4661
4662 // Collect mode stats for multiwinner mode processing
4663 const int txfm_search_done = 1;
4664 store_winner_mode_stats(
4665 &cpi->common, x, mbmi, &rd_stats, &rd_stats_y, &rd_stats_uv,
4666 mode_enum, NULL, bsize, rd_stats.rdcost,
4667 cpi->sf.winner_mode_sf.enable_multiwinner_mode_process,
4668 txfm_search_done);
4669
4670 if (rd_stats.rdcost < search_state.best_rd) {
4671 update_search_state(&search_state, rd_cost, ctx, &rd_stats, &rd_stats_y,
4672 &rd_stats_uv, mode_enum, x, txfm_search_done);
4673 search_state.best_skip_rd[0] = skip_rd;
4674 }
4675 }
4676 }
4677 #if CONFIG_COLLECT_COMPONENT_TIMING
4678 end_timing(cpi, do_tx_search_time);
4679 #endif
4680
4681 #if CONFIG_COLLECT_COMPONENT_TIMING
4682 start_timing(cpi, handle_intra_mode_time);
4683 #endif
4684
4685 // Gate intra mode evaluation if best of inter is skip except when source
4686 // variance is extremely low
4687 if (sf->intra_sf.skip_intra_in_interframe &&
4688 (x->source_variance > sf->intra_sf.src_var_thresh_intra_skip)) {
4689 if (inter_cost >= 0 && intra_cost >= 0) {
4690 aom_clear_system_state();
4691 const NN_CONFIG *nn_config = (AOMMIN(cm->width, cm->height) <= 480)
4692 ? &av1_intrap_nn_config
4693 : &av1_intrap_hd_nn_config;
4694 float features[6];
4695 float scores[2] = { 0.0f };
4696 float probs[2] = { 0.0f };
4697
4698 features[0] = (float)search_state.best_mbmode.skip;
4699 features[1] = (float)mi_size_wide_log2[bsize];
4700 features[2] = (float)mi_size_high_log2[bsize];
4701 features[3] = (float)intra_cost;
4702 features[4] = (float)inter_cost;
4703 const int ac_q = av1_ac_quant_QTX(x->qindex, 0, xd->bd);
4704 const int ac_q_max = av1_ac_quant_QTX(255, 0, xd->bd);
4705 features[5] = (float)(ac_q_max / ac_q);
4706
4707 av1_nn_predict(features, nn_config, 1, scores);
4708 aom_clear_system_state();
4709 av1_nn_softmax(scores, probs, 2);
4710
4711 if (probs[1] > 0.8) search_state.intra_search_state.skip_intra_modes = 1;
4712 } else if ((search_state.best_mbmode.skip) &&
4713 (sf->intra_sf.skip_intra_in_interframe >= 2)) {
4714 search_state.intra_search_state.skip_intra_modes = 1;
4715 }
4716 }
4717
4718 const int intra_ref_frame_cost = ref_costs_single[INTRA_FRAME];
4719 for (int j = 0; j < intra_mode_num; ++j) {
4720 if (sf->intra_sf.skip_intra_in_interframe &&
4721 search_state.intra_search_state.skip_intra_modes)
4722 break;
4723 const THR_MODES mode_enum = intra_mode_idx_ls[j];
4724 const MODE_DEFINITION *mode_def = &av1_mode_defs[mode_enum];
4725 const PREDICTION_MODE this_mode = mode_def->mode;
4726
4727 assert(av1_mode_defs[mode_enum].ref_frame[0] == INTRA_FRAME);
4728 assert(av1_mode_defs[mode_enum].ref_frame[1] == NONE_FRAME);
4729 init_mbmi(mbmi, this_mode, av1_mode_defs[mode_enum].ref_frame, cm);
4730 x->force_skip = 0;
4731
4732 if (this_mode != DC_PRED) {
4733 // Only search the oblique modes if the best so far is
4734 // one of the neighboring directional modes
4735 if ((sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
4736 (this_mode >= D45_PRED && this_mode <= PAETH_PRED)) {
4737 if (search_state.best_mode_index != THR_INVALID &&
4738 search_state.best_mbmode.ref_frame[0] > INTRA_FRAME)
4739 continue;
4740 }
4741 if (sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
4742 if (conditional_skipintra(
4743 this_mode, search_state.intra_search_state.best_intra_mode))
4744 continue;
4745 }
4746 }
4747
4748 RD_STATS intra_rd_stats, intra_rd_stats_y, intra_rd_stats_uv;
4749 intra_rd_stats.rdcost = av1_handle_intra_mode(
4750 &search_state.intra_search_state, cpi, x, bsize, intra_ref_frame_cost,
4751 ctx, 0, &intra_rd_stats, &intra_rd_stats_y, &intra_rd_stats_uv,
4752 search_state.best_rd, &search_state.best_intra_rd,
4753 search_state.best_mbmode.skip);
4754 // Collect mode stats for multiwinner mode processing
4755 const int txfm_search_done = 1;
4756 store_winner_mode_stats(
4757 &cpi->common, x, mbmi, &intra_rd_stats, &intra_rd_stats_y,
4758 &intra_rd_stats_uv, mode_enum, NULL, bsize, intra_rd_stats.rdcost,
4759 cpi->sf.winner_mode_sf.enable_multiwinner_mode_process,
4760 txfm_search_done);
4761 if (intra_rd_stats.rdcost < search_state.best_rd) {
4762 update_search_state(&search_state, rd_cost, ctx, &intra_rd_stats,
4763 &intra_rd_stats_y, &intra_rd_stats_uv, mode_enum, x,
4764 txfm_search_done);
4765 }
4766 }
4767 #if CONFIG_COLLECT_COMPONENT_TIMING
4768 end_timing(cpi, handle_intra_mode_time);
4769 #endif
4770
4771 int winner_mode_count = cpi->sf.winner_mode_sf.enable_multiwinner_mode_process
4772 ? x->winner_mode_count
4773 : 1;
4774 // In effect only when fast tx search speed features are enabled.
4775 refine_winner_mode_tx(
4776 cpi, x, rd_cost, bsize, ctx, &search_state.best_mode_index,
4777 &search_state.best_mbmode, yv12_mb, search_state.best_rate_y,
4778 search_state.best_rate_uv, &search_state.best_skip2, winner_mode_count);
4779
4780 // Initialize default mode evaluation params
4781 set_mode_eval_params(cpi, x, DEFAULT_EVAL);
4782
4783 // Only try palette mode when the best mode so far is an intra mode.
4784 const int try_palette =
4785 cpi->oxcf.enable_palette &&
4786 av1_allow_palette(cm->allow_screen_content_tools, mbmi->sb_type) &&
4787 !is_inter_mode(search_state.best_mbmode.mode);
4788 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
4789 RD_STATS this_rd_cost;
4790 int this_skippable = 0;
4791 if (try_palette) {
4792 this_skippable = av1_search_palette_mode(
4793 cpi, x, &this_rd_cost, ctx, bsize, mbmi, pmi, ref_costs_single,
4794 &search_state.intra_search_state, search_state.best_rd);
4795 if (this_rd_cost.rdcost < search_state.best_rd) {
4796 search_state.best_mode_index = THR_DC;
4797 mbmi->mv[0].as_int = 0;
4798 rd_cost->rate = this_rd_cost.rate;
4799 rd_cost->dist = this_rd_cost.dist;
4800 rd_cost->rdcost = this_rd_cost.rdcost;
4801 search_state.best_rd = rd_cost->rdcost;
4802 search_state.best_mbmode = *mbmi;
4803 search_state.best_skip2 = 0;
4804 search_state.best_mode_skippable = this_skippable;
4805 memcpy(ctx->blk_skip, x->blk_skip,
4806 sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
4807 av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
4808 }
4809 }
4810
4811 search_state.best_mbmode.skip_mode = 0;
4812 if (cm->current_frame.skip_mode_info.skip_mode_flag &&
4813 is_comp_ref_allowed(bsize)) {
4814 const struct segmentation *const seg = &cm->seg;
4815 unsigned char segment_id = mbmi->segment_id;
4816 if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
4817 rd_pick_skip_mode(rd_cost, &search_state, cpi, x, bsize, yv12_mb);
4818 }
4819 }
4820
4821 // Make sure that the ref_mv_idx is only nonzero when we're
4822 // using a mode which can support ref_mv_idx
4823 if (search_state.best_mbmode.ref_mv_idx != 0 &&
4824 !(search_state.best_mbmode.mode == NEWMV ||
4825 search_state.best_mbmode.mode == NEW_NEWMV ||
4826 have_nearmv_in_inter_mode(search_state.best_mbmode.mode))) {
4827 search_state.best_mbmode.ref_mv_idx = 0;
4828 }
4829
4830 if (search_state.best_mode_index == THR_INVALID ||
4831 search_state.best_rd >= best_rd_so_far) {
4832 rd_cost->rate = INT_MAX;
4833 rd_cost->rdcost = INT64_MAX;
4834 return;
4835 }
4836
4837 assert((cm->interp_filter == SWITCHABLE) ||
4838 (cm->interp_filter ==
4839 search_state.best_mbmode.interp_filters.as_filters.y_filter) ||
4840 !is_inter_block(&search_state.best_mbmode));
4841 assert((cm->interp_filter == SWITCHABLE) ||
4842 (cm->interp_filter ==
4843 search_state.best_mbmode.interp_filters.as_filters.x_filter) ||
4844 !is_inter_block(&search_state.best_mbmode));
4845
4846 if (!cpi->rc.is_src_frame_alt_ref && cpi->sf.inter_sf.adaptive_rd_thresh) {
4847 av1_update_rd_thresh_fact(cm, x->thresh_freq_fact,
4848 sf->inter_sf.adaptive_rd_thresh, bsize,
4849 search_state.best_mode_index);
4850 }
4851
4852 // macroblock modes
4853 *mbmi = search_state.best_mbmode;
4854 x->force_skip |= search_state.best_skip2;
4855
4856 // Note: this section is needed since the mode may have been forced to
4857 // GLOBALMV by the all-zero mode handling of ref-mv.
4858 if (mbmi->mode == GLOBALMV || mbmi->mode == GLOBAL_GLOBALMV) {
4859 // Correct the interp filters for GLOBALMV
4860 if (is_nontrans_global_motion(xd, xd->mi[0])) {
4861 int_interpfilters filters = av1_broadcast_interp_filter(
4862 av1_unswitchable_filter(cm->interp_filter));
4863 assert(mbmi->interp_filters.as_int == filters.as_int);
4864 (void)filters;
4865 }
4866 }
4867
4868 for (i = 0; i < REFERENCE_MODES; ++i) {
4869 if (search_state.intra_search_state.best_pred_rd[i] == INT64_MAX) {
4870 search_state.best_pred_diff[i] = INT_MIN;
4871 } else {
4872 search_state.best_pred_diff[i] =
4873 search_state.best_rd -
4874 search_state.intra_search_state.best_pred_rd[i];
4875 }
4876 }
4877
4878 x->force_skip |= search_state.best_mode_skippable;
4879
4880 assert(search_state.best_mode_index != THR_INVALID);
4881
4882 #if CONFIG_INTERNAL_STATS
4883 store_coding_context(x, ctx, search_state.best_mode_index,
4884 search_state.best_pred_diff,
4885 search_state.best_mode_skippable);
4886 #else
4887 store_coding_context(x, ctx, search_state.best_pred_diff,
4888 search_state.best_mode_skippable);
4889 #endif // CONFIG_INTERNAL_STATS
4890
4891 if (pmi->palette_size[1] > 0) {
4892 assert(try_palette);
4893 av1_restore_uv_color_map(cpi, x);
4894 }
4895 }
4896
av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP * cpi,TileDataEnc * tile_data,MACROBLOCK * x,int mi_row,int mi_col,RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,int64_t best_rd_so_far)4897 void av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP *cpi,
4898 TileDataEnc *tile_data, MACROBLOCK *x,
4899 int mi_row, int mi_col,
4900 RD_STATS *rd_cost, BLOCK_SIZE bsize,
4901 PICK_MODE_CONTEXT *ctx,
4902 int64_t best_rd_so_far) {
4903 const AV1_COMMON *const cm = &cpi->common;
4904 MACROBLOCKD *const xd = &x->e_mbd;
4905 MB_MODE_INFO *const mbmi = xd->mi[0];
4906 unsigned char segment_id = mbmi->segment_id;
4907 const int comp_pred = 0;
4908 int i;
4909 int64_t best_pred_diff[REFERENCE_MODES];
4910 unsigned int ref_costs_single[REF_FRAMES];
4911 unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES];
4912 int *comp_inter_cost = x->comp_inter_cost[av1_get_reference_mode_context(xd)];
4913 InterpFilter best_filter = SWITCHABLE;
4914 int64_t this_rd = INT64_MAX;
4915 int rate2 = 0;
4916 const int64_t distortion2 = 0;
4917 (void)mi_row;
4918 (void)mi_col;
4919 (void)tile_data;
4920
4921 av1_collect_neighbors_ref_counts(xd);
4922
4923 estimate_ref_frame_costs(cm, xd, x, segment_id, ref_costs_single,
4924 ref_costs_comp);
4925
4926 for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;
4927 for (i = LAST_FRAME; i < REF_FRAMES; ++i) x->pred_mv_sad[i] = INT_MAX;
4928
4929 rd_cost->rate = INT_MAX;
4930
4931 assert(segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP));
4932
4933 mbmi->palette_mode_info.palette_size[0] = 0;
4934 mbmi->palette_mode_info.palette_size[1] = 0;
4935 mbmi->filter_intra_mode_info.use_filter_intra = 0;
4936 mbmi->mode = GLOBALMV;
4937 mbmi->motion_mode = SIMPLE_TRANSLATION;
4938 mbmi->uv_mode = UV_DC_PRED;
4939 if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME))
4940 mbmi->ref_frame[0] = get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
4941 else
4942 mbmi->ref_frame[0] = LAST_FRAME;
4943 mbmi->ref_frame[1] = NONE_FRAME;
4944 mbmi->mv[0].as_int =
4945 gm_get_motion_vector(&cm->global_motion[mbmi->ref_frame[0]],
4946 cm->allow_high_precision_mv, bsize, mi_col, mi_row,
4947 cm->cur_frame_force_integer_mv)
4948 .as_int;
4949 mbmi->tx_size = max_txsize_lookup[bsize];
4950 x->force_skip = 1;
4951
4952 mbmi->ref_mv_idx = 0;
4953
4954 mbmi->motion_mode = SIMPLE_TRANSLATION;
4955 av1_count_overlappable_neighbors(cm, xd);
4956 if (is_motion_variation_allowed_bsize(bsize) && !has_second_ref(mbmi)) {
4957 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
4958 mbmi->num_proj_ref = av1_findSamples(cm, xd, pts, pts_inref);
4959 // Select the samples according to motion vector difference
4960 if (mbmi->num_proj_ref > 1)
4961 mbmi->num_proj_ref = av1_selectSamples(&mbmi->mv[0].as_mv, pts, pts_inref,
4962 mbmi->num_proj_ref, bsize);
4963 }
4964
4965 set_default_interp_filters(mbmi, cm->interp_filter);
4966
4967 if (cm->interp_filter != SWITCHABLE) {
4968 best_filter = cm->interp_filter;
4969 } else {
4970 best_filter = EIGHTTAP_REGULAR;
4971 if (av1_is_interp_needed(xd) &&
4972 x->source_variance >=
4973 cpi->sf.interp_sf.disable_filter_search_var_thresh) {
4974 int rs;
4975 int best_rs = INT_MAX;
4976 for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
4977 mbmi->interp_filters = av1_broadcast_interp_filter(i);
4978 rs = av1_get_switchable_rate(cm, x, xd);
4979 if (rs < best_rs) {
4980 best_rs = rs;
4981 best_filter = mbmi->interp_filters.as_filters.y_filter;
4982 }
4983 }
4984 }
4985 }
4986 // Set the appropriate filter
4987 mbmi->interp_filters = av1_broadcast_interp_filter(best_filter);
4988 rate2 += av1_get_switchable_rate(cm, x, xd);
4989
4990 if (cm->current_frame.reference_mode == REFERENCE_MODE_SELECT)
4991 rate2 += comp_inter_cost[comp_pred];
4992
4993 // Estimate the reference frame signaling cost and add it
4994 // to the rolling cost variable.
4995 rate2 += ref_costs_single[LAST_FRAME];
4996 this_rd = RDCOST(x->rdmult, rate2, distortion2);
4997
4998 rd_cost->rate = rate2;
4999 rd_cost->dist = distortion2;
5000 rd_cost->rdcost = this_rd;
5001
5002 if (this_rd >= best_rd_so_far) {
5003 rd_cost->rate = INT_MAX;
5004 rd_cost->rdcost = INT64_MAX;
5005 return;
5006 }
5007
5008 assert((cm->interp_filter == SWITCHABLE) ||
5009 (cm->interp_filter == mbmi->interp_filters.as_filters.y_filter));
5010
5011 if (cpi->sf.inter_sf.adaptive_rd_thresh) {
5012 av1_update_rd_thresh_fact(cm, x->thresh_freq_fact,
5013 cpi->sf.inter_sf.adaptive_rd_thresh, bsize,
5014 THR_GLOBALMV);
5015 }
5016
5017 av1_zero(best_pred_diff);
5018
5019 #if CONFIG_INTERNAL_STATS
5020 store_coding_context(x, ctx, THR_GLOBALMV, best_pred_diff, 0);
5021 #else
5022 store_coding_context(x, ctx, best_pred_diff, 0);
5023 #endif // CONFIG_INTERNAL_STATS
5024 }
5025
5026 struct calc_target_weighted_pred_ctxt {
5027 const MACROBLOCK *x;
5028 const uint8_t *tmp;
5029 int tmp_stride;
5030 int overlap;
5031 };
5032
calc_target_weighted_pred_above(MACROBLOCKD * xd,int rel_mi_row,int rel_mi_col,uint8_t op_mi_size,int dir,MB_MODE_INFO * nb_mi,void * fun_ctxt,const int num_planes)5033 static INLINE void calc_target_weighted_pred_above(
5034 MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
5035 int dir, MB_MODE_INFO *nb_mi, void *fun_ctxt, const int num_planes) {
5036 (void)nb_mi;
5037 (void)num_planes;
5038 (void)rel_mi_row;
5039 (void)dir;
5040
5041 struct calc_target_weighted_pred_ctxt *ctxt =
5042 (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
5043
5044 const int bw = xd->n4_w << MI_SIZE_LOG2;
5045 const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
5046
5047 int32_t *wsrc = ctxt->x->wsrc_buf + (rel_mi_col * MI_SIZE);
5048 int32_t *mask = ctxt->x->mask_buf + (rel_mi_col * MI_SIZE);
5049 const uint8_t *tmp = ctxt->tmp + rel_mi_col * MI_SIZE;
5050 const int is_hbd = is_cur_buf_hbd(xd);
5051
5052 if (!is_hbd) {
5053 for (int row = 0; row < ctxt->overlap; ++row) {
5054 const uint8_t m0 = mask1d[row];
5055 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
5056 for (int col = 0; col < op_mi_size * MI_SIZE; ++col) {
5057 wsrc[col] = m1 * tmp[col];
5058 mask[col] = m0;
5059 }
5060 wsrc += bw;
5061 mask += bw;
5062 tmp += ctxt->tmp_stride;
5063 }
5064 } else {
5065 const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
5066
5067 for (int row = 0; row < ctxt->overlap; ++row) {
5068 const uint8_t m0 = mask1d[row];
5069 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
5070 for (int col = 0; col < op_mi_size * MI_SIZE; ++col) {
5071 wsrc[col] = m1 * tmp16[col];
5072 mask[col] = m0;
5073 }
5074 wsrc += bw;
5075 mask += bw;
5076 tmp16 += ctxt->tmp_stride;
5077 }
5078 }
5079 }
5080
calc_target_weighted_pred_left(MACROBLOCKD * xd,int rel_mi_row,int rel_mi_col,uint8_t op_mi_size,int dir,MB_MODE_INFO * nb_mi,void * fun_ctxt,const int num_planes)5081 static INLINE void calc_target_weighted_pred_left(
5082 MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
5083 int dir, MB_MODE_INFO *nb_mi, void *fun_ctxt, const int num_planes) {
5084 (void)nb_mi;
5085 (void)num_planes;
5086 (void)rel_mi_col;
5087 (void)dir;
5088
5089 struct calc_target_weighted_pred_ctxt *ctxt =
5090 (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
5091
5092 const int bw = xd->n4_w << MI_SIZE_LOG2;
5093 const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
5094
5095 int32_t *wsrc = ctxt->x->wsrc_buf + (rel_mi_row * MI_SIZE * bw);
5096 int32_t *mask = ctxt->x->mask_buf + (rel_mi_row * MI_SIZE * bw);
5097 const uint8_t *tmp = ctxt->tmp + (rel_mi_row * MI_SIZE * ctxt->tmp_stride);
5098 const int is_hbd = is_cur_buf_hbd(xd);
5099
5100 if (!is_hbd) {
5101 for (int row = 0; row < op_mi_size * MI_SIZE; ++row) {
5102 for (int col = 0; col < ctxt->overlap; ++col) {
5103 const uint8_t m0 = mask1d[col];
5104 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
5105 wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
5106 (tmp[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
5107 mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
5108 }
5109 wsrc += bw;
5110 mask += bw;
5111 tmp += ctxt->tmp_stride;
5112 }
5113 } else {
5114 const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
5115
5116 for (int row = 0; row < op_mi_size * MI_SIZE; ++row) {
5117 for (int col = 0; col < ctxt->overlap; ++col) {
5118 const uint8_t m0 = mask1d[col];
5119 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
5120 wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
5121 (tmp16[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
5122 mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
5123 }
5124 wsrc += bw;
5125 mask += bw;
5126 tmp16 += ctxt->tmp_stride;
5127 }
5128 }
5129 }
5130
5131 // This function has a structure similar to av1_build_obmc_inter_prediction
5132 //
5133 // The OBMC predictor is computed as:
5134 //
5135 // PObmc(x,y) =
5136 // AOM_BLEND_A64(Mh(x),
5137 // AOM_BLEND_A64(Mv(y), P(x,y), PAbove(x,y)),
5138 // PLeft(x, y))
5139 //
5140 // Scaling up by AOM_BLEND_A64_MAX_ALPHA ** 2 and omitting the intermediate
5141 // rounding, this can be written as:
5142 //
5143 // AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * Pobmc(x,y) =
5144 // Mh(x) * Mv(y) * P(x,y) +
5145 // Mh(x) * Cv(y) * Pabove(x,y) +
5146 // AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
5147 //
5148 // Where :
5149 //
5150 // Cv(y) = AOM_BLEND_A64_MAX_ALPHA - Mv(y)
5151 // Ch(y) = AOM_BLEND_A64_MAX_ALPHA - Mh(y)
5152 //
5153 // This function computes 'wsrc' and 'mask' as:
5154 //
5155 // wsrc(x, y) =
5156 // AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * src(x, y) -
5157 // Mh(x) * Cv(y) * Pabove(x,y) +
5158 // AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
5159 //
5160 // mask(x, y) = Mh(x) * Mv(y)
5161 //
5162 // These can then be used to efficiently approximate the error for any
5163 // predictor P in the context of the provided neighbouring predictors by
5164 // computing:
5165 //
5166 // error(x, y) =
5167 // wsrc(x, y) - mask(x, y) * P(x, y) / (AOM_BLEND_A64_MAX_ALPHA ** 2)
5168 //
calc_target_weighted_pred(const AV1_COMMON * cm,const MACROBLOCK * x,const MACROBLOCKD * xd,const uint8_t * above,int above_stride,const uint8_t * left,int left_stride)5169 static AOM_INLINE void calc_target_weighted_pred(
5170 const AV1_COMMON *cm, const MACROBLOCK *x, const MACROBLOCKD *xd,
5171 const uint8_t *above, int above_stride, const uint8_t *left,
5172 int left_stride) {
5173 const BLOCK_SIZE bsize = xd->mi[0]->sb_type;
5174 const int bw = xd->n4_w << MI_SIZE_LOG2;
5175 const int bh = xd->n4_h << MI_SIZE_LOG2;
5176 int32_t *mask_buf = x->mask_buf;
5177 int32_t *wsrc_buf = x->wsrc_buf;
5178
5179 const int is_hbd = is_cur_buf_hbd(xd);
5180 const int src_scale = AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA;
5181
5182 // plane 0 should not be sub-sampled
5183 assert(xd->plane[0].subsampling_x == 0);
5184 assert(xd->plane[0].subsampling_y == 0);
5185
5186 av1_zero_array(wsrc_buf, bw * bh);
5187 for (int i = 0; i < bw * bh; ++i) mask_buf[i] = AOM_BLEND_A64_MAX_ALPHA;
5188
5189 // handle above row
5190 if (xd->up_available) {
5191 const int overlap =
5192 AOMMIN(block_size_high[bsize], block_size_high[BLOCK_64X64]) >> 1;
5193 struct calc_target_weighted_pred_ctxt ctxt = { x, above, above_stride,
5194 overlap };
5195 foreach_overlappable_nb_above(cm, (MACROBLOCKD *)xd,
5196 max_neighbor_obmc[mi_size_wide_log2[bsize]],
5197 calc_target_weighted_pred_above, &ctxt);
5198 }
5199
5200 for (int i = 0; i < bw * bh; ++i) {
5201 wsrc_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
5202 mask_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
5203 }
5204
5205 // handle left column
5206 if (xd->left_available) {
5207 const int overlap =
5208 AOMMIN(block_size_wide[bsize], block_size_wide[BLOCK_64X64]) >> 1;
5209 struct calc_target_weighted_pred_ctxt ctxt = { x, left, left_stride,
5210 overlap };
5211 foreach_overlappable_nb_left(cm, (MACROBLOCKD *)xd,
5212 max_neighbor_obmc[mi_size_high_log2[bsize]],
5213 calc_target_weighted_pred_left, &ctxt);
5214 }
5215
5216 if (!is_hbd) {
5217 const uint8_t *src = x->plane[0].src.buf;
5218
5219 for (int row = 0; row < bh; ++row) {
5220 for (int col = 0; col < bw; ++col) {
5221 wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
5222 }
5223 wsrc_buf += bw;
5224 src += x->plane[0].src.stride;
5225 }
5226 } else {
5227 const uint16_t *src = CONVERT_TO_SHORTPTR(x->plane[0].src.buf);
5228
5229 for (int row = 0; row < bh; ++row) {
5230 for (int col = 0; col < bw; ++col) {
5231 wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
5232 }
5233 wsrc_buf += bw;
5234 src += x->plane[0].src.stride;
5235 }
5236 }
5237 }
5238
5239 /* Use standard 3x3 Sobel matrix. Macro so it can be used for either high or
5240 low bit-depth arrays. */
5241 #define SOBEL_X(src, stride, i, j) \
5242 ((src)[((i)-1) + (stride) * ((j)-1)] - \
5243 (src)[((i) + 1) + (stride) * ((j)-1)] + /* NOLINT */ \
5244 2 * (src)[((i)-1) + (stride) * (j)] - /* NOLINT */ \
5245 2 * (src)[((i) + 1) + (stride) * (j)] + /* NOLINT */ \
5246 (src)[((i)-1) + (stride) * ((j) + 1)] - /* NOLINT */ \
5247 (src)[((i) + 1) + (stride) * ((j) + 1)]) /* NOLINT */
5248 #define SOBEL_Y(src, stride, i, j) \
5249 ((src)[((i)-1) + (stride) * ((j)-1)] + \
5250 2 * (src)[(i) + (stride) * ((j)-1)] + /* NOLINT */ \
5251 (src)[((i) + 1) + (stride) * ((j)-1)] - /* NOLINT */ \
5252 (src)[((i)-1) + (stride) * ((j) + 1)] - /* NOLINT */ \
5253 2 * (src)[(i) + (stride) * ((j) + 1)] - /* NOLINT */ \
5254 (src)[((i) + 1) + (stride) * ((j) + 1)]) /* NOLINT */
5255
av1_sobel(const uint8_t * input,int stride,int i,int j,bool high_bd)5256 sobel_xy av1_sobel(const uint8_t *input, int stride, int i, int j,
5257 bool high_bd) {
5258 int16_t s_x;
5259 int16_t s_y;
5260 if (high_bd) {
5261 const uint16_t *src = CONVERT_TO_SHORTPTR(input);
5262 s_x = SOBEL_X(src, stride, i, j);
5263 s_y = SOBEL_Y(src, stride, i, j);
5264 } else {
5265 s_x = SOBEL_X(input, stride, i, j);
5266 s_y = SOBEL_Y(input, stride, i, j);
5267 }
5268 sobel_xy r = { .x = s_x, .y = s_y };
5269 return r;
5270 }
5271
5272 // 8-tap Gaussian convolution filter with sigma = 1.3, sums to 128,
5273 // all co-efficients must be even.
5274 DECLARE_ALIGNED(16, static const int16_t, gauss_filter[8]) = { 2, 12, 30, 40,
5275 30, 12, 2, 0 };
5276
av1_gaussian_blur(const uint8_t * src,int src_stride,int w,int h,uint8_t * dst,bool high_bd,int bd)5277 void av1_gaussian_blur(const uint8_t *src, int src_stride, int w, int h,
5278 uint8_t *dst, bool high_bd, int bd) {
5279 ConvolveParams conv_params = get_conv_params(0, 0, bd);
5280 InterpFilterParams filter = { .filter_ptr = gauss_filter,
5281 .taps = 8,
5282 .subpel_shifts = 0,
5283 .interp_filter = EIGHTTAP_REGULAR };
5284 // Requirements from the vector-optimized implementations.
5285 assert(h % 4 == 0);
5286 assert(w % 8 == 0);
5287 // Because we use an eight tap filter, the stride should be at least 7 + w.
5288 assert(src_stride >= w + 7);
5289 #if CONFIG_AV1_HIGHBITDEPTH
5290 if (high_bd) {
5291 av1_highbd_convolve_2d_sr(CONVERT_TO_SHORTPTR(src), src_stride,
5292 CONVERT_TO_SHORTPTR(dst), w, w, h, &filter,
5293 &filter, 0, 0, &conv_params, bd);
5294 } else {
5295 av1_convolve_2d_sr(src, src_stride, dst, w, w, h, &filter, &filter, 0, 0,
5296 &conv_params);
5297 }
5298 #else
5299 (void)high_bd;
5300 av1_convolve_2d_sr(src, src_stride, dst, w, w, h, &filter, &filter, 0, 0,
5301 &conv_params);
5302 #endif
5303 }
5304
edge_probability(const uint8_t * input,int w,int h,bool high_bd,int bd)5305 static EdgeInfo edge_probability(const uint8_t *input, int w, int h,
5306 bool high_bd, int bd) {
5307 // The probability of an edge in the whole image is the same as the highest
5308 // probability of an edge for any individual pixel. Use Sobel as the metric
5309 // for finding an edge.
5310 uint16_t highest = 0;
5311 uint16_t highest_x = 0;
5312 uint16_t highest_y = 0;
5313 // Ignore the 1 pixel border around the image for the computation.
5314 for (int j = 1; j < h - 1; ++j) {
5315 for (int i = 1; i < w - 1; ++i) {
5316 sobel_xy g = av1_sobel(input, w, i, j, high_bd);
5317 // Scale down to 8-bit to get same output regardless of bit depth.
5318 int16_t g_x = g.x >> (bd - 8);
5319 int16_t g_y = g.y >> (bd - 8);
5320 uint16_t magnitude = (uint16_t)sqrt(g_x * g_x + g_y * g_y);
5321 highest = AOMMAX(highest, magnitude);
5322 highest_x = AOMMAX(highest_x, g_x);
5323 highest_y = AOMMAX(highest_y, g_y);
5324 }
5325 }
5326 EdgeInfo ei = { .magnitude = highest, .x = highest_x, .y = highest_y };
5327 return ei;
5328 }
5329
5330 /* Uses most of the Canny edge detection algorithm to find if there are any
5331 * edges in the image.
5332 */
av1_edge_exists(const uint8_t * src,int src_stride,int w,int h,bool high_bd,int bd)5333 EdgeInfo av1_edge_exists(const uint8_t *src, int src_stride, int w, int h,
5334 bool high_bd, int bd) {
5335 if (w < 3 || h < 3) {
5336 EdgeInfo n = { .magnitude = 0, .x = 0, .y = 0 };
5337 return n;
5338 }
5339 uint8_t *blurred;
5340 if (high_bd) {
5341 blurred = CONVERT_TO_BYTEPTR(aom_memalign(32, sizeof(uint16_t) * w * h));
5342 } else {
5343 blurred = (uint8_t *)aom_memalign(32, sizeof(uint8_t) * w * h);
5344 }
5345 av1_gaussian_blur(src, src_stride, w, h, blurred, high_bd, bd);
5346 // Skip the non-maximum suppression step in Canny edge detection. We just
5347 // want a probability of an edge existing in the buffer, which is determined
5348 // by the strongest edge in it -- we don't need to eliminate the weaker
5349 // edges. Use Sobel for the edge detection.
5350 EdgeInfo prob = edge_probability(blurred, w, h, high_bd, bd);
5351 if (high_bd) {
5352 aom_free(CONVERT_TO_SHORTPTR(blurred));
5353 } else {
5354 aom_free(blurred);
5355 }
5356 return prob;
5357 }
5358