LCOV - code coverage report
Current view: top level - third_party/aom/av1/common - mvref_common.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 548 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "av1/common/mvref_common.h"
      13             : #if CONFIG_WARPED_MOTION
      14             : #include "av1/common/warped_motion.h"
      15             : #endif  // CONFIG_WARPED_MOTION
      16             : 
      17           0 : static uint8_t add_ref_mv_candidate(
      18             :     const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
      19             :     const MV_REFERENCE_FRAME rf[2], uint8_t *refmv_count,
      20             :     CANDIDATE_MV *ref_mv_stack, const int use_hp, int len, int block, int col) {
      21           0 :   int index = 0, ref;
      22           0 :   int newmv_count = 0;
      23             : #if CONFIG_CB4X4
      24           0 :   const int unify_bsize = 1;
      25             : #else
      26             :   const int unify_bsize = 0;
      27             : #endif
      28             : 
      29           0 :   if (rf[1] == NONE_FRAME) {
      30             :     // single reference frame
      31           0 :     for (ref = 0; ref < 2; ++ref) {
      32           0 :       if (candidate->ref_frame[ref] == rf[0]) {
      33           0 :         int_mv this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
      34           0 :         lower_mv_precision(&this_refmv.as_mv, use_hp);
      35             : 
      36           0 :         for (index = 0; index < *refmv_count; ++index)
      37           0 :           if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
      38             : 
      39           0 :         if (index < *refmv_count) ref_mv_stack[index].weight += 2 * len;
      40             : 
      41             :         // Add a new item to the list.
      42           0 :         if (index == *refmv_count) {
      43           0 :           ref_mv_stack[index].this_mv = this_refmv;
      44           0 :           ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
      45             :               get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
      46           0 :           ref_mv_stack[index].weight = 2 * len;
      47           0 :           ++(*refmv_count);
      48             : 
      49           0 :           if (candidate->mode == NEWMV) ++newmv_count;
      50             :         }
      51             : 
      52           0 :         if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
      53             :             !unify_bsize) {
      54           0 :           int alt_block = 3 - block;
      55           0 :           this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
      56           0 :           lower_mv_precision(&this_refmv.as_mv, use_hp);
      57             : 
      58           0 :           for (index = 0; index < *refmv_count; ++index)
      59           0 :             if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
      60             : 
      61           0 :           if (index < *refmv_count) ref_mv_stack[index].weight += len;
      62             : 
      63             :           // Add a new item to the list.
      64           0 :           if (index == *refmv_count) {
      65           0 :             ref_mv_stack[index].this_mv = this_refmv;
      66           0 :             ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
      67             :                 get_sub_block_pred_mv(candidate_mi, ref, col, alt_block),
      68             :                 this_refmv);
      69           0 :             ref_mv_stack[index].weight = len;
      70           0 :             ++(*refmv_count);
      71             : 
      72           0 :             if (candidate->mode == NEWMV) ++newmv_count;
      73             :           }
      74             :         }
      75             :       }
      76             :     }
      77             :   } else {
      78             :     // compound reference frame
      79           0 :     if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
      80             :       int_mv this_refmv[2];
      81             : 
      82           0 :       for (ref = 0; ref < 2; ++ref) {
      83           0 :         this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
      84           0 :         lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
      85             :       }
      86             : 
      87           0 :       for (index = 0; index < *refmv_count; ++index)
      88           0 :         if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
      89           0 :             (ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
      90           0 :           break;
      91             : 
      92           0 :       if (index < *refmv_count) ref_mv_stack[index].weight += 2 * len;
      93             : 
      94             :       // Add a new item to the list.
      95           0 :       if (index == *refmv_count) {
      96           0 :         ref_mv_stack[index].this_mv = this_refmv[0];
      97           0 :         ref_mv_stack[index].comp_mv = this_refmv[1];
      98           0 :         ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
      99             :             get_sub_block_pred_mv(candidate_mi, 0, col, block), this_refmv[0]);
     100           0 :         ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
     101             :             get_sub_block_pred_mv(candidate_mi, 1, col, block), this_refmv[1]);
     102           0 :         ref_mv_stack[index].weight = 2 * len;
     103           0 :         ++(*refmv_count);
     104             : 
     105             : #if CONFIG_EXT_INTER
     106           0 :         if (candidate->mode == NEW_NEWMV)
     107             : #else
     108             :         if (candidate->mode == NEWMV)
     109             : #endif  // CONFIG_EXT_INTER
     110           0 :           ++newmv_count;
     111             :       }
     112             : 
     113           0 :       if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
     114             :           !unify_bsize) {
     115           0 :         int alt_block = 3 - block;
     116           0 :         this_refmv[0] = get_sub_block_mv(candidate_mi, 0, col, alt_block);
     117           0 :         this_refmv[1] = get_sub_block_mv(candidate_mi, 1, col, alt_block);
     118             : 
     119           0 :         for (ref = 0; ref < 2; ++ref)
     120           0 :           lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
     121             : 
     122           0 :         for (index = 0; index < *refmv_count; ++index)
     123           0 :           if (ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int &&
     124           0 :               ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int)
     125           0 :             break;
     126             : 
     127           0 :         if (index < *refmv_count) ref_mv_stack[index].weight += len;
     128             : 
     129             :         // Add a new item to the list.
     130           0 :         if (index == *refmv_count) {
     131           0 :           ref_mv_stack[index].this_mv = this_refmv[0];
     132           0 :           ref_mv_stack[index].comp_mv = this_refmv[1];
     133           0 :           ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
     134             :               get_sub_block_pred_mv(candidate_mi, 0, col, block),
     135             :               this_refmv[0]);
     136           0 :           ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
     137             :               get_sub_block_pred_mv(candidate_mi, 1, col, block),
     138             :               this_refmv[1]);
     139           0 :           ref_mv_stack[index].weight = len;
     140           0 :           ++(*refmv_count);
     141             : 
     142             : #if CONFIG_EXT_INTER
     143           0 :           if (candidate->mode == NEW_NEWMV)
     144             : #else
     145             :           if (candidate->mode == NEWMV)
     146             : #endif  // CONFIG_EXT_INTER
     147           0 :             ++newmv_count;
     148             :         }
     149             :       }
     150             :     }
     151             :   }
     152           0 :   return newmv_count;
     153             : }
     154             : 
     155           0 : static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
     156             :                              const int mi_row, const int mi_col, int block,
     157             :                              const MV_REFERENCE_FRAME rf[2], int row_offset,
     158             :                              CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
     159           0 :   const TileInfo *const tile = &xd->tile;
     160             :   int i;
     161           0 :   uint8_t newmv_count = 0;
     162             : #if CONFIG_CB4X4
     163           0 :   const int bsize = xd->mi[0]->mbmi.sb_type;
     164           0 :   const int mi_offset =
     165           0 :       bsize < BLOCK_8X8 ? mi_size_wide[BLOCK_4X4] : mi_size_wide[BLOCK_8X8];
     166             :   // TODO(jingning): Revisit this part after cb4x4 is stable.
     167           0 :   if (bsize >= BLOCK_8X8) row_offset *= 2;
     168             : #else
     169             :   const int mi_offset = mi_size_wide[BLOCK_8X8];
     170             : #endif
     171             : 
     172           0 :   for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
     173             :     POSITION mi_pos;
     174             : #if CONFIG_CB4X4
     175           0 :     const int use_step_16 = (xd->n8_w >= 16);
     176             : #else
     177             :     const int use_step_16 = (xd->n8_w >= 8);
     178             : #endif
     179             : 
     180           0 :     mi_pos.row = row_offset;
     181           0 :     mi_pos.col = i;
     182           0 :     if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
     183           0 :       const MODE_INFO *const candidate_mi =
     184           0 :           xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
     185           0 :       const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
     186           0 :       int len = AOMMIN(xd->n8_w, mi_size_wide[candidate->sb_type]);
     187           0 :       if (use_step_16) len = AOMMAX(mi_size_wide[BLOCK_16X16], len);
     188           0 :       newmv_count += add_ref_mv_candidate(
     189             :           candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
     190             :           cm->allow_high_precision_mv, len, block, mi_pos.col);
     191           0 :       i += len;
     192             :     } else {
     193           0 :       if (use_step_16)
     194           0 :         i += (mi_offset << 1);
     195             :       else
     196           0 :         i += mi_offset;
     197             :     }
     198             :   }
     199             : 
     200           0 :   return newmv_count;
     201             : }
     202             : 
     203           0 : static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
     204             :                              const int mi_row, const int mi_col, int block,
     205             :                              const MV_REFERENCE_FRAME rf[2], int col_offset,
     206             :                              CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
     207           0 :   const TileInfo *const tile = &xd->tile;
     208             :   int i;
     209           0 :   uint8_t newmv_count = 0;
     210             : #if CONFIG_CB4X4
     211           0 :   const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
     212           0 :   const int mi_offset =
     213           0 :       (bsize < BLOCK_8X8) ? mi_size_high[BLOCK_4X4] : mi_size_high[BLOCK_8X8];
     214           0 :   if (bsize >= BLOCK_8X8) col_offset *= 2;
     215             : #else
     216             :   const int mi_offset = mi_size_wide[BLOCK_8X8];
     217             : #endif
     218             : 
     219           0 :   for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
     220             :     POSITION mi_pos;
     221             : #if CONFIG_CB4X4
     222           0 :     const int use_step_16 = (xd->n8_h >= 16);
     223             : #else
     224             :     const int use_step_16 = (xd->n8_h >= 8);
     225             : #endif
     226             : 
     227           0 :     mi_pos.row = i;
     228           0 :     mi_pos.col = col_offset;
     229           0 :     if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
     230           0 :       const MODE_INFO *const candidate_mi =
     231           0 :           xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
     232           0 :       const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
     233           0 :       int len = AOMMIN(xd->n8_h, mi_size_high[candidate->sb_type]);
     234           0 :       if (use_step_16) len = AOMMAX(mi_size_high[BLOCK_16X16], len);
     235           0 :       newmv_count += add_ref_mv_candidate(
     236             :           candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
     237             :           cm->allow_high_precision_mv, len, block, mi_pos.col);
     238           0 :       i += len;
     239             :     } else {
     240           0 :       if (use_step_16)
     241           0 :         i += (mi_offset << 1);
     242             :       else
     243           0 :         i += mi_offset;
     244             :     }
     245             :   }
     246             : 
     247           0 :   return newmv_count;
     248             : }
     249             : 
     250           0 : static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
     251             :                              const int mi_row, const int mi_col, int block,
     252             :                              const MV_REFERENCE_FRAME rf[2], int row_offset,
     253             :                              int col_offset, CANDIDATE_MV *ref_mv_stack,
     254             :                              uint8_t *refmv_count) {
     255           0 :   const TileInfo *const tile = &xd->tile;
     256             :   POSITION mi_pos;
     257           0 :   uint8_t newmv_count = 0;
     258             : 
     259           0 :   mi_pos.row = row_offset;
     260           0 :   mi_pos.col = col_offset;
     261             : 
     262           0 :   if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
     263           0 :       *refmv_count < MAX_REF_MV_STACK_SIZE) {
     264           0 :     const MODE_INFO *const candidate_mi =
     265           0 :         xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
     266           0 :     const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
     267           0 :     const int len = mi_size_wide[BLOCK_8X8];
     268             : 
     269           0 :     newmv_count += add_ref_mv_candidate(
     270             :         candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
     271             :         cm->allow_high_precision_mv, len, block, mi_pos.col);
     272             :   }  // Analyze a single 8x8 block motion information.
     273             : 
     274           0 :   return newmv_count;
     275             : }
     276             : 
     277           0 : static int has_top_right(const MACROBLOCKD *xd, int mi_row, int mi_col,
     278             :                          int bs) {
     279           0 :   const int mask_row = mi_row & MAX_MIB_MASK;
     280           0 :   const int mask_col = mi_col & MAX_MIB_MASK;
     281             : 
     282             :   // In a split partition all apart from the bottom right has a top right
     283           0 :   int has_tr = !((mask_row & bs) && (mask_col & bs));
     284             : 
     285             :   // bs > 0 and bs is a power of 2
     286           0 :   assert(bs > 0 && !(bs & (bs - 1)));
     287             : 
     288             :   // For each 4x4 group of blocks, when the bottom right is decoded the blocks
     289             :   // to the right have not been decoded therefore the bottom right does
     290             :   // not have a top right
     291           0 :   while (bs < MAX_MIB_SIZE) {
     292           0 :     if (mask_col & bs) {
     293           0 :       if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
     294           0 :         has_tr = 0;
     295           0 :         break;
     296             :       }
     297             :     } else {
     298           0 :       break;
     299             :     }
     300           0 :     bs <<= 1;
     301             :   }
     302             : 
     303             :   // The left hand of two vertical rectangles always has a top right (as the
     304             :   // block above will have been decoded)
     305           0 :   if (xd->n8_w < xd->n8_h)
     306           0 :     if (!xd->is_sec_rect) has_tr = 1;
     307             : 
     308             :   // The bottom of two horizontal rectangles never has a top right (as the block
     309             :   // to the right won't have been decoded)
     310           0 :   if (xd->n8_w > xd->n8_h)
     311           0 :     if (xd->is_sec_rect) has_tr = 0;
     312             : 
     313             : #if CONFIG_EXT_PARTITION_TYPES
     314             :   // The bottom left square of a Vertical A does not have a top right as it is
     315             :   // decoded before the right hand rectangle of the partition
     316             :   if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
     317             :     if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
     318             : #endif  // CONFIG_EXT_PARTITION_TYPES
     319             : 
     320           0 :   return has_tr;
     321             : }
     322             : 
     323           0 : static int add_col_ref_mv(const AV1_COMMON *cm,
     324             :                           const MV_REF *prev_frame_mvs_base,
     325             :                           const MACROBLOCKD *xd, int mi_row, int mi_col,
     326             :                           MV_REFERENCE_FRAME ref_frame, int blk_row,
     327             :                           int blk_col, uint8_t *refmv_count,
     328             :                           CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
     329           0 :   const MV_REF *prev_frame_mvs =
     330           0 :       prev_frame_mvs_base + blk_row * cm->mi_cols + blk_col;
     331             :   POSITION mi_pos;
     332             :   int ref, idx;
     333           0 :   int coll_blk_count = 0;
     334           0 :   const int weight_unit = mi_size_wide[BLOCK_8X8];
     335             : 
     336             : #if CONFIG_MV_COMPRESS
     337           0 :   mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
     338           0 :   mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
     339             : #else
     340             :   mi_pos.row = blk_row;
     341             :   mi_pos.col = blk_col;
     342             : #endif
     343             : 
     344           0 :   if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
     345           0 :     return coll_blk_count;
     346           0 :   for (ref = 0; ref < 2; ++ref) {
     347           0 :     if (prev_frame_mvs->ref_frame[ref] == ref_frame) {
     348           0 :       int_mv this_refmv = prev_frame_mvs->mv[ref];
     349           0 :       lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
     350             : 
     351           0 :       if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16)
     352           0 :         mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
     353             : 
     354           0 :       for (idx = 0; idx < *refmv_count; ++idx)
     355           0 :         if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
     356             : 
     357           0 :       if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
     358             : 
     359           0 :       if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
     360           0 :         ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
     361           0 :         ref_mv_stack[idx].pred_diff[0] =
     362           0 :             av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
     363           0 :         ref_mv_stack[idx].weight = 2 * weight_unit;
     364           0 :         ++(*refmv_count);
     365             :       }
     366             : 
     367           0 :       ++coll_blk_count;
     368             :     }
     369             :   }
     370             : 
     371           0 :   return coll_blk_count;
     372             : }
     373             : 
     374           0 : static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
     375             :                               MV_REFERENCE_FRAME ref_frame,
     376             :                               uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
     377             :                               int_mv *mv_ref_list, int block, int mi_row,
     378             :                               int mi_col, int16_t *mode_context) {
     379           0 :   int idx, nearest_refmv_count = 0;
     380           0 :   uint8_t newmv_count = 0;
     381             :   CANDIDATE_MV tmp_mv;
     382             :   int len, nr_len;
     383             : 
     384             : #if CONFIG_MV_COMPRESS
     385           0 :   const MV_REF *const prev_frame_mvs_base =
     386           0 :       cm->use_prev_frame_mvs
     387           0 :           ? cm->prev_frame->mvs + (((mi_row >> 1) << 1) + 1) * cm->mi_cols +
     388           0 :                 ((mi_col >> 1) << 1) + 1
     389           0 :           : NULL;
     390             : #else
     391             :   const MV_REF *const prev_frame_mvs_base =
     392             :       cm->use_prev_frame_mvs
     393             :           ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
     394             :           : NULL;
     395             : #endif
     396             : 
     397           0 :   const int bs = AOMMAX(xd->n8_w, xd->n8_h);
     398           0 :   const int has_tr = has_top_right(xd, mi_row, mi_col, bs);
     399             :   MV_REFERENCE_FRAME rf[2];
     400             : 
     401           0 :   av1_set_ref_frame(rf, ref_frame);
     402           0 :   mode_context[ref_frame] = 0;
     403           0 :   *refmv_count = 0;
     404             : 
     405             :   // Scan the first above row mode info.
     406           0 :   newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
     407             :                                ref_mv_stack, refmv_count);
     408             :   // Scan the first left column mode info.
     409           0 :   newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
     410             :                                ref_mv_stack, refmv_count);
     411             : 
     412             :   // Check top-right boundary
     413           0 :   if (has_tr)
     414           0 :     newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
     415           0 :                                  xd->n8_w, ref_mv_stack, refmv_count);
     416             : 
     417           0 :   nearest_refmv_count = *refmv_count;
     418             : 
     419           0 :   for (idx = 0; idx < nearest_refmv_count; ++idx)
     420           0 :     ref_mv_stack[idx].weight += REF_CAT_LEVEL;
     421             : #if CONFIG_TEMPMV_SIGNALING
     422           0 :   if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME) {
     423             : #else
     424             :   if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
     425             :       rf[1] == NONE_FRAME) {
     426             : #endif
     427             :     int blk_row, blk_col;
     428           0 :     int coll_blk_count = 0;
     429             : #if CONFIG_CB4X4
     430           0 :     const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
     431           0 :                             ? mi_size_wide[BLOCK_8X8]
     432           0 :                             : mi_size_wide[BLOCK_16X16];
     433             : #else
     434             :     const int mi_step = mi_size_wide[BLOCK_16X16];
     435             : #endif
     436             : 
     437             : #if CONFIG_TPL_MV
     438             :     int tpl_sample_pos[5][2] = { { -1, xd->n8_w },
     439             :                                  { 0, xd->n8_w },
     440             :                                  { xd->n8_h, xd->n8_w },
     441             :                                  { xd->n8_h, 0 },
     442             :                                  { xd->n8_h, -1 } };
     443             :     int i;
     444             : #endif
     445             : 
     446           0 :     for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
     447           0 :       for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
     448           0 :         coll_blk_count += add_col_ref_mv(
     449             :             cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
     450             :             blk_col, refmv_count, ref_mv_stack, mode_context);
     451             :       }
     452             :     }
     453             : 
     454             : #if CONFIG_TPL_MV
     455             :     for (i = 0; i < 5; ++i) {
     456             :       blk_row = tpl_sample_pos[i][0];
     457             :       blk_col = tpl_sample_pos[i][1];
     458             :       coll_blk_count += add_col_ref_mv(cm, prev_frame_mvs_base, xd, mi_row,
     459             :                                        mi_col, ref_frame, blk_row, blk_col,
     460             :                                        refmv_count, ref_mv_stack, mode_context);
     461             :     }
     462             : #endif
     463             : 
     464           0 :     if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
     465             :   } else {
     466           0 :     mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
     467             :   }
     468             : 
     469             :   // Scan the second outer area.
     470           0 :   scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
     471             :                 refmv_count);
     472           0 :   for (idx = 2; idx <= 3; ++idx) {
     473           0 :     scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
     474             :                   refmv_count);
     475           0 :     scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
     476             :                   refmv_count);
     477             :   }
     478           0 :   scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -4, ref_mv_stack,
     479             :                 refmv_count);
     480             : 
     481           0 :   switch (nearest_refmv_count) {
     482             :     case 0:
     483           0 :       mode_context[ref_frame] |= 0;
     484           0 :       if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
     485             : 
     486           0 :       if (*refmv_count == 1)
     487           0 :         mode_context[ref_frame] |= (1 << REFMV_OFFSET);
     488           0 :       else if (*refmv_count >= 2)
     489           0 :         mode_context[ref_frame] |= (2 << REFMV_OFFSET);
     490           0 :       break;
     491             :     case 1:
     492           0 :       mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
     493             : 
     494           0 :       if (*refmv_count == 1)
     495           0 :         mode_context[ref_frame] |= (3 << REFMV_OFFSET);
     496           0 :       else if (*refmv_count >= 2)
     497           0 :         mode_context[ref_frame] |= (4 << REFMV_OFFSET);
     498           0 :       break;
     499             : 
     500             :     case 2:
     501             :     default:
     502           0 :       if (newmv_count >= 2)
     503           0 :         mode_context[ref_frame] |= 4;
     504           0 :       else if (newmv_count == 1)
     505           0 :         mode_context[ref_frame] |= 5;
     506             :       else
     507           0 :         mode_context[ref_frame] |= 6;
     508             : 
     509           0 :       mode_context[ref_frame] |= (5 << REFMV_OFFSET);
     510           0 :       break;
     511             :   }
     512             : 
     513             :   // Rank the likelihood and assign nearest and near mvs.
     514           0 :   len = nearest_refmv_count;
     515           0 :   while (len > 0) {
     516           0 :     nr_len = 0;
     517           0 :     for (idx = 1; idx < len; ++idx) {
     518           0 :       if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
     519           0 :         tmp_mv = ref_mv_stack[idx - 1];
     520           0 :         ref_mv_stack[idx - 1] = ref_mv_stack[idx];
     521           0 :         ref_mv_stack[idx] = tmp_mv;
     522           0 :         nr_len = idx;
     523             :       }
     524             :     }
     525           0 :     len = nr_len;
     526             :   }
     527             : 
     528           0 :   len = *refmv_count;
     529           0 :   while (len > nearest_refmv_count) {
     530           0 :     nr_len = nearest_refmv_count;
     531           0 :     for (idx = nearest_refmv_count + 1; idx < len; ++idx) {
     532           0 :       if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
     533           0 :         tmp_mv = ref_mv_stack[idx - 1];
     534           0 :         ref_mv_stack[idx - 1] = ref_mv_stack[idx];
     535           0 :         ref_mv_stack[idx] = tmp_mv;
     536           0 :         nr_len = idx;
     537             :       }
     538             :     }
     539           0 :     len = nr_len;
     540             :   }
     541             : 
     542           0 :   if (rf[1] > NONE_FRAME) {
     543           0 :     for (idx = 0; idx < *refmv_count; ++idx) {
     544           0 :       clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
     545           0 :                    xd->n8_h << MI_SIZE_LOG2, xd);
     546           0 :       clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
     547           0 :                    xd->n8_h << MI_SIZE_LOG2, xd);
     548             :     }
     549             :   } else {
     550           0 :     for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
     551           0 :       mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
     552           0 :       clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
     553           0 :                    xd->n8_h << MI_SIZE_LOG2, xd);
     554             :     }
     555             :   }
     556           0 : }
     557             : 
     558             : // This function searches the neighbourhood of a given MB/SB
     559             : // to try and find candidate reference vectors.
     560           0 : static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
     561             :                              MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
     562             :                              int_mv *mv_ref_list, int block, int mi_row,
     563             :                              int mi_col, find_mv_refs_sync sync,
     564             :                              void *const data, int16_t *mode_context,
     565             :                              int_mv zeromv) {
     566           0 :   const int *ref_sign_bias = cm->ref_frame_sign_bias;
     567           0 :   int i, refmv_count = 0;
     568           0 :   int different_ref_found = 0;
     569           0 :   int context_counter = 0;
     570             : #if CONFIG_MV_COMPRESS
     571           0 :   const TileInfo *const tile_ = &xd->tile;
     572           0 :   int mi_row_end = tile_->mi_row_end;
     573           0 :   int mi_col_end = tile_->mi_col_end;
     574           0 :   const MV_REF *const prev_frame_mvs =
     575           0 :       cm->use_prev_frame_mvs
     576           0 :           ? cm->prev_frame->mvs +
     577           0 :                 AOMMIN(((mi_row >> 1) << 1) + 1 + (((xd->n8_h - 1) >> 1) << 1),
     578           0 :                        mi_row_end - 1) *
     579           0 :                     cm->mi_cols +
     580           0 :                 AOMMIN(((mi_col >> 1) << 1) + 1 + (((xd->n8_w - 1) >> 1) << 1),
     581             :                        mi_col_end - 1)
     582           0 :           : NULL;
     583             : #else
     584             :   const MV_REF *const prev_frame_mvs =
     585             :       cm->use_prev_frame_mvs
     586             :           ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
     587             :           : NULL;
     588             : #endif
     589             : #if CONFIG_INTRABC
     590             :   assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
     591             : #endif
     592           0 :   const TileInfo *const tile = &xd->tile;
     593           0 :   const BLOCK_SIZE bsize = mi->mbmi.sb_type;
     594           0 :   const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
     595           0 :   const int bh = block_size_high[AOMMAX(bsize, BLOCK_8X8)];
     596             :   POSITION mv_ref_search[MVREF_NEIGHBOURS];
     597           0 :   const int num_8x8_blocks_wide = num_8x8_blocks_wide_lookup[bsize];
     598           0 :   const int num_8x8_blocks_high = num_8x8_blocks_high_lookup[bsize];
     599           0 :   mv_ref_search[0].row = num_8x8_blocks_high - 1;
     600           0 :   mv_ref_search[0].col = -1;
     601           0 :   mv_ref_search[1].row = -1;
     602           0 :   mv_ref_search[1].col = num_8x8_blocks_wide - 1;
     603           0 :   mv_ref_search[2].row = -1;
     604           0 :   mv_ref_search[2].col = (num_8x8_blocks_wide - 1) >> 1;
     605           0 :   mv_ref_search[3].row = (num_8x8_blocks_high - 1) >> 1;
     606           0 :   mv_ref_search[3].col = -1;
     607           0 :   mv_ref_search[4].row = -1;
     608           0 :   mv_ref_search[4].col = -1;
     609             : #if CONFIG_EXT_PARTITION_TYPES
     610             :   if (num_8x8_blocks_wide == num_8x8_blocks_high) {
     611             :     mv_ref_search[5].row = -1;
     612             :     mv_ref_search[5].col = 0;
     613             :     mv_ref_search[6].row = 0;
     614             :     mv_ref_search[6].col = -1;
     615             :   } else {
     616             :     mv_ref_search[5].row = -1;
     617             :     mv_ref_search[5].col = num_8x8_blocks_wide;
     618             :     mv_ref_search[6].row = num_8x8_blocks_high;
     619             :     mv_ref_search[6].col = -1;
     620             :   }
     621             : #else
     622           0 :   mv_ref_search[5].row = -1;
     623           0 :   mv_ref_search[5].col = num_8x8_blocks_wide;
     624           0 :   mv_ref_search[6].row = num_8x8_blocks_high;
     625           0 :   mv_ref_search[6].col = -1;
     626             : #endif  // CONFIG_EXT_PARTITION_TYPES
     627           0 :   mv_ref_search[7].row = -1;
     628           0 :   mv_ref_search[7].col = -3;
     629           0 :   mv_ref_search[8].row = num_8x8_blocks_high - 1;
     630           0 :   mv_ref_search[8].col = -3;
     631             : 
     632             : #if CONFIG_CB4X4
     633           0 :   for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
     634           0 :     mv_ref_search[i].row *= 2;
     635           0 :     mv_ref_search[i].col *= 2;
     636             :   }
     637             : #endif  // CONFIG_CB4X4
     638             : 
     639             :   // The nearest 2 blocks are treated differently
     640             :   // if the size < 8x8 we get the mv from the bmi substructure,
     641             :   // and we also need to keep a mode count.
     642           0 :   for (i = 0; i < 2; ++i) {
     643           0 :     const POSITION *const mv_ref = &mv_ref_search[i];
     644           0 :     if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
     645           0 :       const MODE_INFO *const candidate_mi =
     646           0 :           xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
     647           0 :       const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
     648             :       // Keep counts for entropy encoding.
     649           0 :       context_counter += mode_2_counter[candidate->mode];
     650           0 :       different_ref_found = 1;
     651             : 
     652           0 :       if (candidate->ref_frame[0] == ref_frame)
     653           0 :         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
     654             :                         refmv_count, mv_ref_list, bw, bh, xd, Done);
     655           0 :       else if (candidate->ref_frame[1] == ref_frame)
     656           0 :         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
     657             :                         refmv_count, mv_ref_list, bw, bh, xd, Done);
     658             :     }
     659             :   }
     660             : 
     661             :   // Check the rest of the neighbors in much the same way
     662             :   // as before except we don't need to keep track of sub blocks or
     663             :   // mode counts.
     664           0 :   for (; i < MVREF_NEIGHBOURS; ++i) {
     665           0 :     const POSITION *const mv_ref = &mv_ref_search[i];
     666           0 :     if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
     667           0 :       const MB_MODE_INFO *const candidate =
     668           0 :           !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
     669             :               ? NULL
     670           0 :               : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
     671           0 :       if (candidate == NULL) continue;
     672           0 :       if ((mi_row % MAX_MIB_SIZE) + mv_ref->row >= MAX_MIB_SIZE ||
     673           0 :           (mi_col % MAX_MIB_SIZE) + mv_ref->col >= MAX_MIB_SIZE)
     674           0 :         continue;
     675           0 :       different_ref_found = 1;
     676             : 
     677           0 :       if (candidate->ref_frame[0] == ref_frame)
     678           0 :         ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
     679             :                         Done);
     680           0 :       else if (candidate->ref_frame[1] == ref_frame)
     681           0 :         ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
     682             :                         Done);
     683             :     }
     684             :   }
     685             : 
     686             : // TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
     687             : // on windows platform. The sync here is unncessary if use_perv_frame_mvs
     688             : // is 0. But after removing it, there will be hang in the unit test on windows
     689             : // due to several threads waiting for a thread's signal.
     690             : #if defined(_WIN32) && !HAVE_PTHREAD_H
     691             :   if (cm->frame_parallel_decode && sync != NULL) {
     692             :     sync(data, mi_row);
     693             :   }
     694             : #endif
     695             : 
     696             :   // Check the last frame's mode and mv info.
     697           0 :   if (cm->use_prev_frame_mvs) {
     698             :     // Synchronize here for frame parallel decode if sync function is provided.
     699           0 :     if (cm->frame_parallel_decode && sync != NULL) {
     700           0 :       sync(data, mi_row);
     701             :     }
     702             : 
     703           0 :     if (prev_frame_mvs->ref_frame[0] == ref_frame) {
     704           0 :       ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, bw, bh,
     705             :                       xd, Done);
     706           0 :     } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
     707           0 :       ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, bw, bh,
     708             :                       xd, Done);
     709             :     }
     710             :   }
     711             : 
     712             :   // Since we couldn't find 2 mvs from the same reference frame
     713             :   // go back through the neighbors and find motion vectors from
     714             :   // different reference frames.
     715           0 :   if (different_ref_found) {
     716           0 :     for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
     717           0 :       const POSITION *mv_ref = &mv_ref_search[i];
     718           0 :       if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
     719           0 :         const MB_MODE_INFO *const candidate =
     720           0 :             !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
     721             :                 ? NULL
     722           0 :                 : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
     723           0 :         if (candidate == NULL) continue;
     724           0 :         if ((mi_row % MAX_MIB_SIZE) + mv_ref->row >= MAX_MIB_SIZE ||
     725           0 :             (mi_col % MAX_MIB_SIZE) + mv_ref->col >= MAX_MIB_SIZE)
     726           0 :           continue;
     727             : 
     728             :         // If the candidate is INTRA we don't want to consider its mv.
     729           0 :         IF_DIFF_REF_FRAME_ADD_MV(candidate, ref_frame, ref_sign_bias,
     730             :                                  refmv_count, mv_ref_list, bw, bh, xd, Done);
     731             :       }
     732             :     }
     733             :   }
     734             : 
     735             :   // Since we still don't have a candidate we'll try the last frame.
     736           0 :   if (cm->use_prev_frame_mvs) {
     737           0 :     if (prev_frame_mvs->ref_frame[0] != ref_frame &&
     738           0 :         prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
     739           0 :       int_mv mv = prev_frame_mvs->mv[0];
     740           0 :       if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
     741           0 :           ref_sign_bias[ref_frame]) {
     742           0 :         mv.as_mv.row *= -1;
     743           0 :         mv.as_mv.col *= -1;
     744             :       }
     745           0 :       ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
     746             :     }
     747             : 
     748           0 :     if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
     749           0 :         prev_frame_mvs->ref_frame[1] != ref_frame) {
     750           0 :       int_mv mv = prev_frame_mvs->mv[1];
     751           0 :       if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
     752           0 :           ref_sign_bias[ref_frame]) {
     753           0 :         mv.as_mv.row *= -1;
     754           0 :         mv.as_mv.col *= -1;
     755             :       }
     756           0 :       ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
     757             :     }
     758             :   }
     759             : 
     760             : Done:
     761           0 :   if (mode_context)
     762           0 :     mode_context[ref_frame] = counter_to_context[context_counter];
     763           0 :   for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
     764           0 :     mv_ref_list[i].as_int = zeromv.as_int;
     765           0 : }
     766             : 
     767             : #if CONFIG_EXT_INTER
     768             : // This function keeps a mode count for a given MB/SB
     769           0 : void av1_update_mv_context(const AV1_COMMON *cm, const MACROBLOCKD *xd,
     770             :                            MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
     771             :                            int_mv *mv_ref_list, int block, int mi_row,
     772             :                            int mi_col, int16_t *mode_context) {
     773           0 :   int i, refmv_count = 0;
     774           0 :   int context_counter = 0;
     775           0 :   const int bw = block_size_wide[mi->mbmi.sb_type];
     776           0 :   const int bh = block_size_high[mi->mbmi.sb_type];
     777           0 :   const TileInfo *const tile = &xd->tile;
     778             :   POSITION mv_ref_search[2];
     779           0 :   const int num_8x8_blocks_wide = mi_size_wide[mi->mbmi.sb_type];
     780           0 :   const int num_8x8_blocks_high = mi_size_high[mi->mbmi.sb_type];
     781             : 
     782           0 :   mv_ref_search[0].row = num_8x8_blocks_high - 1;
     783           0 :   mv_ref_search[0].col = -1;
     784           0 :   mv_ref_search[1].row = -1;
     785           0 :   mv_ref_search[1].col = num_8x8_blocks_wide - 1;
     786             : 
     787             :   // Blank the reference vector list
     788           0 :   memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
     789             : 
     790             :   // The nearest 2 blocks are examined only.
     791             :   // If the size < 8x8, we get the mv from the bmi substructure;
     792           0 :   for (i = 0; i < 2; ++i) {
     793           0 :     const POSITION *const mv_ref = &mv_ref_search[i];
     794           0 :     if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
     795           0 :       const MODE_INFO *const candidate_mi =
     796           0 :           xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
     797           0 :       const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
     798             : 
     799             :       // Keep counts for entropy encoding.
     800           0 :       context_counter += mode_2_counter[candidate->mode];
     801             : 
     802           0 :       if (candidate->ref_frame[0] == ref_frame) {
     803           0 :         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
     804             :                         refmv_count, mv_ref_list, bw, bh, xd, Done);
     805           0 :       } else if (candidate->ref_frame[1] == ref_frame) {
     806           0 :         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
     807             :                         refmv_count, mv_ref_list, bw, bh, xd, Done);
     808             :       }
     809             :     }
     810             :   }
     811             : 
     812             : Done:
     813             : 
     814           0 :   if (mode_context)
     815           0 :     mode_context[ref_frame] = counter_to_context[context_counter];
     816           0 : }
     817             : #endif  // CONFIG_EXT_INTER
     818             : 
     819           0 : void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
     820             :                       MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
     821             :                       uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack,
     822             : #if CONFIG_EXT_INTER
     823             :                       int16_t *compound_mode_context,
     824             : #endif  // CONFIG_EXT_INTER
     825             :                       int_mv *mv_ref_list, int mi_row, int mi_col,
     826             :                       find_mv_refs_sync sync, void *const data,
     827             :                       int16_t *mode_context) {
     828             :   int_mv zeromv[2];
     829             : #if CONFIG_GLOBAL_MOTION
     830           0 :   BLOCK_SIZE bsize = mi->mbmi.sb_type;
     831             : #endif  // CONFIG_GLOBAL_MOTION
     832           0 :   int idx, all_zero = 1;
     833             : #if CONFIG_GLOBAL_MOTION
     834             :   MV_REFERENCE_FRAME rf[2];
     835             : #endif  // CONFIG_GLOBAL_MOTION
     836             : 
     837             : #if CONFIG_EXT_INTER
     838           0 :   av1_update_mv_context(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
     839             :                         compound_mode_context);
     840             : #endif  // CONFIG_EXT_INTER
     841             : 
     842             : #if CONFIG_GLOBAL_MOTION
     843           0 :   av1_set_ref_frame(rf, ref_frame);
     844           0 :   zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
     845             :                                           cm->allow_high_precision_mv, bsize,
     846             :                                           mi_col, mi_row, 0)
     847           0 :                          .as_int;
     848           0 :   zeromv[1].as_int = (rf[1] != NONE_FRAME)
     849           0 :                          ? gm_get_motion_vector(&cm->global_motion[rf[1]],
     850             :                                                 cm->allow_high_precision_mv,
     851             :                                                 bsize, mi_col, mi_row, 0)
     852             :                                .as_int
     853           0 :                          : 0;
     854             : #else
     855             :   zeromv[0].as_int = zeromv[1].as_int = 0;
     856             : #endif  // CONFIG_GLOBAL_MOTION
     857             : 
     858           0 :   if (ref_frame <= ALTREF_FRAME)
     859           0 :     find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
     860             :                      sync, data, mode_context, zeromv[0]);
     861             : 
     862           0 :   setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
     863             :                     -1, mi_row, mi_col, mode_context);
     864             :   /* Note: If global motion is enabled, then we want to set the ALL_ZERO flag
     865             :      iff all of the MVs we could generate with NEARMV/NEARESTMV are equivalent
     866             :      to the global motion vector.
     867             :      Note: For the following to work properly, the encoder can't throw away
     868             :      any global motion models after calling this function, even if they are
     869             :      unused. Instead we rely on the recode loop: If any non-IDENTITY model
     870             :      is unused, the whole frame will be re-encoded without it.
     871             :      The problem is that, otherwise, we can end up in the following situation:
     872             :      * Encoder has a global motion model with nonzero translational part,
     873             :        and all candidate MVs are zero. So the ALL_ZERO flag is unset.
     874             :      * Encoder throws away global motion because it is never used.
     875             :      * Decoder sees that there is no global motion and all candidate MVs are
     876             :        zero, so sets the ALL_ZERO flag.
     877             :      * This leads to an encode/decode mismatch.
     878             :   */
     879           0 :   if (*ref_mv_count >= 2) {
     880           0 :     for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
     881           0 :       if (ref_mv_stack[idx].this_mv.as_int != zeromv[0].as_int) all_zero = 0;
     882           0 :       if (ref_frame > ALTREF_FRAME)
     883           0 :         if (ref_mv_stack[idx].comp_mv.as_int != zeromv[1].as_int) all_zero = 0;
     884             :     }
     885           0 :   } else if (ref_frame <= ALTREF_FRAME) {
     886           0 :     for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
     887           0 :       if (mv_ref_list[idx].as_int != zeromv[0].as_int) all_zero = 0;
     888             :   }
     889             : 
     890           0 :   if (all_zero) mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
     891           0 : }
     892             : 
     893           0 : void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,
     894             :                            int_mv *near_mv) {
     895             :   int i;
     896             :   // Make sure all the candidates are properly clamped etc
     897           0 :   for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
     898           0 :     lower_mv_precision(&mvlist[i].as_mv, allow_hp);
     899             :   }
     900           0 :   *nearest_mv = mvlist[0];
     901           0 :   *near_mv = mvlist[1];
     902           0 : }
     903             : 
     904           0 : void av1_append_sub8x8_mvs_for_idx(const AV1_COMMON *cm, MACROBLOCKD *xd,
     905             :                                    int block, int ref, int mi_row, int mi_col,
     906             :                                    CANDIDATE_MV *ref_mv_stack,
     907             :                                    uint8_t *ref_mv_count,
     908             : #if CONFIG_EXT_INTER
     909             :                                    int_mv *mv_list,
     910             : #endif  // CONFIG_EXT_INTER
     911             :                                    int_mv *nearest_mv, int_mv *near_mv) {
     912             : #if !CONFIG_EXT_INTER
     913             :   int_mv mv_list[MAX_MV_REF_CANDIDATES];
     914             : #endif  // !CONFIG_EXT_INTER
     915           0 :   MODE_INFO *const mi = xd->mi[0];
     916           0 :   b_mode_info *bmi = mi->bmi;
     917             :   int n;
     918             :   int_mv zeromv;
     919             :   CANDIDATE_MV tmp_mv;
     920             :   uint8_t idx;
     921           0 :   uint8_t above_count = 0, left_count = 0;
     922           0 :   MV_REFERENCE_FRAME rf[2] = { mi->mbmi.ref_frame[ref], NONE_FRAME };
     923           0 :   *ref_mv_count = 0;
     924             : 
     925             :   assert(MAX_MV_REF_CANDIDATES == 2);
     926             : 
     927             : #if CONFIG_GLOBAL_MOTION
     928           0 :   zeromv.as_int =
     929           0 :       gm_get_motion_vector(&cm->global_motion[ref], cm->allow_high_precision_mv,
     930           0 :                            mi->mbmi.sb_type, mi_col, mi_row, block)
     931           0 :           .as_int;
     932             : #else
     933             :   zeromv.as_int = 0;
     934             : #endif
     935           0 :   find_mv_refs_idx(cm, xd, mi, mi->mbmi.ref_frame[ref], mv_list, block, mi_row,
     936             :                    mi_col, NULL, NULL, NULL, zeromv);
     937             : 
     938           0 :   scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, 0, ref_mv_stack,
     939             :                 ref_mv_count);
     940           0 :   above_count = *ref_mv_count;
     941             : 
     942           0 :   scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, 0, -1, ref_mv_stack,
     943             :                 ref_mv_count);
     944           0 :   left_count = *ref_mv_count - above_count;
     945             : 
     946           0 :   if (above_count > 1 && left_count > 0) {
     947           0 :     tmp_mv = ref_mv_stack[1];
     948           0 :     ref_mv_stack[1] = ref_mv_stack[above_count];
     949           0 :     ref_mv_stack[above_count] = tmp_mv;
     950             :   }
     951             : 
     952           0 :   for (idx = 0; idx < *ref_mv_count; ++idx)
     953           0 :     clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
     954           0 :                  xd->n8_h << MI_SIZE_LOG2, xd);
     955             : 
     956           0 :   for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *ref_mv_count); ++idx)
     957           0 :     mv_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
     958             : 
     959           0 :   near_mv->as_int = 0;
     960           0 :   switch (block) {
     961             :     case 0:
     962           0 :       nearest_mv->as_int = mv_list[0].as_int;
     963           0 :       near_mv->as_int = mv_list[1].as_int;
     964           0 :       break;
     965             :     case 1:
     966             :     case 2:
     967           0 :       nearest_mv->as_int = bmi[0].as_mv[ref].as_int;
     968           0 :       for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
     969           0 :         if (nearest_mv->as_int != mv_list[n].as_int) {
     970           0 :           near_mv->as_int = mv_list[n].as_int;
     971           0 :           break;
     972             :         }
     973           0 :       break;
     974             :     case 3: {
     975             :       int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
     976           0 :       candidates[0] = bmi[1].as_mv[ref];
     977           0 :       candidates[1] = bmi[0].as_mv[ref];
     978           0 :       candidates[2] = mv_list[0];
     979           0 :       candidates[3] = mv_list[1];
     980             : 
     981           0 :       nearest_mv->as_int = bmi[2].as_mv[ref].as_int;
     982           0 :       for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
     983           0 :         if (nearest_mv->as_int != candidates[n].as_int) {
     984           0 :           near_mv->as_int = candidates[n].as_int;
     985           0 :           break;
     986             :         }
     987           0 :       break;
     988             :     }
     989           0 :     default: assert(0 && "Invalid block index.");
     990             :   }
     991           0 : }
     992             : 
     993             : #if CONFIG_WARPED_MOTION
     994           0 : void calc_projection_samples(MB_MODE_INFO *const mbmi, int x, int y,
     995             :                              int *pts_inref) {
     996           0 :   pts_inref[0] = (x * 8) + mbmi->mv[0].as_mv.col;
     997           0 :   pts_inref[1] = (y * 8) + mbmi->mv[0].as_mv.row;
     998           0 : }
     999             : 
    1000             : // Note: Samples returned are at 1/8-pel precision
    1001           0 : int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
    1002             :                 int *pts, int *pts_inref) {
    1003           0 :   MB_MODE_INFO *const mbmi0 = &(xd->mi[0]->mbmi);
    1004           0 :   int ref_frame = mbmi0->ref_frame[0];
    1005           0 :   int up_available = xd->up_available;
    1006           0 :   int left_available = xd->left_available;
    1007           0 :   int i, mi_step, np = 0;
    1008           0 :   int global_offset_c = mi_col * MI_SIZE;
    1009           0 :   int global_offset_r = mi_row * MI_SIZE;
    1010             : 
    1011             :   // scan the above row
    1012           0 :   if (up_available) {
    1013           0 :     for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
    1014           0 :       int mi_row_offset = -1;
    1015           0 :       int mi_col_offset = i;
    1016             : 
    1017           0 :       MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
    1018           0 :       MB_MODE_INFO *mbmi = &mi->mbmi;
    1019             : 
    1020           0 :       mi_step = AOMMIN(xd->n8_w, mi_size_wide[mbmi->sb_type]);
    1021             : 
    1022           0 :       if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
    1023           0 :         int bw = block_size_wide[mbmi->sb_type];
    1024           0 :         int bh = block_size_high[mbmi->sb_type];
    1025           0 :         int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
    1026           0 :         int cc_offset = i * MI_SIZE + AOMMAX(bw, MI_SIZE) / 2 - 1;
    1027           0 :         int x = cc_offset + global_offset_c;
    1028           0 :         int y = cr_offset + global_offset_r;
    1029             : 
    1030           0 :         pts[0] = (x * 8);
    1031           0 :         pts[1] = (y * 8);
    1032           0 :         calc_projection_samples(mbmi, x, y, pts_inref);
    1033           0 :         pts += 2;
    1034           0 :         pts_inref += 2;
    1035           0 :         np++;
    1036           0 :         if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
    1037             :       }
    1038             :     }
    1039             :   }
    1040           0 :   assert(2 * np <= SAMPLES_ARRAY_SIZE);
    1041             : 
    1042             :   // scan the left column
    1043           0 :   if (left_available) {
    1044           0 :     for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
    1045           0 :       int mi_row_offset = i;
    1046           0 :       int mi_col_offset = -1;
    1047             : 
    1048           0 :       MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
    1049           0 :       MB_MODE_INFO *mbmi = &mi->mbmi;
    1050             : 
    1051           0 :       mi_step = AOMMIN(xd->n8_h, mi_size_high[mbmi->sb_type]);
    1052             : 
    1053           0 :       if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
    1054           0 :         int bw = block_size_wide[mbmi->sb_type];
    1055           0 :         int bh = block_size_high[mbmi->sb_type];
    1056           0 :         int cr_offset = i * MI_SIZE + AOMMAX(bh, MI_SIZE) / 2 - 1;
    1057           0 :         int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
    1058           0 :         int x = cc_offset + global_offset_c;
    1059           0 :         int y = cr_offset + global_offset_r;
    1060             : 
    1061           0 :         pts[0] = (x * 8);
    1062           0 :         pts[1] = (y * 8);
    1063           0 :         calc_projection_samples(mbmi, x, y, pts_inref);
    1064           0 :         pts += 2;
    1065           0 :         pts_inref += 2;
    1066           0 :         np++;
    1067           0 :         if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
    1068             :       }
    1069             :     }
    1070             :   }
    1071           0 :   assert(2 * np <= SAMPLES_ARRAY_SIZE);
    1072             : 
    1073           0 :   if (left_available && up_available) {
    1074           0 :     int mi_row_offset = -1;
    1075           0 :     int mi_col_offset = -1;
    1076             : 
    1077           0 :     MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
    1078           0 :     MB_MODE_INFO *mbmi = &mi->mbmi;
    1079             : 
    1080           0 :     if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
    1081           0 :       int bw = block_size_wide[mbmi->sb_type];
    1082           0 :       int bh = block_size_high[mbmi->sb_type];
    1083           0 :       int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
    1084           0 :       int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
    1085           0 :       int x = cc_offset + global_offset_c;
    1086           0 :       int y = cr_offset + global_offset_r;
    1087             : 
    1088           0 :       pts[0] = (x * 8);
    1089           0 :       pts[1] = (y * 8);
    1090           0 :       calc_projection_samples(mbmi, x, y, pts_inref);
    1091           0 :       np++;
    1092             :     }
    1093             :   }
    1094           0 :   assert(2 * np <= SAMPLES_ARRAY_SIZE);
    1095             : 
    1096           0 :   return np;
    1097             : }
    1098             : #endif  // CONFIG_WARPED_MOTION

Generated by: LCOV version 1.13