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