1 2 /* 3 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 4 * 5 * Use of this source code is governed by a BSD-style license 6 * that can be found in the LICENSE file in the root of the source 7 * tree. An additional intellectual property rights grant can be found 8 * in the file PATENTS. All contributing project authors may 9 * be found in the AUTHORS file in the root of the source tree. 10 */ 11 12 #include "vp9/common/vp9_mvref_common.h" 13 14 // This function searches the neighbourhood of a given MB/SB 15 // to try and find candidate reference vectors. 16 static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd, 17 const TileInfo *const tile, 18 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame, 19 int_mv *mv_ref_list, 20 int block, int mi_row, int mi_col) { 21 const int *ref_sign_bias = cm->ref_frame_sign_bias; 22 int i, refmv_count = 0; 23 const MODE_INFO *prev_mi = !cm->error_resilient_mode && cm->prev_mi 24 ? cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col] 25 : NULL; 26 const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL; 27 28 29 const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type]; 30 31 int different_ref_found = 0; 32 int context_counter = 0; 33 34 // Blank the reference vector list 35 vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES); 36 37 // The nearest 2 blocks are treated differently 38 // if the size < 8x8 we get the mv from the bmi substructure, 39 // and we also need to keep a mode count. 40 for (i = 0; i < 2; ++i) { 41 const POSITION *const mv_ref = &mv_ref_search[i]; 42 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { 43 const MODE_INFO *const candidate_mi = xd->mi[mv_ref->col + mv_ref->row * 44 xd->mi_stride]; 45 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi; 46 // Keep counts for entropy encoding. 47 context_counter += mode_2_counter[candidate->mode]; 48 different_ref_found = 1; 49 50 if (candidate->ref_frame[0] == ref_frame) 51 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block)); 52 else if (candidate->ref_frame[1] == ref_frame) 53 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block)); 54 } 55 } 56 57 // Check the rest of the neighbors in much the same way 58 // as before except we don't need to keep track of sub blocks or 59 // mode counts. 60 for (; i < MVREF_NEIGHBOURS; ++i) { 61 const POSITION *const mv_ref = &mv_ref_search[i]; 62 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { 63 const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row * 64 xd->mi_stride]->mbmi; 65 different_ref_found = 1; 66 67 if (candidate->ref_frame[0] == ref_frame) 68 ADD_MV_REF_LIST(candidate->mv[0]); 69 else if (candidate->ref_frame[1] == ref_frame) 70 ADD_MV_REF_LIST(candidate->mv[1]); 71 } 72 } 73 74 // Check the last frame's mode and mv info. 75 if (prev_mbmi) { 76 if (prev_mbmi->ref_frame[0] == ref_frame) 77 ADD_MV_REF_LIST(prev_mbmi->mv[0]); 78 else if (prev_mbmi->ref_frame[1] == ref_frame) 79 ADD_MV_REF_LIST(prev_mbmi->mv[1]); 80 } 81 82 // Since we couldn't find 2 mvs from the same reference frame 83 // go back through the neighbors and find motion vectors from 84 // different reference frames. 85 if (different_ref_found) { 86 for (i = 0; i < MVREF_NEIGHBOURS; ++i) { 87 const POSITION *mv_ref = &mv_ref_search[i]; 88 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { 89 const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row 90 * xd->mi_stride]->mbmi; 91 92 // If the candidate is INTRA we don't want to consider its mv. 93 IF_DIFF_REF_FRAME_ADD_MV(candidate); 94 } 95 } 96 } 97 98 // Since we still don't have a candidate we'll try the last frame. 99 if (prev_mbmi) 100 IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi); 101 102 Done: 103 104 mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter]; 105 106 // Clamp vectors 107 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) 108 clamp_mv_ref(&mv_ref_list[i].as_mv, xd); 109 } 110 111 void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd, 112 const TileInfo *const tile, 113 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame, 114 int_mv *mv_ref_list, 115 int mi_row, int mi_col) { 116 find_mv_refs_idx(cm, xd, tile, mi, ref_frame, mv_ref_list, -1, 117 mi_row, mi_col); 118 } 119 120 static void lower_mv_precision(MV *mv, int allow_hp) { 121 const int use_hp = allow_hp && vp9_use_mv_hp(mv); 122 if (!use_hp) { 123 if (mv->row & 1) 124 mv->row += (mv->row > 0 ? -1 : 1); 125 if (mv->col & 1) 126 mv->col += (mv->col > 0 ? -1 : 1); 127 } 128 } 129 130 131 void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp, 132 int_mv *mvlist, int_mv *nearest, int_mv *near) { 133 int i; 134 // Make sure all the candidates are properly clamped etc 135 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) { 136 lower_mv_precision(&mvlist[i].as_mv, allow_hp); 137 clamp_mv2(&mvlist[i].as_mv, xd); 138 } 139 *nearest = mvlist[0]; 140 *near = mvlist[1]; 141 } 142 143 void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd, 144 const TileInfo *const tile, 145 int block, int ref, int mi_row, int mi_col, 146 int_mv *nearest, int_mv *near) { 147 int_mv mv_list[MAX_MV_REF_CANDIDATES]; 148 MODE_INFO *const mi = xd->mi[0]; 149 b_mode_info *bmi = mi->bmi; 150 int n; 151 152 assert(MAX_MV_REF_CANDIDATES == 2); 153 154 find_mv_refs_idx(cm, xd, tile, mi, mi->mbmi.ref_frame[ref], mv_list, block, 155 mi_row, mi_col); 156 157 near->as_int = 0; 158 switch (block) { 159 case 0: 160 nearest->as_int = mv_list[0].as_int; 161 near->as_int = mv_list[1].as_int; 162 break; 163 case 1: 164 case 2: 165 nearest->as_int = bmi[0].as_mv[ref].as_int; 166 for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n) 167 if (nearest->as_int != mv_list[n].as_int) { 168 near->as_int = mv_list[n].as_int; 169 break; 170 } 171 break; 172 case 3: { 173 int_mv candidates[2 + MAX_MV_REF_CANDIDATES]; 174 candidates[0] = bmi[1].as_mv[ref]; 175 candidates[1] = bmi[0].as_mv[ref]; 176 candidates[2] = mv_list[0]; 177 candidates[3] = mv_list[1]; 178 179 nearest->as_int = bmi[2].as_mv[ref].as_int; 180 for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n) 181 if (nearest->as_int != candidates[n].as_int) { 182 near->as_int = candidates[n].as_int; 183 break; 184 } 185 break; 186 } 187 default: 188 assert("Invalid block index."); 189 } 190 } 191