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
vp8_get_mb_ss_c(const short * src_ptr)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
variance(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,int w,int h,unsigned int * sse,int * sum)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
vp8_get8x8var_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * SSE,int * Sum)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
vp8_get16x16var_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * SSE,int * Sum)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
vp8_variance16x16_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_variance8x16_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_variance16x8_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_variance8x8_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_variance4x4_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_mse16x16_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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 ****************************************************************************/
var_filter_block2d_bil_first_pass(const unsigned char * src_ptr,unsigned short * output_ptr,unsigned int src_pixels_per_line,int pixel_step,unsigned int output_height,unsigned int output_width,const short * vp8_filter)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 ****************************************************************************/
var_filter_block2d_bil_second_pass(const unsigned short * src_ptr,unsigned char * output_ptr,unsigned int src_pixels_per_line,unsigned int pixel_step,unsigned int output_height,unsigned int output_width,const short * vp8_filter)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
vp8_sub_pixel_variance4x4_c(const unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,const unsigned char * dst_ptr,int dst_pixels_per_line,unsigned int * sse)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
vp8_sub_pixel_variance8x8_c(const unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,const unsigned char * dst_ptr,int dst_pixels_per_line,unsigned int * sse)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
vp8_sub_pixel_variance16x16_c(const unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,const unsigned char * dst_ptr,int dst_pixels_per_line,unsigned int * sse)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
vp8_variance_halfpixvar16x16_h_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_variance_halfpixvar16x16_v_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_variance_halfpixvar16x16_hv_c(const unsigned char * src_ptr,int source_stride,const unsigned char * ref_ptr,int recon_stride,unsigned int * sse)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
vp8_sub_pixel_mse16x16_c(const unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,const unsigned char * dst_ptr,int dst_pixels_per_line,unsigned int * sse)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
vp8_sub_pixel_variance16x8_c(const unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,const unsigned char * dst_ptr,int dst_pixels_per_line,unsigned int * sse)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
vp8_sub_pixel_variance8x16_c(const unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,const unsigned char * dst_ptr,int dst_pixels_per_line,unsigned int * sse)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