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 "variance.h" 13 #include "vp8/common/filter.h" 14 15 16 unsigned int vp8_get_mb_ss_c 17 ( 18 const short *src_ptr 19 ) 20 { 21 unsigned int i = 0, sum = 0; 22 23 do 24 { 25 sum += (src_ptr[i] * src_ptr[i]); 26 i++; 27 } 28 while (i < 256); 29 30 return sum; 31 } 32 33 34 static void variance( 35 const unsigned char *src_ptr, 36 int source_stride, 37 const unsigned char *ref_ptr, 38 int recon_stride, 39 int w, 40 int h, 41 unsigned int *sse, 42 int *sum) 43 { 44 int i, j; 45 int diff; 46 47 *sum = 0; 48 *sse = 0; 49 50 for (i = 0; i < h; i++) 51 { 52 for (j = 0; j < w; j++) 53 { 54 diff = src_ptr[j] - ref_ptr[j]; 55 *sum += diff; 56 *sse += diff * diff; 57 } 58 59 src_ptr += source_stride; 60 ref_ptr += recon_stride; 61 } 62 } 63 64 unsigned int 65 vp8_get8x8var_c 66 ( 67 const unsigned char *src_ptr, 68 int source_stride, 69 const unsigned char *ref_ptr, 70 int recon_stride, 71 unsigned int *SSE, 72 int *Sum 73 ) 74 { 75 76 variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 8, SSE, Sum); 77 return (*SSE - (((*Sum) * (*Sum)) >> 6)); 78 } 79 80 unsigned int 81 vp8_get16x16var_c 82 ( 83 const unsigned char *src_ptr, 84 int source_stride, 85 const unsigned char *ref_ptr, 86 int recon_stride, 87 unsigned int *SSE, 88 int *Sum 89 ) 90 { 91 92 variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, SSE, Sum); 93 return (*SSE - (((*Sum) * (*Sum)) >> 8)); 94 95 } 96 97 98 99 unsigned int vp8_variance16x16_c( 100 const unsigned char *src_ptr, 101 int source_stride, 102 const unsigned char *ref_ptr, 103 int recon_stride, 104 unsigned int *sse) 105 { 106 unsigned int var; 107 int avg; 108 109 110 variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg); 111 *sse = var; 112 return (var - ((avg * avg) >> 8)); 113 } 114 115 unsigned int vp8_variance8x16_c( 116 const unsigned char *src_ptr, 117 int source_stride, 118 const unsigned char *ref_ptr, 119 int recon_stride, 120 unsigned int *sse) 121 { 122 unsigned int var; 123 int avg; 124 125 126 variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 16, &var, &avg); 127 *sse = var; 128 return (var - ((avg * avg) >> 7)); 129 } 130 131 unsigned int vp8_variance16x8_c( 132 const unsigned char *src_ptr, 133 int source_stride, 134 const unsigned char *ref_ptr, 135 int recon_stride, 136 unsigned int *sse) 137 { 138 unsigned int var; 139 int avg; 140 141 142 variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 8, &var, &avg); 143 *sse = var; 144 return (var - ((avg * avg) >> 7)); 145 } 146 147 148 unsigned int vp8_variance8x8_c( 149 const unsigned char *src_ptr, 150 int source_stride, 151 const unsigned char *ref_ptr, 152 int recon_stride, 153 unsigned int *sse) 154 { 155 unsigned int var; 156 int avg; 157 158 159 variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 8, &var, &avg); 160 *sse = var; 161 return (var - ((avg * avg) >> 6)); 162 } 163 164 unsigned int vp8_variance4x4_c( 165 const unsigned char *src_ptr, 166 int source_stride, 167 const unsigned char *ref_ptr, 168 int recon_stride, 169 unsigned int *sse) 170 { 171 unsigned int var; 172 int avg; 173 174 175 variance(src_ptr, source_stride, ref_ptr, recon_stride, 4, 4, &var, &avg); 176 *sse = var; 177 return (var - ((avg * avg) >> 4)); 178 } 179 180 181 unsigned int vp8_mse16x16_c( 182 const unsigned char *src_ptr, 183 int source_stride, 184 const unsigned char *ref_ptr, 185 int recon_stride, 186 unsigned int *sse) 187 { 188 unsigned int var; 189 int avg; 190 191 variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg); 192 *sse = var; 193 return var; 194 } 195 196 197 /**************************************************************************** 198 * 199 * ROUTINE : filter_block2d_bil_first_pass 200 * 201 * INPUTS : UINT8 *src_ptr : Pointer to source block. 202 * UINT32 src_pixels_per_line : Stride of input block. 203 * UINT32 pixel_step : Offset between filter input samples (see notes). 204 * UINT32 output_height : Input block height. 205 * UINT32 output_width : Input block width. 206 * INT32 *vp8_filter : Array of 2 bi-linear filter taps. 207 * 208 * OUTPUTS : INT32 *output_ptr : Pointer to filtered block. 209 * 210 * RETURNS : void 211 * 212 * FUNCTION : Applies a 1-D 2-tap bi-linear filter to the source block in 213 * either horizontal or vertical direction to produce the 214 * filtered output block. Used to implement first-pass 215 * of 2-D separable filter. 216 * 217 * SPECIAL NOTES : Produces INT32 output to retain precision for next pass. 218 * Two filter taps should sum to VP8_FILTER_WEIGHT. 219 * pixel_step defines whether the filter is applied 220 * horizontally (pixel_step=1) or vertically (pixel_step=stride). 221 * It defines the offset required to move from one input 222 * to the next. 223 * 224 ****************************************************************************/ 225 static void var_filter_block2d_bil_first_pass 226 ( 227 const unsigned char *src_ptr, 228 unsigned short *output_ptr, 229 unsigned int src_pixels_per_line, 230 int pixel_step, 231 unsigned int output_height, 232 unsigned int output_width, 233 const short *vp8_filter 234 ) 235 { 236 unsigned int i, j; 237 238 for (i = 0; i < output_height; i++) 239 { 240 for (j = 0; j < output_width; j++) 241 { 242 // Apply bilinear filter 243 output_ptr[j] = (((int)src_ptr[0] * vp8_filter[0]) + 244 ((int)src_ptr[pixel_step] * vp8_filter[1]) + 245 (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT; 246 src_ptr++; 247 } 248 249 // Next row... 250 src_ptr += src_pixels_per_line - output_width; 251 output_ptr += output_width; 252 } 253 } 254 255 /**************************************************************************** 256 * 257 * ROUTINE : filter_block2d_bil_second_pass 258 * 259 * INPUTS : INT32 *src_ptr : Pointer to source block. 260 * UINT32 src_pixels_per_line : Stride of input block. 261 * UINT32 pixel_step : Offset between filter input samples (see notes). 262 * UINT32 output_height : Input block height. 263 * UINT32 output_width : Input block width. 264 * INT32 *vp8_filter : Array of 2 bi-linear filter taps. 265 * 266 * OUTPUTS : UINT16 *output_ptr : Pointer to filtered block. 267 * 268 * RETURNS : void 269 * 270 * FUNCTION : Applies a 1-D 2-tap bi-linear filter to the source block in 271 * either horizontal or vertical direction to produce the 272 * filtered output block. Used to implement second-pass 273 * of 2-D separable filter. 274 * 275 * SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass. 276 * Two filter taps should sum to VP8_FILTER_WEIGHT. 277 * pixel_step defines whether the filter is applied 278 * horizontally (pixel_step=1) or vertically (pixel_step=stride). 279 * It defines the offset required to move from one input 280 * to the next. 281 * 282 ****************************************************************************/ 283 static void var_filter_block2d_bil_second_pass 284 ( 285 const unsigned short *src_ptr, 286 unsigned char *output_ptr, 287 unsigned int src_pixels_per_line, 288 unsigned int pixel_step, 289 unsigned int output_height, 290 unsigned int output_width, 291 const short *vp8_filter 292 ) 293 { 294 unsigned int i, j; 295 int Temp; 296 297 for (i = 0; i < output_height; i++) 298 { 299 for (j = 0; j < output_width; j++) 300 { 301 // Apply filter 302 Temp = ((int)src_ptr[0] * vp8_filter[0]) + 303 ((int)src_ptr[pixel_step] * vp8_filter[1]) + 304 (VP8_FILTER_WEIGHT / 2); 305 output_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT); 306 src_ptr++; 307 } 308 309 // Next row... 310 src_ptr += src_pixels_per_line - output_width; 311 output_ptr += output_width; 312 } 313 } 314 315 316 unsigned int vp8_sub_pixel_variance4x4_c 317 ( 318 const unsigned char *src_ptr, 319 int src_pixels_per_line, 320 int xoffset, 321 int yoffset, 322 const unsigned char *dst_ptr, 323 int dst_pixels_per_line, 324 unsigned int *sse 325 ) 326 { 327 unsigned char temp2[20*16]; 328 const short *HFilter, *VFilter; 329 unsigned short FData3[5*4]; // Temp data bufffer used in filtering 330 331 HFilter = vp8_bilinear_filters[xoffset]; 332 VFilter = vp8_bilinear_filters[yoffset]; 333 334 // First filter 1d Horizontal 335 var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 5, 4, HFilter); 336 337 // Now filter Verticaly 338 var_filter_block2d_bil_second_pass(FData3, temp2, 4, 4, 4, 4, VFilter); 339 340 return vp8_variance4x4_c(temp2, 4, dst_ptr, dst_pixels_per_line, sse); 341 } 342 343 344 unsigned int vp8_sub_pixel_variance8x8_c 345 ( 346 const unsigned char *src_ptr, 347 int src_pixels_per_line, 348 int xoffset, 349 int yoffset, 350 const unsigned char *dst_ptr, 351 int dst_pixels_per_line, 352 unsigned int *sse 353 ) 354 { 355 unsigned short FData3[9*8]; // Temp data bufffer used in filtering 356 unsigned char temp2[20*16]; 357 const short *HFilter, *VFilter; 358 359 HFilter = vp8_bilinear_filters[xoffset]; 360 VFilter = vp8_bilinear_filters[yoffset]; 361 362 var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 8, HFilter); 363 var_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 8, 8, VFilter); 364 365 return vp8_variance8x8_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse); 366 } 367 368 unsigned int vp8_sub_pixel_variance16x16_c 369 ( 370 const unsigned char *src_ptr, 371 int src_pixels_per_line, 372 int xoffset, 373 int yoffset, 374 const unsigned char *dst_ptr, 375 int dst_pixels_per_line, 376 unsigned int *sse 377 ) 378 { 379 unsigned short FData3[17*16]; // Temp data bufffer used in filtering 380 unsigned char temp2[20*16]; 381 const short *HFilter, *VFilter; 382 383 HFilter = vp8_bilinear_filters[xoffset]; 384 VFilter = vp8_bilinear_filters[yoffset]; 385 386 var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 16, HFilter); 387 var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 16, 16, VFilter); 388 389 return vp8_variance16x16_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse); 390 } 391 392 393 unsigned int vp8_variance_halfpixvar16x16_h_c( 394 const unsigned char *src_ptr, 395 int source_stride, 396 const unsigned char *ref_ptr, 397 int recon_stride, 398 unsigned int *sse) 399 { 400 return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 0, 401 ref_ptr, recon_stride, sse); 402 } 403 404 405 unsigned int vp8_variance_halfpixvar16x16_v_c( 406 const unsigned char *src_ptr, 407 int source_stride, 408 const unsigned char *ref_ptr, 409 int recon_stride, 410 unsigned int *sse) 411 { 412 return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 0, 4, 413 ref_ptr, recon_stride, sse); 414 } 415 416 417 unsigned int vp8_variance_halfpixvar16x16_hv_c( 418 const unsigned char *src_ptr, 419 int source_stride, 420 const unsigned char *ref_ptr, 421 int recon_stride, 422 unsigned int *sse) 423 { 424 return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 4, 425 ref_ptr, recon_stride, sse); 426 } 427 428 429 unsigned int vp8_sub_pixel_mse16x16_c 430 ( 431 const unsigned char *src_ptr, 432 int src_pixels_per_line, 433 int xoffset, 434 int yoffset, 435 const unsigned char *dst_ptr, 436 int dst_pixels_per_line, 437 unsigned int *sse 438 ) 439 { 440 vp8_sub_pixel_variance16x16_c(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse); 441 return *sse; 442 } 443 444 unsigned int vp8_sub_pixel_variance16x8_c 445 ( 446 const unsigned char *src_ptr, 447 int src_pixels_per_line, 448 int xoffset, 449 int yoffset, 450 const unsigned char *dst_ptr, 451 int dst_pixels_per_line, 452 unsigned int *sse 453 ) 454 { 455 unsigned short FData3[16*9]; // Temp data bufffer used in filtering 456 unsigned char temp2[20*16]; 457 const short *HFilter, *VFilter; 458 459 HFilter = vp8_bilinear_filters[xoffset]; 460 VFilter = vp8_bilinear_filters[yoffset]; 461 462 var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 16, HFilter); 463 var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 8, 16, VFilter); 464 465 return vp8_variance16x8_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse); 466 } 467 468 unsigned int vp8_sub_pixel_variance8x16_c 469 ( 470 const unsigned char *src_ptr, 471 int src_pixels_per_line, 472 int xoffset, 473 int yoffset, 474 const unsigned char *dst_ptr, 475 int dst_pixels_per_line, 476 unsigned int *sse 477 ) 478 { 479 unsigned short FData3[9*16]; // Temp data bufffer used in filtering 480 unsigned char temp2[20*16]; 481 const short *HFilter, *VFilter; 482 483 484 HFilter = vp8_bilinear_filters[xoffset]; 485 VFilter = vp8_bilinear_filters[yoffset]; 486 487 488 var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 8, HFilter); 489 var_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 16, 8, VFilter); 490 491 return vp8_variance8x16_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse); 492 } 493