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