OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 |
| 12 #include "vp9/common/vp9_findnearmv.h" |
| 13 #include "vp9/common/vp9_sadmxn.h" |
| 14 #include "vp9/common/vp9_subpelvar.h" |
| 15 #include <limits.h> |
| 16 |
| 17 const unsigned char vp9_mbsplit_offset[4][16] = { |
| 18 { 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
| 19 { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
| 20 { 0, 2, 8, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
| 21 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} |
| 22 }; |
| 23 |
| 24 static void lower_mv_precision(int_mv *mv, int usehp) |
| 25 { |
| 26 if (!usehp || !vp9_use_nmv_hp(&mv->as_mv)) { |
| 27 if (mv->as_mv.row & 1) |
| 28 mv->as_mv.row += (mv->as_mv.row > 0 ? -1 : 1); |
| 29 if (mv->as_mv.col & 1) |
| 30 mv->as_mv.col += (mv->as_mv.col > 0 ? -1 : 1); |
| 31 } |
| 32 } |
| 33 |
| 34 vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc, |
| 35 vp9_prob p[4], const int context |
| 36 ) { |
| 37 p[0] = pc->fc.vp9_mode_contexts[context][0]; |
| 38 p[1] = pc->fc.vp9_mode_contexts[context][1]; |
| 39 p[2] = pc->fc.vp9_mode_contexts[context][2]; |
| 40 p[3] = pc->fc.vp9_mode_contexts[context][3]; |
| 41 return p; |
| 42 } |
| 43 |
| 44 #define SP(x) (((x) & 7) << 1) |
| 45 unsigned int vp9_sad3x16_c(const unsigned char *src_ptr, |
| 46 int src_stride, |
| 47 const unsigned char *ref_ptr, |
| 48 int ref_stride) { |
| 49 return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 3, 16); |
| 50 } |
| 51 unsigned int vp9_sad16x3_c(const unsigned char *src_ptr, |
| 52 int src_stride, |
| 53 const unsigned char *ref_ptr, |
| 54 int ref_stride) { |
| 55 return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 16, 3); |
| 56 } |
| 57 |
| 58 #if CONFIG_SUBPELREFMV |
| 59 unsigned int vp9_variance2x16_c(const unsigned char *src_ptr, |
| 60 const int source_stride, |
| 61 const unsigned char *ref_ptr, |
| 62 const int recon_stride, |
| 63 unsigned int *sse) { |
| 64 int sum; |
| 65 variance(src_ptr, source_stride, ref_ptr, recon_stride, 2, 16, sse, &sum); |
| 66 return (*sse - (((unsigned int)sum * sum) >> 5)); |
| 67 } |
| 68 |
| 69 unsigned int vp9_variance16x2_c(const unsigned char *src_ptr, |
| 70 const int source_stride, |
| 71 const unsigned char *ref_ptr, |
| 72 const int recon_stride, |
| 73 unsigned int *sse) { |
| 74 int sum; |
| 75 variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 2, sse, &sum); |
| 76 return (*sse - (((unsigned int)sum * sum) >> 5)); |
| 77 } |
| 78 |
| 79 unsigned int vp9_sub_pixel_variance16x2_c(const unsigned char *src_ptr, |
| 80 const int src_pixels_per_line, |
| 81 const int xoffset, |
| 82 const int yoffset, |
| 83 const unsigned char *dst_ptr, |
| 84 const int dst_pixels_per_line, |
| 85 unsigned int *sse) { |
| 86 unsigned short FData3[16 * 3]; // Temp data buffer used in filtering |
| 87 unsigned char temp2[2 * 16]; |
| 88 const short *HFilter, *VFilter; |
| 89 |
| 90 HFilter = vp9_bilinear_filters[xoffset]; |
| 91 VFilter = vp9_bilinear_filters[yoffset]; |
| 92 |
| 93 var_filter_block2d_bil_first_pass(src_ptr, FData3, |
| 94 src_pixels_per_line, 1, 3, 16, HFilter); |
| 95 var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 2, 16, VFilter); |
| 96 |
| 97 return vp9_variance16x2_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse); |
| 98 } |
| 99 |
| 100 unsigned int vp9_sub_pixel_variance2x16_c(const unsigned char *src_ptr, |
| 101 const int src_pixels_per_line, |
| 102 const int xoffset, |
| 103 const int yoffset, |
| 104 const unsigned char *dst_ptr, |
| 105 const int dst_pixels_per_line, |
| 106 unsigned int *sse) { |
| 107 unsigned short FData3[2 * 17]; // Temp data buffer used in filtering |
| 108 unsigned char temp2[2 * 16]; |
| 109 const short *HFilter, *VFilter; |
| 110 |
| 111 HFilter = vp9_bilinear_filters[xoffset]; |
| 112 VFilter = vp9_bilinear_filters[yoffset]; |
| 113 |
| 114 var_filter_block2d_bil_first_pass(src_ptr, FData3, |
| 115 src_pixels_per_line, 1, 17, 2, HFilter); |
| 116 var_filter_block2d_bil_second_pass(FData3, temp2, 2, 2, 16, 2, VFilter); |
| 117 |
| 118 return vp9_variance2x16_c(temp2, 2, dst_ptr, dst_pixels_per_line, sse); |
| 119 } |
| 120 #endif |
| 121 |
| 122 /* check a list of motion vectors by sad score using a number rows of pixels |
| 123 * above and a number cols of pixels in the left to select the one with best |
| 124 * score to use as ref motion vector |
| 125 */ |
| 126 void vp9_find_best_ref_mvs(MACROBLOCKD *xd, |
| 127 unsigned char *ref_y_buffer, |
| 128 int ref_y_stride, |
| 129 int_mv *mvlist, |
| 130 int_mv *best_mv, |
| 131 int_mv *nearest, |
| 132 int_mv *near) { |
| 133 int i, j; |
| 134 unsigned char *above_src; |
| 135 unsigned char *left_src; |
| 136 unsigned char *above_ref; |
| 137 unsigned char *left_ref; |
| 138 unsigned int score; |
| 139 #if CONFIG_SUBPELREFMV |
| 140 unsigned int sse; |
| 141 #endif |
| 142 unsigned int ref_scores[MAX_MV_REFS] = {0}; |
| 143 int_mv sorted_mvs[MAX_MV_REFS]; |
| 144 int zero_seen = FALSE; |
| 145 |
| 146 // Default all to 0,0 if nothing else available |
| 147 best_mv->as_int = nearest->as_int = near->as_int = 0; |
| 148 vpx_memset(sorted_mvs, 0, sizeof(sorted_mvs)); |
| 149 |
| 150 #if CONFIG_SUBPELREFMV |
| 151 above_src = xd->dst.y_buffer - xd->dst.y_stride * 2; |
| 152 left_src = xd->dst.y_buffer - 2; |
| 153 above_ref = ref_y_buffer - ref_y_stride * 2; |
| 154 left_ref = ref_y_buffer - 2; |
| 155 #else |
| 156 above_src = xd->dst.y_buffer - xd->dst.y_stride * 3; |
| 157 left_src = xd->dst.y_buffer - 3; |
| 158 above_ref = ref_y_buffer - ref_y_stride * 3; |
| 159 left_ref = ref_y_buffer - 3; |
| 160 #endif |
| 161 |
| 162 //for(i = 0; i < MAX_MV_REFS; ++i) { |
| 163 // Limit search to the predicted best 4 |
| 164 for(i = 0; i < 4; ++i) { |
| 165 int_mv this_mv; |
| 166 int offset = 0; |
| 167 int row_offset, col_offset; |
| 168 |
| 169 this_mv.as_int = mvlist[i].as_int; |
| 170 |
| 171 // If we see a 0,0 vector for a second time we have reached the end of |
| 172 // the list of valid candidate vectors. |
| 173 if (!this_mv.as_int && zero_seen) |
| 174 break; |
| 175 |
| 176 zero_seen = zero_seen || !this_mv.as_int; |
| 177 |
| 178 clamp_mv(&this_mv, |
| 179 xd->mb_to_left_edge - LEFT_TOP_MARGIN + 24, |
| 180 xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN, |
| 181 xd->mb_to_top_edge - LEFT_TOP_MARGIN + 24, |
| 182 xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN); |
| 183 |
| 184 #if CONFIG_SUBPELREFMV |
| 185 row_offset = this_mv.as_mv.row >> 3; |
| 186 col_offset = this_mv.as_mv.col >> 3; |
| 187 offset = ref_y_stride * row_offset + col_offset; |
| 188 score = 0; |
| 189 if (xd->up_available) { |
| 190 vp9_sub_pixel_variance16x2_c(above_ref + offset, ref_y_stride, |
| 191 SP(this_mv.as_mv.col), |
| 192 SP(this_mv.as_mv.row), |
| 193 above_src, xd->dst.y_stride, &sse); |
| 194 score += sse; |
| 195 #if CONFIG_SUPERBLOCKS |
| 196 if (xd->mode_info_context->mbmi.encoded_as_sb) { |
| 197 vp9_sub_pixel_variance16x2_c(above_ref + offset + 16, |
| 198 ref_y_stride, |
| 199 SP(this_mv.as_mv.col), |
| 200 SP(this_mv.as_mv.row), |
| 201 above_src + 16, xd->dst.y_stride, &sse); |
| 202 score += sse; |
| 203 } |
| 204 #endif |
| 205 } |
| 206 if (xd->left_available) { |
| 207 vp9_sub_pixel_variance2x16_c(left_ref + offset, ref_y_stride, |
| 208 SP(this_mv.as_mv.col), |
| 209 SP(this_mv.as_mv.row), |
| 210 left_src, xd->dst.y_stride, &sse); |
| 211 score += sse; |
| 212 #if CONFIG_SUPERBLOCKS |
| 213 if (xd->mode_info_context->mbmi.encoded_as_sb) { |
| 214 vp9_sub_pixel_variance2x16_c(left_ref + offset + ref_y_stride * 16, |
| 215 ref_y_stride, |
| 216 SP(this_mv.as_mv.col), |
| 217 SP(this_mv.as_mv.row), |
| 218 left_src + xd->dst.y_stride * 16, |
| 219 xd->dst.y_stride, &sse); |
| 220 score += sse; |
| 221 } |
| 222 #endif |
| 223 } |
| 224 #else |
| 225 row_offset = (this_mv.as_mv.row > 0) ? |
| 226 ((this_mv.as_mv.row + 3) >> 3):((this_mv.as_mv.row + 4) >> 3); |
| 227 col_offset = (this_mv.as_mv.col > 0) ? |
| 228 ((this_mv.as_mv.col + 3) >> 3):((this_mv.as_mv.col + 4) >> 3); |
| 229 offset = ref_y_stride * row_offset + col_offset; |
| 230 score = 0; |
| 231 if (xd->up_available) { |
| 232 score += vp9_sad16x3(above_src, xd->dst.y_stride, |
| 233 above_ref + offset, ref_y_stride); |
| 234 #if CONFIG_SUPERBLOCKS |
| 235 if (xd->mode_info_context->mbmi.encoded_as_sb) { |
| 236 score += vp9_sad16x3(above_src + 16, xd->dst.y_stride, |
| 237 above_ref + offset + 16, ref_y_stride); |
| 238 } |
| 239 #endif |
| 240 } |
| 241 if (xd->left_available) { |
| 242 score += vp9_sad3x16(left_src, xd->dst.y_stride, |
| 243 left_ref + offset, ref_y_stride); |
| 244 #if CONFIG_SUPERBLOCKS |
| 245 if (xd->mode_info_context->mbmi.encoded_as_sb) { |
| 246 score += vp9_sad3x16(left_src + xd->dst.y_stride * 16, |
| 247 xd->dst.y_stride, |
| 248 left_ref + offset + ref_y_stride * 16, |
| 249 ref_y_stride); |
| 250 } |
| 251 #endif |
| 252 } |
| 253 #endif |
| 254 // Add the entry to our list and then resort the list on score. |
| 255 ref_scores[i] = score; |
| 256 sorted_mvs[i].as_int = this_mv.as_int; |
| 257 j = i; |
| 258 while (j > 0) { |
| 259 if (ref_scores[j] < ref_scores[j-1]) { |
| 260 ref_scores[j] = ref_scores[j-1]; |
| 261 sorted_mvs[j].as_int = sorted_mvs[j-1].as_int; |
| 262 ref_scores[j-1] = score; |
| 263 sorted_mvs[j-1].as_int = this_mv.as_int; |
| 264 j--; |
| 265 } else |
| 266 break; |
| 267 } |
| 268 } |
| 269 |
| 270 // Make sure all the candidates are properly clamped etc |
| 271 for (i = 0; i < 4; ++i) { |
| 272 lower_mv_precision(&sorted_mvs[i], xd->allow_high_precision_mv); |
| 273 clamp_mv2(&sorted_mvs[i], xd); |
| 274 } |
| 275 |
| 276 // Set the best mv to the first entry in the sorted list |
| 277 best_mv->as_int = sorted_mvs[0].as_int; |
| 278 |
| 279 // Provided that there are non zero vectors available there will not |
| 280 // be more than one 0,0 entry in the sorted list. |
| 281 // The best ref mv is always set to the first entry (which gave the best |
| 282 // results. The nearest is set to the first non zero vector if available and |
| 283 // near to the second non zero vector if available. |
| 284 // We do not use 0,0 as a nearest or near as 0,0 has its own mode. |
| 285 if ( sorted_mvs[0].as_int ) { |
| 286 nearest->as_int = sorted_mvs[0].as_int; |
| 287 if ( sorted_mvs[1].as_int ) |
| 288 near->as_int = sorted_mvs[1].as_int; |
| 289 else |
| 290 near->as_int = sorted_mvs[2].as_int; |
| 291 } else { |
| 292 nearest->as_int = sorted_mvs[1].as_int; |
| 293 near->as_int = sorted_mvs[2].as_int; |
| 294 } |
| 295 |
| 296 // Copy back the re-ordered mv list |
| 297 vpx_memcpy(mvlist, sorted_mvs, sizeof(sorted_mvs)); |
| 298 } |
OLD | NEW |