1 /*
2 * Copyright (c) 2020, 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 "aom_ports/system_state.h"
13
14 #include "av1/common/reconinter.h"
15
16 #include "av1/encoder/encodemv.h"
17 #include "av1/encoder/encoder.h"
18 #include "av1/encoder/mcomp.h"
19 #include "av1/encoder/motion_search_facade.h"
20 #include "av1/encoder/partition_strategy.h"
21 #include "av1/encoder/reconinter_enc.h"
22 #include "av1/encoder/tpl_model.h"
23
24 #define RIGHT_SHIFT_MV(x) (((x) + 3 + ((x) >= 0)) >> 3)
25
26 typedef struct {
27 FULLPEL_MV fmv;
28 int weight;
29 } cand_mv_t;
30
compare_weight(const void * a,const void * b)31 static int compare_weight(const void *a, const void *b) {
32 const int diff = ((cand_mv_t *)a)->weight - ((cand_mv_t *)b)->weight;
33 if (diff < 0)
34 return 1;
35 else if (diff > 0)
36 return -1;
37 return 0;
38 }
39
av1_single_motion_search(const AV1_COMP * const cpi,MACROBLOCK * x,BLOCK_SIZE bsize,int ref_idx,int * rate_mv,int search_range,inter_mode_info * mode_info,int_mv * best_mv)40 void av1_single_motion_search(const AV1_COMP *const cpi, MACROBLOCK *x,
41 BLOCK_SIZE bsize, int ref_idx, int *rate_mv,
42 int search_range, inter_mode_info *mode_info,
43 int_mv *best_mv) {
44 MACROBLOCKD *xd = &x->e_mbd;
45 const AV1_COMMON *cm = &cpi->common;
46 const MotionVectorSearchParams *mv_search_params = &cpi->mv_search_params;
47 const int num_planes = av1_num_planes(cm);
48 MB_MODE_INFO *mbmi = xd->mi[0];
49 struct buf_2d backup_yv12[MAX_MB_PLANE] = { { 0, 0, 0, 0, 0 } };
50 int bestsme = INT_MAX;
51 const int ref = mbmi->ref_frame[ref_idx];
52 const YV12_BUFFER_CONFIG *scaled_ref_frame =
53 av1_get_scaled_ref_frame(cpi, ref);
54 const int mi_row = xd->mi_row;
55 const int mi_col = xd->mi_col;
56
57 if (scaled_ref_frame) {
58 // Swap out the reference frame for a version that's been scaled to
59 // match the resolution of the current frame, allowing the existing
60 // full-pixel motion search code to be used without additional
61 // modifications.
62 for (int i = 0; i < num_planes; i++) {
63 backup_yv12[i] = xd->plane[i].pre[ref_idx];
64 }
65 av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL,
66 num_planes);
67 }
68
69 // Work out the size of the first step in the mv step search.
70 // 0 here is maximum length first step. 1 is AOMMAX >> 1 etc.
71 int step_param;
72 if (cpi->sf.mv_sf.auto_mv_step_size && cm->show_frame) {
73 // Take the weighted average of the step_params based on the last frame's
74 // max mv magnitude and that based on the best ref mvs of the current
75 // block for the given reference.
76 step_param = (av1_init_search_range(x->max_mv_context[ref]) +
77 mv_search_params->mv_step_param) /
78 2;
79 } else {
80 step_param = mv_search_params->mv_step_param;
81 }
82
83 if (cpi->sf.mv_sf.adaptive_motion_search && bsize < cm->seq_params.sb_size) {
84 int boffset =
85 2 * (mi_size_wide_log2[cm->seq_params.sb_size] -
86 AOMMIN(mi_size_high_log2[bsize], mi_size_wide_log2[bsize]));
87 step_param = AOMMAX(step_param, boffset);
88 }
89
90 if (cpi->sf.mv_sf.adaptive_motion_search) {
91 int bwl = mi_size_wide_log2[bsize];
92 int bhl = mi_size_high_log2[bsize];
93 int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
94
95 if (tlevel < 5) {
96 step_param += 2;
97 step_param = AOMMIN(step_param, MAX_MVSEARCH_STEPS - 1);
98 }
99
100 // prev_mv_sad is not setup for dynamically scaled frames.
101 if (cpi->oxcf.resize_mode != RESIZE_RANDOM) {
102 int i;
103 for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
104 if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
105 x->pred_mv[ref].row = 0;
106 x->pred_mv[ref].col = 0;
107 best_mv->as_int = INVALID_MV;
108
109 if (scaled_ref_frame) {
110 // Swap back the original buffers before returning.
111 for (int j = 0; j < num_planes; ++j)
112 xd->plane[j].pre[ref_idx] = backup_yv12[j];
113 }
114 return;
115 }
116 }
117 }
118 }
119
120 const MV ref_mv = av1_get_ref_mv(x, ref_idx).as_mv;
121 FULLPEL_MV start_mv;
122 if (mbmi->motion_mode != SIMPLE_TRANSLATION)
123 start_mv = get_fullmv_from_mv(&mbmi->mv[0].as_mv);
124 else
125 start_mv = get_fullmv_from_mv(&ref_mv);
126
127 // cand stores start_mv and all possible MVs in a SB.
128 cand_mv_t cand[MAX_MC_FLOW_BLK_IN_SB * MAX_MC_FLOW_BLK_IN_SB + 1] = {
129 { { 0, 0 }, 0 }
130 };
131 cand[0].fmv = start_mv;
132 int cnt = 1;
133 int total_weight = 0;
134
135 if (!cpi->sf.mv_sf.full_pixel_search_level &&
136 mbmi->motion_mode == SIMPLE_TRANSLATION) {
137 if (x->valid_cost_b) {
138 const BLOCK_SIZE tpl_bsize = convert_length_to_bsize(MC_FLOW_BSIZE_1D);
139 const int tplw = mi_size_wide[tpl_bsize];
140 const int tplh = mi_size_high[tpl_bsize];
141 const int nw = mi_size_wide[bsize] / tplw;
142 const int nh = mi_size_high[bsize] / tplh;
143
144 if (nw >= 1 && nh >= 1) {
145 const int of_h = mi_row % mi_size_high[cm->seq_params.sb_size];
146 const int of_w = mi_col % mi_size_wide[cm->seq_params.sb_size];
147 const int start = of_h / tplh * x->cost_stride + of_w / tplw;
148 int valid = 1;
149
150 // Assign large weight to start_mv, so it is always tested.
151 cand[0].weight = nw * nh;
152
153 for (int k = 0; k < nh; k++) {
154 for (int l = 0; l < nw; l++) {
155 const int_mv mv =
156 x->mv_b[start + k * x->cost_stride + l][ref - LAST_FRAME];
157 if (mv.as_int == INVALID_MV) {
158 valid = 0;
159 break;
160 }
161
162 const FULLPEL_MV fmv = { GET_MV_RAWPEL(mv.as_mv.row),
163 GET_MV_RAWPEL(mv.as_mv.col) };
164 int unique = 1;
165 for (int m = 0; m < cnt; m++) {
166 if (RIGHT_SHIFT_MV(fmv.row) == RIGHT_SHIFT_MV(cand[m].fmv.row) &&
167 RIGHT_SHIFT_MV(fmv.col) == RIGHT_SHIFT_MV(cand[m].fmv.col)) {
168 unique = 0;
169 cand[m].weight++;
170 break;
171 }
172 }
173
174 if (unique) {
175 cand[cnt].fmv = fmv;
176 cand[cnt].weight = 1;
177 cnt++;
178 }
179 }
180 if (!valid) break;
181 }
182
183 if (valid) {
184 total_weight = 2 * nh * nw;
185 if (cnt > 2) qsort(cand, cnt, sizeof(cand[0]), &compare_weight);
186 }
187 }
188 }
189 }
190
191 // Further reduce the search range.
192 if (search_range < INT_MAX) {
193 const search_site_config *ss_cfg = &mv_search_params->ss_cfg[SS_CFG_SRC];
194 // MAx step_param is ss_cfg->ss_count.
195 if (search_range < 1) {
196 step_param = ss_cfg->ss_count;
197 } else {
198 while (ss_cfg->radius[ss_cfg->ss_count - step_param - 1] >
199 (search_range << 1) &&
200 ss_cfg->ss_count - step_param - 1 > 0)
201 step_param++;
202 }
203 }
204
205 int cost_list[5];
206 int_mv second_best_mv;
207 best_mv->as_int = second_best_mv.as_int = INVALID_MV;
208
209 const search_site_config *src_search_sites =
210 &mv_search_params->ss_cfg[SS_CFG_SRC];
211 FULLPEL_MOTION_SEARCH_PARAMS full_ms_params;
212 av1_make_default_fullpel_ms_params(&full_ms_params, cpi, x, bsize, &ref_mv,
213 src_search_sites);
214
215 switch (mbmi->motion_mode) {
216 case SIMPLE_TRANSLATION: {
217 int sum_weight = 0;
218
219 for (int m = 0; m < cnt; m++) {
220 FULLPEL_MV smv = cand[m].fmv;
221 FULLPEL_MV this_best_mv, this_second_best_mv;
222
223 int thissme = av1_full_pixel_search(
224 smv, &full_ms_params, step_param, cond_cost_list(cpi, cost_list),
225 &this_best_mv, &this_second_best_mv);
226
227 if (thissme < bestsme) {
228 bestsme = thissme;
229 best_mv->as_fullmv = this_best_mv;
230 second_best_mv.as_fullmv = this_second_best_mv;
231 }
232
233 sum_weight += cand[m].weight;
234 if (m >= 2 || 4 * sum_weight > 3 * total_weight) break;
235 }
236 } break;
237 case OBMC_CAUSAL:
238 bestsme = av1_obmc_full_pixel_search(start_mv, &full_ms_params,
239 step_param, &best_mv->as_fullmv);
240 break;
241 default: assert(0 && "Invalid motion mode!\n");
242 }
243
244 if (scaled_ref_frame) {
245 // Swap back the original buffers for subpel motion search.
246 for (int i = 0; i < num_planes; i++) {
247 xd->plane[i].pre[ref_idx] = backup_yv12[i];
248 }
249 }
250
251 // Terminate search with the current ref_idx if we have already encountered
252 // another ref_mv in the drl such that:
253 // 1. The other drl has the same fullpel_mv during the SIMPLE_TRANSLATION
254 // search process as the current fullpel_mv.
255 // 2. The rate needed to encode the current fullpel_mv is larger than that
256 // for the other ref_mv.
257 if (cpi->sf.inter_sf.skip_repeated_full_newmv &&
258 mbmi->motion_mode == SIMPLE_TRANSLATION &&
259 best_mv->as_int != INVALID_MV) {
260 int_mv this_mv;
261 this_mv.as_mv = get_mv_from_fullmv(&best_mv->as_fullmv);
262 const int ref_mv_idx = mbmi->ref_mv_idx;
263 const int this_mv_rate =
264 av1_mv_bit_cost(&this_mv.as_mv, &ref_mv, x->nmv_vec_cost,
265 x->mv_cost_stack, MV_COST_WEIGHT);
266 mode_info[ref_mv_idx].full_search_mv.as_int = this_mv.as_int;
267 mode_info[ref_mv_idx].full_mv_rate = this_mv_rate;
268
269 for (int prev_ref_idx = 0; prev_ref_idx < ref_mv_idx; ++prev_ref_idx) {
270 // Check if the motion search result same as previous results
271 if (this_mv.as_int == mode_info[prev_ref_idx].full_search_mv.as_int) {
272 // Compare the rate cost
273 const int prev_rate_cost = mode_info[prev_ref_idx].full_mv_rate +
274 mode_info[prev_ref_idx].drl_cost;
275 const int this_rate_cost =
276 this_mv_rate + mode_info[ref_mv_idx].drl_cost;
277
278 if (prev_rate_cost <= this_rate_cost) {
279 // If the current rate_cost is worse than the previous rate_cost, then
280 // we terminate the search. Since av1_single_motion_search is only
281 // called by handle_new_mv in SIMPLE_TRANSLATION mode, we set the
282 // best_mv to INVALID mv to signal that we wish to terminate search
283 // for the current mode.
284 best_mv->as_int = INVALID_MV;
285 return;
286 }
287 }
288 }
289 }
290
291 if (cpi->common.features.cur_frame_force_integer_mv) {
292 convert_fullmv_to_mv(best_mv);
293 }
294
295 const int use_fractional_mv =
296 bestsme < INT_MAX && cpi->common.features.cur_frame_force_integer_mv == 0;
297 if (use_fractional_mv) {
298 int_mv fractional_ms_list[3];
299 av1_set_fractional_mv(fractional_ms_list);
300 int dis; /* TODO: use dis in distortion calculation later. */
301
302 SUBPEL_MOTION_SEARCH_PARAMS ms_params;
303 av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
304 cost_list);
305 MV subpel_start_mv = get_mv_from_fullmv(&best_mv->as_fullmv);
306
307 switch (mbmi->motion_mode) {
308 case SIMPLE_TRANSLATION:
309 if (cpi->sf.mv_sf.use_accurate_subpel_search) {
310 const int try_second = second_best_mv.as_int != INVALID_MV &&
311 second_best_mv.as_int != best_mv->as_int;
312 const int best_mv_var = mv_search_params->find_fractional_mv_step(
313 xd, cm, &ms_params, subpel_start_mv, &best_mv->as_mv, &dis,
314 &x->pred_sse[ref], fractional_ms_list);
315
316 if (try_second) {
317 MV this_best_mv;
318 subpel_start_mv = get_mv_from_fullmv(&second_best_mv.as_fullmv);
319 if (av1_is_subpelmv_in_range(&ms_params.mv_limits,
320 subpel_start_mv)) {
321 const int this_var = mv_search_params->find_fractional_mv_step(
322 xd, cm, &ms_params, subpel_start_mv, &this_best_mv, &dis,
323 &x->pred_sse[ref], fractional_ms_list);
324 if (this_var < best_mv_var) best_mv->as_mv = this_best_mv;
325 }
326 }
327 } else {
328 mv_search_params->find_fractional_mv_step(
329 xd, cm, &ms_params, subpel_start_mv, &best_mv->as_mv, &dis,
330 &x->pred_sse[ref], NULL);
331 }
332 break;
333 case OBMC_CAUSAL:
334 av1_find_best_obmc_sub_pixel_tree_up(xd, cm, &ms_params,
335 subpel_start_mv, &best_mv->as_mv,
336 &dis, &x->pred_sse[ref], NULL);
337 break;
338 default: assert(0 && "Invalid motion mode!\n");
339 }
340 }
341 *rate_mv = av1_mv_bit_cost(&best_mv->as_mv, &ref_mv, x->nmv_vec_cost,
342 x->mv_cost_stack, MV_COST_WEIGHT);
343
344 if (cpi->sf.mv_sf.adaptive_motion_search &&
345 mbmi->motion_mode == SIMPLE_TRANSLATION)
346 x->pred_mv[ref] = best_mv->as_mv;
347 }
348
av1_joint_motion_search(const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,int_mv * cur_mv,const uint8_t * mask,int mask_stride,int * rate_mv)349 void av1_joint_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
350 BLOCK_SIZE bsize, int_mv *cur_mv,
351 const uint8_t *mask, int mask_stride,
352 int *rate_mv) {
353 const AV1_COMMON *const cm = &cpi->common;
354 const int num_planes = av1_num_planes(cm);
355 const int pw = block_size_wide[bsize];
356 const int ph = block_size_high[bsize];
357 const int plane = 0;
358 MACROBLOCKD *xd = &x->e_mbd;
359 MB_MODE_INFO *mbmi = xd->mi[0];
360 // This function should only ever be called for compound modes
361 assert(has_second_ref(mbmi));
362 const int_mv init_mv[2] = { cur_mv[0], cur_mv[1] };
363 const int refs[2] = { mbmi->ref_frame[0], mbmi->ref_frame[1] };
364 int_mv ref_mv[2];
365 int ite, ref;
366
367 // Get the prediction block from the 'other' reference frame.
368 const int_interpfilters interp_filters =
369 av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
370
371 InterPredParams inter_pred_params;
372 const int mi_row = xd->mi_row;
373 const int mi_col = xd->mi_col;
374
375 // Do joint motion search in compound mode to get more accurate mv.
376 struct buf_2d backup_yv12[2][MAX_MB_PLANE];
377 int last_besterr[2] = { INT_MAX, INT_MAX };
378 const YV12_BUFFER_CONFIG *const scaled_ref_frame[2] = {
379 av1_get_scaled_ref_frame(cpi, refs[0]),
380 av1_get_scaled_ref_frame(cpi, refs[1])
381 };
382
383 // Prediction buffer from second frame.
384 DECLARE_ALIGNED(16, uint8_t, second_pred16[MAX_SB_SQUARE * sizeof(uint16_t)]);
385 uint8_t *second_pred = get_buf_by_bd(xd, second_pred16);
386 int_mv best_mv;
387
388 // Allow joint search multiple times iteratively for each reference frame
389 // and break out of the search loop if it couldn't find a better mv.
390 for (ite = 0; ite < 4; ite++) {
391 struct buf_2d ref_yv12[2];
392 int bestsme = INT_MAX;
393 int id = ite % 2; // Even iterations search in the first reference frame,
394 // odd iterations search in the second. The predictor
395 // found for the 'other' reference frame is factored in.
396 if (ite >= 2 && cur_mv[!id].as_int == init_mv[!id].as_int) {
397 if (cur_mv[id].as_int == init_mv[id].as_int) {
398 break;
399 } else {
400 int_mv cur_int_mv, init_int_mv;
401 cur_int_mv.as_mv.col = cur_mv[id].as_mv.col >> 3;
402 cur_int_mv.as_mv.row = cur_mv[id].as_mv.row >> 3;
403 init_int_mv.as_mv.row = init_mv[id].as_mv.row >> 3;
404 init_int_mv.as_mv.col = init_mv[id].as_mv.col >> 3;
405 if (cur_int_mv.as_int == init_int_mv.as_int) {
406 break;
407 }
408 }
409 }
410 for (ref = 0; ref < 2; ++ref) {
411 ref_mv[ref] = av1_get_ref_mv(x, ref);
412 // Swap out the reference frame for a version that's been scaled to
413 // match the resolution of the current frame, allowing the existing
414 // motion search code to be used without additional modifications.
415 if (scaled_ref_frame[ref]) {
416 int i;
417 for (i = 0; i < num_planes; i++)
418 backup_yv12[ref][i] = xd->plane[i].pre[ref];
419 av1_setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col,
420 NULL, num_planes);
421 }
422 }
423
424 assert(IMPLIES(scaled_ref_frame[0] != NULL,
425 cm->width == scaled_ref_frame[0]->y_crop_width &&
426 cm->height == scaled_ref_frame[0]->y_crop_height));
427 assert(IMPLIES(scaled_ref_frame[1] != NULL,
428 cm->width == scaled_ref_frame[1]->y_crop_width &&
429 cm->height == scaled_ref_frame[1]->y_crop_height));
430
431 // Initialize based on (possibly scaled) prediction buffers.
432 ref_yv12[0] = xd->plane[plane].pre[0];
433 ref_yv12[1] = xd->plane[plane].pre[1];
434
435 av1_init_inter_params(&inter_pred_params, pw, ph, mi_row * MI_SIZE,
436 mi_col * MI_SIZE, 0, 0, xd->bd, is_cur_buf_hbd(xd), 0,
437 &cm->sf_identity, &ref_yv12[!id], interp_filters);
438 inter_pred_params.conv_params = get_conv_params(0, 0, xd->bd);
439
440 // Since we have scaled the reference frames to match the size of the
441 // current frame we must use a unit scaling factor during mode selection.
442 av1_enc_build_one_inter_predictor(second_pred, pw, &cur_mv[!id].as_mv,
443 &inter_pred_params);
444
445 const int order_idx = id != 0;
446 av1_dist_wtd_comp_weight_assign(
447 cm, mbmi, order_idx, &xd->jcp_param.fwd_offset,
448 &xd->jcp_param.bck_offset, &xd->jcp_param.use_dist_wtd_comp_avg, 1);
449
450 // Do full-pixel compound motion search on the current reference frame.
451 if (id) xd->plane[plane].pre[0] = ref_yv12[id];
452
453 // Make motion search params
454 FULLPEL_MOTION_SEARCH_PARAMS full_ms_params;
455 av1_make_default_fullpel_ms_params(&full_ms_params, cpi, x, bsize,
456 &ref_mv[id].as_mv, NULL);
457 av1_set_ms_compound_refs(&full_ms_params.ms_buffers, second_pred, mask,
458 mask_stride, id);
459
460 // Use the mv result from the single mode as mv predictor.
461 const FULLPEL_MV start_fullmv = get_fullmv_from_mv(&cur_mv[id].as_mv);
462
463 // Small-range full-pixel motion search.
464 bestsme = av1_refining_search_8p_c(&full_ms_params, start_fullmv,
465 &best_mv.as_fullmv);
466
467 if (bestsme < INT_MAX) {
468 bestsme = av1_get_mvpred_compound_var(
469 &full_ms_params.mv_cost_params, best_mv.as_fullmv, second_pred, mask,
470 mask_stride, id, &cpi->fn_ptr[bsize], &x->plane[0].src,
471 &ref_yv12[id]);
472 }
473
474 // Restore the pointer to the first (possibly scaled) prediction buffer.
475 if (id) xd->plane[plane].pre[0] = ref_yv12[0];
476
477 for (ref = 0; ref < 2; ++ref) {
478 if (scaled_ref_frame[ref]) {
479 // Swap back the original buffers for subpel motion search.
480 for (int i = 0; i < num_planes; i++) {
481 xd->plane[i].pre[ref] = backup_yv12[ref][i];
482 }
483 // Re-initialize based on unscaled prediction buffers.
484 ref_yv12[ref] = xd->plane[plane].pre[ref];
485 }
486 }
487
488 // Do sub-pixel compound motion search on the current reference frame.
489 if (id) xd->plane[plane].pre[0] = ref_yv12[id];
490
491 if (cpi->common.features.cur_frame_force_integer_mv) {
492 convert_fullmv_to_mv(&best_mv);
493 }
494 if (bestsme < INT_MAX &&
495 cpi->common.features.cur_frame_force_integer_mv == 0) {
496 int dis; /* TODO: use dis in distortion calculation later. */
497 unsigned int sse;
498 SUBPEL_MOTION_SEARCH_PARAMS ms_params;
499 av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize,
500 &ref_mv[id].as_mv, NULL);
501 av1_set_ms_compound_refs(&ms_params.var_params.ms_buffers, second_pred,
502 mask, mask_stride, id);
503 ms_params.forced_stop = EIGHTH_PEL;
504 MV start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
505 bestsme = cpi->mv_search_params.find_fractional_mv_step(
506 xd, cm, &ms_params, start_mv, &best_mv.as_mv, &dis, &sse, NULL);
507 }
508
509 // Restore the pointer to the first prediction buffer.
510 if (id) xd->plane[plane].pre[0] = ref_yv12[0];
511 if (bestsme < last_besterr[id]) {
512 cur_mv[id] = best_mv;
513 last_besterr[id] = bestsme;
514 } else {
515 break;
516 }
517 }
518
519 *rate_mv = 0;
520
521 for (ref = 0; ref < 2; ++ref) {
522 const int_mv curr_ref_mv = av1_get_ref_mv(x, ref);
523 *rate_mv +=
524 av1_mv_bit_cost(&cur_mv[ref].as_mv, &curr_ref_mv.as_mv, x->nmv_vec_cost,
525 x->mv_cost_stack, MV_COST_WEIGHT);
526 }
527 }
528
529 // Search for the best mv for one component of a compound,
530 // given that the other component is fixed.
av1_compound_single_motion_search(const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,MV * this_mv,const uint8_t * second_pred,const uint8_t * mask,int mask_stride,int * rate_mv,int ref_idx)531 void av1_compound_single_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
532 BLOCK_SIZE bsize, MV *this_mv,
533 const uint8_t *second_pred,
534 const uint8_t *mask, int mask_stride,
535 int *rate_mv, int ref_idx) {
536 const AV1_COMMON *const cm = &cpi->common;
537 const int num_planes = av1_num_planes(cm);
538 MACROBLOCKD *xd = &x->e_mbd;
539 MB_MODE_INFO *mbmi = xd->mi[0];
540 const int ref = mbmi->ref_frame[ref_idx];
541 const int_mv ref_mv = av1_get_ref_mv(x, ref_idx);
542 struct macroblockd_plane *const pd = &xd->plane[0];
543
544 struct buf_2d backup_yv12[MAX_MB_PLANE];
545 const YV12_BUFFER_CONFIG *const scaled_ref_frame =
546 av1_get_scaled_ref_frame(cpi, ref);
547
548 // Check that this is either an interinter or an interintra block
549 assert(has_second_ref(mbmi) || (ref_idx == 0 && is_interintra_mode(mbmi)));
550
551 // Store the first prediction buffer.
552 struct buf_2d orig_yv12;
553 struct buf_2d ref_yv12 = pd->pre[ref_idx];
554 if (ref_idx) {
555 orig_yv12 = pd->pre[0];
556 pd->pre[0] = pd->pre[ref_idx];
557 }
558
559 if (scaled_ref_frame) {
560 // Swap out the reference frame for a version that's been scaled to
561 // match the resolution of the current frame, allowing the existing
562 // full-pixel motion search code to be used without additional
563 // modifications.
564 for (int i = 0; i < num_planes; i++) {
565 backup_yv12[i] = xd->plane[i].pre[ref_idx];
566 }
567 const int mi_row = xd->mi_row;
568 const int mi_col = xd->mi_col;
569 av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL,
570 num_planes);
571 }
572
573 int bestsme = INT_MAX;
574 int_mv best_mv;
575
576 // Make motion search params
577 FULLPEL_MOTION_SEARCH_PARAMS full_ms_params;
578 av1_make_default_fullpel_ms_params(&full_ms_params, cpi, x, bsize,
579 &ref_mv.as_mv, NULL);
580 av1_set_ms_compound_refs(&full_ms_params.ms_buffers, second_pred, mask,
581 mask_stride, ref_idx);
582
583 // Use the mv result from the single mode as mv predictor.
584 const FULLPEL_MV start_fullmv = get_fullmv_from_mv(this_mv);
585
586 // Small-range full-pixel motion search.
587 bestsme = av1_refining_search_8p_c(&full_ms_params, start_fullmv,
588 &best_mv.as_fullmv);
589
590 if (bestsme < INT_MAX) {
591 bestsme = av1_get_mvpred_compound_var(
592 &full_ms_params.mv_cost_params, best_mv.as_fullmv, second_pred, mask,
593 mask_stride, ref_idx, &cpi->fn_ptr[bsize], &x->plane[0].src, &ref_yv12);
594 }
595
596 if (scaled_ref_frame) {
597 // Swap back the original buffers for subpel motion search.
598 for (int i = 0; i < num_planes; i++) {
599 xd->plane[i].pre[ref_idx] = backup_yv12[i];
600 }
601 }
602
603 if (cpi->common.features.cur_frame_force_integer_mv) {
604 convert_fullmv_to_mv(&best_mv);
605 }
606 const int use_fractional_mv =
607 bestsme < INT_MAX && cpi->common.features.cur_frame_force_integer_mv == 0;
608 if (use_fractional_mv) {
609 int dis; /* TODO: use dis in distortion calculation later. */
610 unsigned int sse;
611 SUBPEL_MOTION_SEARCH_PARAMS ms_params;
612 av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv.as_mv,
613 NULL);
614 av1_set_ms_compound_refs(&ms_params.var_params.ms_buffers, second_pred,
615 mask, mask_stride, ref_idx);
616 ms_params.forced_stop = EIGHTH_PEL;
617 MV start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
618 bestsme = cpi->mv_search_params.find_fractional_mv_step(
619 xd, cm, &ms_params, start_mv, &best_mv.as_mv, &dis, &sse, NULL);
620 }
621
622 // Restore the pointer to the first unscaled prediction buffer.
623 if (ref_idx) pd->pre[0] = orig_yv12;
624
625 if (bestsme < INT_MAX) *this_mv = best_mv.as_mv;
626
627 *rate_mv = 0;
628
629 *rate_mv += av1_mv_bit_cost(this_mv, &ref_mv.as_mv, x->nmv_vec_cost,
630 x->mv_cost_stack, MV_COST_WEIGHT);
631 }
632
build_second_inter_pred(const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,const MV * other_mv,int ref_idx,uint8_t * second_pred)633 static AOM_INLINE void build_second_inter_pred(const AV1_COMP *cpi,
634 MACROBLOCK *x, BLOCK_SIZE bsize,
635 const MV *other_mv, int ref_idx,
636 uint8_t *second_pred) {
637 const AV1_COMMON *const cm = &cpi->common;
638 const int pw = block_size_wide[bsize];
639 const int ph = block_size_high[bsize];
640 MACROBLOCKD *xd = &x->e_mbd;
641 MB_MODE_INFO *mbmi = xd->mi[0];
642 struct macroblockd_plane *const pd = &xd->plane[0];
643 const int mi_row = xd->mi_row;
644 const int mi_col = xd->mi_col;
645 const int p_col = ((mi_col * MI_SIZE) >> pd->subsampling_x);
646 const int p_row = ((mi_row * MI_SIZE) >> pd->subsampling_y);
647
648 // This function should only ever be called for compound modes
649 assert(has_second_ref(mbmi));
650
651 const int plane = 0;
652 struct buf_2d ref_yv12 = xd->plane[plane].pre[!ref_idx];
653
654 struct scale_factors sf;
655 av1_setup_scale_factors_for_frame(&sf, ref_yv12.width, ref_yv12.height,
656 cm->width, cm->height);
657
658 InterPredParams inter_pred_params;
659
660 av1_init_inter_params(&inter_pred_params, pw, ph, p_row, p_col,
661 pd->subsampling_x, pd->subsampling_y, xd->bd,
662 is_cur_buf_hbd(xd), 0, &sf, &ref_yv12,
663 mbmi->interp_filters);
664 inter_pred_params.conv_params = get_conv_params(0, plane, xd->bd);
665
666 // Get the prediction block from the 'other' reference frame.
667 av1_enc_build_one_inter_predictor(second_pred, pw, other_mv,
668 &inter_pred_params);
669
670 av1_dist_wtd_comp_weight_assign(cm, mbmi, 0, &xd->jcp_param.fwd_offset,
671 &xd->jcp_param.bck_offset,
672 &xd->jcp_param.use_dist_wtd_comp_avg, 1);
673 }
674
675 // Wrapper for av1_compound_single_motion_search, for the common case
676 // where the second prediction is also an inter mode.
av1_compound_single_motion_search_interinter(const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,int_mv * cur_mv,const uint8_t * mask,int mask_stride,int * rate_mv,int ref_idx)677 void av1_compound_single_motion_search_interinter(
678 const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int_mv *cur_mv,
679 const uint8_t *mask, int mask_stride, int *rate_mv, int ref_idx) {
680 MACROBLOCKD *xd = &x->e_mbd;
681 // This function should only ever be called for compound modes
682 assert(has_second_ref(xd->mi[0]));
683
684 // Prediction buffer from second frame.
685 DECLARE_ALIGNED(16, uint16_t, second_pred_alloc_16[MAX_SB_SQUARE]);
686 uint8_t *second_pred;
687 if (is_cur_buf_hbd(xd))
688 second_pred = CONVERT_TO_BYTEPTR(second_pred_alloc_16);
689 else
690 second_pred = (uint8_t *)second_pred_alloc_16;
691
692 MV *this_mv = &cur_mv[ref_idx].as_mv;
693 const MV *other_mv = &cur_mv[!ref_idx].as_mv;
694 build_second_inter_pred(cpi, x, bsize, other_mv, ref_idx, second_pred);
695 av1_compound_single_motion_search(cpi, x, bsize, this_mv, second_pred, mask,
696 mask_stride, rate_mv, ref_idx);
697 }
698
do_masked_motion_search_indexed(const AV1_COMP * const cpi,MACROBLOCK * x,const int_mv * const cur_mv,const INTERINTER_COMPOUND_DATA * const comp_data,BLOCK_SIZE bsize,int_mv * tmp_mv,int * rate_mv,int which)699 static AOM_INLINE void do_masked_motion_search_indexed(
700 const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
701 const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE bsize,
702 int_mv *tmp_mv, int *rate_mv, int which) {
703 // NOTE: which values: 0 - 0 only, 1 - 1 only, 2 - both
704 MACROBLOCKD *xd = &x->e_mbd;
705 MB_MODE_INFO *mbmi = xd->mi[0];
706 BLOCK_SIZE sb_type = mbmi->sb_type;
707 const uint8_t *mask;
708 const int mask_stride = block_size_wide[bsize];
709
710 mask = av1_get_compound_type_mask(comp_data, sb_type);
711
712 tmp_mv[0].as_int = cur_mv[0].as_int;
713 tmp_mv[1].as_int = cur_mv[1].as_int;
714 if (which == 0 || which == 1) {
715 av1_compound_single_motion_search_interinter(cpi, x, bsize, tmp_mv, mask,
716 mask_stride, rate_mv, which);
717 } else if (which == 2) {
718 av1_joint_motion_search(cpi, x, bsize, tmp_mv, mask, mask_stride, rate_mv);
719 }
720 }
721
av1_interinter_compound_motion_search(const AV1_COMP * const cpi,MACROBLOCK * x,const int_mv * const cur_mv,const BLOCK_SIZE bsize,const PREDICTION_MODE this_mode)722 int av1_interinter_compound_motion_search(const AV1_COMP *const cpi,
723 MACROBLOCK *x,
724 const int_mv *const cur_mv,
725 const BLOCK_SIZE bsize,
726 const PREDICTION_MODE this_mode) {
727 MACROBLOCKD *const xd = &x->e_mbd;
728 MB_MODE_INFO *const mbmi = xd->mi[0];
729 int_mv tmp_mv[2];
730 int tmp_rate_mv = 0;
731 mbmi->interinter_comp.seg_mask = xd->seg_mask;
732 const INTERINTER_COMPOUND_DATA *compound_data = &mbmi->interinter_comp;
733
734 if (this_mode == NEW_NEWMV) {
735 do_masked_motion_search_indexed(cpi, x, cur_mv, compound_data, bsize,
736 tmp_mv, &tmp_rate_mv, 2);
737 mbmi->mv[0].as_int = tmp_mv[0].as_int;
738 mbmi->mv[1].as_int = tmp_mv[1].as_int;
739 } else if (this_mode >= NEAREST_NEWMV && this_mode <= NEW_NEARMV) {
740 // which = 1 if this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV
741 // which = 0 if this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV
742 int which = (NEWMV == compound_ref1_mode(this_mode));
743 do_masked_motion_search_indexed(cpi, x, cur_mv, compound_data, bsize,
744 tmp_mv, &tmp_rate_mv, which);
745 mbmi->mv[which].as_int = tmp_mv[which].as_int;
746 }
747 return tmp_rate_mv;
748 }
749
av1_simple_motion_search(AV1_COMP * const cpi,MACROBLOCK * x,int mi_row,int mi_col,BLOCK_SIZE bsize,int ref,FULLPEL_MV start_mv,int num_planes,int use_subpixel)750 int_mv av1_simple_motion_search(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
751 int mi_col, BLOCK_SIZE bsize, int ref,
752 FULLPEL_MV start_mv, int num_planes,
753 int use_subpixel) {
754 assert(num_planes == 1 &&
755 "Currently simple_motion_search only supports luma plane");
756 assert(!frame_is_intra_only(&cpi->common) &&
757 "Simple motion search only enabled for non-key frames");
758 AV1_COMMON *const cm = &cpi->common;
759 MACROBLOCKD *xd = &x->e_mbd;
760
761 set_offsets_for_motion_search(cpi, x, mi_row, mi_col, bsize);
762
763 MB_MODE_INFO *mbmi = xd->mi[0];
764 mbmi->sb_type = bsize;
765 mbmi->ref_frame[0] = ref;
766 mbmi->ref_frame[1] = NONE_FRAME;
767 mbmi->motion_mode = SIMPLE_TRANSLATION;
768 mbmi->interp_filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
769
770 const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_yv12_buf(cm, ref);
771 const YV12_BUFFER_CONFIG *scaled_ref_frame =
772 av1_get_scaled_ref_frame(cpi, ref);
773 struct buf_2d backup_yv12;
774 // ref_mv is used to calculate the cost of the motion vector
775 const MV ref_mv = kZeroMv;
776 const int step_param = cpi->mv_search_params.mv_step_param;
777 const search_site_config *src_search_sites =
778 &cpi->mv_search_params.ss_cfg[SS_CFG_SRC];
779 int cost_list[5];
780 const int ref_idx = 0;
781 int var;
782 int_mv best_mv;
783
784 av1_setup_pre_planes(xd, ref_idx, yv12, mi_row, mi_col,
785 get_ref_scale_factors(cm, ref), num_planes);
786 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
787 if (scaled_ref_frame) {
788 backup_yv12 = xd->plane[AOM_PLANE_Y].pre[ref_idx];
789 av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL,
790 num_planes);
791 }
792
793 FULLPEL_MOTION_SEARCH_PARAMS full_ms_params;
794 av1_make_default_fullpel_ms_params(&full_ms_params, cpi, x, bsize, &ref_mv,
795 src_search_sites);
796
797 var = av1_full_pixel_search(start_mv, &full_ms_params, step_param,
798 cond_cost_list(cpi, cost_list),
799 &best_mv.as_fullmv, NULL);
800
801 const int use_subpel_search =
802 var < INT_MAX && !cpi->common.features.cur_frame_force_integer_mv &&
803 use_subpixel;
804 if (scaled_ref_frame) {
805 xd->plane[AOM_PLANE_Y].pre[ref_idx] = backup_yv12;
806 }
807 if (use_subpel_search) {
808 int not_used = 0;
809
810 SUBPEL_MOTION_SEARCH_PARAMS ms_params;
811 av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
812 cost_list);
813 // TODO(yunqing): integrate this into av1_make_default_subpel_ms_params().
814 ms_params.forced_stop = cpi->sf.mv_sf.simple_motion_subpel_force_stop;
815
816 MV subpel_start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
817
818 cpi->mv_search_params.find_fractional_mv_step(
819 xd, cm, &ms_params, subpel_start_mv, &best_mv.as_mv, ¬_used,
820 &x->pred_sse[ref], NULL);
821 } else {
822 // Manually convert from units of pixel to 1/8-pixels if we are not doing
823 // subpel search
824 convert_fullmv_to_mv(&best_mv);
825 }
826
827 mbmi->mv[0] = best_mv;
828
829 // Get a copy of the prediction output
830 av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
831 AOM_PLANE_Y, AOM_PLANE_Y);
832
833 aom_clear_system_state();
834
835 if (scaled_ref_frame) {
836 xd->plane[AOM_PLANE_Y].pre[ref_idx] = backup_yv12;
837 }
838
839 return best_mv;
840 }
841
av1_simple_motion_sse_var(AV1_COMP * cpi,MACROBLOCK * x,int mi_row,int mi_col,BLOCK_SIZE bsize,const FULLPEL_MV start_mv,int use_subpixel,unsigned int * sse,unsigned int * var)842 int_mv av1_simple_motion_sse_var(AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
843 int mi_col, BLOCK_SIZE bsize,
844 const FULLPEL_MV start_mv, int use_subpixel,
845 unsigned int *sse, unsigned int *var) {
846 MACROBLOCKD *xd = &x->e_mbd;
847 const MV_REFERENCE_FRAME ref =
848 cpi->rc.is_src_frame_alt_ref ? ALTREF_FRAME : LAST_FRAME;
849
850 int_mv best_mv = av1_simple_motion_search(cpi, x, mi_row, mi_col, bsize, ref,
851 start_mv, 1, use_subpixel);
852
853 const uint8_t *src = x->plane[0].src.buf;
854 const int src_stride = x->plane[0].src.stride;
855 const uint8_t *dst = xd->plane[0].dst.buf;
856 const int dst_stride = xd->plane[0].dst.stride;
857
858 *var = cpi->fn_ptr[bsize].vf(src, src_stride, dst, dst_stride, sse);
859
860 return best_mv;
861 }
862