1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp9/common/vp9_mvref_common.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,286 @@ 1.4 + 1.5 +/* 1.6 + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license 1.9 + * that can be found in the LICENSE file in the root of the source 1.10 + * tree. An additional intellectual property rights grant can be found 1.11 + * in the file PATENTS. All contributing project authors may 1.12 + * be found in the AUTHORS file in the root of the source tree. 1.13 + */ 1.14 + 1.15 +#include "vp9/common/vp9_mvref_common.h" 1.16 + 1.17 +#define MVREF_NEIGHBOURS 8 1.18 + 1.19 +typedef enum { 1.20 + BOTH_ZERO = 0, 1.21 + ZERO_PLUS_PREDICTED = 1, 1.22 + BOTH_PREDICTED = 2, 1.23 + NEW_PLUS_NON_INTRA = 3, 1.24 + BOTH_NEW = 4, 1.25 + INTRA_PLUS_NON_INTRA = 5, 1.26 + BOTH_INTRA = 6, 1.27 + INVALID_CASE = 9 1.28 +} motion_vector_context; 1.29 + 1.30 +// This is used to figure out a context for the ref blocks. The code flattens 1.31 +// an array that would have 3 possible counts (0, 1 & 2) for 3 choices by 1.32 +// adding 9 for each intra block, 3 for each zero mv and 1 for each new 1.33 +// motion vector. This single number is then converted into a context 1.34 +// with a single lookup ( counter_to_context ). 1.35 +static const int mode_2_counter[MB_MODE_COUNT] = { 1.36 + 9, // DC_PRED 1.37 + 9, // V_PRED 1.38 + 9, // H_PRED 1.39 + 9, // D45_PRED 1.40 + 9, // D135_PRED 1.41 + 9, // D117_PRED 1.42 + 9, // D153_PRED 1.43 + 9, // D207_PRED 1.44 + 9, // D63_PRED 1.45 + 9, // TM_PRED 1.46 + 0, // NEARESTMV 1.47 + 0, // NEARMV 1.48 + 3, // ZEROMV 1.49 + 1, // NEWMV 1.50 +}; 1.51 + 1.52 +// There are 3^3 different combinations of 3 counts that can be either 0,1 or 1.53 +// 2. However the actual count can never be greater than 2 so the highest 1.54 +// counter we need is 18. 9 is an invalid counter that's never used. 1.55 +static const int counter_to_context[19] = { 1.56 + BOTH_PREDICTED, // 0 1.57 + NEW_PLUS_NON_INTRA, // 1 1.58 + BOTH_NEW, // 2 1.59 + ZERO_PLUS_PREDICTED, // 3 1.60 + NEW_PLUS_NON_INTRA, // 4 1.61 + INVALID_CASE, // 5 1.62 + BOTH_ZERO, // 6 1.63 + INVALID_CASE, // 7 1.64 + INVALID_CASE, // 8 1.65 + INTRA_PLUS_NON_INTRA, // 9 1.66 + INTRA_PLUS_NON_INTRA, // 10 1.67 + INVALID_CASE, // 11 1.68 + INTRA_PLUS_NON_INTRA, // 12 1.69 + INVALID_CASE, // 13 1.70 + INVALID_CASE, // 14 1.71 + INVALID_CASE, // 15 1.72 + INVALID_CASE, // 16 1.73 + INVALID_CASE, // 17 1.74 + BOTH_INTRA // 18 1.75 +}; 1.76 + 1.77 +static const MV mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = { 1.78 + // 4X4 1.79 + {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, 1.80 + // 4X8 1.81 + {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, 1.82 + // 8X4 1.83 + {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, 1.84 + // 8X8 1.85 + {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, 1.86 + // 8X16 1.87 + {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}}, 1.88 + // 16X8 1.89 + {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}}, 1.90 + // 16X16 1.91 + {{-1, 0}, {0, -1}, {-1, 1}, {1, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}}, 1.92 + // 16X32 1.93 + {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}}, 1.94 + // 32X16 1.95 + {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}}, 1.96 + // 32X32 1.97 + {{-1, 1}, {1, -1}, {-1, 2}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}}, 1.98 + // 32X64 1.99 + {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}}, 1.100 + // 64X32 1.101 + {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}}, 1.102 + // 64X64 1.103 + {{-1, 3}, {3, -1}, {-1, 4}, {4, -1}, {-1, -1}, {-1, 0}, {0, -1}, {-1, 6}} 1.104 +}; 1.105 + 1.106 +static const int idx_n_column_to_subblock[4][2] = { 1.107 + {1, 2}, 1.108 + {1, 3}, 1.109 + {3, 2}, 1.110 + {3, 3} 1.111 +}; 1.112 + 1.113 +// clamp_mv_ref 1.114 +#define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units 1.115 + 1.116 +static void clamp_mv_ref(MV *mv, const MACROBLOCKD *xd) { 1.117 + clamp_mv(mv, xd->mb_to_left_edge - MV_BORDER, 1.118 + xd->mb_to_right_edge + MV_BORDER, 1.119 + xd->mb_to_top_edge - MV_BORDER, 1.120 + xd->mb_to_bottom_edge + MV_BORDER); 1.121 +} 1.122 + 1.123 +// This function returns either the appropriate sub block or block's mv 1.124 +// on whether the block_size < 8x8 and we have check_sub_blocks set. 1.125 +static INLINE int_mv get_sub_block_mv(const MODE_INFO *candidate, int which_mv, 1.126 + int search_col, int block_idx) { 1.127 + return block_idx >= 0 && candidate->mbmi.sb_type < BLOCK_8X8 1.128 + ? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]] 1.129 + .as_mv[which_mv] 1.130 + : candidate->mbmi.mv[which_mv]; 1.131 +} 1.132 + 1.133 + 1.134 +// Performs mv sign inversion if indicated by the reference frame combination. 1.135 +static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref, 1.136 + const MV_REFERENCE_FRAME this_ref_frame, 1.137 + const int *ref_sign_bias) { 1.138 + int_mv mv = mbmi->mv[ref]; 1.139 + if (ref_sign_bias[mbmi->ref_frame[ref]] != ref_sign_bias[this_ref_frame]) { 1.140 + mv.as_mv.row *= -1; 1.141 + mv.as_mv.col *= -1; 1.142 + } 1.143 + return mv; 1.144 +} 1.145 + 1.146 +// This macro is used to add a motion vector mv_ref list if it isn't 1.147 +// already in the list. If it's the second motion vector it will also 1.148 +// skip all additional processing and jump to done! 1.149 +#define ADD_MV_REF_LIST(MV) \ 1.150 + do { \ 1.151 + if (refmv_count) { \ 1.152 + if ((MV).as_int != mv_ref_list[0].as_int) { \ 1.153 + mv_ref_list[refmv_count] = (MV); \ 1.154 + goto Done; \ 1.155 + } \ 1.156 + } else { \ 1.157 + mv_ref_list[refmv_count++] = (MV); \ 1.158 + } \ 1.159 + } while (0) 1.160 + 1.161 +// If either reference frame is different, not INTRA, and they 1.162 +// are different from each other scale and add the mv to our list. 1.163 +#define IF_DIFF_REF_FRAME_ADD_MV(CANDIDATE) \ 1.164 + do { \ 1.165 + if ((CANDIDATE)->ref_frame[0] != ref_frame) \ 1.166 + ADD_MV_REF_LIST(scale_mv((CANDIDATE), 0, ref_frame, ref_sign_bias)); \ 1.167 + if ((CANDIDATE)->ref_frame[1] != ref_frame && \ 1.168 + has_second_ref(CANDIDATE) && \ 1.169 + (CANDIDATE)->mv[1].as_int != (CANDIDATE)->mv[0].as_int) \ 1.170 + ADD_MV_REF_LIST(scale_mv((CANDIDATE), 1, ref_frame, ref_sign_bias)); \ 1.171 + } while (0) 1.172 + 1.173 + 1.174 +// Checks that the given mi_row, mi_col and search point 1.175 +// are inside the borders of the tile. 1.176 +static INLINE int is_inside(const TileInfo *const tile, 1.177 + int mi_col, int mi_row, int mi_rows, 1.178 + const MV *mv) { 1.179 + return !(mi_row + mv->row < 0 || 1.180 + mi_col + mv->col < tile->mi_col_start || 1.181 + mi_row + mv->row >= mi_rows || 1.182 + mi_col + mv->col >= tile->mi_col_end); 1.183 +} 1.184 + 1.185 +// This function searches the neighbourhood of a given MB/SB 1.186 +// to try and find candidate reference vectors. 1.187 +void vp9_find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd, 1.188 + const TileInfo *const tile, 1.189 + MODE_INFO *mi, const MODE_INFO *prev_mi, 1.190 + MV_REFERENCE_FRAME ref_frame, 1.191 + int_mv *mv_ref_list, 1.192 + int block_idx, 1.193 + int mi_row, int mi_col) { 1.194 + const int *ref_sign_bias = cm->ref_frame_sign_bias; 1.195 + int i, refmv_count = 0; 1.196 + const MV *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type]; 1.197 + const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL; 1.198 + int different_ref_found = 0; 1.199 + int context_counter = 0; 1.200 + 1.201 + // Blank the reference vector list 1.202 + vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES); 1.203 + 1.204 + // The nearest 2 blocks are treated differently 1.205 + // if the size < 8x8 we get the mv from the bmi substructure, 1.206 + // and we also need to keep a mode count. 1.207 + for (i = 0; i < 2; ++i) { 1.208 + const MV *const mv_ref = &mv_ref_search[i]; 1.209 + if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { 1.210 + const MODE_INFO *const candidate_mi = xd->mi_8x8[mv_ref->col + mv_ref->row 1.211 + * xd->mode_info_stride]; 1.212 + const MB_MODE_INFO *const candidate = &candidate_mi->mbmi; 1.213 + // Keep counts for entropy encoding. 1.214 + context_counter += mode_2_counter[candidate->mode]; 1.215 + 1.216 + // Check if the candidate comes from the same reference frame. 1.217 + if (candidate->ref_frame[0] == ref_frame) { 1.218 + ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, 1.219 + mv_ref->col, block_idx)); 1.220 + different_ref_found = candidate->ref_frame[1] != ref_frame; 1.221 + } else { 1.222 + if (candidate->ref_frame[1] == ref_frame) 1.223 + // Add second motion vector if it has the same ref_frame. 1.224 + ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, 1.225 + mv_ref->col, block_idx)); 1.226 + different_ref_found = 1; 1.227 + } 1.228 + } 1.229 + } 1.230 + 1.231 + // Check the rest of the neighbors in much the same way 1.232 + // as before except we don't need to keep track of sub blocks or 1.233 + // mode counts. 1.234 + for (; i < MVREF_NEIGHBOURS; ++i) { 1.235 + const MV *const mv_ref = &mv_ref_search[i]; 1.236 + if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { 1.237 + const MB_MODE_INFO *const candidate = &xd->mi_8x8[mv_ref->col + 1.238 + mv_ref->row 1.239 + * xd->mode_info_stride]->mbmi; 1.240 + 1.241 + if (candidate->ref_frame[0] == ref_frame) { 1.242 + ADD_MV_REF_LIST(candidate->mv[0]); 1.243 + different_ref_found = candidate->ref_frame[1] != ref_frame; 1.244 + } else { 1.245 + if (candidate->ref_frame[1] == ref_frame) 1.246 + ADD_MV_REF_LIST(candidate->mv[1]); 1.247 + different_ref_found = 1; 1.248 + } 1.249 + } 1.250 + } 1.251 + 1.252 + // Check the last frame's mode and mv info. 1.253 + if (prev_mbmi) { 1.254 + if (prev_mbmi->ref_frame[0] == ref_frame) 1.255 + ADD_MV_REF_LIST(prev_mbmi->mv[0]); 1.256 + else if (prev_mbmi->ref_frame[1] == ref_frame) 1.257 + ADD_MV_REF_LIST(prev_mbmi->mv[1]); 1.258 + } 1.259 + 1.260 + // Since we couldn't find 2 mvs from the same reference frame 1.261 + // go back through the neighbors and find motion vectors from 1.262 + // different reference frames. 1.263 + if (different_ref_found) { 1.264 + for (i = 0; i < MVREF_NEIGHBOURS; ++i) { 1.265 + const MV *mv_ref = &mv_ref_search[i]; 1.266 + if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { 1.267 + const MB_MODE_INFO *const candidate = &xd->mi_8x8[mv_ref->col + 1.268 + mv_ref->row 1.269 + * xd->mode_info_stride]->mbmi; 1.270 + 1.271 + // If the candidate is INTRA we don't want to consider its mv. 1.272 + if (is_inter_block(candidate)) 1.273 + IF_DIFF_REF_FRAME_ADD_MV(candidate); 1.274 + } 1.275 + } 1.276 + } 1.277 + 1.278 + // Since we still don't have a candidate we'll try the last frame. 1.279 + if (prev_mbmi && is_inter_block(prev_mbmi)) 1.280 + IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi); 1.281 + 1.282 + Done: 1.283 + 1.284 + mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter]; 1.285 + 1.286 + // Clamp vectors 1.287 + for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) 1.288 + clamp_mv_ref(&mv_ref_list[i].as_mv, xd); 1.289 +}