Home | History | Annotate | Download | only in common
      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 <stdlib.h>
     13 
     14 #include "av1/common/mvref_common.h"
     15 #include "av1/common/warped_motion.h"
     16 
     17 // Although we assign 32 bit integers, all the values are strictly under 14
     18 // bits.
     19 static int div_mult[32] = { 0,    16384, 8192, 5461, 4096, 3276, 2730, 2340,
     20                             2048, 1820,  1638, 1489, 1365, 1260, 1170, 1092,
     21                             1024, 963,   910,  862,  819,  780,  744,  712,
     22                             682,  655,   630,  606,  585,  564,  546,  528 };
     23 
     24 // TODO(jingning): Consider the use of lookup table for (num / den)
     25 // altogether.
     26 static void get_mv_projection(MV *output, MV ref, int num, int den) {
     27   den = AOMMIN(den, MAX_FRAME_DISTANCE);
     28   num = num > 0 ? AOMMIN(num, MAX_FRAME_DISTANCE)
     29                 : AOMMAX(num, -MAX_FRAME_DISTANCE);
     30   const int mv_row =
     31       ROUND_POWER_OF_TWO_SIGNED(ref.row * num * div_mult[den], 14);
     32   const int mv_col =
     33       ROUND_POWER_OF_TWO_SIGNED(ref.col * num * div_mult[den], 14);
     34   const int clamp_max = MV_UPP - 1;
     35   const int clamp_min = MV_LOW + 1;
     36   output->row = (int16_t)clamp(mv_row, clamp_min, clamp_max);
     37   output->col = (int16_t)clamp(mv_col, clamp_min, clamp_max);
     38 }
     39 
     40 void av1_copy_frame_mvs(const AV1_COMMON *const cm,
     41                         const MB_MODE_INFO *const mi, int mi_row, int mi_col,
     42                         int x_mis, int y_mis) {
     43   const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
     44   MV_REF *frame_mvs =
     45       cm->cur_frame->mvs + (mi_row >> 1) * frame_mvs_stride + (mi_col >> 1);
     46   x_mis = ROUND_POWER_OF_TWO(x_mis, 1);
     47   y_mis = ROUND_POWER_OF_TWO(y_mis, 1);
     48   int w, h;
     49 
     50   for (h = 0; h < y_mis; h++) {
     51     MV_REF *mv = frame_mvs;
     52     for (w = 0; w < x_mis; w++) {
     53       mv->ref_frame = NONE_FRAME;
     54       mv->mv.as_int = 0;
     55 
     56       for (int idx = 0; idx < 2; ++idx) {
     57         MV_REFERENCE_FRAME ref_frame = mi->ref_frame[idx];
     58         if (ref_frame > INTRA_FRAME) {
     59           int8_t ref_idx = cm->ref_frame_side[ref_frame];
     60           if (ref_idx) continue;
     61           if ((abs(mi->mv[idx].as_mv.row) > REFMVS_LIMIT) ||
     62               (abs(mi->mv[idx].as_mv.col) > REFMVS_LIMIT))
     63             continue;
     64           mv->ref_frame = ref_frame;
     65           mv->mv.as_int = mi->mv[idx].as_int;
     66         }
     67       }
     68       mv++;
     69     }
     70     frame_mvs += frame_mvs_stride;
     71   }
     72 }
     73 
     74 static void add_ref_mv_candidate(
     75     const MB_MODE_INFO *const candidate, const MV_REFERENCE_FRAME rf[2],
     76     uint8_t *refmv_count, uint8_t *ref_match_count, uint8_t *newmv_count,
     77     CANDIDATE_MV *ref_mv_stack, int_mv *gm_mv_candidates,
     78     const WarpedMotionParams *gm_params, int col, int weight) {
     79   if (!is_inter_block(candidate)) return;  // for intrabc
     80   int index = 0, ref;
     81   assert(weight % 2 == 0);
     82 
     83   if (rf[1] == NONE_FRAME) {
     84     // single reference frame
     85     for (ref = 0; ref < 2; ++ref) {
     86       if (candidate->ref_frame[ref] == rf[0]) {
     87         int_mv this_refmv;
     88         if (is_global_mv_block(candidate, gm_params[rf[0]].wmtype))
     89           this_refmv = gm_mv_candidates[0];
     90         else
     91           this_refmv = get_sub_block_mv(candidate, ref, col);
     92 
     93         for (index = 0; index < *refmv_count; ++index)
     94           if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
     95 
     96         if (index < *refmv_count) ref_mv_stack[index].weight += weight;
     97 
     98         // Add a new item to the list.
     99         if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
    100           ref_mv_stack[index].this_mv = this_refmv;
    101           ref_mv_stack[index].weight = weight;
    102           ++(*refmv_count);
    103         }
    104         if (have_newmv_in_inter_mode(candidate->mode)) ++*newmv_count;
    105         ++*ref_match_count;
    106       }
    107     }
    108   } else {
    109     // compound reference frame
    110     if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
    111       int_mv this_refmv[2];
    112 
    113       for (ref = 0; ref < 2; ++ref) {
    114         if (is_global_mv_block(candidate, gm_params[rf[ref]].wmtype))
    115           this_refmv[ref] = gm_mv_candidates[ref];
    116         else
    117           this_refmv[ref] = get_sub_block_mv(candidate, ref, col);
    118       }
    119 
    120       for (index = 0; index < *refmv_count; ++index)
    121         if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
    122             (ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
    123           break;
    124 
    125       if (index < *refmv_count) ref_mv_stack[index].weight += weight;
    126 
    127       // Add a new item to the list.
    128       if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
    129         ref_mv_stack[index].this_mv = this_refmv[0];
    130         ref_mv_stack[index].comp_mv = this_refmv[1];
    131         ref_mv_stack[index].weight = weight;
    132         ++(*refmv_count);
    133       }
    134       if (have_newmv_in_inter_mode(candidate->mode)) ++*newmv_count;
    135       ++*ref_match_count;
    136     }
    137   }
    138 }
    139 
    140 static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
    141                           int mi_row, int mi_col,
    142                           const MV_REFERENCE_FRAME rf[2], int row_offset,
    143                           CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
    144                           uint8_t *ref_match_count, uint8_t *newmv_count,
    145                           int_mv *gm_mv_candidates, int max_row_offset,
    146                           int *processed_rows) {
    147   int end_mi = AOMMIN(xd->n4_w, cm->mi_cols - mi_col);
    148   end_mi = AOMMIN(end_mi, mi_size_wide[BLOCK_64X64]);
    149   const int n8_w_8 = mi_size_wide[BLOCK_8X8];
    150   const int n8_w_16 = mi_size_wide[BLOCK_16X16];
    151   int i;
    152   int col_offset = 0;
    153   // TODO(jingning): Revisit this part after cb4x4 is stable.
    154   if (abs(row_offset) > 1) {
    155     col_offset = 1;
    156     if ((mi_col & 0x01) && xd->n4_w < n8_w_8) --col_offset;
    157   }
    158   const int use_step_16 = (xd->n4_w >= 16);
    159   MB_MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
    160   (void)mi_row;
    161 
    162   for (i = 0; i < end_mi;) {
    163     const MB_MODE_INFO *const candidate = candidate_mi0[col_offset + i];
    164     const int candidate_bsize = candidate->sb_type;
    165     const int n4_w = mi_size_wide[candidate_bsize];
    166     int len = AOMMIN(xd->n4_w, n4_w);
    167     if (use_step_16)
    168       len = AOMMAX(n8_w_16, len);
    169     else if (abs(row_offset) > 1)
    170       len = AOMMAX(len, n8_w_8);
    171 
    172     int weight = 2;
    173     if (xd->n4_w >= n8_w_8 && xd->n4_w <= n4_w) {
    174       int inc = AOMMIN(-max_row_offset + row_offset + 1,
    175                        mi_size_high[candidate_bsize]);
    176       // Obtain range used in weight calculation.
    177       weight = AOMMAX(weight, inc);
    178       // Update processed rows.
    179       *processed_rows = inc - row_offset - 1;
    180     }
    181 
    182     add_ref_mv_candidate(candidate, rf, refmv_count, ref_match_count,
    183                          newmv_count, ref_mv_stack, gm_mv_candidates,
    184                          cm->global_motion, col_offset + i, len * weight);
    185 
    186     i += len;
    187   }
    188 }
    189 
    190 static void scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
    191                           int mi_row, int mi_col,
    192                           const MV_REFERENCE_FRAME rf[2], int col_offset,
    193                           CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
    194                           uint8_t *ref_match_count, uint8_t *newmv_count,
    195                           int_mv *gm_mv_candidates, int max_col_offset,
    196                           int *processed_cols) {
    197   int end_mi = AOMMIN(xd->n4_h, cm->mi_rows - mi_row);
    198   end_mi = AOMMIN(end_mi, mi_size_high[BLOCK_64X64]);
    199   const int n8_h_8 = mi_size_high[BLOCK_8X8];
    200   const int n8_h_16 = mi_size_high[BLOCK_16X16];
    201   int i;
    202   int row_offset = 0;
    203   if (abs(col_offset) > 1) {
    204     row_offset = 1;
    205     if ((mi_row & 0x01) && xd->n4_h < n8_h_8) --row_offset;
    206   }
    207   const int use_step_16 = (xd->n4_h >= 16);
    208   (void)mi_col;
    209 
    210   for (i = 0; i < end_mi;) {
    211     const MB_MODE_INFO *const candidate =
    212         xd->mi[(row_offset + i) * xd->mi_stride + col_offset];
    213     const int candidate_bsize = candidate->sb_type;
    214     const int n4_h = mi_size_high[candidate_bsize];
    215     int len = AOMMIN(xd->n4_h, n4_h);
    216     if (use_step_16)
    217       len = AOMMAX(n8_h_16, len);
    218     else if (abs(col_offset) > 1)
    219       len = AOMMAX(len, n8_h_8);
    220 
    221     int weight = 2;
    222     if (xd->n4_h >= n8_h_8 && xd->n4_h <= n4_h) {
    223       int inc = AOMMIN(-max_col_offset + col_offset + 1,
    224                        mi_size_wide[candidate_bsize]);
    225       // Obtain range used in weight calculation.
    226       weight = AOMMAX(weight, inc);
    227       // Update processed cols.
    228       *processed_cols = inc - col_offset - 1;
    229     }
    230 
    231     add_ref_mv_candidate(candidate, rf, refmv_count, ref_match_count,
    232                          newmv_count, ref_mv_stack, gm_mv_candidates,
    233                          cm->global_motion, col_offset, len * weight);
    234 
    235     i += len;
    236   }
    237 }
    238 
    239 static void scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
    240                           const int mi_row, const int mi_col,
    241                           const MV_REFERENCE_FRAME rf[2], int row_offset,
    242                           int col_offset, CANDIDATE_MV *ref_mv_stack,
    243                           uint8_t *ref_match_count, uint8_t *newmv_count,
    244                           int_mv *gm_mv_candidates,
    245                           uint8_t refmv_count[MODE_CTX_REF_FRAMES]) {
    246   const TileInfo *const tile = &xd->tile;
    247   POSITION mi_pos;
    248 
    249   mi_pos.row = row_offset;
    250   mi_pos.col = col_offset;
    251 
    252   if (is_inside(tile, mi_col, mi_row, &mi_pos)) {
    253     const MB_MODE_INFO *const candidate =
    254         xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
    255     const int len = mi_size_wide[BLOCK_8X8];
    256 
    257     add_ref_mv_candidate(candidate, rf, refmv_count, ref_match_count,
    258                          newmv_count, ref_mv_stack, gm_mv_candidates,
    259                          cm->global_motion, mi_pos.col, 2 * len);
    260   }  // Analyze a single 8x8 block motion information.
    261 }
    262 
    263 static int has_top_right(const AV1_COMMON *cm, const MACROBLOCKD *xd,
    264                          int mi_row, int mi_col, int bs) {
    265   const int sb_mi_size = mi_size_wide[cm->seq_params.sb_size];
    266   const int mask_row = mi_row & (sb_mi_size - 1);
    267   const int mask_col = mi_col & (sb_mi_size - 1);
    268 
    269   if (bs > mi_size_wide[BLOCK_64X64]) return 0;
    270 
    271   // In a split partition all apart from the bottom right has a top right
    272   int has_tr = !((mask_row & bs) && (mask_col & bs));
    273 
    274   // bs > 0 and bs is a power of 2
    275   assert(bs > 0 && !(bs & (bs - 1)));
    276 
    277   // For each 4x4 group of blocks, when the bottom right is decoded the blocks
    278   // to the right have not been decoded therefore the bottom right does
    279   // not have a top right
    280   while (bs < sb_mi_size) {
    281     if (mask_col & bs) {
    282       if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
    283         has_tr = 0;
    284         break;
    285       }
    286     } else {
    287       break;
    288     }
    289     bs <<= 1;
    290   }
    291 
    292   // The left hand of two vertical rectangles always has a top right (as the
    293   // block above will have been decoded)
    294   if (xd->n4_w < xd->n4_h)
    295     if (!xd->is_sec_rect) has_tr = 1;
    296 
    297   // The bottom of two horizontal rectangles never has a top right (as the block
    298   // to the right won't have been decoded)
    299   if (xd->n4_w > xd->n4_h)
    300     if (xd->is_sec_rect) has_tr = 0;
    301 
    302   // The bottom left square of a Vertical A (in the old format) does
    303   // not have a top right as it is decoded before the right hand
    304   // rectangle of the partition
    305   if (xd->mi[0]->partition == PARTITION_VERT_A) {
    306     if (xd->n4_w == xd->n4_h)
    307       if (mask_row & bs) has_tr = 0;
    308   }
    309 
    310   return has_tr;
    311 }
    312 
    313 static int check_sb_border(const int mi_row, const int mi_col,
    314                            const int row_offset, const int col_offset) {
    315   const int sb_mi_size = mi_size_wide[BLOCK_64X64];
    316   const int row = mi_row & (sb_mi_size - 1);
    317   const int col = mi_col & (sb_mi_size - 1);
    318 
    319   if (row + row_offset < 0 || row + row_offset >= sb_mi_size ||
    320       col + col_offset < 0 || col + col_offset >= sb_mi_size)
    321     return 0;
    322 
    323   return 1;
    324 }
    325 
    326 static int add_tpl_ref_mv(const AV1_COMMON *cm, const MACROBLOCKD *xd,
    327                           int mi_row, int mi_col, MV_REFERENCE_FRAME ref_frame,
    328                           int blk_row, int blk_col, int_mv *gm_mv_candidates,
    329                           uint8_t refmv_count[MODE_CTX_REF_FRAMES],
    330                           CANDIDATE_MV ref_mv_stacks[][MAX_REF_MV_STACK_SIZE],
    331                           int16_t *mode_context) {
    332   POSITION mi_pos;
    333   int idx;
    334   const int weight_unit = 1;  // mi_size_wide[BLOCK_8X8];
    335 
    336   mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
    337   mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
    338 
    339   if (!is_inside(&xd->tile, mi_col, mi_row, &mi_pos)) return 0;
    340 
    341   const TPL_MV_REF *prev_frame_mvs =
    342       cm->tpl_mvs + ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
    343       ((mi_col + mi_pos.col) >> 1);
    344 
    345   MV_REFERENCE_FRAME rf[2];
    346   av1_set_ref_frame(rf, ref_frame);
    347 
    348   if (rf[1] == NONE_FRAME) {
    349     int cur_frame_index = cm->cur_frame->order_hint;
    350     const RefCntBuffer *const buf_0 = get_ref_frame_buf(cm, rf[0]);
    351     int frame0_index = buf_0->order_hint;
    352     int cur_offset_0 = get_relative_dist(&cm->seq_params.order_hint_info,
    353                                          cur_frame_index, frame0_index);
    354     CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[rf[0]];
    355 
    356     if (prev_frame_mvs->mfmv0.as_int != INVALID_MV) {
    357       int_mv this_refmv;
    358 
    359       get_mv_projection(&this_refmv.as_mv, prev_frame_mvs->mfmv0.as_mv,
    360                         cur_offset_0, prev_frame_mvs->ref_frame_offset);
    361       lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
    362                          cm->cur_frame_force_integer_mv);
    363 
    364       if (blk_row == 0 && blk_col == 0)
    365         if (abs(this_refmv.as_mv.row - gm_mv_candidates[0].as_mv.row) >= 16 ||
    366             abs(this_refmv.as_mv.col - gm_mv_candidates[0].as_mv.col) >= 16)
    367           mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
    368 
    369       for (idx = 0; idx < refmv_count[rf[0]]; ++idx)
    370         if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
    371 
    372       if (idx < refmv_count[rf[0]]) ref_mv_stack[idx].weight += 2 * weight_unit;
    373 
    374       if (idx == refmv_count[rf[0]] &&
    375           refmv_count[rf[0]] < MAX_REF_MV_STACK_SIZE) {
    376         ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
    377         ref_mv_stack[idx].weight = 2 * weight_unit;
    378         ++(refmv_count[rf[0]]);
    379       }
    380       return 1;
    381     }
    382   } else {
    383     // Process compound inter mode
    384     int cur_frame_index = cm->cur_frame->order_hint;
    385     const RefCntBuffer *const buf_0 = get_ref_frame_buf(cm, rf[0]);
    386     int frame0_index = buf_0->order_hint;
    387 
    388     int cur_offset_0 = get_relative_dist(&cm->seq_params.order_hint_info,
    389                                          cur_frame_index, frame0_index);
    390     const RefCntBuffer *const buf_1 = get_ref_frame_buf(cm, rf[1]);
    391     int frame1_index = buf_1->order_hint;
    392     int cur_offset_1 = get_relative_dist(&cm->seq_params.order_hint_info,
    393                                          cur_frame_index, frame1_index);
    394     CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[ref_frame];
    395 
    396     if (prev_frame_mvs->mfmv0.as_int != INVALID_MV) {
    397       int_mv this_refmv;
    398       int_mv comp_refmv;
    399       get_mv_projection(&this_refmv.as_mv, prev_frame_mvs->mfmv0.as_mv,
    400                         cur_offset_0, prev_frame_mvs->ref_frame_offset);
    401       get_mv_projection(&comp_refmv.as_mv, prev_frame_mvs->mfmv0.as_mv,
    402                         cur_offset_1, prev_frame_mvs->ref_frame_offset);
    403 
    404       lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
    405                          cm->cur_frame_force_integer_mv);
    406       lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv,
    407                          cm->cur_frame_force_integer_mv);
    408 
    409       if (blk_row == 0 && blk_col == 0)
    410         if (abs(this_refmv.as_mv.row - gm_mv_candidates[0].as_mv.row) >= 16 ||
    411             abs(this_refmv.as_mv.col - gm_mv_candidates[0].as_mv.col) >= 16 ||
    412             abs(comp_refmv.as_mv.row - gm_mv_candidates[1].as_mv.row) >= 16 ||
    413             abs(comp_refmv.as_mv.col - gm_mv_candidates[1].as_mv.col) >= 16)
    414           mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
    415 
    416       for (idx = 0; idx < refmv_count[ref_frame]; ++idx)
    417         if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int &&
    418             comp_refmv.as_int == ref_mv_stack[idx].comp_mv.as_int)
    419           break;
    420 
    421       if (idx < refmv_count[ref_frame])
    422         ref_mv_stack[idx].weight += 2 * weight_unit;
    423 
    424       if (idx == refmv_count[ref_frame] &&
    425           refmv_count[ref_frame] < MAX_REF_MV_STACK_SIZE) {
    426         ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
    427         ref_mv_stack[idx].comp_mv.as_int = comp_refmv.as_int;
    428         ref_mv_stack[idx].weight = 2 * weight_unit;
    429         ++(refmv_count[ref_frame]);
    430       }
    431       return 1;
    432     }
    433   }
    434   return 0;
    435 }
    436 
    437 static void process_compound_ref_mv_candidate(
    438     const MB_MODE_INFO *const candidate, const AV1_COMMON *const cm,
    439     const MV_REFERENCE_FRAME *const rf, int_mv ref_id[2][2],
    440     int ref_id_count[2], int_mv ref_diff[2][2], int ref_diff_count[2]) {
    441   for (int rf_idx = 0; rf_idx < 2; ++rf_idx) {
    442     MV_REFERENCE_FRAME can_rf = candidate->ref_frame[rf_idx];
    443 
    444     for (int cmp_idx = 0; cmp_idx < 2; ++cmp_idx) {
    445       if (can_rf == rf[cmp_idx] && ref_id_count[cmp_idx] < 2) {
    446         ref_id[cmp_idx][ref_id_count[cmp_idx]] = candidate->mv[rf_idx];
    447         ++ref_id_count[cmp_idx];
    448       } else if (can_rf > INTRA_FRAME && ref_diff_count[cmp_idx] < 2) {
    449         int_mv this_mv = candidate->mv[rf_idx];
    450         if (cm->ref_frame_sign_bias[can_rf] !=
    451             cm->ref_frame_sign_bias[rf[cmp_idx]]) {
    452           this_mv.as_mv.row = -this_mv.as_mv.row;
    453           this_mv.as_mv.col = -this_mv.as_mv.col;
    454         }
    455         ref_diff[cmp_idx][ref_diff_count[cmp_idx]] = this_mv;
    456         ++ref_diff_count[cmp_idx];
    457       }
    458     }
    459   }
    460 }
    461 
    462 static void process_single_ref_mv_candidate(
    463     const MB_MODE_INFO *const candidate, const AV1_COMMON *const cm,
    464     MV_REFERENCE_FRAME ref_frame, uint8_t refmv_count[MODE_CTX_REF_FRAMES],
    465     CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE]) {
    466   for (int rf_idx = 0; rf_idx < 2; ++rf_idx) {
    467     if (candidate->ref_frame[rf_idx] > INTRA_FRAME) {
    468       int_mv this_mv = candidate->mv[rf_idx];
    469       if (cm->ref_frame_sign_bias[candidate->ref_frame[rf_idx]] !=
    470           cm->ref_frame_sign_bias[ref_frame]) {
    471         this_mv.as_mv.row = -this_mv.as_mv.row;
    472         this_mv.as_mv.col = -this_mv.as_mv.col;
    473       }
    474       int stack_idx;
    475       for (stack_idx = 0; stack_idx < refmv_count[ref_frame]; ++stack_idx) {
    476         const int_mv stack_mv = ref_mv_stack[ref_frame][stack_idx].this_mv;
    477         if (this_mv.as_int == stack_mv.as_int) break;
    478       }
    479 
    480       if (stack_idx == refmv_count[ref_frame]) {
    481         ref_mv_stack[ref_frame][stack_idx].this_mv = this_mv;
    482 
    483         // TODO(jingning): Set an arbitrary small number here. The weight
    484         // doesn't matter as long as it is properly initialized.
    485         ref_mv_stack[ref_frame][stack_idx].weight = 2;
    486         ++refmv_count[ref_frame];
    487       }
    488     }
    489   }
    490 }
    491 
    492 static void setup_ref_mv_list(
    493     const AV1_COMMON *cm, const MACROBLOCKD *xd, MV_REFERENCE_FRAME ref_frame,
    494     uint8_t refmv_count[MODE_CTX_REF_FRAMES],
    495     CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
    496     int_mv mv_ref_list[][MAX_MV_REF_CANDIDATES], int_mv *gm_mv_candidates,
    497     int mi_row, int mi_col, int16_t *mode_context) {
    498   const int bs = AOMMAX(xd->n4_w, xd->n4_h);
    499   const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
    500   MV_REFERENCE_FRAME rf[2];
    501 
    502   const TileInfo *const tile = &xd->tile;
    503   int max_row_offset = 0, max_col_offset = 0;
    504   const int row_adj = (xd->n4_h < mi_size_high[BLOCK_8X8]) && (mi_row & 0x01);
    505   const int col_adj = (xd->n4_w < mi_size_wide[BLOCK_8X8]) && (mi_col & 0x01);
    506   int processed_rows = 0;
    507   int processed_cols = 0;
    508 
    509   av1_set_ref_frame(rf, ref_frame);
    510   mode_context[ref_frame] = 0;
    511   refmv_count[ref_frame] = 0;
    512 
    513   // Find valid maximum row/col offset.
    514   if (xd->up_available) {
    515     max_row_offset = -(MVREF_ROW_COLS << 1) + row_adj;
    516 
    517     if (xd->n4_h < mi_size_high[BLOCK_8X8])
    518       max_row_offset = -(2 << 1) + row_adj;
    519 
    520     max_row_offset = find_valid_row_offset(tile, mi_row, max_row_offset);
    521   }
    522 
    523   if (xd->left_available) {
    524     max_col_offset = -(MVREF_ROW_COLS << 1) + col_adj;
    525 
    526     if (xd->n4_w < mi_size_wide[BLOCK_8X8])
    527       max_col_offset = -(2 << 1) + col_adj;
    528 
    529     max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
    530   }
    531 
    532   uint8_t col_match_count = 0;
    533   uint8_t row_match_count = 0;
    534   uint8_t newmv_count = 0;
    535 
    536   // Scan the first above row mode info. row_offset = -1;
    537   if (abs(max_row_offset) >= 1)
    538     scan_row_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack[ref_frame],
    539                   &refmv_count[ref_frame], &row_match_count, &newmv_count,
    540                   gm_mv_candidates, max_row_offset, &processed_rows);
    541   // Scan the first left column mode info. col_offset = -1;
    542   if (abs(max_col_offset) >= 1)
    543     scan_col_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack[ref_frame],
    544                   &refmv_count[ref_frame], &col_match_count, &newmv_count,
    545                   gm_mv_candidates, max_col_offset, &processed_cols);
    546   // Check top-right boundary
    547   if (has_tr)
    548     scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, xd->n4_w,
    549                   ref_mv_stack[ref_frame], &row_match_count, &newmv_count,
    550                   gm_mv_candidates, &refmv_count[ref_frame]);
    551 
    552   const uint8_t nearest_match = (row_match_count > 0) + (col_match_count > 0);
    553   const uint8_t nearest_refmv_count = refmv_count[ref_frame];
    554 
    555   // TODO(yunqing): for comp_search, do it for all 3 cases.
    556   for (int idx = 0; idx < nearest_refmv_count; ++idx)
    557     ref_mv_stack[ref_frame][idx].weight += REF_CAT_LEVEL;
    558 
    559   if (cm->allow_ref_frame_mvs) {
    560     int is_available = 0;
    561     const int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n4_h);
    562     const int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n4_w);
    563     const int blk_row_end = AOMMIN(xd->n4_h, mi_size_high[BLOCK_64X64]);
    564     const int blk_col_end = AOMMIN(xd->n4_w, mi_size_wide[BLOCK_64X64]);
    565 
    566     const int tpl_sample_pos[3][2] = {
    567       { voffset, -2 },
    568       { voffset, hoffset },
    569       { voffset - 2, hoffset },
    570     };
    571     const int allow_extension = (xd->n4_h >= mi_size_high[BLOCK_8X8]) &&
    572                                 (xd->n4_h < mi_size_high[BLOCK_64X64]) &&
    573                                 (xd->n4_w >= mi_size_wide[BLOCK_8X8]) &&
    574                                 (xd->n4_w < mi_size_wide[BLOCK_64X64]);
    575 
    576     const int step_h = (xd->n4_h >= mi_size_high[BLOCK_64X64])
    577                            ? mi_size_high[BLOCK_16X16]
    578                            : mi_size_high[BLOCK_8X8];
    579     const int step_w = (xd->n4_w >= mi_size_wide[BLOCK_64X64])
    580                            ? mi_size_wide[BLOCK_16X16]
    581                            : mi_size_wide[BLOCK_8X8];
    582 
    583     for (int blk_row = 0; blk_row < blk_row_end; blk_row += step_h) {
    584       for (int blk_col = 0; blk_col < blk_col_end; blk_col += step_w) {
    585         int ret = add_tpl_ref_mv(cm, xd, mi_row, mi_col, ref_frame, blk_row,
    586                                  blk_col, gm_mv_candidates, refmv_count,
    587                                  ref_mv_stack, mode_context);
    588         if (blk_row == 0 && blk_col == 0) is_available = ret;
    589       }
    590     }
    591 
    592     if (is_available == 0) mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
    593 
    594     for (int i = 0; i < 3 && allow_extension; ++i) {
    595       const int blk_row = tpl_sample_pos[i][0];
    596       const int blk_col = tpl_sample_pos[i][1];
    597 
    598       if (!check_sb_border(mi_row, mi_col, blk_row, blk_col)) continue;
    599       add_tpl_ref_mv(cm, xd, mi_row, mi_col, ref_frame, blk_row, blk_col,
    600                      gm_mv_candidates, refmv_count, ref_mv_stack, mode_context);
    601     }
    602   }
    603 
    604   uint8_t dummy_newmv_count = 0;
    605 
    606   // Scan the second outer area.
    607   scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, -1, ref_mv_stack[ref_frame],
    608                 &row_match_count, &dummy_newmv_count, gm_mv_candidates,
    609                 &refmv_count[ref_frame]);
    610 
    611   for (int idx = 2; idx <= MVREF_ROW_COLS; ++idx) {
    612     const int row_offset = -(idx << 1) + 1 + row_adj;
    613     const int col_offset = -(idx << 1) + 1 + col_adj;
    614 
    615     if (abs(row_offset) <= abs(max_row_offset) &&
    616         abs(row_offset) > processed_rows)
    617       scan_row_mbmi(cm, xd, mi_row, mi_col, rf, row_offset,
    618                     ref_mv_stack[ref_frame], &refmv_count[ref_frame],
    619                     &row_match_count, &dummy_newmv_count, gm_mv_candidates,
    620                     max_row_offset, &processed_rows);
    621 
    622     if (abs(col_offset) <= abs(max_col_offset) &&
    623         abs(col_offset) > processed_cols)
    624       scan_col_mbmi(cm, xd, mi_row, mi_col, rf, col_offset,
    625                     ref_mv_stack[ref_frame], &refmv_count[ref_frame],
    626                     &col_match_count, &dummy_newmv_count, gm_mv_candidates,
    627                     max_col_offset, &processed_cols);
    628   }
    629 
    630   const uint8_t ref_match_count = (row_match_count > 0) + (col_match_count > 0);
    631 
    632   switch (nearest_match) {
    633     case 0:
    634       mode_context[ref_frame] |= 0;
    635       if (ref_match_count >= 1) mode_context[ref_frame] |= 1;
    636       if (ref_match_count == 1)
    637         mode_context[ref_frame] |= (1 << REFMV_OFFSET);
    638       else if (ref_match_count >= 2)
    639         mode_context[ref_frame] |= (2 << REFMV_OFFSET);
    640       break;
    641     case 1:
    642       mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
    643       if (ref_match_count == 1)
    644         mode_context[ref_frame] |= (3 << REFMV_OFFSET);
    645       else if (ref_match_count >= 2)
    646         mode_context[ref_frame] |= (4 << REFMV_OFFSET);
    647       break;
    648     case 2:
    649     default:
    650       if (newmv_count >= 1)
    651         mode_context[ref_frame] |= 4;
    652       else
    653         mode_context[ref_frame] |= 5;
    654 
    655       mode_context[ref_frame] |= (5 << REFMV_OFFSET);
    656       break;
    657   }
    658 
    659   // Rank the likelihood and assign nearest and near mvs.
    660   int len = nearest_refmv_count;
    661   while (len > 0) {
    662     int nr_len = 0;
    663     for (int idx = 1; idx < len; ++idx) {
    664       if (ref_mv_stack[ref_frame][idx - 1].weight <
    665           ref_mv_stack[ref_frame][idx].weight) {
    666         CANDIDATE_MV tmp_mv = ref_mv_stack[ref_frame][idx - 1];
    667         ref_mv_stack[ref_frame][idx - 1] = ref_mv_stack[ref_frame][idx];
    668         ref_mv_stack[ref_frame][idx] = tmp_mv;
    669         nr_len = idx;
    670       }
    671     }
    672     len = nr_len;
    673   }
    674 
    675   len = refmv_count[ref_frame];
    676   while (len > nearest_refmv_count) {
    677     int nr_len = nearest_refmv_count;
    678     for (int idx = nearest_refmv_count + 1; idx < len; ++idx) {
    679       if (ref_mv_stack[ref_frame][idx - 1].weight <
    680           ref_mv_stack[ref_frame][idx].weight) {
    681         CANDIDATE_MV tmp_mv = ref_mv_stack[ref_frame][idx - 1];
    682         ref_mv_stack[ref_frame][idx - 1] = ref_mv_stack[ref_frame][idx];
    683         ref_mv_stack[ref_frame][idx] = tmp_mv;
    684         nr_len = idx;
    685       }
    686     }
    687     len = nr_len;
    688   }
    689 
    690   if (rf[1] > NONE_FRAME) {
    691     // TODO(jingning, yunqing): Refactor and consolidate the compound and
    692     // single reference frame modes. Reduce unnecessary redundancy.
    693     if (refmv_count[ref_frame] < MAX_MV_REF_CANDIDATES) {
    694       int_mv ref_id[2][2], ref_diff[2][2];
    695       int ref_id_count[2] = { 0 }, ref_diff_count[2] = { 0 };
    696 
    697       int mi_width = AOMMIN(mi_size_wide[BLOCK_64X64], xd->n4_w);
    698       mi_width = AOMMIN(mi_width, cm->mi_cols - mi_col);
    699       int mi_height = AOMMIN(mi_size_high[BLOCK_64X64], xd->n4_h);
    700       mi_height = AOMMIN(mi_height, cm->mi_rows - mi_row);
    701       int mi_size = AOMMIN(mi_width, mi_height);
    702 
    703       for (int idx = 0; abs(max_row_offset) >= 1 && idx < mi_size;) {
    704         const MB_MODE_INFO *const candidate = xd->mi[-xd->mi_stride + idx];
    705         process_compound_ref_mv_candidate(
    706             candidate, cm, rf, ref_id, ref_id_count, ref_diff, ref_diff_count);
    707         idx += mi_size_wide[candidate->sb_type];
    708       }
    709 
    710       for (int idx = 0; abs(max_col_offset) >= 1 && idx < mi_size;) {
    711         const MB_MODE_INFO *const candidate = xd->mi[idx * xd->mi_stride - 1];
    712         process_compound_ref_mv_candidate(
    713             candidate, cm, rf, ref_id, ref_id_count, ref_diff, ref_diff_count);
    714         idx += mi_size_high[candidate->sb_type];
    715       }
    716 
    717       // Build up the compound mv predictor
    718       int_mv comp_list[3][2];
    719 
    720       for (int idx = 0; idx < 2; ++idx) {
    721         int comp_idx = 0;
    722         for (int list_idx = 0; list_idx < ref_id_count[idx] && comp_idx < 2;
    723              ++list_idx, ++comp_idx)
    724           comp_list[comp_idx][idx] = ref_id[idx][list_idx];
    725         for (int list_idx = 0; list_idx < ref_diff_count[idx] && comp_idx < 2;
    726              ++list_idx, ++comp_idx)
    727           comp_list[comp_idx][idx] = ref_diff[idx][list_idx];
    728         for (; comp_idx < 3; ++comp_idx)
    729           comp_list[comp_idx][idx] = gm_mv_candidates[idx];
    730       }
    731 
    732       if (refmv_count[ref_frame]) {
    733         assert(refmv_count[ref_frame] == 1);
    734         if (comp_list[0][0].as_int ==
    735                 ref_mv_stack[ref_frame][0].this_mv.as_int &&
    736             comp_list[0][1].as_int ==
    737                 ref_mv_stack[ref_frame][0].comp_mv.as_int) {
    738           ref_mv_stack[ref_frame][refmv_count[ref_frame]].this_mv =
    739               comp_list[1][0];
    740           ref_mv_stack[ref_frame][refmv_count[ref_frame]].comp_mv =
    741               comp_list[1][1];
    742         } else {
    743           ref_mv_stack[ref_frame][refmv_count[ref_frame]].this_mv =
    744               comp_list[0][0];
    745           ref_mv_stack[ref_frame][refmv_count[ref_frame]].comp_mv =
    746               comp_list[0][1];
    747         }
    748         ref_mv_stack[ref_frame][refmv_count[ref_frame]].weight = 2;
    749         ++refmv_count[ref_frame];
    750       } else {
    751         for (int idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx) {
    752           ref_mv_stack[ref_frame][refmv_count[ref_frame]].this_mv =
    753               comp_list[idx][0];
    754           ref_mv_stack[ref_frame][refmv_count[ref_frame]].comp_mv =
    755               comp_list[idx][1];
    756           ref_mv_stack[ref_frame][refmv_count[ref_frame]].weight = 2;
    757           ++refmv_count[ref_frame];
    758         }
    759       }
    760     }
    761 
    762     assert(refmv_count[ref_frame] >= 2);
    763 
    764     for (int idx = 0; idx < refmv_count[ref_frame]; ++idx) {
    765       clamp_mv_ref(&ref_mv_stack[ref_frame][idx].this_mv.as_mv,
    766                    xd->n4_w << MI_SIZE_LOG2, xd->n4_h << MI_SIZE_LOG2, xd);
    767       clamp_mv_ref(&ref_mv_stack[ref_frame][idx].comp_mv.as_mv,
    768                    xd->n4_w << MI_SIZE_LOG2, xd->n4_h << MI_SIZE_LOG2, xd);
    769     }
    770   } else {
    771     // Handle single reference frame extension
    772     int mi_width = AOMMIN(mi_size_wide[BLOCK_64X64], xd->n4_w);
    773     mi_width = AOMMIN(mi_width, cm->mi_cols - mi_col);
    774     int mi_height = AOMMIN(mi_size_high[BLOCK_64X64], xd->n4_h);
    775     mi_height = AOMMIN(mi_height, cm->mi_rows - mi_row);
    776     int mi_size = AOMMIN(mi_width, mi_height);
    777 
    778     for (int idx = 0; abs(max_row_offset) >= 1 && idx < mi_size &&
    779                       refmv_count[ref_frame] < MAX_MV_REF_CANDIDATES;) {
    780       const MB_MODE_INFO *const candidate = xd->mi[-xd->mi_stride + idx];
    781       process_single_ref_mv_candidate(candidate, cm, ref_frame, refmv_count,
    782                                       ref_mv_stack);
    783       idx += mi_size_wide[candidate->sb_type];
    784     }
    785 
    786     for (int idx = 0; abs(max_col_offset) >= 1 && idx < mi_size &&
    787                       refmv_count[ref_frame] < MAX_MV_REF_CANDIDATES;) {
    788       const MB_MODE_INFO *const candidate = xd->mi[idx * xd->mi_stride - 1];
    789       process_single_ref_mv_candidate(candidate, cm, ref_frame, refmv_count,
    790                                       ref_mv_stack);
    791       idx += mi_size_high[candidate->sb_type];
    792     }
    793 
    794     for (int idx = 0; idx < refmv_count[ref_frame]; ++idx) {
    795       clamp_mv_ref(&ref_mv_stack[ref_frame][idx].this_mv.as_mv,
    796                    xd->n4_w << MI_SIZE_LOG2, xd->n4_h << MI_SIZE_LOG2, xd);
    797     }
    798 
    799     if (mv_ref_list != NULL) {
    800       for (int idx = refmv_count[ref_frame]; idx < MAX_MV_REF_CANDIDATES; ++idx)
    801         mv_ref_list[rf[0]][idx].as_int = gm_mv_candidates[0].as_int;
    802 
    803       for (int idx = 0;
    804            idx < AOMMIN(MAX_MV_REF_CANDIDATES, refmv_count[ref_frame]); ++idx) {
    805         mv_ref_list[rf[0]][idx].as_int =
    806             ref_mv_stack[ref_frame][idx].this_mv.as_int;
    807       }
    808     }
    809   }
    810 }
    811 
    812 void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
    813                       MB_MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
    814                       uint8_t ref_mv_count[MODE_CTX_REF_FRAMES],
    815                       CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
    816                       int_mv mv_ref_list[][MAX_MV_REF_CANDIDATES],
    817                       int_mv *global_mvs, int mi_row, int mi_col,
    818                       int16_t *mode_context) {
    819   int_mv zeromv[2];
    820   BLOCK_SIZE bsize = mi->sb_type;
    821   MV_REFERENCE_FRAME rf[2];
    822   av1_set_ref_frame(rf, ref_frame);
    823 
    824   if (global_mvs != NULL && ref_frame < REF_FRAMES) {
    825     if (ref_frame != INTRA_FRAME) {
    826       global_mvs[ref_frame] = gm_get_motion_vector(
    827           &cm->global_motion[ref_frame], cm->allow_high_precision_mv, bsize,
    828           mi_col, mi_row, cm->cur_frame_force_integer_mv);
    829     } else {
    830       global_mvs[ref_frame].as_int = INVALID_MV;
    831     }
    832   }
    833 
    834   if (ref_frame != INTRA_FRAME) {
    835     zeromv[0].as_int =
    836         gm_get_motion_vector(&cm->global_motion[rf[0]],
    837                              cm->allow_high_precision_mv, bsize, mi_col, mi_row,
    838                              cm->cur_frame_force_integer_mv)
    839             .as_int;
    840     zeromv[1].as_int =
    841         (rf[1] != NONE_FRAME)
    842             ? gm_get_motion_vector(&cm->global_motion[rf[1]],
    843                                    cm->allow_high_precision_mv, bsize, mi_col,
    844                                    mi_row, cm->cur_frame_force_integer_mv)
    845                   .as_int
    846             : 0;
    847   } else {
    848     zeromv[0].as_int = zeromv[1].as_int = 0;
    849   }
    850 
    851   setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
    852                     zeromv, mi_row, mi_col, mode_context);
    853 }
    854 
    855 void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,
    856                            int_mv *near_mv, int is_integer) {
    857   int i;
    858   // Make sure all the candidates are properly clamped etc
    859   for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
    860     lower_mv_precision(&mvlist[i].as_mv, allow_hp, is_integer);
    861   }
    862   *nearest_mv = mvlist[0];
    863   *near_mv = mvlist[1];
    864 }
    865 
    866 void av1_setup_frame_buf_refs(AV1_COMMON *cm) {
    867   cm->cur_frame->order_hint = cm->current_frame.order_hint;
    868 
    869   MV_REFERENCE_FRAME ref_frame;
    870   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
    871     const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame);
    872     if (buf != NULL)
    873       cm->cur_frame->ref_order_hints[ref_frame - LAST_FRAME] = buf->order_hint;
    874   }
    875 }
    876 
    877 void av1_setup_frame_sign_bias(AV1_COMMON *cm) {
    878   MV_REFERENCE_FRAME ref_frame;
    879   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
    880     const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame);
    881     if (cm->seq_params.order_hint_info.enable_order_hint && buf != NULL) {
    882       const int ref_order_hint = buf->order_hint;
    883       cm->ref_frame_sign_bias[ref_frame] =
    884           (get_relative_dist(&cm->seq_params.order_hint_info, ref_order_hint,
    885                              (int)cm->current_frame.order_hint) <= 0)
    886               ? 0
    887               : 1;
    888     } else {
    889       cm->ref_frame_sign_bias[ref_frame] = 0;
    890     }
    891   }
    892 }
    893 
    894 #define MAX_OFFSET_WIDTH 64
    895 #define MAX_OFFSET_HEIGHT 0
    896 
    897 static int get_block_position(AV1_COMMON *cm, int *mi_r, int *mi_c, int blk_row,
    898                               int blk_col, MV mv, int sign_bias) {
    899   const int base_blk_row = (blk_row >> 3) << 3;
    900   const int base_blk_col = (blk_col >> 3) << 3;
    901 
    902   const int row_offset = (mv.row >= 0) ? (mv.row >> (4 + MI_SIZE_LOG2))
    903                                        : -((-mv.row) >> (4 + MI_SIZE_LOG2));
    904 
    905   const int col_offset = (mv.col >= 0) ? (mv.col >> (4 + MI_SIZE_LOG2))
    906                                        : -((-mv.col) >> (4 + MI_SIZE_LOG2));
    907 
    908   const int row =
    909       (sign_bias == 1) ? blk_row - row_offset : blk_row + row_offset;
    910   const int col =
    911       (sign_bias == 1) ? blk_col - col_offset : blk_col + col_offset;
    912 
    913   if (row < 0 || row >= (cm->mi_rows >> 1) || col < 0 ||
    914       col >= (cm->mi_cols >> 1))
    915     return 0;
    916 
    917   if (row < base_blk_row - (MAX_OFFSET_HEIGHT >> 3) ||
    918       row >= base_blk_row + 8 + (MAX_OFFSET_HEIGHT >> 3) ||
    919       col < base_blk_col - (MAX_OFFSET_WIDTH >> 3) ||
    920       col >= base_blk_col + 8 + (MAX_OFFSET_WIDTH >> 3))
    921     return 0;
    922 
    923   *mi_r = row;
    924   *mi_c = col;
    925 
    926   return 1;
    927 }
    928 
    929 // Note: motion_filed_projection finds motion vectors of current frame's
    930 // reference frame, and projects them to current frame. To make it clear,
    931 // let's call current frame's reference frame as start frame.
    932 // Call Start frame's reference frames as reference frames.
    933 // Call ref_offset as frame distances between start frame and its reference
    934 // frames.
    935 static int motion_field_projection(AV1_COMMON *cm,
    936                                    MV_REFERENCE_FRAME start_frame, int dir) {
    937   TPL_MV_REF *tpl_mvs_base = cm->tpl_mvs;
    938   int ref_offset[REF_FRAMES] = { 0 };
    939 
    940   const RefCntBuffer *const start_frame_buf =
    941       get_ref_frame_buf(cm, start_frame);
    942   if (start_frame_buf == NULL) return 0;
    943 
    944   if (start_frame_buf->frame_type == KEY_FRAME ||
    945       start_frame_buf->frame_type == INTRA_ONLY_FRAME)
    946     return 0;
    947 
    948   if (start_frame_buf->mi_rows != cm->mi_rows ||
    949       start_frame_buf->mi_cols != cm->mi_cols)
    950     return 0;
    951 
    952   const int start_frame_order_hint = start_frame_buf->order_hint;
    953   const unsigned int *const ref_order_hints =
    954       &start_frame_buf->ref_order_hints[0];
    955   const int cur_order_hint = cm->cur_frame->order_hint;
    956   int start_to_current_frame_offset = get_relative_dist(
    957       &cm->seq_params.order_hint_info, start_frame_order_hint, cur_order_hint);
    958 
    959   for (MV_REFERENCE_FRAME rf = LAST_FRAME; rf <= INTER_REFS_PER_FRAME; ++rf) {
    960     ref_offset[rf] = get_relative_dist(&cm->seq_params.order_hint_info,
    961                                        start_frame_order_hint,
    962                                        ref_order_hints[rf - LAST_FRAME]);
    963   }
    964 
    965   if (dir == 2) start_to_current_frame_offset = -start_to_current_frame_offset;
    966 
    967   MV_REF *mv_ref_base = start_frame_buf->mvs;
    968   const int mvs_rows = (cm->mi_rows + 1) >> 1;
    969   const int mvs_cols = (cm->mi_cols + 1) >> 1;
    970 
    971   for (int blk_row = 0; blk_row < mvs_rows; ++blk_row) {
    972     for (int blk_col = 0; blk_col < mvs_cols; ++blk_col) {
    973       MV_REF *mv_ref = &mv_ref_base[blk_row * mvs_cols + blk_col];
    974       MV fwd_mv = mv_ref->mv.as_mv;
    975 
    976       if (mv_ref->ref_frame > INTRA_FRAME) {
    977         int_mv this_mv;
    978         int mi_r, mi_c;
    979         const int ref_frame_offset = ref_offset[mv_ref->ref_frame];
    980 
    981         int pos_valid =
    982             abs(ref_frame_offset) <= MAX_FRAME_DISTANCE &&
    983             ref_frame_offset > 0 &&
    984             abs(start_to_current_frame_offset) <= MAX_FRAME_DISTANCE;
    985 
    986         if (pos_valid) {
    987           get_mv_projection(&this_mv.as_mv, fwd_mv,
    988                             start_to_current_frame_offset, ref_frame_offset);
    989           pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
    990                                          this_mv.as_mv, dir >> 1);
    991         }
    992 
    993         if (pos_valid) {
    994           const int mi_offset = mi_r * (cm->mi_stride >> 1) + mi_c;
    995 
    996           tpl_mvs_base[mi_offset].mfmv0.as_mv.row = fwd_mv.row;
    997           tpl_mvs_base[mi_offset].mfmv0.as_mv.col = fwd_mv.col;
    998           tpl_mvs_base[mi_offset].ref_frame_offset = ref_frame_offset;
    999         }
   1000       }
   1001     }
   1002   }
   1003 
   1004   return 1;
   1005 }
   1006 
   1007 void av1_setup_motion_field(AV1_COMMON *cm) {
   1008   const OrderHintInfo *const order_hint_info = &cm->seq_params.order_hint_info;
   1009 
   1010   memset(cm->ref_frame_side, 0, sizeof(cm->ref_frame_side));
   1011   if (!order_hint_info->enable_order_hint) return;
   1012 
   1013   TPL_MV_REF *tpl_mvs_base = cm->tpl_mvs;
   1014   int size = ((cm->mi_rows + MAX_MIB_SIZE) >> 1) * (cm->mi_stride >> 1);
   1015   for (int idx = 0; idx < size; ++idx) {
   1016     tpl_mvs_base[idx].mfmv0.as_int = INVALID_MV;
   1017     tpl_mvs_base[idx].ref_frame_offset = 0;
   1018   }
   1019 
   1020   const int cur_order_hint = cm->cur_frame->order_hint;
   1021 
   1022   const RefCntBuffer *ref_buf[INTER_REFS_PER_FRAME];
   1023   int ref_order_hint[INTER_REFS_PER_FRAME];
   1024 
   1025   for (int ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
   1026     const int ref_idx = ref_frame - LAST_FRAME;
   1027     const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame);
   1028     int order_hint = 0;
   1029 
   1030     if (buf != NULL) order_hint = buf->order_hint;
   1031 
   1032     ref_buf[ref_idx] = buf;
   1033     ref_order_hint[ref_idx] = order_hint;
   1034 
   1035     if (get_relative_dist(order_hint_info, order_hint, cur_order_hint) > 0)
   1036       cm->ref_frame_side[ref_frame] = 1;
   1037     else if (order_hint == cur_order_hint)
   1038       cm->ref_frame_side[ref_frame] = -1;
   1039   }
   1040 
   1041   int ref_stamp = MFMV_STACK_SIZE - 1;
   1042 
   1043   if (ref_buf[LAST_FRAME - LAST_FRAME] != NULL) {
   1044     const int alt_of_lst_order_hint =
   1045         ref_buf[LAST_FRAME - LAST_FRAME]
   1046             ->ref_order_hints[ALTREF_FRAME - LAST_FRAME];
   1047 
   1048     const int is_lst_overlay =
   1049         (alt_of_lst_order_hint == ref_order_hint[GOLDEN_FRAME - LAST_FRAME]);
   1050     if (!is_lst_overlay) motion_field_projection(cm, LAST_FRAME, 2);
   1051     --ref_stamp;
   1052   }
   1053 
   1054   if (get_relative_dist(order_hint_info,
   1055                         ref_order_hint[BWDREF_FRAME - LAST_FRAME],
   1056                         cur_order_hint) > 0) {
   1057     if (motion_field_projection(cm, BWDREF_FRAME, 0)) --ref_stamp;
   1058   }
   1059 
   1060   if (get_relative_dist(order_hint_info,
   1061                         ref_order_hint[ALTREF2_FRAME - LAST_FRAME],
   1062                         cur_order_hint) > 0) {
   1063     if (motion_field_projection(cm, ALTREF2_FRAME, 0)) --ref_stamp;
   1064   }
   1065 
   1066   if (get_relative_dist(order_hint_info,
   1067                         ref_order_hint[ALTREF_FRAME - LAST_FRAME],
   1068                         cur_order_hint) > 0 &&
   1069       ref_stamp >= 0)
   1070     if (motion_field_projection(cm, ALTREF_FRAME, 0)) --ref_stamp;
   1071 
   1072   if (ref_stamp >= 0) motion_field_projection(cm, LAST2_FRAME, 2);
   1073 }
   1074 
   1075 static INLINE void record_samples(MB_MODE_INFO *mbmi, int *pts, int *pts_inref,
   1076                                   int row_offset, int sign_r, int col_offset,
   1077                                   int sign_c) {
   1078   int bw = block_size_wide[mbmi->sb_type];
   1079   int bh = block_size_high[mbmi->sb_type];
   1080   int x = col_offset * MI_SIZE + sign_c * AOMMAX(bw, MI_SIZE) / 2 - 1;
   1081   int y = row_offset * MI_SIZE + sign_r * AOMMAX(bh, MI_SIZE) / 2 - 1;
   1082 
   1083   pts[0] = (x * 8);
   1084   pts[1] = (y * 8);
   1085   pts_inref[0] = (x * 8) + mbmi->mv[0].as_mv.col;
   1086   pts_inref[1] = (y * 8) + mbmi->mv[0].as_mv.row;
   1087 }
   1088 
   1089 // Select samples according to the motion vector difference.
   1090 int selectSamples(MV *mv, int *pts, int *pts_inref, int len, BLOCK_SIZE bsize) {
   1091   const int bw = block_size_wide[bsize];
   1092   const int bh = block_size_high[bsize];
   1093   const int thresh = clamp(AOMMAX(bw, bh), 16, 112);
   1094   int pts_mvd[SAMPLES_ARRAY_SIZE] = { 0 };
   1095   int i, j, k, l = len;
   1096   int ret = 0;
   1097   assert(len <= LEAST_SQUARES_SAMPLES_MAX);
   1098 
   1099   // Obtain the motion vector difference.
   1100   for (i = 0; i < len; ++i) {
   1101     pts_mvd[i] = abs(pts_inref[2 * i] - pts[2 * i] - mv->col) +
   1102                  abs(pts_inref[2 * i + 1] - pts[2 * i + 1] - mv->row);
   1103 
   1104     if (pts_mvd[i] > thresh)
   1105       pts_mvd[i] = -1;
   1106     else
   1107       ret++;
   1108   }
   1109 
   1110   // Keep at least 1 sample.
   1111   if (!ret) return 1;
   1112 
   1113   i = 0;
   1114   j = l - 1;
   1115   for (k = 0; k < l - ret; k++) {
   1116     while (pts_mvd[i] != -1) i++;
   1117     while (pts_mvd[j] == -1) j--;
   1118     assert(i != j);
   1119     if (i > j) break;
   1120 
   1121     // Replace the discarded samples;
   1122     pts_mvd[i] = pts_mvd[j];
   1123     pts[2 * i] = pts[2 * j];
   1124     pts[2 * i + 1] = pts[2 * j + 1];
   1125     pts_inref[2 * i] = pts_inref[2 * j];
   1126     pts_inref[2 * i + 1] = pts_inref[2 * j + 1];
   1127     i++;
   1128     j--;
   1129   }
   1130 
   1131   return ret;
   1132 }
   1133 
   1134 // Note: Samples returned are at 1/8-pel precision
   1135 // Sample are the neighbor block center point's coordinates relative to the
   1136 // left-top pixel of current block.
   1137 int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
   1138                 int *pts, int *pts_inref) {
   1139   MB_MODE_INFO *const mbmi0 = xd->mi[0];
   1140   int ref_frame = mbmi0->ref_frame[0];
   1141   int up_available = xd->up_available;
   1142   int left_available = xd->left_available;
   1143   int i, mi_step = 1, np = 0;
   1144 
   1145   const TileInfo *const tile = &xd->tile;
   1146   int do_tl = 1;
   1147   int do_tr = 1;
   1148 
   1149   // scan the nearest above rows
   1150   if (up_available) {
   1151     int mi_row_offset = -1;
   1152     MB_MODE_INFO *mbmi = xd->mi[mi_row_offset * xd->mi_stride];
   1153     uint8_t n4_w = mi_size_wide[mbmi->sb_type];
   1154 
   1155     if (xd->n4_w <= n4_w) {
   1156       // Handle "current block width <= above block width" case.
   1157       int col_offset = -mi_col % n4_w;
   1158 
   1159       if (col_offset < 0) do_tl = 0;
   1160       if (col_offset + n4_w > xd->n4_w) do_tr = 0;
   1161 
   1162       if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
   1163         record_samples(mbmi, pts, pts_inref, 0, -1, col_offset, 1);
   1164         pts += 2;
   1165         pts_inref += 2;
   1166         np++;
   1167         if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
   1168       }
   1169     } else {
   1170       // Handle "current block width > above block width" case.
   1171       for (i = 0; i < AOMMIN(xd->n4_w, cm->mi_cols - mi_col); i += mi_step) {
   1172         int mi_col_offset = i;
   1173         mbmi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
   1174         n4_w = mi_size_wide[mbmi->sb_type];
   1175         mi_step = AOMMIN(xd->n4_w, n4_w);
   1176 
   1177         if (mbmi->ref_frame[0] == ref_frame &&
   1178             mbmi->ref_frame[1] == NONE_FRAME) {
   1179           record_samples(mbmi, pts, pts_inref, 0, -1, i, 1);
   1180           pts += 2;
   1181           pts_inref += 2;
   1182           np++;
   1183           if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
   1184         }
   1185       }
   1186     }
   1187   }
   1188   assert(np <= LEAST_SQUARES_SAMPLES_MAX);
   1189 
   1190   // scan the nearest left columns
   1191   if (left_available) {
   1192     int mi_col_offset = -1;
   1193 
   1194     MB_MODE_INFO *mbmi = xd->mi[mi_col_offset];
   1195     uint8_t n4_h = mi_size_high[mbmi->sb_type];
   1196 
   1197     if (xd->n4_h <= n4_h) {
   1198       // Handle "current block height <= above block height" case.
   1199       int row_offset = -mi_row % n4_h;
   1200 
   1201       if (row_offset < 0) do_tl = 0;
   1202 
   1203       if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
   1204         record_samples(mbmi, pts, pts_inref, row_offset, 1, 0, -1);
   1205         pts += 2;
   1206         pts_inref += 2;
   1207         np++;
   1208         if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
   1209       }
   1210     } else {
   1211       // Handle "current block height > above block height" case.
   1212       for (i = 0; i < AOMMIN(xd->n4_h, cm->mi_rows - mi_row); i += mi_step) {
   1213         int mi_row_offset = i;
   1214         mbmi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
   1215         n4_h = mi_size_high[mbmi->sb_type];
   1216         mi_step = AOMMIN(xd->n4_h, n4_h);
   1217 
   1218         if (mbmi->ref_frame[0] == ref_frame &&
   1219             mbmi->ref_frame[1] == NONE_FRAME) {
   1220           record_samples(mbmi, pts, pts_inref, i, 1, 0, -1);
   1221           pts += 2;
   1222           pts_inref += 2;
   1223           np++;
   1224           if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
   1225         }
   1226       }
   1227     }
   1228   }
   1229   assert(np <= LEAST_SQUARES_SAMPLES_MAX);
   1230 
   1231   // Top-left block
   1232   if (do_tl && left_available && up_available) {
   1233     int mi_row_offset = -1;
   1234     int mi_col_offset = -1;
   1235 
   1236     MB_MODE_INFO *mbmi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
   1237 
   1238     if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
   1239       record_samples(mbmi, pts, pts_inref, 0, -1, 0, -1);
   1240       pts += 2;
   1241       pts_inref += 2;
   1242       np++;
   1243       if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
   1244     }
   1245   }
   1246   assert(np <= LEAST_SQUARES_SAMPLES_MAX);
   1247 
   1248   // Top-right block
   1249   if (do_tr &&
   1250       has_top_right(cm, xd, mi_row, mi_col, AOMMAX(xd->n4_w, xd->n4_h))) {
   1251     POSITION trb_pos = { -1, xd->n4_w };
   1252 
   1253     if (is_inside(tile, mi_col, mi_row, &trb_pos)) {
   1254       int mi_row_offset = -1;
   1255       int mi_col_offset = xd->n4_w;
   1256 
   1257       MB_MODE_INFO *mbmi =
   1258           xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
   1259 
   1260       if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
   1261         record_samples(mbmi, pts, pts_inref, 0, -1, xd->n4_w, 1);
   1262         np++;
   1263         if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
   1264       }
   1265     }
   1266   }
   1267   assert(np <= LEAST_SQUARES_SAMPLES_MAX);
   1268 
   1269   return np;
   1270 }
   1271 
   1272 void av1_setup_skip_mode_allowed(AV1_COMMON *cm) {
   1273   const OrderHintInfo *const order_hint_info = &cm->seq_params.order_hint_info;
   1274   SkipModeInfo *const skip_mode_info = &cm->current_frame.skip_mode_info;
   1275 
   1276   skip_mode_info->skip_mode_allowed = 0;
   1277   skip_mode_info->ref_frame_idx_0 = INVALID_IDX;
   1278   skip_mode_info->ref_frame_idx_1 = INVALID_IDX;
   1279 
   1280   if (!order_hint_info->enable_order_hint || frame_is_intra_only(cm) ||
   1281       cm->current_frame.reference_mode == SINGLE_REFERENCE)
   1282     return;
   1283 
   1284   const int cur_order_hint = cm->current_frame.order_hint;
   1285   int ref_order_hints[2] = { -1, INT_MAX };
   1286   int ref_idx[2] = { INVALID_IDX, INVALID_IDX };
   1287 
   1288   // Identify the nearest forward and backward references.
   1289   for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
   1290     const RefCntBuffer *const buf = get_ref_frame_buf(cm, LAST_FRAME + i);
   1291     if (buf == NULL) continue;
   1292 
   1293     const int ref_order_hint = buf->order_hint;
   1294     if (get_relative_dist(order_hint_info, ref_order_hint, cur_order_hint) <
   1295         0) {
   1296       // Forward reference
   1297       if (ref_order_hints[0] == -1 ||
   1298           get_relative_dist(order_hint_info, ref_order_hint,
   1299                             ref_order_hints[0]) > 0) {
   1300         ref_order_hints[0] = ref_order_hint;
   1301         ref_idx[0] = i;
   1302       }
   1303     } else if (get_relative_dist(order_hint_info, ref_order_hint,
   1304                                  cur_order_hint) > 0) {
   1305       // Backward reference
   1306       if (ref_order_hints[1] == INT_MAX ||
   1307           get_relative_dist(order_hint_info, ref_order_hint,
   1308                             ref_order_hints[1]) < 0) {
   1309         ref_order_hints[1] = ref_order_hint;
   1310         ref_idx[1] = i;
   1311       }
   1312     }
   1313   }
   1314 
   1315   if (ref_idx[0] != INVALID_IDX && ref_idx[1] != INVALID_IDX) {
   1316     // == Bi-directional prediction ==
   1317     skip_mode_info->skip_mode_allowed = 1;
   1318     skip_mode_info->ref_frame_idx_0 = AOMMIN(ref_idx[0], ref_idx[1]);
   1319     skip_mode_info->ref_frame_idx_1 = AOMMAX(ref_idx[0], ref_idx[1]);
   1320   } else if (ref_idx[0] != INVALID_IDX && ref_idx[1] == INVALID_IDX) {
   1321     // == Forward prediction only ==
   1322     // Identify the second nearest forward reference.
   1323     ref_order_hints[1] = -1;
   1324     for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
   1325       const RefCntBuffer *const buf = get_ref_frame_buf(cm, LAST_FRAME + i);
   1326       if (buf == NULL) continue;
   1327 
   1328       const int ref_order_hint = buf->order_hint;
   1329       if ((ref_order_hints[0] != -1 &&
   1330            get_relative_dist(order_hint_info, ref_order_hint,
   1331                              ref_order_hints[0]) < 0) &&
   1332           (ref_order_hints[1] == -1 ||
   1333            get_relative_dist(order_hint_info, ref_order_hint,
   1334                              ref_order_hints[1]) > 0)) {
   1335         // Second closest forward reference
   1336         ref_order_hints[1] = ref_order_hint;
   1337         ref_idx[1] = i;
   1338       }
   1339     }
   1340     if (ref_order_hints[1] != -1) {
   1341       skip_mode_info->skip_mode_allowed = 1;
   1342       skip_mode_info->ref_frame_idx_0 = AOMMIN(ref_idx[0], ref_idx[1]);
   1343       skip_mode_info->ref_frame_idx_1 = AOMMAX(ref_idx[0], ref_idx[1]);
   1344     }
   1345   }
   1346 }
   1347 
   1348 typedef struct {
   1349   int map_idx;        // frame map index
   1350   RefCntBuffer *buf;  // frame buffer
   1351   int sort_idx;       // index based on the offset to be used for sorting
   1352 } REF_FRAME_INFO;
   1353 
   1354 // Compares the sort_idx fields. If they are equal, then compares the map_idx
   1355 // fields to break the tie. This ensures a stable sort.
   1356 static int compare_ref_frame_info(const void *arg_a, const void *arg_b) {
   1357   const REF_FRAME_INFO *info_a = (REF_FRAME_INFO *)arg_a;
   1358   const REF_FRAME_INFO *info_b = (REF_FRAME_INFO *)arg_b;
   1359 
   1360   const int sort_idx_diff = info_a->sort_idx - info_b->sort_idx;
   1361   if (sort_idx_diff != 0) return sort_idx_diff;
   1362   return info_a->map_idx - info_b->map_idx;
   1363 }
   1364 
   1365 static void set_ref_frame_info(int *remapped_ref_idx, int frame_idx,
   1366                                REF_FRAME_INFO *ref_info) {
   1367   assert(frame_idx >= 0 && frame_idx < INTER_REFS_PER_FRAME);
   1368 
   1369   remapped_ref_idx[frame_idx] = ref_info->map_idx;
   1370 }
   1371 
   1372 void av1_set_frame_refs(AV1_COMMON *const cm, int *remapped_ref_idx,
   1373                         int lst_map_idx, int gld_map_idx) {
   1374   int lst_frame_sort_idx = -1;
   1375   int gld_frame_sort_idx = -1;
   1376 
   1377   assert(cm->seq_params.order_hint_info.enable_order_hint);
   1378   assert(cm->seq_params.order_hint_info.order_hint_bits_minus_1 >= 0);
   1379   const int cur_order_hint = (int)cm->current_frame.order_hint;
   1380   const int cur_frame_sort_idx =
   1381       1 << cm->seq_params.order_hint_info.order_hint_bits_minus_1;
   1382 
   1383   REF_FRAME_INFO ref_frame_info[REF_FRAMES];
   1384   int ref_flag_list[INTER_REFS_PER_FRAME] = { 0, 0, 0, 0, 0, 0, 0 };
   1385 
   1386   for (int i = 0; i < REF_FRAMES; ++i) {
   1387     const int map_idx = i;
   1388 
   1389     ref_frame_info[i].map_idx = map_idx;
   1390     ref_frame_info[i].sort_idx = -1;
   1391 
   1392     RefCntBuffer *const buf = cm->ref_frame_map[map_idx];
   1393     ref_frame_info[i].buf = buf;
   1394 
   1395     if (buf == NULL) continue;
   1396     // If this assertion fails, there is a reference leak.
   1397     assert(buf->ref_count > 0);
   1398 
   1399     const int offset = (int)buf->order_hint;
   1400     ref_frame_info[i].sort_idx =
   1401         (offset == -1) ? -1
   1402                        : cur_frame_sort_idx +
   1403                              get_relative_dist(&cm->seq_params.order_hint_info,
   1404                                                offset, cur_order_hint);
   1405     assert(ref_frame_info[i].sort_idx >= -1);
   1406 
   1407     if (map_idx == lst_map_idx) lst_frame_sort_idx = ref_frame_info[i].sort_idx;
   1408     if (map_idx == gld_map_idx) gld_frame_sort_idx = ref_frame_info[i].sort_idx;
   1409   }
   1410 
   1411   // Confirm both LAST_FRAME and GOLDEN_FRAME are valid forward reference
   1412   // frames.
   1413   if (lst_frame_sort_idx == -1 || lst_frame_sort_idx >= cur_frame_sort_idx) {
   1414     aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
   1415                        "Inter frame requests a look-ahead frame as LAST");
   1416   }
   1417   if (gld_frame_sort_idx == -1 || gld_frame_sort_idx >= cur_frame_sort_idx) {
   1418     aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
   1419                        "Inter frame requests a look-ahead frame as GOLDEN");
   1420   }
   1421 
   1422   // Sort ref frames based on their frame_offset values.
   1423   qsort(ref_frame_info, REF_FRAMES, sizeof(REF_FRAME_INFO),
   1424         compare_ref_frame_info);
   1425 
   1426   // Identify forward and backward reference frames.
   1427   // Forward  reference: offset < order_hint
   1428   // Backward reference: offset >= order_hint
   1429   int fwd_start_idx = 0, fwd_end_idx = REF_FRAMES - 1;
   1430 
   1431   for (int i = 0; i < REF_FRAMES; i++) {
   1432     if (ref_frame_info[i].sort_idx == -1) {
   1433       fwd_start_idx++;
   1434       continue;
   1435     }
   1436 
   1437     if (ref_frame_info[i].sort_idx >= cur_frame_sort_idx) {
   1438       fwd_end_idx = i - 1;
   1439       break;
   1440     }
   1441   }
   1442 
   1443   int bwd_start_idx = fwd_end_idx + 1;
   1444   int bwd_end_idx = REF_FRAMES - 1;
   1445 
   1446   // === Backward Reference Frames ===
   1447 
   1448   // == ALTREF_FRAME ==
   1449   if (bwd_start_idx <= bwd_end_idx) {
   1450     set_ref_frame_info(remapped_ref_idx, ALTREF_FRAME - LAST_FRAME,
   1451                        &ref_frame_info[bwd_end_idx]);
   1452     ref_flag_list[ALTREF_FRAME - LAST_FRAME] = 1;
   1453     bwd_end_idx--;
   1454   }
   1455 
   1456   // == BWDREF_FRAME ==
   1457   if (bwd_start_idx <= bwd_end_idx) {
   1458     set_ref_frame_info(remapped_ref_idx, BWDREF_FRAME - LAST_FRAME,
   1459                        &ref_frame_info[bwd_start_idx]);
   1460     ref_flag_list[BWDREF_FRAME - LAST_FRAME] = 1;
   1461     bwd_start_idx++;
   1462   }
   1463 
   1464   // == ALTREF2_FRAME ==
   1465   if (bwd_start_idx <= bwd_end_idx) {
   1466     set_ref_frame_info(remapped_ref_idx, ALTREF2_FRAME - LAST_FRAME,
   1467                        &ref_frame_info[bwd_start_idx]);
   1468     ref_flag_list[ALTREF2_FRAME - LAST_FRAME] = 1;
   1469   }
   1470 
   1471   // === Forward Reference Frames ===
   1472 
   1473   for (int i = fwd_start_idx; i <= fwd_end_idx; ++i) {
   1474     // == LAST_FRAME ==
   1475     if (ref_frame_info[i].map_idx == lst_map_idx) {
   1476       set_ref_frame_info(remapped_ref_idx, LAST_FRAME - LAST_FRAME,
   1477                          &ref_frame_info[i]);
   1478       ref_flag_list[LAST_FRAME - LAST_FRAME] = 1;
   1479     }
   1480 
   1481     // == GOLDEN_FRAME ==
   1482     if (ref_frame_info[i].map_idx == gld_map_idx) {
   1483       set_ref_frame_info(remapped_ref_idx, GOLDEN_FRAME - LAST_FRAME,
   1484                          &ref_frame_info[i]);
   1485       ref_flag_list[GOLDEN_FRAME - LAST_FRAME] = 1;
   1486     }
   1487   }
   1488 
   1489   assert(ref_flag_list[LAST_FRAME - LAST_FRAME] == 1 &&
   1490          ref_flag_list[GOLDEN_FRAME - LAST_FRAME] == 1);
   1491 
   1492   // == LAST2_FRAME ==
   1493   // == LAST3_FRAME ==
   1494   // == BWDREF_FRAME ==
   1495   // == ALTREF2_FRAME ==
   1496   // == ALTREF_FRAME ==
   1497 
   1498   // Set up the reference frames in the anti-chronological order.
   1499   static const MV_REFERENCE_FRAME ref_frame_list[INTER_REFS_PER_FRAME - 2] = {
   1500     LAST2_FRAME, LAST3_FRAME, BWDREF_FRAME, ALTREF2_FRAME, ALTREF_FRAME
   1501   };
   1502 
   1503   int ref_idx;
   1504   for (ref_idx = 0; ref_idx < (INTER_REFS_PER_FRAME - 2); ref_idx++) {
   1505     const MV_REFERENCE_FRAME ref_frame = ref_frame_list[ref_idx];
   1506 
   1507     if (ref_flag_list[ref_frame - LAST_FRAME] == 1) continue;
   1508 
   1509     while (fwd_start_idx <= fwd_end_idx &&
   1510            (ref_frame_info[fwd_end_idx].map_idx == lst_map_idx ||
   1511             ref_frame_info[fwd_end_idx].map_idx == gld_map_idx)) {
   1512       fwd_end_idx--;
   1513     }
   1514     if (fwd_start_idx > fwd_end_idx) break;
   1515 
   1516     set_ref_frame_info(remapped_ref_idx, ref_frame - LAST_FRAME,
   1517                        &ref_frame_info[fwd_end_idx]);
   1518     ref_flag_list[ref_frame - LAST_FRAME] = 1;
   1519 
   1520     fwd_end_idx--;
   1521   }
   1522 
   1523   // Assign all the remaining frame(s), if any, to the earliest reference frame.
   1524   for (; ref_idx < (INTER_REFS_PER_FRAME - 2); ref_idx++) {
   1525     const MV_REFERENCE_FRAME ref_frame = ref_frame_list[ref_idx];
   1526     if (ref_flag_list[ref_frame - LAST_FRAME] == 1) continue;
   1527     set_ref_frame_info(remapped_ref_idx, ref_frame - LAST_FRAME,
   1528                        &ref_frame_info[fwd_start_idx]);
   1529     ref_flag_list[ref_frame - LAST_FRAME] = 1;
   1530   }
   1531 
   1532   for (int i = 0; i < INTER_REFS_PER_FRAME; i++) {
   1533     assert(ref_flag_list[i] == 1);
   1534   }
   1535 }
   1536