• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &not_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