blob: 3b41f58aa7047ec0f7908b62672ce73be950e517 [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * 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.
Yaowu Xuc27fc142016-08-22 16:08:15 -070010 */
11
12#include "av1/common/mvref_common.h"
Yue Chen69f18e12016-09-08 14:48:15 -070013#include "av1/common/warped_motion.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070014
Sarah Parker0a5cc5f2017-10-03 17:53:53 -070015#define USE_CUR_GM_REFMV 1
Sarah Parker0a5cc5f2017-10-03 17:53:53 -070016
Yunqing Wangd1d511f2017-10-05 08:44:46 -070017void av1_copy_frame_mvs(const AV1_COMMON *const cm, MODE_INFO *mi, int mi_row,
18 int mi_col, int x_mis, int y_mis) {
Jingning Hanc7d198e2017-10-12 16:11:06 -070019#if CONFIG_TMV || CONFIG_MFMV
Yunqing Wangd1d511f2017-10-05 08:44:46 -070020 const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
Jingning Han17dc4c72017-10-10 09:37:43 -070021 MV_REF *frame_mvs =
22 cm->cur_frame->mvs + (mi_row >> 1) * frame_mvs_stride + (mi_col >> 1);
Yunqing Wangd1d511f2017-10-05 08:44:46 -070023 x_mis = ROUND_POWER_OF_TWO(x_mis, 1);
24 y_mis = ROUND_POWER_OF_TWO(y_mis, 1);
25#else
26 const int frame_mvs_stride = cm->mi_cols;
27 MV_REF *frame_mvs = cm->cur_frame->mvs +
28 (mi_row & 0xfffe) * frame_mvs_stride + (mi_col & 0xfffe);
29 x_mis = AOMMAX(x_mis, 2);
30 y_mis = AOMMAX(y_mis, 2);
31#endif // CONFIG_TMV
32 int w, h;
33
34 for (h = 0; h < y_mis; h++) {
Yunqing Wangb90a97a2017-10-24 11:50:15 -070035 MV_REF *mv = frame_mvs;
Yunqing Wangd1d511f2017-10-05 08:44:46 -070036 for (w = 0; w < x_mis; w++) {
Yunqing Wangd1d511f2017-10-05 08:44:46 -070037 mv->ref_frame[0] = mi->mbmi.ref_frame[0];
38 mv->ref_frame[1] = mi->mbmi.ref_frame[1];
39 mv->mv[0].as_int = mi->mbmi.mv[0].as_int;
40 mv->mv[1].as_int = mi->mbmi.mv[1].as_int;
41 // (TODO:yunqing) The following 2 lines won't be used and can be removed.
42 mv->pred_mv[0].as_int = mi->mbmi.pred_mv[0].as_int;
43 mv->pred_mv[1].as_int = mi->mbmi.pred_mv[1].as_int;
Yunqing Wangb90a97a2017-10-24 11:50:15 -070044 mv++;
Yunqing Wangd1d511f2017-10-05 08:44:46 -070045 }
Yunqing Wangb90a97a2017-10-24 11:50:15 -070046 frame_mvs += frame_mvs_stride;
Yunqing Wangd1d511f2017-10-05 08:44:46 -070047 }
48}
49
Sarah Parker0a5cc5f2017-10-03 17:53:53 -070050static uint8_t add_ref_mv_candidate(
51 const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
52 const MV_REFERENCE_FRAME rf[2], uint8_t *refmv_count,
53 CANDIDATE_MV *ref_mv_stack, const int use_hp, int len, int block,
Sebastien Alaiwan48795802017-10-30 12:07:13 +010054#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -070055 int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
Sebastien Alaiwan48795802017-10-30 12:07:13 +010056#endif // USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -070057 int col, int weight,
RogerZhou3b635242017-09-19 10:06:46 -070058#if CONFIG_AMVR
Yunqing Wang97d6a372017-10-09 14:15:15 -070059 int is_integer,
RogerZhou3b635242017-09-19 10:06:46 -070060#endif
Yunqing Wang97d6a372017-10-09 14:15:15 -070061 BLOCK_SIZE bsize, int mi_row, int mi_col, int subsampling_x,
62 int subsampling_y) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070063 int index = 0, ref;
64 int newmv_count = 0;
Yunqing Wangd1121fa2017-09-13 14:34:45 -070065 assert(weight % 2 == 0);
Yunqing Wang97d6a372017-10-09 14:15:15 -070066#if !CONFIG_EXT_WARPED_MOTION
67 (void)bsize;
68 (void)mi_row;
69 (void)mi_col;
70 (void)subsampling_x;
71 (void)subsampling_y;
72#endif // CONFIG_EXT_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070073
Emil Keyder01770b32017-01-20 18:03:11 -050074 if (rf[1] == NONE_FRAME) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070075 // single reference frame
76 for (ref = 0; ref < 2; ++ref) {
77 if (candidate->ref_frame[ref] == rf[0]) {
Sarah Parker0a5cc5f2017-10-03 17:53:53 -070078 int_mv this_refmv;
Yunqing Wang97d6a372017-10-09 14:15:15 -070079#if CONFIG_EXT_WARPED_MOTION
80 if (candidate->motion_mode == WARPED_CAUSAL) {
81 WarpedMotionParams wm = candidate->wm_params[0];
82 const int bw = block_size_wide[bsize];
83 const int bh = block_size_high[bsize];
84 int global_offset_c = mi_col * MI_SIZE;
85 int global_offset_r = mi_row * MI_SIZE;
86 int cc_offset = bw / 2 - 1;
87 int cr_offset = bh / 2 - 1;
88 int xc0 = cc_offset + global_offset_c;
89 int yc0 = cr_offset + global_offset_r;
90 int xc1 = xc0 + 1;
91 int yc1 = yc0 + 1;
92 int in[4] = { xc0, yc0, xc1, yc1 };
93 int out[4] = { 0, 0, 0, 0 };
94
95 assert(ref == 0);
96 // For WARPED_CAUSAL, wmtype is always AFFINE.
97 assert(wm.wmtype == AFFINE);
98 project_points_affine(wm.wmmat, in, out, 2, 2, 2, subsampling_x,
99 subsampling_y);
100
101 // assert(x_scale == 1024 && y_scale == 1024);
102 // out[]'s precision is 1/64, adjust xc, yc accordingly.
103 out[0] -= (xc0 << (3 + SCALING_FCT));
104 out[1] -= (yc0 << (3 + SCALING_FCT));
105 out[2] -= (xc1 << (3 + SCALING_FCT));
106 out[3] -= (yc1 << (3 + SCALING_FCT));
107
108 this_refmv.as_mv.col =
109 ROUND_POWER_OF_TWO_SIGNED(out[0] + out[2], SCALING_FCT + 1);
110 this_refmv.as_mv.row =
111 ROUND_POWER_OF_TWO_SIGNED(out[1] + out[3], SCALING_FCT + 1);
112 lower_mv_precision(&this_refmv.as_mv, use_hp);
113 } else {
114#endif // CONFIG_EXT_WARPED_MOTION
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100115#if USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700116 if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
117 this_refmv = gm_mv_candidates[0];
118 else
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100119#endif // USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700120 this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou3b635242017-09-19 10:06:46 -0700121#if CONFIG_AMVR
Yunqing Wang97d6a372017-10-09 14:15:15 -0700122 lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
RogerZhou3b635242017-09-19 10:06:46 -0700123#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700124 lower_mv_precision(&this_refmv.as_mv, use_hp);
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700125#endif // CONFIG_AMVR
Yunqing Wang97d6a372017-10-09 14:15:15 -0700126#if CONFIG_EXT_WARPED_MOTION
127 }
128#endif // CONFIG_EXT_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -0700129
130 for (index = 0; index < *refmv_count; ++index)
131 if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
132
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700133 if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700134
135 // Add a new item to the list.
Jonathan Matthewsca9132d2017-10-31 10:32:38 +0000136 if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700137 ref_mv_stack[index].this_mv = this_refmv;
Jingning Han3f338832016-11-18 11:01:48 -0800138 ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
139 get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700140 ref_mv_stack[index].weight = weight * len;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700141 ++(*refmv_count);
142
Zoe Liu7f24e1b2017-03-17 17:42:05 -0700143 if (candidate->mode == NEWMV) ++newmv_count;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700144 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700145 }
146 }
147 } else {
148 // compound reference frame
149 if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
150 int_mv this_refmv[2];
151
152 for (ref = 0; ref < 2; ++ref) {
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100153#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700154 if (is_global_mv_block(candidate_mi, block, gm_params[rf[ref]].wmtype))
155 this_refmv[ref] = gm_mv_candidates[ref];
156 else
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100157#endif // USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700158 this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou3b635242017-09-19 10:06:46 -0700159#if CONFIG_AMVR
160 lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
161#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700162 lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou3b635242017-09-19 10:06:46 -0700163#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700164 }
165
166 for (index = 0; index < *refmv_count; ++index)
167 if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
168 (ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
169 break;
170
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700171 if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700172
173 // Add a new item to the list.
Jonathan Matthewsca9132d2017-10-31 10:32:38 +0000174 if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700175 ref_mv_stack[index].this_mv = this_refmv[0];
176 ref_mv_stack[index].comp_mv = this_refmv[1];
Jingning Han3f338832016-11-18 11:01:48 -0800177 ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
178 get_sub_block_pred_mv(candidate_mi, 0, col, block), this_refmv[0]);
179 ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
180 get_sub_block_pred_mv(candidate_mi, 1, col, block), this_refmv[1]);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700181 ref_mv_stack[index].weight = weight * len;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700182 ++(*refmv_count);
183
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +0200184 if (candidate->mode == NEW_NEWMV) ++newmv_count;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700185 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700186 }
187 }
188 return newmv_count;
189}
190
Yaowu Xuf883b422016-08-30 14:01:10 -0700191static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang97d6a372017-10-09 14:15:15 -0700192 int mi_row, int mi_col, int block,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700193 const MV_REFERENCE_FRAME rf[2], int row_offset,
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700194 CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100195#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700196 int_mv *gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100197#endif // USE_CUR_GM_REFMV
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700198 int max_row_offset, int *processed_rows) {
Yunqing Wangd797ea92017-08-27 18:05:55 -0700199 const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700200 const int n8_w_8 = mi_size_wide[BLOCK_8X8];
201 const int n8_w_16 = mi_size_wide[BLOCK_16X16];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700202 int i;
203 uint8_t newmv_count = 0;
Jingning Han7f994772017-07-27 08:02:16 -0700204 int col_offset = 0;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700205 const int shift = 0;
Jingning Hanc016df82016-12-09 12:37:28 -0800206 // TODO(jingning): Revisit this part after cb4x4 is stable.
Jingning Han74978fc2017-07-27 15:27:55 -0700207 if (abs(row_offset) > 1) {
Jingning Han74978fc2017-07-27 15:27:55 -0700208 col_offset = 1;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700209 if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
Jingning Han7f994772017-07-27 08:02:16 -0700210 }
Yunqing Wangd797ea92017-08-27 18:05:55 -0700211 const int use_step_16 = (xd->n8_w >= 16);
Yunqing Wangd797ea92017-08-27 18:05:55 -0700212 MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700213
Jonathan Matthewsca9132d2017-10-31 10:32:38 +0000214 for (i = 0; i < end_mi;) {
Yunqing Wangd797ea92017-08-27 18:05:55 -0700215 const MODE_INFO *const candidate_mi = candidate_mi0[col_offset + i];
216 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700217 const int candidate_bsize = candidate->sb_type;
218 const int n8_w = mi_size_wide[candidate_bsize];
219 int len = AOMMIN(xd->n8_w, n8_w);
Yunqing Wangd797ea92017-08-27 18:05:55 -0700220 if (use_step_16)
221 len = AOMMAX(n8_w_16, len);
222 else if (abs(row_offset) > 1)
223 len = AOMMAX(len, n8_w_8);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700224
225 int weight = 2;
226 if (xd->n8_w >= n8_w_8 && xd->n8_w <= n8_w) {
227 int inc = AOMMIN(-max_row_offset + row_offset + 1,
228 mi_size_high[candidate_bsize]);
229 // Obtain range used in weight calculation.
230 weight = AOMMAX(weight, (inc << shift));
231 // Update processed rows.
232 *processed_rows = inc - row_offset - 1;
233 }
234
RogerZhou3b635242017-09-19 10:06:46 -0700235#if CONFIG_AMVR
236 newmv_count += add_ref_mv_candidate(
237 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700238 cm->allow_high_precision_mv, len, block,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100239#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700240 gm_mv_candidates, cm->global_motion,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100241#endif // USE_CUR_GM_REFMV
RogerZhou10a03802017-10-26 11:49:48 -0700242 col_offset + i, weight, cm->cur_frame_force_integer_mv,
Yunqing Wang97d6a372017-10-09 14:15:15 -0700243 xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
244 xd->plane[0].subsampling_y);
RogerZhou3b635242017-09-19 10:06:46 -0700245#else
Yunqing Wang97d6a372017-10-09 14:15:15 -0700246 newmv_count += add_ref_mv_candidate(
247 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
248 cm->allow_high_precision_mv, len, block,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100249#if USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700250 gm_mv_candidates, cm->global_motion,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100251#endif // USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700252 col_offset + i, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
253 xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou3b635242017-09-19 10:06:46 -0700254#endif
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700255
Yunqing Wangd797ea92017-08-27 18:05:55 -0700256 i += len;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700257 }
258
259 return newmv_count;
260}
261
Yaowu Xuf883b422016-08-30 14:01:10 -0700262static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang97d6a372017-10-09 14:15:15 -0700263 int mi_row, int mi_col, int block,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700264 const MV_REFERENCE_FRAME rf[2], int col_offset,
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700265 CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100266#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700267 int_mv *gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100268#endif // USE_CUR_GM_REFMV
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700269 int max_col_offset, int *processed_cols) {
Yunqing Wangd797ea92017-08-27 18:05:55 -0700270 const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700271 const int n8_h_8 = mi_size_high[BLOCK_8X8];
272 const int n8_h_16 = mi_size_high[BLOCK_16X16];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700273 int i;
274 uint8_t newmv_count = 0;
Jingning Han7f994772017-07-27 08:02:16 -0700275 int row_offset = 0;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700276 const int shift = 0;
Jingning Han74978fc2017-07-27 15:27:55 -0700277 if (abs(col_offset) > 1) {
Jingning Han74978fc2017-07-27 15:27:55 -0700278 row_offset = 1;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700279 if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
Jingning Han7f994772017-07-27 08:02:16 -0700280 }
Yunqing Wangd797ea92017-08-27 18:05:55 -0700281 const int use_step_16 = (xd->n8_h >= 16);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700282
Jonathan Matthewsca9132d2017-10-31 10:32:38 +0000283 for (i = 0; i < end_mi;) {
Yunqing Wangd797ea92017-08-27 18:05:55 -0700284 const MODE_INFO *const candidate_mi =
285 xd->mi[(row_offset + i) * xd->mi_stride + col_offset];
286 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700287 const int candidate_bsize = candidate->sb_type;
288 const int n8_h = mi_size_high[candidate_bsize];
289 int len = AOMMIN(xd->n8_h, n8_h);
Yunqing Wangd797ea92017-08-27 18:05:55 -0700290 if (use_step_16)
291 len = AOMMAX(n8_h_16, len);
292 else if (abs(col_offset) > 1)
293 len = AOMMAX(len, n8_h_8);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700294
295 int weight = 2;
296 if (xd->n8_h >= n8_h_8 && xd->n8_h <= n8_h) {
297 int inc = AOMMIN(-max_col_offset + col_offset + 1,
298 mi_size_wide[candidate_bsize]);
299 // Obtain range used in weight calculation.
300 weight = AOMMAX(weight, (inc << shift));
301 // Update processed cols.
302 *processed_cols = inc - col_offset - 1;
303 }
304
RogerZhou3b635242017-09-19 10:06:46 -0700305#if CONFIG_AMVR
306 newmv_count += add_ref_mv_candidate(
307 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700308 cm->allow_high_precision_mv, len, block,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100309#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700310 gm_mv_candidates, cm->global_motion,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100311#endif // USE_CUR_GM_REFMV
RogerZhou10a03802017-10-26 11:49:48 -0700312 col_offset, weight, cm->cur_frame_force_integer_mv,
Yunqing Wang97d6a372017-10-09 14:15:15 -0700313 xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
314 xd->plane[0].subsampling_y);
RogerZhou3b635242017-09-19 10:06:46 -0700315#else
Yunqing Wang97d6a372017-10-09 14:15:15 -0700316 newmv_count += add_ref_mv_candidate(
317 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
318 cm->allow_high_precision_mv, len, block,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100319#if USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700320 gm_mv_candidates, cm->global_motion,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100321#endif // USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700322 col_offset, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
323 xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou3b635242017-09-19 10:06:46 -0700324#endif
Yunqing Wangd797ea92017-08-27 18:05:55 -0700325 i += len;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700326 }
327
328 return newmv_count;
329}
330
Yaowu Xuf883b422016-08-30 14:01:10 -0700331static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700332 const int mi_row, const int mi_col, int block,
333 const MV_REFERENCE_FRAME rf[2], int row_offset,
334 int col_offset, CANDIDATE_MV *ref_mv_stack,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100335#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700336 int_mv *gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100337#endif // USE_CUR_GM_REFMV
Yaowu Xuc27fc142016-08-22 16:08:15 -0700338 uint8_t *refmv_count) {
339 const TileInfo *const tile = &xd->tile;
340 POSITION mi_pos;
341 uint8_t newmv_count = 0;
342
343 mi_pos.row = row_offset;
344 mi_pos.col = col_offset;
345
Jonathan Matthewsca9132d2017-10-31 10:32:38 +0000346 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700347 const MODE_INFO *const candidate_mi =
348 xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
349 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
Jingning Hanc016df82016-12-09 12:37:28 -0800350 const int len = mi_size_wide[BLOCK_8X8];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700351
RogerZhou3b635242017-09-19 10:06:46 -0700352#if CONFIG_AMVR
353 newmv_count += add_ref_mv_candidate(
354 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700355 cm->allow_high_precision_mv, len, block,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100356#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700357 gm_mv_candidates, cm->global_motion,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100358#endif // USE_CUR_GM_REFMV
RogerZhou10a03802017-10-26 11:49:48 -0700359 mi_pos.col, 2, cm->cur_frame_force_integer_mv, xd->mi[0]->mbmi.sb_type,
360 mi_row, mi_col, xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou3b635242017-09-19 10:06:46 -0700361#else
Yunqing Wang97d6a372017-10-09 14:15:15 -0700362 newmv_count += add_ref_mv_candidate(
363 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
364 cm->allow_high_precision_mv, len, block,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100365#if USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700366 gm_mv_candidates, cm->global_motion,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100367#endif // USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700368 mi_pos.col, 2, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
369 xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou3b635242017-09-19 10:06:46 -0700370#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700371 } // Analyze a single 8x8 block motion information.
Yaowu Xu4306b6e2016-09-27 12:55:32 -0700372
Yaowu Xuc27fc142016-08-22 16:08:15 -0700373 return newmv_count;
374}
375
David Barker761b1ac2017-09-25 11:23:03 +0100376static int has_top_right(const AV1_COMMON *cm, const MACROBLOCKD *xd,
377 int mi_row, int mi_col, int bs) {
378 const int sb_mi_size = mi_size_wide[cm->sb_size];
379 const int mask_row = mi_row & (sb_mi_size - 1);
380 const int mask_col = mi_col & (sb_mi_size - 1);
Jingning Han3eb1f072016-11-17 15:17:25 -0800381
Yaowu Xuc27fc142016-08-22 16:08:15 -0700382 // In a split partition all apart from the bottom right has a top right
Jingning Han3eb1f072016-11-17 15:17:25 -0800383 int has_tr = !((mask_row & bs) && (mask_col & bs));
Yaowu Xuc27fc142016-08-22 16:08:15 -0700384
385 // bs > 0 and bs is a power of 2
386 assert(bs > 0 && !(bs & (bs - 1)));
387
388 // For each 4x4 group of blocks, when the bottom right is decoded the blocks
389 // to the right have not been decoded therefore the bottom right does
390 // not have a top right
David Barker761b1ac2017-09-25 11:23:03 +0100391 while (bs < sb_mi_size) {
Jingning Han3eb1f072016-11-17 15:17:25 -0800392 if (mask_col & bs) {
393 if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700394 has_tr = 0;
395 break;
396 }
397 } else {
398 break;
399 }
400 bs <<= 1;
401 }
402
403 // The left hand of two vertical rectangles always has a top right (as the
404 // block above will have been decoded)
405 if (xd->n8_w < xd->n8_h)
406 if (!xd->is_sec_rect) has_tr = 1;
407
408 // The bottom of two horizontal rectangles never has a top right (as the block
409 // to the right won't have been decoded)
410 if (xd->n8_w > xd->n8_h)
411 if (xd->is_sec_rect) has_tr = 0;
412
Rupert Swarbrick3dd33912017-09-12 14:24:11 +0100413#if CONFIG_EXT_PARTITION_TYPES && !CONFIG_EXT_PARTITION_TYPES_AB
414 // The bottom left square of a Vertical A (in the old format) does
415 // not have a top right as it is decoded before the right hand
416 // rectangle of the partition
Yaowu Xuc27fc142016-08-22 16:08:15 -0700417 if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
Jingning Han3eb1f072016-11-17 15:17:25 -0800418 if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700419#endif // CONFIG_EXT_PARTITION_TYPES
420
421 return has_tr;
422}
423
Jingning Hanffbb0f92017-08-24 11:52:21 -0700424#if CONFIG_MFMV
David Barker761b1ac2017-09-25 11:23:03 +0100425static int check_sb_border(const AV1_COMMON *cm, const int mi_row,
426 const int mi_col, const int row_offset,
427 const int col_offset) {
428 const int sb_mi_size = mi_size_wide[cm->sb_size];
429 const int row = mi_row & (sb_mi_size - 1);
430 const int col = mi_col & (sb_mi_size - 1);
Jingning Han83c27ec2017-09-20 08:05:17 -0700431
David Barker761b1ac2017-09-25 11:23:03 +0100432 if (row + row_offset < 0 || row + row_offset >= sb_mi_size ||
433 col + col_offset < 0 || col + col_offset >= sb_mi_size)
Jingning Han83c27ec2017-09-20 08:05:17 -0700434 return 0;
435
436 return 1;
437}
438
Jingning Hanffbb0f92017-08-24 11:52:21 -0700439static int add_tpl_ref_mv(const AV1_COMMON *cm,
440 const MV_REF *prev_frame_mvs_base,
441 const MACROBLOCKD *xd, int mi_row, int mi_col,
442 MV_REFERENCE_FRAME ref_frame, int blk_row,
443 int blk_col, uint8_t *refmv_count,
444 CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
Jingning Hanffbb0f92017-08-24 11:52:21 -0700445 (void)prev_frame_mvs_base;
446 POSITION mi_pos;
447 int idx;
448 int coll_blk_count = 0;
449 const int weight_unit = 1; // mi_size_wide[BLOCK_8X8];
450
451#if CONFIG_MV_COMPRESS
452 mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
453 mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
454#else
455 mi_pos.row = blk_row;
456 mi_pos.col = blk_col;
457#endif
458
459 if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
460 return coll_blk_count;
461
Jingning Hanc7d198e2017-10-12 16:11:06 -0700462 const TPL_MV_REF *prev_frame_mvs =
Jingning Han6cc1fd32017-10-13 09:05:36 -0700463 cm->tpl_mvs + ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
Jingning Hanc7d198e2017-10-12 16:11:06 -0700464 ((mi_col + mi_pos.col) >> 1);
Jingning Han5946d362017-09-18 12:56:00 -0700465
Jingning Hanffbb0f92017-08-24 11:52:21 -0700466 MV_REFERENCE_FRAME rf[2];
467 av1_set_ref_frame(rf, ref_frame);
468
469 if (rf[1] == NONE_FRAME) {
470 for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
471 if (prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i].as_int !=
472 INVALID_MV) {
473 int_mv this_refmv = prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i];
474 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
475
Jingning Han0e4c8062017-10-03 20:27:22 -0700476 if (blk_row == 0 && blk_col == 0)
477 if (abs(this_refmv.as_mv.row) >= 16 ||
478 abs(this_refmv.as_mv.col) >= 16)
Sarah Parker2b9ec2e2017-10-30 17:34:08 -0700479 mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
Jingning Hanffbb0f92017-08-24 11:52:21 -0700480
481 for (idx = 0; idx < *refmv_count; ++idx)
482 if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) <
483 4 &&
484 abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) <
485 4)
486 break;
487
488 if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
489
490 if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
491 ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
492 // TODO(jingning): Hard coded context number. Need to make it better
493 // sense.
494 ref_mv_stack[idx].pred_diff[0] = 1;
495 ref_mv_stack[idx].weight = 2 * weight_unit;
496 ++(*refmv_count);
497 }
498
499 ++coll_blk_count;
500 }
501 }
502 } else {
503 // Process compound inter mode
504 for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
505 if (prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i].as_int != INVALID_MV &&
506 prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i].as_int != INVALID_MV) {
507 int_mv this_refmv = prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i];
508 int_mv comp_refmv = prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i];
509 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
510 lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv);
511
Jingning Han0e4c8062017-10-03 20:27:22 -0700512 if (blk_row == 0 && blk_col == 0)
513 if (abs(this_refmv.as_mv.row) >= 16 ||
514 abs(this_refmv.as_mv.col) >= 16 ||
515 abs(comp_refmv.as_mv.row) >= 16 ||
516 abs(comp_refmv.as_mv.col) >= 16)
Sarah Parker2b9ec2e2017-10-30 17:34:08 -0700517 mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
Jingning Hanffbb0f92017-08-24 11:52:21 -0700518
519 for (idx = 0; idx < *refmv_count; ++idx)
520 if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) <
521 4 &&
522 abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) <
523 4 &&
524 abs(comp_refmv.as_mv.row - ref_mv_stack[idx].comp_mv.as_mv.row) <
525 4 &&
526 abs(comp_refmv.as_mv.col - ref_mv_stack[idx].comp_mv.as_mv.col) <
527 4)
528 break;
529
530 if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
531
532 if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
533 ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
534 ref_mv_stack[idx].comp_mv.as_int = comp_refmv.as_int;
535 // TODO(jingning): Hard coded context number. Need to make it better
536 // sense.
537 ref_mv_stack[idx].pred_diff[0] = 1;
538 ref_mv_stack[idx].pred_diff[1] = 1;
539 ref_mv_stack[idx].weight = 2 * weight_unit;
540 ++(*refmv_count);
541 }
542
543 ++coll_blk_count;
544 }
545 }
546 }
547
548 return coll_blk_count;
549}
550#else
Yaowu Xudc035da2016-09-27 10:29:34 -0700551static int add_col_ref_mv(const AV1_COMMON *cm,
552 const MV_REF *prev_frame_mvs_base,
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700553 int prev_frame_mvs_stride, const MACROBLOCKD *xd,
554 int mi_row, int mi_col, MV_REFERENCE_FRAME ref_frame,
555 int blk_row, int blk_col, uint8_t *refmv_count,
Yaowu Xudc035da2016-09-27 10:29:34 -0700556 CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700557#if CONFIG_TMV
558 const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
Yunqing Wangc99a5642017-10-11 13:48:22 -0700559 (blk_row >> 1) * prev_frame_mvs_stride +
560 (blk_col >> 1);
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700561#else
Yaowu Xudc035da2016-09-27 10:29:34 -0700562 const MV_REF *prev_frame_mvs =
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700563 prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
564#endif
Yaowu Xudc035da2016-09-27 10:29:34 -0700565 POSITION mi_pos;
566 int ref, idx;
567 int coll_blk_count = 0;
Jingning Hanc016df82016-12-09 12:37:28 -0800568 const int weight_unit = mi_size_wide[BLOCK_8X8];
Yaowu Xudc035da2016-09-27 10:29:34 -0700569
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700570#if CONFIG_TMV
571 mi_pos.row = blk_row;
572 mi_pos.col = blk_col;
573#else
zhipin dengeb019b82017-02-17 17:49:03 +0800574#if CONFIG_MV_COMPRESS
575 mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
576 mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
577#else
Yaowu Xudc035da2016-09-27 10:29:34 -0700578 mi_pos.row = blk_row;
579 mi_pos.col = blk_col;
zhipin dengeb019b82017-02-17 17:49:03 +0800580#endif
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700581#endif // CONFIG_TMV
Yaowu Xudc035da2016-09-27 10:29:34 -0700582
Yaowu Xu531d6af2017-03-07 17:48:52 -0800583 if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
Fangwen Fu7b9f2b32017-01-17 14:01:52 -0800584 return coll_blk_count;
Yaowu Xudc035da2016-09-27 10:29:34 -0700585 for (ref = 0; ref < 2; ++ref) {
586 if (prev_frame_mvs->ref_frame[ref] == ref_frame) {
587 int_mv this_refmv = prev_frame_mvs->mv[ref];
RogerZhou3b635242017-09-19 10:06:46 -0700588#if CONFIG_AMVR
589 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
RogerZhou10a03802017-10-26 11:49:48 -0700590 cm->cur_frame_force_integer_mv);
RogerZhou3b635242017-09-19 10:06:46 -0700591#else
Yaowu Xudc035da2016-09-27 10:29:34 -0700592 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -0700593#endif
Jingning Han0e4c8062017-10-03 20:27:22 -0700594
595#if CONFIG_OPT_REF_MV
596 if (blk_row == 0 && blk_col == 0)
597#endif
598 {
599 if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16)
Sarah Parker2b9ec2e2017-10-30 17:34:08 -0700600 mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
Jingning Han0e4c8062017-10-03 20:27:22 -0700601 }
Yaowu Xudc035da2016-09-27 10:29:34 -0700602
603 for (idx = 0; idx < *refmv_count; ++idx)
604 if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
605
Jingning Hanc016df82016-12-09 12:37:28 -0800606 if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
Yaowu Xudc035da2016-09-27 10:29:34 -0700607
608 if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
609 ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
Jingning Han3f338832016-11-18 11:01:48 -0800610 ref_mv_stack[idx].pred_diff[0] =
611 av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
Jingning Hanc016df82016-12-09 12:37:28 -0800612 ref_mv_stack[idx].weight = 2 * weight_unit;
Yaowu Xudc035da2016-09-27 10:29:34 -0700613 ++(*refmv_count);
614 }
615
616 ++coll_blk_count;
617 }
618 }
619
620 return coll_blk_count;
621}
Zoe Liu294f59d2017-10-31 23:02:04 -0700622#endif // CONFIG_MFMV
Yaowu Xudc035da2016-09-27 10:29:34 -0700623
Yaowu Xuf883b422016-08-30 14:01:10 -0700624static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700625 MV_REFERENCE_FRAME ref_frame,
626 uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700627 int_mv *mv_ref_list,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100628#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700629 int_mv *gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100630#endif // USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700631 int block, int mi_row, int mi_col,
632 int16_t *mode_context) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700633 int idx, nearest_refmv_count = 0;
634 uint8_t newmv_count = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700635 CANDIDATE_MV tmp_mv;
636 int len, nr_len;
637
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700638#if CONFIG_TMV
639 const int prev_frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
640 const int tmi_row = mi_row & 0xfffe;
641 const int tmi_col = mi_col & 0xfffe;
642 const MV_REF *const prev_frame_mvs_base =
643 cm->use_prev_frame_mvs
644 ? cm->prev_frame->mvs + (tmi_row >> 1) * prev_frame_mvs_stride +
645 (tmi_col >> 1)
646 : NULL;
647#else
648 const int prev_frame_mvs_stride = cm->mi_cols;
zhipin dengeb019b82017-02-17 17:49:03 +0800649#if CONFIG_MV_COMPRESS
650 const MV_REF *const prev_frame_mvs_base =
651 cm->use_prev_frame_mvs
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700652 ? cm->prev_frame->mvs +
653 (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
zhipin dengeb019b82017-02-17 17:49:03 +0800654 ((mi_col >> 1) << 1) + 1
655 : NULL;
656#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700657 const MV_REF *const prev_frame_mvs_base =
658 cm->use_prev_frame_mvs
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700659 ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
Yaowu Xuc27fc142016-08-22 16:08:15 -0700660 : NULL;
zhipin dengeb019b82017-02-17 17:49:03 +0800661#endif
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700662#endif // CONFIG_TMV
Yaowu Xuc27fc142016-08-22 16:08:15 -0700663
Yaowu Xudc035da2016-09-27 10:29:34 -0700664 const int bs = AOMMAX(xd->n8_w, xd->n8_h);
David Barker761b1ac2017-09-25 11:23:03 +0100665 const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700666 MV_REFERENCE_FRAME rf[2];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700667
Yunqing Wangd797ea92017-08-27 18:05:55 -0700668 const TileInfo *const tile = &xd->tile;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700669 int max_row_offset = 0, max_col_offset = 0;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700670 const int row_adj = (xd->n8_h < mi_size_high[BLOCK_8X8]) && (mi_row & 0x01);
671 const int col_adj = (xd->n8_w < mi_size_wide[BLOCK_8X8]) && (mi_col & 0x01);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700672 int processed_rows = 0;
673 int processed_cols = 0;
Yunqing Wangd797ea92017-08-27 18:05:55 -0700674 int row_offset, col_offset;
675
Yaowu Xudc035da2016-09-27 10:29:34 -0700676 av1_set_ref_frame(rf, ref_frame);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700677 mode_context[ref_frame] = 0;
678 *refmv_count = 0;
679
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700680 // Find valid maximum row/col offset.
681 if (xd->up_available) {
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700682 max_row_offset = -(MVREF_ROWS << 1) + row_adj;
Yunqing Wangd797ea92017-08-27 18:05:55 -0700683 max_row_offset =
684 find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
Yunqing Wangd797ea92017-08-27 18:05:55 -0700685 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700686
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700687 if (xd->left_available) {
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700688 max_col_offset = -(MVREF_COLS << 1) + col_adj;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700689 max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
690 }
691
692 // Scan the first above row mode info. row_offset = -1;
693 if (abs(max_row_offset) >= 1)
Yunqing Wang97d6a372017-10-09 14:15:15 -0700694 newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
695 ref_mv_stack, refmv_count,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100696#if USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700697 gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100698#endif // USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700699 max_row_offset, &processed_rows);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700700 // Scan the first left column mode info. col_offset = -1;
701 if (abs(max_col_offset) >= 1)
Yunqing Wang97d6a372017-10-09 14:15:15 -0700702 newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
703 ref_mv_stack, refmv_count,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100704#if USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700705 gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100706#endif // USE_CUR_GM_REFMV
Yunqing Wang97d6a372017-10-09 14:15:15 -0700707 max_col_offset, &processed_cols);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700708 // Check top-right boundary
709 if (has_tr)
Jingning Hanea9cf092016-10-28 14:19:12 -0700710 newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700711 xd->n8_w, ref_mv_stack,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100712#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700713 gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100714#endif // USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700715 refmv_count);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700716
717 nearest_refmv_count = *refmv_count;
718
Yaowu Xudc035da2016-09-27 10:29:34 -0700719 for (idx = 0; idx < nearest_refmv_count; ++idx)
Yaowu Xuc27fc142016-08-22 16:08:15 -0700720 ref_mv_stack[idx].weight += REF_CAT_LEVEL;
Jingning Hanffbb0f92017-08-24 11:52:21 -0700721
722#if CONFIG_MFMV
Jingning Hand4e87162017-10-31 09:22:58 -0700723 if (cm->use_prev_frame_mvs) {
724 int blk_row, blk_col;
725 int coll_blk_count = 0;
726 int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n8_h);
727 int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n8_w);
Jingning Hanffbb0f92017-08-24 11:52:21 -0700728
Jingning Hand4e87162017-10-31 09:22:58 -0700729 int tpl_sample_pos[9][2] = {
730 { -2, hoffset }, { 0, hoffset }, { voffset, hoffset },
731 { voffset, 0 }, { voffset, -2 }, { voffset, -4 },
732 { -4, hoffset }, { voffset, 4 }, { 2, hoffset + 4 },
733 };
734 int i;
Jingning Hanffbb0f92017-08-24 11:52:21 -0700735
Jingning Hand4e87162017-10-31 09:22:58 -0700736 for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_size_high[BLOCK_8X8]) {
737 for (blk_col = 0; blk_col < xd->n8_w;
738 blk_col += mi_size_wide[BLOCK_8X8]) {
739 // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is
740 // used.
741 // Can be modified the same way.
742 int is_available = add_tpl_ref_mv(
743 cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
744 blk_col, refmv_count, ref_mv_stack, mode_context);
745 if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
746 }
747 }
748
Sarah Parker2b9ec2e2017-10-30 17:34:08 -0700749 if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
Jingning Hand4e87162017-10-31 09:22:58 -0700750
751 for (i = 0; i < 9; ++i) {
752 blk_row = tpl_sample_pos[i][0];
753 blk_col = tpl_sample_pos[i][1];
754
755 if (!check_sb_border(cm, mi_row, mi_col, blk_row, blk_col)) continue;
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700756 // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
757 // Can be modified the same way.
Jingning Hand4e87162017-10-31 09:22:58 -0700758 coll_blk_count += add_tpl_ref_mv(cm, prev_frame_mvs_base, xd, mi_row,
759 mi_col, ref_frame, blk_row, blk_col,
760 refmv_count, ref_mv_stack, mode_context);
Jingning Hanffbb0f92017-08-24 11:52:21 -0700761 }
762 }
Jingning Hanffbb0f92017-08-24 11:52:21 -0700763#else
Fangwen Fu8d164de2016-12-14 13:40:54 -0800764#if CONFIG_TEMPMV_SIGNALING
Yushin Cho127c5832017-07-28 16:39:04 -0700765 if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME)
Fangwen Fu8d164de2016-12-14 13:40:54 -0800766#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700767 if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
Yushin Cho127c5832017-07-28 16:39:04 -0700768 rf[1] == NONE_FRAME)
Fangwen Fu8d164de2016-12-14 13:40:54 -0800769#endif
Yushin Cho127c5832017-07-28 16:39:04 -0700770 {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700771 int blk_row, blk_col;
Yaowu Xudc035da2016-09-27 10:29:34 -0700772 int coll_blk_count = 0;
Jingning Hanfab16032016-12-16 14:52:45 -0800773 const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
774 ? mi_size_wide[BLOCK_8X8]
775 : mi_size_wide[BLOCK_16X16];
Jingning Han8cf83642017-01-30 14:39:28 -0800776
777#if CONFIG_TPL_MV
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700778 // Modified sample positions to be consistent with frame_mvs
779 // spatial resolution.
Jingning Han8cf83642017-01-30 14:39:28 -0800780 int tpl_sample_pos[5][2] = { { -1, xd->n8_w },
781 { 0, xd->n8_w },
782 { xd->n8_h, xd->n8_w },
783 { xd->n8_h, 0 },
784 { xd->n8_h, -1 } };
785 int i;
786#endif
787
Jingning Hanc016df82016-12-09 12:37:28 -0800788 for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
789 for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700790#if CONFIG_TMV
791 int is_available =
792 add_col_ref_mv(cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd,
793 tmi_row, tmi_col, ref_frame, blk_row, blk_col,
794 refmv_count, ref_mv_stack, mode_context);
795#else
796 int is_available =
797 add_col_ref_mv(cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd,
798 mi_row, mi_col, ref_frame, blk_row, blk_col,
799 refmv_count, ref_mv_stack, mode_context);
800#endif // CONFIG_TMV
Jingning Han0e4c8062017-10-03 20:27:22 -0700801#if CONFIG_OPT_REF_MV
802 if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
803#else
804 coll_blk_count += is_available;
805#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700806 }
807 }
Jingning Han8cf83642017-01-30 14:39:28 -0800808
809#if CONFIG_TPL_MV
810 for (i = 0; i < 5; ++i) {
811 blk_row = tpl_sample_pos[i][0];
812 blk_col = tpl_sample_pos[i][1];
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700813#if CONFIG_TMV
814 coll_blk_count += add_col_ref_mv(
815 cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd, tmi_row, tmi_col,
816 ref_frame, blk_row, blk_col, refmv_count, ref_mv_stack, mode_context);
817#else
818 coll_blk_count += add_col_ref_mv(
819 cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd, mi_row, mi_col,
820 ref_frame, blk_row, blk_col, refmv_count, ref_mv_stack, mode_context);
821#endif // CONFIG_TMV
Jingning Han8cf83642017-01-30 14:39:28 -0800822 }
823#endif
824
Sarah Parker2b9ec2e2017-10-30 17:34:08 -0700825 if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
Yaowu Xudc035da2016-09-27 10:29:34 -0700826 } else {
Sarah Parker2b9ec2e2017-10-30 17:34:08 -0700827 mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700828 }
Zoe Liu294f59d2017-10-31 23:02:04 -0700829#endif // CONFIG_MFMV
Yaowu Xuc27fc142016-08-22 16:08:15 -0700830
Jingning Han24e0a182016-11-20 22:34:12 -0800831 // Scan the second outer area.
Dengca8d24d2016-10-17 14:06:35 +0800832 scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100833#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700834 gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100835#endif // USE_CUR_GM_REFMV
Dengca8d24d2016-10-17 14:06:35 +0800836 refmv_count);
Yunqing Wangd797ea92017-08-27 18:05:55 -0700837 for (idx = 2; idx <= MVREF_ROWS; ++idx) {
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700838 row_offset = -(idx << 1) + 1 + row_adj;
839 col_offset = -(idx << 1) + 1 + col_adj;
Yunqing Wangd797ea92017-08-27 18:05:55 -0700840
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700841 if (abs(row_offset) <= abs(max_row_offset) &&
842 abs(row_offset) > processed_rows)
Yunqing Wang97d6a372017-10-09 14:15:15 -0700843 scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, row_offset, ref_mv_stack,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700844 refmv_count,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100845#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700846 gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100847#endif // USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700848 max_row_offset, &processed_rows);
Yunqing Wangd797ea92017-08-27 18:05:55 -0700849
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700850 if (abs(col_offset) <= abs(max_col_offset) &&
851 abs(col_offset) > processed_cols)
Yunqing Wang97d6a372017-10-09 14:15:15 -0700852 scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700853 refmv_count,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100854#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700855 gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100856#endif // USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700857 max_col_offset, &processed_cols);
Yunqing Wangd797ea92017-08-27 18:05:55 -0700858 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700859
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700860 col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700861 if (abs(col_offset) <= abs(max_col_offset) &&
862 abs(col_offset) > processed_cols)
Yunqing Wang97d6a372017-10-09 14:15:15 -0700863 scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700864 refmv_count,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100865#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700866 gm_mv_candidates,
Sebastien Alaiwan48795802017-10-30 12:07:13 +0100867#endif // USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -0700868 max_col_offset, &processed_cols);
Yunqing Wangd1121fa2017-09-13 14:34:45 -0700869
Yaowu Xuc27fc142016-08-22 16:08:15 -0700870 switch (nearest_refmv_count) {
Jingning Han8a8c50a2017-10-08 11:25:41 -0700871 case 0: mode_context[ref_frame] |= 0;
872#if !CONFIG_OPT_REF_MV
Yaowu Xuc27fc142016-08-22 16:08:15 -0700873 if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700874 if (*refmv_count == 1)
875 mode_context[ref_frame] |= (1 << REFMV_OFFSET);
876 else if (*refmv_count >= 2)
877 mode_context[ref_frame] |= (2 << REFMV_OFFSET);
Jingning Hanabf6f282017-10-09 13:18:59 -0700878#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700879 break;
Jingning Hanabf6f282017-10-09 13:18:59 -0700880 case 1: mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
881#if CONFIG_OPT_REF_MV
882 mode_context[ref_frame] |= (3 << REFMV_OFFSET);
883#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700884 if (*refmv_count == 1)
885 mode_context[ref_frame] |= (3 << REFMV_OFFSET);
886 else if (*refmv_count >= 2)
887 mode_context[ref_frame] |= (4 << REFMV_OFFSET);
Jingning Hanabf6f282017-10-09 13:18:59 -0700888#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -0700889 break;
890
891 case 2:
892 default:
893 if (newmv_count >= 2)
894 mode_context[ref_frame] |= 4;
895 else if (newmv_count == 1)
896 mode_context[ref_frame] |= 5;
897 else
898 mode_context[ref_frame] |= 6;
899
900 mode_context[ref_frame] |= (5 << REFMV_OFFSET);
901 break;
902 }
903
904 // Rank the likelihood and assign nearest and near mvs.
905 len = nearest_refmv_count;
906 while (len > 0) {
907 nr_len = 0;
908 for (idx = 1; idx < len; ++idx) {
909 if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
910 tmp_mv = ref_mv_stack[idx - 1];
911 ref_mv_stack[idx - 1] = ref_mv_stack[idx];
912 ref_mv_stack[idx] = tmp_mv;
913 nr_len = idx;
914 }
915 }
916 len = nr_len;
917 }
918
919 len = *refmv_count;
920 while (len > nearest_refmv_count) {
921 nr_len = nearest_refmv_count;
922 for (idx = nearest_refmv_count + 1; idx < len; ++idx) {
923 if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
924 tmp_mv = ref_mv_stack[idx - 1];
925 ref_mv_stack[idx - 1] = ref_mv_stack[idx];
926 ref_mv_stack[idx] = tmp_mv;
927 nr_len = idx;
928 }
929 }
930 len = nr_len;
931 }
932
Emil Keyder01770b32017-01-20 18:03:11 -0500933 if (rf[1] > NONE_FRAME) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700934 for (idx = 0; idx < *refmv_count; ++idx) {
Jingning Hanff6ee6a2016-12-07 09:55:21 -0800935 clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
936 xd->n8_h << MI_SIZE_LOG2, xd);
937 clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
938 xd->n8_h << MI_SIZE_LOG2, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700939 }
940 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700941 for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700942 mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
Jingning Hanff6ee6a2016-12-07 09:55:21 -0800943 clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
944 xd->n8_h << MI_SIZE_LOG2, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700945 }
946 }
947}
Yaowu Xuc27fc142016-08-22 16:08:15 -0700948
949// This function searches the neighbourhood of a given MB/SB
950// to try and find candidate reference vectors.
Yaowu Xuf883b422016-08-30 14:01:10 -0700951static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700952 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
953 int_mv *mv_ref_list, int block, int mi_row,
954 int mi_col, find_mv_refs_sync sync,
David Barkercdcac6d2016-12-01 17:04:16 +0000955 void *const data, int16_t *mode_context,
956 int_mv zeromv) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700957 const int *ref_sign_bias = cm->ref_frame_sign_bias;
David Barker761b1ac2017-09-25 11:23:03 +0100958 const int sb_mi_size = mi_size_wide[cm->sb_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700959 int i, refmv_count = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700960 int different_ref_found = 0;
961 int context_counter = 0;
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700962
Zoe Liu294f59d2017-10-31 23:02:04 -0700963#if CONFIG_MFMV
964 (void)sync;
965 (void)data;
966#else
967#if CONFIG_TMV
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700968 int tmi_row = mi_row & 0xfffe;
969 int tmi_col = mi_col & 0xfffe;
970 POSITION mi_pos = { 0, 0 };
971 int inside = is_inside(&xd->tile, tmi_col, tmi_row, cm->mi_rows, cm, &mi_pos);
972 const MV_REF *const prev_frame_mvs =
973 cm->use_prev_frame_mvs && inside
974 ? cm->prev_frame->mvs + (tmi_row >> 1) * ((cm->mi_cols + 1) >> 1) +
975 (tmi_col >> 1)
976 : NULL;
977#else
zhipin dengeb019b82017-02-17 17:49:03 +0800978#if CONFIG_MV_COMPRESS
979 const TileInfo *const tile_ = &xd->tile;
980 int mi_row_end = tile_->mi_row_end;
981 int mi_col_end = tile_->mi_col_end;
982 const MV_REF *const prev_frame_mvs =
983 cm->use_prev_frame_mvs
984 ? cm->prev_frame->mvs +
985 AOMMIN(((mi_row >> 1) << 1) + 1 + (((xd->n8_h - 1) >> 1) << 1),
986 mi_row_end - 1) *
987 cm->mi_cols +
988 AOMMIN(((mi_col >> 1) << 1) + 1 + (((xd->n8_w - 1) >> 1) << 1),
989 mi_col_end - 1)
990 : NULL;
991#else
Yaowu Xuc27fc142016-08-22 16:08:15 -0700992 const MV_REF *const prev_frame_mvs =
993 cm->use_prev_frame_mvs
994 ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
995 : NULL;
Zoe Liu294f59d2017-10-31 23:02:04 -0700996#endif // CONFIG_MV_COMPRESS
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700997#endif // CONFIG_TMV
Zoe Liu294f59d2017-10-31 23:02:04 -0700998#endif // CONFIG_MFMV
Yunqing Wangd1d511f2017-10-05 08:44:46 -0700999
Alex Converse44c2bad2017-05-11 09:36:10 -07001000#if CONFIG_INTRABC
1001 assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
1002#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001003 const TileInfo *const tile = &xd->tile;
Jingning Hanc016df82016-12-09 12:37:28 -08001004 const BLOCK_SIZE bsize = mi->mbmi.sb_type;
1005 const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
1006 const int bh = block_size_high[AOMMAX(bsize, BLOCK_8X8)];
Dengca8d24d2016-10-17 14:06:35 +08001007 POSITION mv_ref_search[MVREF_NEIGHBOURS];
Jingning Hanc016df82016-12-09 12:37:28 -08001008 const int num_8x8_blocks_wide = num_8x8_blocks_wide_lookup[bsize];
1009 const int num_8x8_blocks_high = num_8x8_blocks_high_lookup[bsize];
Dengca8d24d2016-10-17 14:06:35 +08001010 mv_ref_search[0].row = num_8x8_blocks_high - 1;
1011 mv_ref_search[0].col = -1;
1012 mv_ref_search[1].row = -1;
1013 mv_ref_search[1].col = num_8x8_blocks_wide - 1;
1014 mv_ref_search[2].row = -1;
1015 mv_ref_search[2].col = (num_8x8_blocks_wide - 1) >> 1;
1016 mv_ref_search[3].row = (num_8x8_blocks_high - 1) >> 1;
1017 mv_ref_search[3].col = -1;
1018 mv_ref_search[4].row = -1;
1019 mv_ref_search[4].col = -1;
Debargha Mukherjeeff59b6a2017-01-26 08:50:48 -08001020#if CONFIG_EXT_PARTITION_TYPES
1021 if (num_8x8_blocks_wide == num_8x8_blocks_high) {
1022 mv_ref_search[5].row = -1;
1023 mv_ref_search[5].col = 0;
1024 mv_ref_search[6].row = 0;
1025 mv_ref_search[6].col = -1;
1026 } else {
1027 mv_ref_search[5].row = -1;
1028 mv_ref_search[5].col = num_8x8_blocks_wide;
1029 mv_ref_search[6].row = num_8x8_blocks_high;
1030 mv_ref_search[6].col = -1;
1031 }
1032#else
Dengca8d24d2016-10-17 14:06:35 +08001033 mv_ref_search[5].row = -1;
1034 mv_ref_search[5].col = num_8x8_blocks_wide;
1035 mv_ref_search[6].row = num_8x8_blocks_high;
1036 mv_ref_search[6].col = -1;
Debargha Mukherjeeff59b6a2017-01-26 08:50:48 -08001037#endif // CONFIG_EXT_PARTITION_TYPES
Dengca8d24d2016-10-17 14:06:35 +08001038 mv_ref_search[7].row = -1;
1039 mv_ref_search[7].col = -3;
1040 mv_ref_search[8].row = num_8x8_blocks_high - 1;
1041 mv_ref_search[8].col = -3;
Jingning Hanc016df82016-12-09 12:37:28 -08001042
Jingning Hanc016df82016-12-09 12:37:28 -08001043 for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
1044 mv_ref_search[i].row *= 2;
1045 mv_ref_search[i].col *= 2;
1046 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001047
1048 // The nearest 2 blocks are treated differently
1049 // if the size < 8x8 we get the mv from the bmi substructure,
1050 // and we also need to keep a mode count.
1051 for (i = 0; i < 2; ++i) {
1052 const POSITION *const mv_ref = &mv_ref_search[i];
Yaowu Xu531d6af2017-03-07 17:48:52 -08001053 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001054 const MODE_INFO *const candidate_mi =
1055 xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
1056 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
1057 // Keep counts for entropy encoding.
1058 context_counter += mode_2_counter[candidate->mode];
1059 different_ref_found = 1;
1060
1061 if (candidate->ref_frame[0] == ref_frame)
1062 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
1063 refmv_count, mv_ref_list, bw, bh, xd, Done);
1064 else if (candidate->ref_frame[1] == ref_frame)
1065 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
1066 refmv_count, mv_ref_list, bw, bh, xd, Done);
1067 }
1068 }
1069
1070 // Check the rest of the neighbors in much the same way
1071 // as before except we don't need to keep track of sub blocks or
1072 // mode counts.
1073 for (; i < MVREF_NEIGHBOURS; ++i) {
1074 const POSITION *const mv_ref = &mv_ref_search[i];
Yaowu Xu531d6af2017-03-07 17:48:52 -08001075 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001076 const MB_MODE_INFO *const candidate =
Yaowu Xuf0602bb2016-12-14 09:30:03 -08001077 !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
1078 ? NULL
1079 : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
Yaowu Xu750955b2016-10-31 08:55:27 -07001080 if (candidate == NULL) continue;
David Barker761b1ac2017-09-25 11:23:03 +01001081 if ((mi_row & (sb_mi_size - 1)) + mv_ref->row >= sb_mi_size ||
1082 (mi_col & (sb_mi_size - 1)) + mv_ref->col >= sb_mi_size)
Dengca8d24d2016-10-17 14:06:35 +08001083 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001084 different_ref_found = 1;
1085
1086 if (candidate->ref_frame[0] == ref_frame)
1087 ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
1088 Done);
1089 else if (candidate->ref_frame[1] == ref_frame)
1090 ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
1091 Done);
1092 }
1093 }
1094
1095// TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
1096// on windows platform. The sync here is unncessary if use_perv_frame_mvs
1097// is 0. But after removing it, there will be hang in the unit test on windows
1098// due to several threads waiting for a thread's signal.
1099#if defined(_WIN32) && !HAVE_PTHREAD_H
1100 if (cm->frame_parallel_decode && sync != NULL) {
1101 sync(data, mi_row);
1102 }
1103#endif
1104
Zoe Liu294f59d2017-10-31 23:02:04 -07001105#if !CONFIG_MFMV
Yaowu Xuc27fc142016-08-22 16:08:15 -07001106 // Check the last frame's mode and mv info.
1107 if (cm->use_prev_frame_mvs) {
1108 // Synchronize here for frame parallel decode if sync function is provided.
1109 if (cm->frame_parallel_decode && sync != NULL) {
1110 sync(data, mi_row);
1111 }
1112
1113 if (prev_frame_mvs->ref_frame[0] == ref_frame) {
1114 ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, bw, bh,
1115 xd, Done);
1116 } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
1117 ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, bw, bh,
1118 xd, Done);
1119 }
1120 }
Zoe Liu294f59d2017-10-31 23:02:04 -07001121#endif // !CONFIG_MFMV
Yaowu Xuc27fc142016-08-22 16:08:15 -07001122
1123 // Since we couldn't find 2 mvs from the same reference frame
1124 // go back through the neighbors and find motion vectors from
1125 // different reference frames.
1126 if (different_ref_found) {
1127 for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
1128 const POSITION *mv_ref = &mv_ref_search[i];
Yaowu Xu531d6af2017-03-07 17:48:52 -08001129 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001130 const MB_MODE_INFO *const candidate =
Yaowu Xuf0602bb2016-12-14 09:30:03 -08001131 !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
1132 ? NULL
1133 : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
Yaowu Xu750955b2016-10-31 08:55:27 -07001134 if (candidate == NULL) continue;
David Barker761b1ac2017-09-25 11:23:03 +01001135 if ((mi_row & (sb_mi_size - 1)) + mv_ref->row >= sb_mi_size ||
1136 (mi_col & (sb_mi_size - 1)) + mv_ref->col >= sb_mi_size)
Dengca8d24d2016-10-17 14:06:35 +08001137 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001138
1139 // If the candidate is INTRA we don't want to consider its mv.
1140 IF_DIFF_REF_FRAME_ADD_MV(candidate, ref_frame, ref_sign_bias,
1141 refmv_count, mv_ref_list, bw, bh, xd, Done);
1142 }
1143 }
1144 }
1145
Zoe Liu294f59d2017-10-31 23:02:04 -07001146#if !CONFIG_MFMV
Yaowu Xuc27fc142016-08-22 16:08:15 -07001147 // Since we still don't have a candidate we'll try the last frame.
1148 if (cm->use_prev_frame_mvs) {
1149 if (prev_frame_mvs->ref_frame[0] != ref_frame &&
1150 prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
1151 int_mv mv = prev_frame_mvs->mv[0];
1152 if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
1153 ref_sign_bias[ref_frame]) {
1154 mv.as_mv.row *= -1;
1155 mv.as_mv.col *= -1;
1156 }
1157 ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
1158 }
1159
1160 if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
1161 prev_frame_mvs->ref_frame[1] != ref_frame) {
1162 int_mv mv = prev_frame_mvs->mv[1];
1163 if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
1164 ref_sign_bias[ref_frame]) {
1165 mv.as_mv.row *= -1;
1166 mv.as_mv.col *= -1;
1167 }
1168 ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
1169 }
1170 }
Zoe Liu294f59d2017-10-31 23:02:04 -07001171#endif // !CONFIG_MFMV
Yaowu Xuc27fc142016-08-22 16:08:15 -07001172
1173Done:
1174 if (mode_context)
1175 mode_context[ref_frame] = counter_to_context[context_counter];
1176 for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
David Barkercdcac6d2016-12-01 17:04:16 +00001177 mv_ref_list[i].as_int = zeromv.as_int;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001178}
1179
Yaowu Xuc27fc142016-08-22 16:08:15 -07001180// This function keeps a mode count for a given MB/SB
Yaowu Xu531d6af2017-03-07 17:48:52 -08001181void av1_update_mv_context(const AV1_COMMON *cm, const MACROBLOCKD *xd,
1182 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
1183 int_mv *mv_ref_list, int block, int mi_row,
1184 int mi_col, int16_t *mode_context) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001185 int i, refmv_count = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001186 int context_counter = 0;
Jingning Han61418bb2017-01-23 17:12:48 -08001187 const int bw = block_size_wide[mi->mbmi.sb_type];
1188 const int bh = block_size_high[mi->mbmi.sb_type];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001189 const TileInfo *const tile = &xd->tile;
Zoe Liu40bc8b82017-05-12 10:18:39 -07001190 POSITION mv_ref_search[2];
Jingning Han61418bb2017-01-23 17:12:48 -08001191 const int num_8x8_blocks_wide = mi_size_wide[mi->mbmi.sb_type];
1192 const int num_8x8_blocks_high = mi_size_high[mi->mbmi.sb_type];
Zoe Liu40bc8b82017-05-12 10:18:39 -07001193
Yaowu Xu33f210c2016-11-17 17:42:20 -08001194 mv_ref_search[0].row = num_8x8_blocks_high - 1;
1195 mv_ref_search[0].col = -1;
1196 mv_ref_search[1].row = -1;
1197 mv_ref_search[1].col = num_8x8_blocks_wide - 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001198
1199 // Blank the reference vector list
1200 memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
1201
1202 // The nearest 2 blocks are examined only.
1203 // If the size < 8x8, we get the mv from the bmi substructure;
1204 for (i = 0; i < 2; ++i) {
1205 const POSITION *const mv_ref = &mv_ref_search[i];
Yaowu Xu531d6af2017-03-07 17:48:52 -08001206 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001207 const MODE_INFO *const candidate_mi =
1208 xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
1209 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
1210
1211 // Keep counts for entropy encoding.
1212 context_counter += mode_2_counter[candidate->mode];
1213
1214 if (candidate->ref_frame[0] == ref_frame) {
1215 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
1216 refmv_count, mv_ref_list, bw, bh, xd, Done);
1217 } else if (candidate->ref_frame[1] == ref_frame) {
1218 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
1219 refmv_count, mv_ref_list, bw, bh, xd, Done);
1220 }
1221 }
1222 }
1223
1224Done:
1225
1226 if (mode_context)
1227 mode_context[ref_frame] = counter_to_context[context_counter];
1228}
Yaowu Xuc27fc142016-08-22 16:08:15 -07001229
Yaowu Xuf883b422016-08-30 14:01:10 -07001230void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
1231 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
Yaowu Xuf883b422016-08-30 14:01:10 -07001232 uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02001233 int16_t *compound_mode_context, int_mv *mv_ref_list,
1234 int mi_row, int mi_col, find_mv_refs_sync sync,
1235 void *const data, int16_t *mode_context) {
David Barkercdcac6d2016-12-01 17:04:16 +00001236 int_mv zeromv[2];
Debargha Mukherjee0bae6242017-05-02 21:54:41 -07001237 BLOCK_SIZE bsize = mi->mbmi.sb_type;
David Barkercdcac6d2016-12-01 17:04:16 +00001238 int idx, all_zero = 1;
David Barkercdcac6d2016-12-01 17:04:16 +00001239 MV_REFERENCE_FRAME rf[2];
Sebastien Alaiwane140c502017-04-27 09:52:34 +02001240
Yaowu Xu531d6af2017-03-07 17:48:52 -08001241 av1_update_mv_context(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
Yaowu Xuf883b422016-08-30 14:01:10 -07001242 compound_mode_context);
David Barkercdcac6d2016-12-01 17:04:16 +00001243
Alex Converse7d5559c2017-06-14 12:32:35 -07001244 if (!CONFIG_INTRABC || ref_frame != INTRA_FRAME) {
1245 av1_set_ref_frame(rf, ref_frame);
1246 zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
1247 cm->allow_high_precision_mv, bsize,
RogerZhou3b635242017-09-19 10:06:46 -07001248 mi_col, mi_row, 0
1249#if CONFIG_AMVR
1250 ,
RogerZhou10a03802017-10-26 11:49:48 -07001251 cm->cur_frame_force_integer_mv
RogerZhou3b635242017-09-19 10:06:46 -07001252#endif
1253 )
Alex Converse7d5559c2017-06-14 12:32:35 -07001254 .as_int;
RogerZhou10a03802017-10-26 11:49:48 -07001255 zeromv[1].as_int = (rf[1] != NONE_FRAME)
1256 ? gm_get_motion_vector(&cm->global_motion[rf[1]],
1257 cm->allow_high_precision_mv,
1258 bsize, mi_col, mi_row, 0
RogerZhou3b635242017-09-19 10:06:46 -07001259#if CONFIG_AMVR
RogerZhou10a03802017-10-26 11:49:48 -07001260 ,
1261 cm->cur_frame_force_integer_mv
RogerZhou3b635242017-09-19 10:06:46 -07001262#endif
RogerZhou10a03802017-10-26 11:49:48 -07001263 )
1264 .as_int
1265 : 0;
Alex Converse7d5559c2017-06-14 12:32:35 -07001266 } else {
1267 zeromv[0].as_int = zeromv[1].as_int = 0;
1268 }
David Barkercdcac6d2016-12-01 17:04:16 +00001269
Yaowu Xu4306b6e2016-09-27 12:55:32 -07001270 if (ref_frame <= ALTREF_FRAME)
David Barkercdcac6d2016-12-01 17:04:16 +00001271 find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
1272 sync, data, mode_context, zeromv[0]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001273
Yaowu Xuc27fc142016-08-22 16:08:15 -07001274 setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
Sebastien Alaiwan48795802017-10-30 12:07:13 +01001275#if USE_CUR_GM_REFMV
Sarah Parker0a5cc5f2017-10-03 17:53:53 -07001276 zeromv,
Sebastien Alaiwan48795802017-10-30 12:07:13 +01001277#endif // USE_CUR_GM_REFMV
Yaowu Xuc27fc142016-08-22 16:08:15 -07001278 -1, mi_row, mi_col, mode_context);
David Barkercdcac6d2016-12-01 17:04:16 +00001279 /* Note: If global motion is enabled, then we want to set the ALL_ZERO flag
1280 iff all of the MVs we could generate with NEARMV/NEARESTMV are equivalent
1281 to the global motion vector.
1282 Note: For the following to work properly, the encoder can't throw away
1283 any global motion models after calling this function, even if they are
1284 unused. Instead we rely on the recode loop: If any non-IDENTITY model
1285 is unused, the whole frame will be re-encoded without it.
1286 The problem is that, otherwise, we can end up in the following situation:
1287 * Encoder has a global motion model with nonzero translational part,
1288 and all candidate MVs are zero. So the ALL_ZERO flag is unset.
1289 * Encoder throws away global motion because it is never used.
1290 * Decoder sees that there is no global motion and all candidate MVs are
1291 zero, so sets the ALL_ZERO flag.
1292 * This leads to an encode/decode mismatch.
1293 */
Jingning Han2484fa02017-08-26 18:59:38 -07001294 for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
1295 if (ref_mv_stack[idx].this_mv.as_int != zeromv[0].as_int) all_zero = 0;
1296 if (ref_frame > ALTREF_FRAME)
1297 if (ref_mv_stack[idx].comp_mv.as_int != zeromv[1].as_int) all_zero = 0;
1298 }
1299 if (*ref_mv_count < 2 && ref_frame <= ALTREF_FRAME) {
Yaowu Xu4306b6e2016-09-27 12:55:32 -07001300 for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
David Barkercdcac6d2016-12-01 17:04:16 +00001301 if (mv_ref_list[idx].as_int != zeromv[0].as_int) all_zero = 0;
Yaowu Xu4306b6e2016-09-27 12:55:32 -07001302 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001303
Jingning Han426caba2017-10-08 14:40:31 -07001304#if !CONFIG_OPT_REF_MV
Yaowu Xuc27fc142016-08-22 16:08:15 -07001305 if (all_zero) mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
Jingning Han426caba2017-10-08 14:40:31 -07001306#else
1307 (void)all_zero;
1308#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001309}
1310
Yaowu Xuf883b422016-08-30 14:01:10 -07001311void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,
RogerZhou3b635242017-09-19 10:06:46 -07001312 int_mv *near_mv
1313#if CONFIG_AMVR
1314 ,
1315 int is_integer
1316#endif
1317 ) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001318 int i;
1319 // Make sure all the candidates are properly clamped etc
1320 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
RogerZhou3b635242017-09-19 10:06:46 -07001321#if CONFIG_AMVR
1322 lower_mv_precision(&mvlist[i].as_mv, allow_hp, is_integer);
1323#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07001324 lower_mv_precision(&mvlist[i].as_mv, allow_hp);
RogerZhou3b635242017-09-19 10:06:46 -07001325#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001326 }
1327 *nearest_mv = mvlist[0];
1328 *near_mv = mvlist[1];
1329}
1330
Jingning Hanea255c92017-09-29 08:12:09 -07001331#if CONFIG_FRAME_MARKER
Jingning Hanc723b342017-08-24 11:19:46 -07001332void av1_setup_frame_buf_refs(AV1_COMMON *cm) {
1333 cm->cur_frame->cur_frame_offset = cm->frame_offset;
1334 int alt_buf_idx = cm->frame_refs[ALTREF_FRAME - LAST_FRAME].idx;
1335 int lst_buf_idx = cm->frame_refs[LAST_FRAME - LAST_FRAME].idx;
1336 int gld_buf_idx = cm->frame_refs[GOLDEN_FRAME - LAST_FRAME].idx;
1337
Jingning Hanc723b342017-08-24 11:19:46 -07001338 int lst2_buf_idx = cm->frame_refs[LAST2_FRAME - LAST_FRAME].idx;
1339 int lst3_buf_idx = cm->frame_refs[LAST3_FRAME - LAST_FRAME].idx;
1340 int bwd_buf_idx = cm->frame_refs[BWDREF_FRAME - LAST_FRAME].idx;
Jingning Han94a504a2017-09-18 16:17:02 -07001341 int alt2_buf_idx = cm->frame_refs[ALTREF2_FRAME - LAST_FRAME].idx;
Jingning Hanc723b342017-08-24 11:19:46 -07001342
1343 if (alt_buf_idx >= 0)
1344 cm->cur_frame->alt_frame_offset =
1345 cm->buffer_pool->frame_bufs[alt_buf_idx].cur_frame_offset;
1346
1347 if (lst_buf_idx >= 0)
1348 cm->cur_frame->lst_frame_offset =
1349 cm->buffer_pool->frame_bufs[lst_buf_idx].cur_frame_offset;
1350
1351 if (gld_buf_idx >= 0)
1352 cm->cur_frame->gld_frame_offset =
1353 cm->buffer_pool->frame_bufs[gld_buf_idx].cur_frame_offset;
1354
Jingning Hanc723b342017-08-24 11:19:46 -07001355 if (lst2_buf_idx >= 0)
1356 cm->cur_frame->lst2_frame_offset =
1357 cm->buffer_pool->frame_bufs[lst2_buf_idx].cur_frame_offset;
1358
1359 if (lst3_buf_idx >= 0)
1360 cm->cur_frame->lst3_frame_offset =
1361 cm->buffer_pool->frame_bufs[lst3_buf_idx].cur_frame_offset;
1362
1363 if (bwd_buf_idx >= 0)
1364 cm->cur_frame->bwd_frame_offset =
1365 cm->buffer_pool->frame_bufs[bwd_buf_idx].cur_frame_offset;
Jingning Han94a504a2017-09-18 16:17:02 -07001366
1367 if (alt2_buf_idx >= 0)
1368 cm->cur_frame->alt2_frame_offset =
1369 cm->buffer_pool->frame_bufs[alt2_buf_idx].cur_frame_offset;
Jingning Hanc723b342017-08-24 11:19:46 -07001370}
Zoe Liu17af2742017-10-06 10:36:42 -07001371
1372#if CONFIG_FRAME_SIGN_BIAS
1373void av1_setup_frame_sign_bias(AV1_COMMON *cm) {
1374 MV_REFERENCE_FRAME ref_frame;
1375 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
1376 const int buf_idx = cm->frame_refs[ref_frame - LAST_FRAME].idx;
1377 if (buf_idx != INVALID_IDX) {
1378 const int ref_frame_offset =
1379 cm->buffer_pool->frame_bufs[buf_idx].cur_frame_offset;
1380 cm->ref_frame_sign_bias[ref_frame] =
1381 (ref_frame_offset <= (int)cm->frame_offset) ? 0 : 1;
1382 } else {
1383 cm->ref_frame_sign_bias[ref_frame] = 0;
1384 }
1385 }
1386}
1387#endif // CONFIG_FRAME_SIGN_BIAS
Zoe Liuf704a1c2017-10-02 16:55:59 -07001388
1389#if CONFIG_EXT_SKIP
1390void av1_setup_skip_mode_allowed(AV1_COMMON *const cm) {
1391 cm->is_skip_mode_allowed = 0;
1392 cm->ref_frame_idx_0 = cm->ref_frame_idx_1 = INVALID_IDX;
1393
1394 if (cm->frame_type == KEY_FRAME || cm->intra_only) return;
1395
1396 BufferPool *const pool = cm->buffer_pool;
1397 RefCntBuffer *const frame_bufs = pool->frame_bufs;
1398
1399 int ref_frame_offset_0 = -1;
1400 int ref_frame_offset_1 = INT_MAX;
1401 int ref_idx_0 = INVALID_IDX;
1402 int ref_idx_1 = INVALID_IDX;
1403
1404 // Identify the nearest forward and backward references
1405 for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
1406 RefBuffer *const ref_frame = &cm->frame_refs[i];
1407 const int buf_idx = ref_frame->idx;
1408
1409 // Invalid reference frame buffer
1410 if (buf_idx == INVALID_IDX) continue;
1411
1412 const int ref_offset = frame_bufs[buf_idx].cur_frame_offset;
1413 if (ref_offset < (int)cm->frame_offset) {
1414 // Forward reference
1415 if (ref_offset > ref_frame_offset_0) {
1416 ref_frame_offset_0 = ref_offset;
1417 ref_idx_0 = i;
1418 }
1419 } else if (ref_offset > (int)cm->frame_offset) {
1420 // Backward reference
1421 if (ref_offset < ref_frame_offset_1) {
1422 ref_frame_offset_1 = ref_offset;
1423 ref_idx_1 = i;
1424 }
1425 }
1426 }
1427
1428 // Flag is set when and only when both forward and backward references
1429 // are available and their distance is no greater than 3, i.e. as
1430 // opposed to the current frame position, the reference distance pair are
1431 // either: (1, 1), (1, 2), or (2, 1).
1432 if (ref_idx_0 != INVALID_IDX && ref_idx_1 != INVALID_IDX) {
1433 if ((ref_frame_offset_1 - ref_frame_offset_0) <= 3) {
1434 cm->is_skip_mode_allowed = 1;
1435 cm->ref_frame_idx_0 = ref_idx_0;
1436 cm->ref_frame_idx_1 = ref_idx_1;
1437 }
1438 }
1439}
1440#endif // CONFIG_EXT_SKIP
Jingning Hanea255c92017-09-29 08:12:09 -07001441#endif // CONFIG_FRAME_MARKER
Jingning Hanffbb0f92017-08-24 11:52:21 -07001442
Jingning Hanea255c92017-09-29 08:12:09 -07001443#if CONFIG_MFMV
Jingning Han00d58682017-09-19 09:20:28 -07001444// Although we assign 32 bit integers, all the values are strictly under 14
1445// bits.
1446static int div_mult[32] = {
1447 0, 16384, 8192, 5461, 4096, 3276, 2730, 2340, 2048, 1820, 1638,
1448 1489, 1365, 1260, 1170, 1092, 1024, 963, 910, 862, 819, 780,
1449 744, 712, 682, 655, 630, 606, 585, 564, 546, 528,
1450};
1451
1452// TODO(jingning): Consider the use of lookup table for (num / den)
1453// altogether.
Jingning Han5c700912017-09-03 16:06:51 -07001454static void get_mv_projection(MV *output, MV ref, int num, int den) {
Jingning Han00d58682017-09-19 09:20:28 -07001455 output->row =
1456 (int16_t)(ROUND_POWER_OF_TWO(ref.row * num * div_mult[den], 14));
1457 output->col =
1458 (int16_t)(ROUND_POWER_OF_TWO(ref.col * num * div_mult[den], 14));
Jingning Hanffbb0f92017-08-24 11:52:21 -07001459}
1460
Jingning Hanb74a72b2017-09-02 08:55:51 -07001461#define MAX_OFFSET_WIDTH 64
Jingning Hanf1639a12017-10-21 17:21:18 -07001462#define MAX_OFFSET_HEIGHT 0
Jingning Hanb74a72b2017-09-02 08:55:51 -07001463
Jingning Han5c700912017-09-03 16:06:51 -07001464static int get_block_position(AV1_COMMON *cm, int *mi_r, int *mi_c, int blk_row,
Jingning Hane84eec52017-09-01 16:49:29 -07001465 int blk_col, MV mv, int sign_bias) {
Jingning Han7f537b82017-10-16 08:47:27 -07001466 const int base_blk_row = (blk_row >> 3) << 3;
1467 const int base_blk_col = (blk_col >> 3) << 3;
Jingning Hanb74a72b2017-09-02 08:55:51 -07001468
Jingning Hanf5b80682017-10-23 09:30:01 -07001469 const int row_offset = (mv.row >= 0) ? (mv.row >> (4 + MI_SIZE_LOG2))
1470 : -((-mv.row) >> (4 + MI_SIZE_LOG2));
1471
1472 const int col_offset = (mv.col >= 0) ? (mv.col >> (4 + MI_SIZE_LOG2))
1473 : -((-mv.col) >> (4 + MI_SIZE_LOG2));
1474
1475 int row = (sign_bias == 1) ? blk_row - row_offset : blk_row + row_offset;
1476 int col = (sign_bias == 1) ? blk_col - col_offset : blk_col + col_offset;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001477
Jingning Hanc7d198e2017-10-12 16:11:06 -07001478 if (row < 0 || row >= (cm->mi_rows >> 1) || col < 0 ||
1479 col >= (cm->mi_cols >> 1))
1480 return 0;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001481
Jingning Hanf1639a12017-10-21 17:21:18 -07001482 if (row <= base_blk_row - (MAX_OFFSET_HEIGHT >> 3) ||
1483 row >= base_blk_row + 8 + (MAX_OFFSET_HEIGHT >> 3) ||
Jingning Han7f537b82017-10-16 08:47:27 -07001484 col <= base_blk_col - (MAX_OFFSET_WIDTH >> 3) ||
Jingning Hanf1639a12017-10-21 17:21:18 -07001485 col >= base_blk_col + 8 + (MAX_OFFSET_WIDTH >> 3))
Jingning Han7f537b82017-10-16 08:47:27 -07001486 return 0;
1487
Jingning Hanffbb0f92017-08-24 11:52:21 -07001488 *mi_r = row;
1489 *mi_c = col;
Jingning Hane84eec52017-09-01 16:49:29 -07001490
1491 return 1;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001492}
1493
Jingning Han5c700912017-09-03 16:06:51 -07001494static uint32_t mv_sign_reverse(int_mv ref) {
Jingning Hanffbb0f92017-08-24 11:52:21 -07001495 int_mv this_mv;
1496 this_mv.as_mv.row = -ref.as_mv.row;
1497 this_mv.as_mv.col = -ref.as_mv.col;
1498
1499 return this_mv.as_int;
1500}
1501
Jingning Han3bd1bc22017-10-18 16:51:23 -07001502static void motion_field_projection(AV1_COMMON *cm,
Jingning Han09723812017-10-20 10:07:21 -07001503 MV_REFERENCE_FRAME ref_frame,
1504 int ref_stamp) {
Jingning Han3bd1bc22017-10-18 16:51:23 -07001505 TPL_MV_REF *tpl_mvs_base = cm->tpl_mvs;
1506
1507 int cur_frame_index = cm->cur_frame->cur_frame_offset;
1508 int lst_frame_index = 0, alt_frame_index = 0, gld_frame_index = 0;
1509 int lst2_frame_index = 0, lst3_frame_index = 0;
1510 int bwd_frame_index = 0, alt2_frame_index = 0;
1511
1512 int alt_buf_idx = cm->frame_refs[FWD_RF_OFFSET(ALTREF_FRAME)].idx;
1513 int lst_buf_idx = cm->frame_refs[FWD_RF_OFFSET(LAST_FRAME)].idx;
1514 int gld_buf_idx = cm->frame_refs[FWD_RF_OFFSET(GOLDEN_FRAME)].idx;
1515 int lst2_buf_idx = cm->frame_refs[FWD_RF_OFFSET(LAST2_FRAME)].idx;
1516 int lst3_buf_idx = cm->frame_refs[FWD_RF_OFFSET(LAST3_FRAME)].idx;
1517 int bwd_buf_idx = cm->frame_refs[FWD_RF_OFFSET(BWDREF_FRAME)].idx;
1518 int alt2_buf_idx = cm->frame_refs[FWD_RF_OFFSET(ALTREF2_FRAME)].idx;
1519
1520 int ref_frame_idx = cm->frame_refs[FWD_RF_OFFSET(ref_frame)].idx;
1521
1522 if (ref_frame_idx < 0) return;
1523
1524 int ref_frame_index =
1525 cm->buffer_pool->frame_bufs[ref_frame_idx].cur_frame_offset;
1526
1527 if (alt_buf_idx >= 0)
1528 alt_frame_index = cm->buffer_pool->frame_bufs[alt_buf_idx].cur_frame_offset;
1529
1530 if (lst_buf_idx >= 0)
1531 lst_frame_index = cm->buffer_pool->frame_bufs[lst_buf_idx].cur_frame_offset;
1532
1533 if (gld_buf_idx >= 0)
1534 gld_frame_index = cm->buffer_pool->frame_bufs[gld_buf_idx].cur_frame_offset;
1535
1536 if (lst2_buf_idx >= 0)
1537 lst2_frame_index =
1538 cm->buffer_pool->frame_bufs[lst2_buf_idx].cur_frame_offset;
1539
1540 if (lst3_buf_idx >= 0)
1541 lst3_frame_index =
1542 cm->buffer_pool->frame_bufs[lst3_buf_idx].cur_frame_offset;
1543
1544 if (bwd_buf_idx >= 0)
1545 bwd_frame_index = cm->buffer_pool->frame_bufs[bwd_buf_idx].cur_frame_offset;
1546
1547 if (alt2_buf_idx >= 0)
1548 alt2_frame_index =
1549 cm->buffer_pool->frame_bufs[alt2_buf_idx].cur_frame_offset;
1550
1551 MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[ref_frame_idx].mvs;
1552 const int lst_frame_idx =
1553 cm->buffer_pool->frame_bufs[ref_frame_idx].lst_frame_offset;
1554 const int gld_frame_idx =
1555 cm->buffer_pool->frame_bufs[ref_frame_idx].gld_frame_offset;
1556 const int lst2_frame_idx =
1557 cm->buffer_pool->frame_bufs[ref_frame_idx].lst2_frame_offset;
1558 const int lst3_frame_idx =
1559 cm->buffer_pool->frame_bufs[ref_frame_idx].lst3_frame_offset;
1560 const int bwd_frame_idx =
1561 cm->buffer_pool->frame_bufs[ref_frame_idx].bwd_frame_offset;
1562 const int alt2_frame_idx =
1563 cm->buffer_pool->frame_bufs[ref_frame_idx].alt2_frame_offset;
1564
1565 int cur_to_ref = ref_frame_index - cur_frame_index;
1566
1567 int lst_offset = AOMMAX(1, ref_frame_index - lst_frame_idx);
1568 int gld_offset = AOMMAX(1, ref_frame_index - gld_frame_idx);
1569 int cur_to_alt = alt_frame_index - cur_frame_index;
1570 int cur_to_lst = cur_frame_index - lst_frame_index;
1571 int cur_to_gld = cur_frame_index - gld_frame_index;
1572 int bwd_offset = AOMMAX(1, ref_frame_index - bwd_frame_idx);
1573 int alt2_offset = AOMMAX(1, ref_frame_index - alt2_frame_idx);
1574 int lst2_offset = AOMMAX(1, ref_frame_index - lst2_frame_idx);
1575 int lst3_offset = AOMMAX(1, ref_frame_index - lst3_frame_idx);
1576 int cur_to_lst2 = cur_frame_index - lst2_frame_index;
1577 int cur_to_lst3 = cur_frame_index - lst3_frame_index;
1578 int cur_to_bwd = bwd_frame_index - cur_frame_index;
1579 int cur_to_alt2 = alt2_frame_index - cur_frame_index;
Jingning Han3bd1bc22017-10-18 16:51:23 -07001580 // clang-format off
1581 const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = {
1582 0, lst_offset, lst2_offset, lst3_offset, gld_offset,
1583 bwd_offset, alt2_offset, 0,
1584 };
1585 // clang-format on
1586 const int mvs_rows = (cm->mi_rows + 1) >> 1;
1587 const int mvs_cols = (cm->mi_cols + 1) >> 1;
1588
1589 for (int blk_row = 0; blk_row < mvs_rows; ++blk_row) {
1590 for (int blk_col = 0; blk_col < mvs_cols; ++blk_col) {
1591 MV_REF *mv_ref = &mv_ref_base[blk_row * mvs_cols + blk_col];
1592 MV fwd_mv = mv_ref->mv[0].as_mv;
1593 MV_REFERENCE_FRAME rf[2] = { mv_ref->ref_frame[0], mv_ref->ref_frame[1] };
1594
1595 const int ref_frame_offset = ref_frame_offset_buffer[rf[0]];
1596
1597 if (rf[0] <= GOLDEN_FRAME && rf[0] > INTRA_FRAME) {
1598 int_mv this_mv;
1599 int mi_r, mi_c;
1600
1601 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_ref, ref_frame_offset);
1602 int pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
1603 this_mv.as_mv, 0);
1604
1605 if (pos_valid) {
1606 int mi_offset = mi_r * (cm->mi_stride >> 1) + mi_c;
1607
1608 if (ref_frame == ALTREF_FRAME) {
1609 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt,
1610 ref_frame_offset);
1611 tpl_mvs_base[mi_offset]
1612 .mfmv[FWD_RF_OFFSET(ALTREF_FRAME)][ref_stamp]
1613 .as_int = mv_sign_reverse(this_mv);
1614 }
1615
1616 if (ref_frame >= ALTREF2_FRAME) {
1617 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt2,
1618 ref_frame_offset);
1619 tpl_mvs_base[mi_offset]
1620 .mfmv[FWD_RF_OFFSET(ALTREF2_FRAME)][ref_stamp]
1621 .as_int = mv_sign_reverse(this_mv);
1622 }
1623
1624 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd,
1625 ref_frame_offset);
1626 tpl_mvs_base[mi_offset]
1627 .mfmv[FWD_RF_OFFSET(BWDREF_FRAME)][ref_stamp]
1628 .as_int = mv_sign_reverse(this_mv);
1629
1630 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst,
1631 ref_frame_offset);
1632 tpl_mvs_base[mi_offset]
1633 .mfmv[FWD_RF_OFFSET(LAST_FRAME)][ref_stamp]
1634 .as_int = this_mv.as_int;
1635
1636 if (rf[0] >= LAST2_FRAME) {
1637 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2,
1638 ref_frame_offset);
1639 tpl_mvs_base[mi_offset]
1640 .mfmv[FWD_RF_OFFSET(LAST2_FRAME)][ref_stamp]
1641 .as_int = this_mv.as_int;
1642 }
1643
1644 if (rf[0] >= LAST3_FRAME) {
1645 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3,
1646 ref_frame_offset);
1647 tpl_mvs_base[mi_offset]
1648 .mfmv[FWD_RF_OFFSET(LAST3_FRAME)][ref_stamp]
1649 .as_int = this_mv.as_int;
1650 }
1651 if (rf[0] >= GOLDEN_FRAME) {
1652 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld,
1653 ref_frame_offset);
1654 tpl_mvs_base[mi_offset]
1655 .mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)][ref_stamp]
1656 .as_int = this_mv.as_int;
1657 }
1658 }
1659 }
1660 }
1661 }
1662}
1663
Jingning Hanffbb0f92017-08-24 11:52:21 -07001664void av1_setup_motion_field(AV1_COMMON *cm) {
1665 int cur_frame_index = cm->cur_frame->cur_frame_offset;
1666 int lst_frame_index = 0, alt_frame_index = 0, gld_frame_index = 0;
Jingning Han94a504a2017-09-18 16:17:02 -07001667 int lst2_frame_index = 0, lst3_frame_index = 0;
1668 int bwd_frame_index = 0, alt2_frame_index = 0;
Jingning Han6cc1fd32017-10-13 09:05:36 -07001669 TPL_MV_REF *tpl_mvs_base = cm->tpl_mvs;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001670
1671 for (int ref_frame = 0; ref_frame < INTER_REFS_PER_FRAME; ++ref_frame) {
Jingning Hanc7d198e2017-10-12 16:11:06 -07001672 int size = ((cm->mi_rows + MAX_MIB_SIZE) >> 1) * (cm->mi_stride >> 1);
Jingning Hanffbb0f92017-08-24 11:52:21 -07001673 for (int idx = 0; idx < size; ++idx) {
1674 for (int i = 0; i < MFMV_STACK_SIZE; ++i)
1675 tpl_mvs_base[idx].mfmv[ref_frame][i].as_int = INVALID_MV;
1676 }
1677 }
1678
1679 int alt_buf_idx = cm->frame_refs[ALTREF_FRAME - LAST_FRAME].idx;
1680 int lst_buf_idx = cm->frame_refs[LAST_FRAME - LAST_FRAME].idx;
1681 int gld_buf_idx = cm->frame_refs[GOLDEN_FRAME - LAST_FRAME].idx;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001682 int lst2_buf_idx = cm->frame_refs[LAST2_FRAME - LAST_FRAME].idx;
1683 int lst3_buf_idx = cm->frame_refs[LAST3_FRAME - LAST_FRAME].idx;
1684 int bwd_buf_idx = cm->frame_refs[BWDREF_FRAME - LAST_FRAME].idx;
Jingning Han94a504a2017-09-18 16:17:02 -07001685 int alt2_buf_idx = cm->frame_refs[ALTREF2_FRAME - LAST_FRAME].idx;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001686
1687 if (alt_buf_idx >= 0)
1688 alt_frame_index = cm->buffer_pool->frame_bufs[alt_buf_idx].cur_frame_offset;
1689
1690 if (lst_buf_idx >= 0)
1691 lst_frame_index = cm->buffer_pool->frame_bufs[lst_buf_idx].cur_frame_offset;
1692
1693 if (gld_buf_idx >= 0)
1694 gld_frame_index = cm->buffer_pool->frame_bufs[gld_buf_idx].cur_frame_offset;
1695
Jingning Hanffbb0f92017-08-24 11:52:21 -07001696 if (lst2_buf_idx >= 0)
1697 lst2_frame_index =
1698 cm->buffer_pool->frame_bufs[lst2_buf_idx].cur_frame_offset;
1699
1700 if (lst3_buf_idx >= 0)
1701 lst3_frame_index =
1702 cm->buffer_pool->frame_bufs[lst3_buf_idx].cur_frame_offset;
1703
1704 if (bwd_buf_idx >= 0)
1705 bwd_frame_index = cm->buffer_pool->frame_bufs[bwd_buf_idx].cur_frame_offset;
Jingning Han94a504a2017-09-18 16:17:02 -07001706
1707 if (alt2_buf_idx >= 0)
1708 alt2_frame_index =
1709 cm->buffer_pool->frame_bufs[alt2_buf_idx].cur_frame_offset;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001710
1711 if (alt_frame_index < cur_frame_index) return;
1712
Jingning Han380e37c2017-10-24 20:35:02 -07001713 int ref_stamp = MFMV_STACK_SIZE - 1;
Jingning Han406591c2017-10-24 12:49:15 -07001714
Jingning Hanffbb0f92017-08-24 11:52:21 -07001715 // ======================
1716 // Process last frame
1717 // ======================
1718 if (lst_buf_idx >= 0) {
1719 MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[lst_buf_idx].mvs;
1720 const int lst_frame_idx =
1721 cm->buffer_pool->frame_bufs[lst_buf_idx].lst_frame_offset;
1722 const int alt_frame_idx =
1723 cm->buffer_pool->frame_bufs[lst_buf_idx].alt_frame_offset;
1724 const int gld_frame_idx =
1725 cm->buffer_pool->frame_bufs[lst_buf_idx].gld_frame_offset;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001726 const int lst2_frame_idx =
1727 cm->buffer_pool->frame_bufs[lst_buf_idx].lst2_frame_offset;
1728 const int lst3_frame_idx =
1729 cm->buffer_pool->frame_bufs[lst_buf_idx].lst3_frame_offset;
1730 const int bwd_frame_idx =
1731 cm->buffer_pool->frame_bufs[lst_buf_idx].bwd_frame_offset;
Jingning Han94a504a2017-09-18 16:17:02 -07001732 const int alt2_frame_idx =
1733 cm->buffer_pool->frame_bufs[lst_buf_idx].alt2_frame_offset;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001734
1735 int alt_offset = AOMMAX(1, alt_frame_idx - lst_frame_index);
1736 int lst_offset = AOMMAX(1, lst_frame_index - lst_frame_idx);
1737 int gld_offset = AOMMAX(1, lst_frame_index - gld_frame_idx);
1738 int cur_to_lst = cur_frame_index - lst_frame_index;
1739 int cur_to_alt = alt_frame_index - cur_frame_index;
1740 int cur_to_gld = cur_frame_index - gld_frame_index;
1741
Jingning Hanffbb0f92017-08-24 11:52:21 -07001742 int bwd_offset = AOMMAX(1, bwd_frame_idx - lst_frame_index);
Jingning Han94a504a2017-09-18 16:17:02 -07001743 int alt2_offset = AOMMAX(1, alt2_frame_idx - lst_frame_index);
Jingning Hanffbb0f92017-08-24 11:52:21 -07001744 int lst2_offset = AOMMAX(1, lst_frame_index - lst2_frame_idx);
1745 int lst3_offset = AOMMAX(1, lst_frame_index - lst3_frame_idx);
1746 int cur_to_lst2 = cur_frame_index - lst2_frame_index;
1747 int cur_to_lst3 = cur_frame_index - lst3_frame_index;
1748 int cur_to_bwd = bwd_frame_index - cur_frame_index;
Jingning Han94a504a2017-09-18 16:17:02 -07001749 int cur_to_alt2 = alt2_frame_index - cur_frame_index;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001750
1751 const int is_lst_overlay = (alt_frame_idx == gld_frame_index);
1752 // clang-format off
1753 const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = {
Jingning Hanffbb0f92017-08-24 11:52:21 -07001754 0, lst_offset, lst2_offset, lst3_offset, gld_offset,
Jingning Han94a504a2017-09-18 16:17:02 -07001755 bwd_offset, alt2_offset, alt_offset
Jingning Hanffbb0f92017-08-24 11:52:21 -07001756 };
1757 // clang-format on
1758
Jingning Hanc7d198e2017-10-12 16:11:06 -07001759 const int mvs_rows = (cm->mi_rows + 1) >> 1;
1760 const int mvs_cols = (cm->mi_cols + 1) >> 1;
1761
1762 for (int blk_row = 0; blk_row < mvs_rows && !is_lst_overlay; ++blk_row) {
1763 for (int blk_col = 0; blk_col < mvs_cols; ++blk_col) {
1764 MV_REF *mv_ref = &mv_ref_base[blk_row * mvs_cols + blk_col];
Jingning Hanffbb0f92017-08-24 11:52:21 -07001765 MV fwd_mv = mv_ref->mv[0].as_mv;
1766 MV_REFERENCE_FRAME ref_frame[2] = { mv_ref->ref_frame[0],
1767 mv_ref->ref_frame[1] };
1768
1769 // Derive motion vectors toward last reference frame.
1770 if (ref_frame[0] <= GOLDEN_FRAME && ref_frame[0] > INTRA_FRAME) {
1771 int_mv this_mv;
1772 int mi_r, mi_c;
1773
1774 const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[0]];
1775
1776 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst,
1777 ref_frame_offset);
Jingning Hane84eec52017-09-01 16:49:29 -07001778 int pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
1779 this_mv.as_mv, 1);
1780
1781 if (pos_valid) {
Jingning Hanc7d198e2017-10-12 16:11:06 -07001782 int mi_offset = mi_r * (cm->mi_stride >> 1) + mi_c;
Jingning Han406591c2017-10-24 12:49:15 -07001783 tpl_mvs_base[mi_offset]
1784 .mfmv[FWD_RF_OFFSET(LAST_FRAME)][ref_stamp]
1785 .as_int = this_mv.as_int;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001786
Jingning Hane84eec52017-09-01 16:49:29 -07001787 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2,
1788 ref_frame_offset);
Jingning Han406591c2017-10-24 12:49:15 -07001789 tpl_mvs_base[mi_offset]
1790 .mfmv[FWD_RF_OFFSET(LAST2_FRAME)][ref_stamp]
1791 .as_int = this_mv.as_int;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001792
Jingning Hane84eec52017-09-01 16:49:29 -07001793 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3,
1794 ref_frame_offset);
Jingning Han406591c2017-10-24 12:49:15 -07001795 tpl_mvs_base[mi_offset]
1796 .mfmv[FWD_RF_OFFSET(LAST3_FRAME)][ref_stamp]
1797 .as_int = this_mv.as_int;
Jingning Hane84eec52017-09-01 16:49:29 -07001798 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld,
1799 ref_frame_offset);
Jingning Han406591c2017-10-24 12:49:15 -07001800 tpl_mvs_base[mi_offset]
1801 .mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)][ref_stamp]
1802 .as_int = this_mv.as_int;
Jingning Hane84eec52017-09-01 16:49:29 -07001803 }
Jingning Hanffbb0f92017-08-24 11:52:21 -07001804 }
1805
1806 for (int idx = 0; idx < 2; ++idx) {
1807 if (ref_frame[idx] <= GOLDEN_FRAME) continue;
1808
1809 int_mv this_mv;
1810 int mi_r, mi_c;
1811 fwd_mv = mv_ref->mv[idx].as_mv;
1812
1813 const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[idx]];
1814
1815 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst,
1816 ref_frame_offset);
Jingning Hane84eec52017-09-01 16:49:29 -07001817 int pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
1818 this_mv.as_mv, 0);
Jingning Hanffbb0f92017-08-24 11:52:21 -07001819
Jingning Hane84eec52017-09-01 16:49:29 -07001820 if (pos_valid) {
Jingning Hanc7d198e2017-10-12 16:11:06 -07001821 int mi_offset = mi_r * (cm->mi_stride >> 1) + mi_c;
Jingning Hane84eec52017-09-01 16:49:29 -07001822 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt,
1823 ref_frame_offset);
Jingning Han406591c2017-10-24 12:49:15 -07001824 tpl_mvs_base[mi_offset]
1825 .mfmv[FWD_RF_OFFSET(ALTREF_FRAME)][ref_stamp]
1826 .as_int = this_mv.as_int;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001827
Jingning Hane84eec52017-09-01 16:49:29 -07001828 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd,
1829 ref_frame_offset);
Jingning Han406591c2017-10-24 12:49:15 -07001830 tpl_mvs_base[mi_offset]
1831 .mfmv[FWD_RF_OFFSET(BWDREF_FRAME)][ref_stamp]
1832 .as_int = this_mv.as_int;
Jingning Han94a504a2017-09-18 16:17:02 -07001833 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt2,
1834 ref_frame_offset);
Jingning Han406591c2017-10-24 12:49:15 -07001835 tpl_mvs_base[mi_offset]
1836 .mfmv[FWD_RF_OFFSET(ALTREF2_FRAME)][ref_stamp]
1837 .as_int = this_mv.as_int;
Jingning Hane84eec52017-09-01 16:49:29 -07001838 }
Jingning Hanffbb0f92017-08-24 11:52:21 -07001839 }
1840 }
1841 }
Jingning Han406591c2017-10-24 12:49:15 -07001842
Jingning Han71da4812017-10-24 14:16:08 -07001843 --ref_stamp;
Jingning Hanffbb0f92017-08-24 11:52:21 -07001844 }
1845
Jingning Han406591c2017-10-24 12:49:15 -07001846 if (bwd_frame_index > cur_frame_index) {
1847 motion_field_projection(cm, BWDREF_FRAME, ref_stamp);
Jingning Han71da4812017-10-24 14:16:08 -07001848 --ref_stamp;
Jingning Han406591c2017-10-24 12:49:15 -07001849 }
1850
1851 if (alt2_frame_index > cur_frame_index) {
1852 motion_field_projection(cm, ALTREF2_FRAME, ref_stamp);
Jingning Han71da4812017-10-24 14:16:08 -07001853 --ref_stamp;
Jingning Han406591c2017-10-24 12:49:15 -07001854 }
1855
Jingning Han71da4812017-10-24 14:16:08 -07001856 if (alt_frame_index > cur_frame_index && ref_stamp >= 0)
Angie Chiangc906e652017-10-31 18:24:40 -07001857 motion_field_projection(cm, ALTREF_FRAME, ref_stamp);
Jingning Hanffbb0f92017-08-24 11:52:21 -07001858}
1859#endif // CONFIG_MFMV
Jingning Hanc723b342017-08-24 11:19:46 -07001860
Yunqing Wang97d6a372017-10-09 14:15:15 -07001861#if CONFIG_EXT_WARPED_MOTION
Yunqing Wang1bc82862017-06-28 15:49:48 -07001862static INLINE void record_samples(MB_MODE_INFO *mbmi, int *pts, int *pts_inref,
1863 int *pts_mv, int global_offset_r,
1864 int global_offset_c, int row_offset,
1865 int sign_r, int col_offset, int sign_c) {
1866 int bw = block_size_wide[mbmi->sb_type];
1867 int bh = block_size_high[mbmi->sb_type];
1868 int cr_offset = row_offset * MI_SIZE + sign_r * AOMMAX(bh, MI_SIZE) / 2 - 1;
1869 int cc_offset = col_offset * MI_SIZE + sign_c * AOMMAX(bw, MI_SIZE) / 2 - 1;
1870 int x = cc_offset + global_offset_c;
1871 int y = cr_offset + global_offset_r;
1872
1873 pts[0] = (x * 8);
1874 pts[1] = (y * 8);
1875 pts_inref[0] = (x * 8) + mbmi->mv[0].as_mv.col;
1876 pts_inref[1] = (y * 8) + mbmi->mv[0].as_mv.row;
1877 pts_mv[0] = mbmi->mv[0].as_mv.col;
1878 pts_mv[1] = mbmi->mv[0].as_mv.row;
1879}
1880
1881// Only sort pts and pts_inref, and pts_mv is not sorted.
1882#define TRIM_THR 16
1883int sortSamples(int *pts_mv, MV *mv, int *pts, int *pts_inref, int len) {
1884 int pts_mvd[SAMPLES_ARRAY_SIZE] = { 0 };
1885 int i, j, k;
1886 int ret = len;
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07001887 assert(len <= SAMPLES_MAX);
Yunqing Wang1bc82862017-06-28 15:49:48 -07001888
1889 for (i = 0; i < len; ++i)
1890 pts_mvd[i] =
1891 abs(pts_mv[2 * i] - mv->col) + abs(pts_mv[2 * i + 1] - mv->row);
1892
1893 for (i = 1; i <= len - 1; ++i) {
1894 for (j = 0; j < i; ++j) {
1895 if (pts_mvd[j] > pts_mvd[i]) {
1896 int temp, tempi, tempj, ptempi, ptempj;
1897
1898 temp = pts_mvd[i];
1899 tempi = pts[2 * i];
1900 tempj = pts[2 * i + 1];
1901 ptempi = pts_inref[2 * i];
1902 ptempj = pts_inref[2 * i + 1];
1903
1904 for (k = i; k > j; k--) {
1905 pts_mvd[k] = pts_mvd[k - 1];
1906 pts[2 * k] = pts[2 * (k - 1)];
1907 pts[2 * k + 1] = pts[2 * (k - 1) + 1];
1908 pts_inref[2 * k] = pts_inref[2 * (k - 1)];
1909 pts_inref[2 * k + 1] = pts_inref[2 * (k - 1) + 1];
1910 }
1911
1912 pts_mvd[j] = temp;
1913 pts[2 * j] = tempi;
1914 pts[2 * j + 1] = tempj;
1915 pts_inref[2 * j] = ptempi;
1916 pts_inref[2 * j + 1] = ptempj;
1917 break;
1918 }
1919 }
1920 }
1921
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07001922 len = AOMMIN(len, LEAST_SQUARES_SAMPLES_MAX);
Yunqing Wang1bc82862017-06-28 15:49:48 -07001923
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07001924 for (i = len - 1; i >= 1; i--) {
1925 if ((pts_mvd[i] - pts_mvd[i - 1]) >= TRIM_THR) ret = i;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001926 }
1927
Yunqing Wang1bc82862017-06-28 15:49:48 -07001928 return ret;
1929}
1930
1931// Note: Samples returned are at 1/8-pel precision
1932int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
1933 int *pts, int *pts_inref, int *pts_mv) {
1934 MB_MODE_INFO *const mbmi0 = &(xd->mi[0]->mbmi);
1935 int ref_frame = mbmi0->ref_frame[0];
1936 int up_available = xd->up_available;
1937 int left_available = xd->left_available;
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001938 int i, mi_step = 1, np = 0;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001939 int global_offset_c = mi_col * MI_SIZE;
1940 int global_offset_r = mi_row * MI_SIZE;
1941
1942 const TileInfo *const tile = &xd->tile;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001943 int do_tl = 1;
1944 int do_tr = 1;
1945
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001946 // scan the nearest above rows
Yunqing Wang1bc82862017-06-28 15:49:48 -07001947 if (up_available) {
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001948 int mi_row_offset = -1;
1949 MODE_INFO *mi = xd->mi[mi_row_offset * xd->mi_stride];
1950 MB_MODE_INFO *mbmi = &mi->mbmi;
1951 uint8_t n8_w = mi_size_wide[mbmi->sb_type];
Yunqing Wang1bc82862017-06-28 15:49:48 -07001952
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001953 if (xd->n8_w <= n8_w) {
1954 // Handle "current block width <= above block width" case.
1955 int col_offset = -mi_col % n8_w;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001956
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001957 if (col_offset < 0) do_tl = 0;
1958 if (col_offset + n8_w > xd->n8_w) do_tr = 0;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001959
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001960 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
1961 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
1962 global_offset_c, 0, -1, col_offset, 1);
1963 pts += 2;
1964 pts_inref += 2;
1965 pts_mv += 2;
1966 np++;
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07001967 if (np >= SAMPLES_MAX) return SAMPLES_MAX;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001968 }
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001969 } else {
Yunqing Wang1bc82862017-06-28 15:49:48 -07001970 // Handle "current block width > above block width" case.
Yunqing Wang1bc82862017-06-28 15:49:48 -07001971 for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
1972 int mi_col_offset = i;
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001973 mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
1974 mbmi = &mi->mbmi;
1975 n8_w = mi_size_wide[mbmi->sb_type];
Yunqing Wang1bc82862017-06-28 15:49:48 -07001976 mi_step = AOMMIN(xd->n8_w, n8_w);
1977
Yunqing Wang1bc82862017-06-28 15:49:48 -07001978 if (mbmi->ref_frame[0] == ref_frame &&
1979 mbmi->ref_frame[1] == NONE_FRAME) {
1980 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001981 global_offset_c, 0, -1, i, 1);
Yunqing Wang1bc82862017-06-28 15:49:48 -07001982 pts += 2;
1983 pts_inref += 2;
1984 pts_mv += 2;
1985 np++;
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07001986 if (np >= SAMPLES_MAX) return SAMPLES_MAX;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001987 }
1988 }
1989 }
1990 }
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07001991 assert(np <= SAMPLES_MAX);
Yunqing Wang1bc82862017-06-28 15:49:48 -07001992
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001993 // scan the nearest left columns
Yunqing Wang1bc82862017-06-28 15:49:48 -07001994 if (left_available) {
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001995 int mi_col_offset = -1;
Yunqing Wang1bc82862017-06-28 15:49:48 -07001996
Yunqing Wang9a7c6602017-08-08 14:04:06 -07001997 MODE_INFO *mi = xd->mi[mi_col_offset];
1998 MB_MODE_INFO *mbmi = &mi->mbmi;
1999 uint8_t n8_h = mi_size_high[mbmi->sb_type];
Yunqing Wang1bc82862017-06-28 15:49:48 -07002000
Yunqing Wang9a7c6602017-08-08 14:04:06 -07002001 if (xd->n8_h <= n8_h) {
2002 // Handle "current block height <= above block height" case.
2003 int row_offset = -mi_row % n8_h;
Yunqing Wang1bc82862017-06-28 15:49:48 -07002004
Yunqing Wang9a7c6602017-08-08 14:04:06 -07002005 if (row_offset < 0) do_tl = 0;
Yunqing Wang1bc82862017-06-28 15:49:48 -07002006
Yunqing Wang9a7c6602017-08-08 14:04:06 -07002007 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2008 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2009 global_offset_c, row_offset, 1, 0, -1);
2010 pts += 2;
2011 pts_inref += 2;
2012 pts_mv += 2;
2013 np++;
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07002014 if (np >= SAMPLES_MAX) return SAMPLES_MAX;
Yunqing Wang1bc82862017-06-28 15:49:48 -07002015 }
Yunqing Wang9a7c6602017-08-08 14:04:06 -07002016 } else {
Yunqing Wang1bc82862017-06-28 15:49:48 -07002017 // Handle "current block height > above block height" case.
Yunqing Wang1bc82862017-06-28 15:49:48 -07002018 for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
2019 int mi_row_offset = i;
Yunqing Wang9a7c6602017-08-08 14:04:06 -07002020 mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2021 mbmi = &mi->mbmi;
2022 n8_h = mi_size_high[mbmi->sb_type];
Yunqing Wang1bc82862017-06-28 15:49:48 -07002023 mi_step = AOMMIN(xd->n8_h, n8_h);
2024
Yunqing Wang1bc82862017-06-28 15:49:48 -07002025 if (mbmi->ref_frame[0] == ref_frame &&
2026 mbmi->ref_frame[1] == NONE_FRAME) {
2027 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
Yunqing Wang9a7c6602017-08-08 14:04:06 -07002028 global_offset_c, i, 1, 0, -1);
Yunqing Wang1bc82862017-06-28 15:49:48 -07002029 pts += 2;
2030 pts_inref += 2;
2031 pts_mv += 2;
2032 np++;
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07002033 if (np >= SAMPLES_MAX) return SAMPLES_MAX;
Yunqing Wang1bc82862017-06-28 15:49:48 -07002034 }
2035 }
2036 }
2037 }
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07002038 assert(np <= SAMPLES_MAX);
Yunqing Wang1bc82862017-06-28 15:49:48 -07002039
2040 // Top-left block
2041 if (do_tl && left_available && up_available) {
2042 int mi_row_offset = -1;
2043 int mi_col_offset = -1;
2044
2045 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2046 MB_MODE_INFO *mbmi = &mi->mbmi;
2047
2048 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2049 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2050 global_offset_c, 0, -1, 0, -1);
2051 pts += 2;
2052 pts_inref += 2;
2053 pts_mv += 2;
2054 np++;
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07002055 if (np >= SAMPLES_MAX) return SAMPLES_MAX;
Yunqing Wang1bc82862017-06-28 15:49:48 -07002056 }
2057 }
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07002058 assert(np <= SAMPLES_MAX);
Yunqing Wang1bc82862017-06-28 15:49:48 -07002059
2060 // Top-right block
David Barker761b1ac2017-09-25 11:23:03 +01002061 if (do_tr &&
2062 has_top_right(cm, xd, mi_row, mi_col, AOMMAX(xd->n8_w, xd->n8_h))) {
Yunqing Wang1bc82862017-06-28 15:49:48 -07002063 POSITION trb_pos = { -1, xd->n8_w };
2064
2065 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &trb_pos)) {
2066 int mi_row_offset = -1;
2067 int mi_col_offset = xd->n8_w;
2068
2069 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2070 MB_MODE_INFO *mbmi = &mi->mbmi;
2071
2072 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2073 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2074 global_offset_c, 0, -1, xd->n8_w, 1);
2075 np++;
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07002076 if (np >= SAMPLES_MAX) return SAMPLES_MAX;
Yunqing Wang1bc82862017-06-28 15:49:48 -07002077 }
2078 }
2079 }
Yunqing Wang5a6dc0e2017-10-12 15:44:48 -07002080 assert(np <= SAMPLES_MAX);
Yunqing Wang1bc82862017-06-28 15:49:48 -07002081
2082 return np;
2083}
2084#else
Yue Chenff616102017-04-04 15:50:12 -07002085void calc_projection_samples(MB_MODE_INFO *const mbmi, int x, int y,
2086 int *pts_inref) {
2087 pts_inref[0] = (x * 8) + mbmi->mv[0].as_mv.col;
2088 pts_inref[1] = (y * 8) + mbmi->mv[0].as_mv.row;
Yue Chend193cdc2017-01-13 00:52:23 -08002089}
2090
Debargha Mukherjeee6eb3b52017-02-26 08:50:56 -08002091// Note: Samples returned are at 1/8-pel precision
Yue Chen69f18e12016-09-08 14:48:15 -07002092int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
Debargha Mukherjeee6eb3b52017-02-26 08:50:56 -08002093 int *pts, int *pts_inref) {
Yue Chen69f18e12016-09-08 14:48:15 -07002094 MB_MODE_INFO *const mbmi0 = &(xd->mi[0]->mbmi);
2095 int ref_frame = mbmi0->ref_frame[0];
2096 int up_available = xd->up_available;
2097 int left_available = xd->left_available;
2098 int i, mi_step, np = 0;
Yue Chend0d3bcc2017-01-30 11:22:32 -08002099 int global_offset_c = mi_col * MI_SIZE;
2100 int global_offset_r = mi_row * MI_SIZE;
Yue Chen69f18e12016-09-08 14:48:15 -07002101
2102 // scan the above row
2103 if (up_available) {
2104 for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
2105 int mi_row_offset = -1;
2106 int mi_col_offset = i;
2107
2108 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2109 MB_MODE_INFO *mbmi = &mi->mbmi;
2110
Yue Chend0d3bcc2017-01-30 11:22:32 -08002111 mi_step = AOMMIN(xd->n8_w, mi_size_wide[mbmi->sb_type]);
Yue Chen69f18e12016-09-08 14:48:15 -07002112
Emil Keyder01770b32017-01-20 18:03:11 -05002113 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
David Barkercdcac6d2016-12-01 17:04:16 +00002114 int bw = block_size_wide[mbmi->sb_type];
2115 int bh = block_size_high[mbmi->sb_type];
Yue Chend0d3bcc2017-01-30 11:22:32 -08002116 int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
2117 int cc_offset = i * MI_SIZE + AOMMAX(bw, MI_SIZE) / 2 - 1;
Yue Chen5558e5d2017-03-31 12:24:42 -07002118 int x = cc_offset + global_offset_c;
2119 int y = cr_offset + global_offset_r;
Yue Chen69f18e12016-09-08 14:48:15 -07002120
Yue Chen5558e5d2017-03-31 12:24:42 -07002121 pts[0] = (x * 8);
2122 pts[1] = (y * 8);
Yue Chenff616102017-04-04 15:50:12 -07002123 calc_projection_samples(mbmi, x, y, pts_inref);
Yue Chen5558e5d2017-03-31 12:24:42 -07002124 pts += 2;
2125 pts_inref += 2;
2126 np++;
2127 if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
Yue Chen69f18e12016-09-08 14:48:15 -07002128 }
2129 }
2130 }
Debargha Mukherjee9868c742017-01-26 15:23:35 -08002131 assert(2 * np <= SAMPLES_ARRAY_SIZE);
Yue Chen69f18e12016-09-08 14:48:15 -07002132
2133 // scan the left column
2134 if (left_available) {
2135 for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
2136 int mi_row_offset = i;
2137 int mi_col_offset = -1;
2138
2139 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2140 MB_MODE_INFO *mbmi = &mi->mbmi;
2141
Yue Chend0d3bcc2017-01-30 11:22:32 -08002142 mi_step = AOMMIN(xd->n8_h, mi_size_high[mbmi->sb_type]);
Yue Chen69f18e12016-09-08 14:48:15 -07002143
Emil Keyder01770b32017-01-20 18:03:11 -05002144 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
David Barkercdcac6d2016-12-01 17:04:16 +00002145 int bw = block_size_wide[mbmi->sb_type];
2146 int bh = block_size_high[mbmi->sb_type];
Yue Chend0d3bcc2017-01-30 11:22:32 -08002147 int cr_offset = i * MI_SIZE + AOMMAX(bh, MI_SIZE) / 2 - 1;
2148 int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
Yue Chen5558e5d2017-03-31 12:24:42 -07002149 int x = cc_offset + global_offset_c;
2150 int y = cr_offset + global_offset_r;
Yue Chen69f18e12016-09-08 14:48:15 -07002151
Yue Chen5558e5d2017-03-31 12:24:42 -07002152 pts[0] = (x * 8);
2153 pts[1] = (y * 8);
Yue Chenff616102017-04-04 15:50:12 -07002154 calc_projection_samples(mbmi, x, y, pts_inref);
Yue Chen5558e5d2017-03-31 12:24:42 -07002155 pts += 2;
2156 pts_inref += 2;
2157 np++;
2158 if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
Yue Chen69f18e12016-09-08 14:48:15 -07002159 }
2160 }
2161 }
Debargha Mukherjee9868c742017-01-26 15:23:35 -08002162 assert(2 * np <= SAMPLES_ARRAY_SIZE);
Yue Chen69f18e12016-09-08 14:48:15 -07002163
2164 if (left_available && up_available) {
2165 int mi_row_offset = -1;
2166 int mi_col_offset = -1;
2167
2168 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2169 MB_MODE_INFO *mbmi = &mi->mbmi;
2170
Emil Keyder01770b32017-01-20 18:03:11 -05002171 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
David Barkercdcac6d2016-12-01 17:04:16 +00002172 int bw = block_size_wide[mbmi->sb_type];
2173 int bh = block_size_high[mbmi->sb_type];
Yue Chend0d3bcc2017-01-30 11:22:32 -08002174 int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
2175 int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
Yue Chen5558e5d2017-03-31 12:24:42 -07002176 int x = cc_offset + global_offset_c;
2177 int y = cr_offset + global_offset_r;
Yue Chen69f18e12016-09-08 14:48:15 -07002178
Yue Chen5558e5d2017-03-31 12:24:42 -07002179 pts[0] = (x * 8);
2180 pts[1] = (y * 8);
Yue Chenff616102017-04-04 15:50:12 -07002181 calc_projection_samples(mbmi, x, y, pts_inref);
Yue Chen5558e5d2017-03-31 12:24:42 -07002182 np++;
Yue Chen69f18e12016-09-08 14:48:15 -07002183 }
2184 }
Debargha Mukherjee9868c742017-01-26 15:23:35 -08002185 assert(2 * np <= SAMPLES_ARRAY_SIZE);
Yue Chen69f18e12016-09-08 14:48:15 -07002186
Yue Chen69f18e12016-09-08 14:48:15 -07002187 return np;
2188}
Yunqing Wang97d6a372017-10-09 14:15:15 -07002189#endif // CONFIG_EXT_WARPED_MOTION