variance_c.c 12.7 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9
10
11
12
 */


#include "variance.h"
13
#include "filter.h"
John Koleszar's avatar
John Koleszar committed
14
15
16
17


unsigned int vp8_get_mb_ss_c
(
18
    const short *src_ptr
John Koleszar's avatar
John Koleszar committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
)
{
    unsigned int i = 0, sum = 0;

    do
    {
        sum += (src_ptr[i] * src_ptr[i]);
        i++;
    }
    while (i < 256);

    return sum;
}


34
static void variance(
35
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
36
    int  source_stride,
37
    const unsigned char *ref_ptr,
John Koleszar's avatar
John Koleszar committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    int  recon_stride,
    int  w,
    int  h,
    unsigned int *sse,
    int *sum)
{
    int i, j;
    int diff;

    *sum = 0;
    *sse = 0;

    for (i = 0; i < h; i++)
    {
        for (j = 0; j < w; j++)
        {
            diff = src_ptr[j] - ref_ptr[j];
            *sum += diff;
            *sse += diff * diff;
        }

        src_ptr += source_stride;
        ref_ptr += recon_stride;
    }
}


unsigned int vp8_variance16x16_c(
66
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
67
    int  source_stride,
68
    const unsigned char *ref_ptr,
John Koleszar's avatar
John Koleszar committed
69
70
71
72
73
74
75
    int  recon_stride,
    unsigned int *sse)
{
    unsigned int var;
    int avg;


76
    variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg);
John Koleszar's avatar
John Koleszar committed
77
    *sse = var;
78
    return (var - (((unsigned int)avg * avg) >> 8));
John Koleszar's avatar
John Koleszar committed
79
80
81
}

unsigned int vp8_variance8x16_c(
82
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
83
    int  source_stride,
84
    const unsigned char *ref_ptr,
John Koleszar's avatar
John Koleszar committed
85
86
87
88
89
90
91
    int  recon_stride,
    unsigned int *sse)
{
    unsigned int var;
    int avg;


92
    variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 16, &var, &avg);
John Koleszar's avatar
John Koleszar committed
93
    *sse = var;
94
    return (var - (((unsigned int)avg * avg) >> 7));
John Koleszar's avatar
John Koleszar committed
95
96
97
}

unsigned int vp8_variance16x8_c(
98
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
99
    int  source_stride,
100
    const unsigned char *ref_ptr,
John Koleszar's avatar
John Koleszar committed
101
102
103
104
105
106
107
    int  recon_stride,
    unsigned int *sse)
{
    unsigned int var;
    int avg;


108
    variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 8, &var, &avg);
John Koleszar's avatar
John Koleszar committed
109
    *sse = var;
110
    return (var - (((unsigned int)avg * avg) >> 7));
John Koleszar's avatar
John Koleszar committed
111
112
113
114
}


unsigned int vp8_variance8x8_c(
115
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
116
    int  source_stride,
117
    const unsigned char *ref_ptr,
John Koleszar's avatar
John Koleszar committed
118
119
120
121
122
123
124
    int  recon_stride,
    unsigned int *sse)
{
    unsigned int var;
    int avg;


125
    variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 8, &var, &avg);
John Koleszar's avatar
John Koleszar committed
126
    *sse = var;
127
    return (var - (((unsigned int)avg * avg) >> 6));
John Koleszar's avatar
John Koleszar committed
128
129
130
}

unsigned int vp8_variance4x4_c(
131
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
132
    int  source_stride,
133
    const unsigned char *ref_ptr,
John Koleszar's avatar
John Koleszar committed
134
135
136
137
138
139
140
    int  recon_stride,
    unsigned int *sse)
{
    unsigned int var;
    int avg;


141
    variance(src_ptr, source_stride, ref_ptr, recon_stride, 4, 4, &var, &avg);
John Koleszar's avatar
John Koleszar committed
142
    *sse = var;
143
    return (var - (((unsigned int)avg * avg) >> 4));
John Koleszar's avatar
John Koleszar committed
144
145
146
147
}


unsigned int vp8_mse16x16_c(
148
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
149
    int  source_stride,
150
    const unsigned char *ref_ptr,
John Koleszar's avatar
John Koleszar committed
151
152
153
154
155
156
    int  recon_stride,
    unsigned int *sse)
{
    unsigned int var;
    int avg;

157
    variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg);
John Koleszar's avatar
John Koleszar committed
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
    *sse = var;
    return var;
}


/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil_first_pass
 *
 *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
 *                  UINT32 src_pixels_per_line : Stride of input block.
 *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
 *                  UINT32 output_height     : Input block height.
 *                  UINT32 output_width      : Input block width.
 *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
 *
 *  OUTPUTS       : INT32 *output_ptr        : Pointer to filtered block.
 *
 *  RETURNS       : void
 *
 *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
 *                  either horizontal or vertical direction to produce the
 *                  filtered output block. Used to implement first-pass
 *                  of 2-D separable filter.
 *
 *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
 *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
 *                  pixel_step defines whether the filter is applied
 *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
 *                  It defines the offset required to move from one input
 *                  to the next.
 *
 ****************************************************************************/
191
static void var_filter_block2d_bil_first_pass
John Koleszar's avatar
John Koleszar committed
192
(
193
    const unsigned char *src_ptr,
John Koleszar's avatar
John Koleszar committed
194
195
196
197
198
    unsigned short *output_ptr,
    unsigned int src_pixels_per_line,
    int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
199
    const short *vp8_filter
John Koleszar's avatar
John Koleszar committed
200
201
202
203
204
205
206
207
)
{
    unsigned int i, j;

    for (i = 0; i < output_height; i++)
    {
        for (j = 0; j < output_width; j++)
        {
John Koleszar's avatar
John Koleszar committed
208
            /* Apply bilinear filter */
John Koleszar's avatar
John Koleszar committed
209
210
211
212
213
214
            output_ptr[j] = (((int)src_ptr[0]          * vp8_filter[0]) +
                             ((int)src_ptr[pixel_step] * vp8_filter[1]) +
                             (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
            src_ptr++;
        }

John Koleszar's avatar
John Koleszar committed
215
        /* Next row... */
John Koleszar's avatar
John Koleszar committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
        src_ptr    += src_pixels_per_line - output_width;
        output_ptr += output_width;
    }
}

/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil_second_pass
 *
 *  INPUTS        : INT32  *src_ptr          : Pointer to source block.
 *                  UINT32 src_pixels_per_line : Stride of input block.
 *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
 *                  UINT32 output_height     : Input block height.
 *                  UINT32 output_width      : Input block width.
 *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
 *
 *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
 *
 *  RETURNS       : void
 *
 *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
 *                  either horizontal or vertical direction to produce the
 *                  filtered output block. Used to implement second-pass
 *                  of 2-D separable filter.
 *
 *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
 *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
 *                  pixel_step defines whether the filter is applied
 *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
 *                  It defines the offset required to move from one input
 *                  to the next.
 *
 ****************************************************************************/
249
static void var_filter_block2d_bil_second_pass
John Koleszar's avatar
John Koleszar committed
250
(
251
    const unsigned short *src_ptr,
John Koleszar's avatar
John Koleszar committed
252
253
254
255
256
    unsigned char  *output_ptr,
    unsigned int  src_pixels_per_line,
    unsigned int  pixel_step,
    unsigned int  output_height,
    unsigned int  output_width,
257
    const short *vp8_filter
John Koleszar's avatar
John Koleszar committed
258
259
260
261
262
263
264
265
266
)
{
    unsigned int  i, j;
    int  Temp;

    for (i = 0; i < output_height; i++)
    {
        for (j = 0; j < output_width; j++)
        {
John Koleszar's avatar
John Koleszar committed
267
268
            /* Apply filter */
            Temp = ((int)src_ptr[0]          * vp8_filter[0]) +
John Koleszar's avatar
John Koleszar committed
269
270
271
272
273
274
                   ((int)src_ptr[pixel_step] * vp8_filter[1]) +
                   (VP8_FILTER_WEIGHT / 2);
            output_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
            src_ptr++;
        }

John Koleszar's avatar
John Koleszar committed
275
        /* Next row... */
John Koleszar's avatar
John Koleszar committed
276
277
278
279
280
281
282
283
        src_ptr    += src_pixels_per_line - output_width;
        output_ptr += output_width;
    }
}


unsigned int vp8_sub_pixel_variance4x4_c
(
284
    const unsigned char  *src_ptr,
John Koleszar's avatar
John Koleszar committed
285
286
287
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
288
    const unsigned char *dst_ptr,
John Koleszar's avatar
John Koleszar committed
289
290
291
292
293
    int dst_pixels_per_line,
    unsigned int *sse
)
{
    unsigned char  temp2[20*16];
294
    const short *HFilter, *VFilter;
John Koleszar's avatar
John Koleszar committed
295
    unsigned short FData3[5*4]; /* Temp data bufffer used in filtering */
John Koleszar's avatar
John Koleszar committed
296

297
298
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
299

John Koleszar's avatar
John Koleszar committed
300
    /* First filter 1d Horizontal */
301
    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 5, 4, HFilter);
John Koleszar's avatar
John Koleszar committed
302

John Koleszar's avatar
John Koleszar committed
303
    /* Now filter Verticaly */
304
    var_filter_block2d_bil_second_pass(FData3, temp2, 4,  4,  4,  4, VFilter);
John Koleszar's avatar
John Koleszar committed
305
306
307
308
309
310
311

    return vp8_variance4x4_c(temp2, 4, dst_ptr, dst_pixels_per_line, sse);
}


unsigned int vp8_sub_pixel_variance8x8_c
(
312
    const unsigned char  *src_ptr,
John Koleszar's avatar
John Koleszar committed
313
314
315
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
316
    const unsigned char *dst_ptr,
John Koleszar's avatar
John Koleszar committed
317
318
319
320
    int dst_pixels_per_line,
    unsigned int *sse
)
{
John Koleszar's avatar
John Koleszar committed
321
    unsigned short FData3[9*8]; /* Temp data bufffer used in filtering */
John Koleszar's avatar
John Koleszar committed
322
    unsigned char  temp2[20*16];
323
    const short *HFilter, *VFilter;
John Koleszar's avatar
John Koleszar committed
324

325
326
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
327

328
329
    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 8, HFilter);
    var_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 8, 8, VFilter);
John Koleszar's avatar
John Koleszar committed
330
331
332
333
334
335

    return vp8_variance8x8_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse);
}

unsigned int vp8_sub_pixel_variance16x16_c
(
336
    const unsigned char  *src_ptr,
John Koleszar's avatar
John Koleszar committed
337
338
339
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
340
    const unsigned char *dst_ptr,
John Koleszar's avatar
John Koleszar committed
341
342
343
344
    int dst_pixels_per_line,
    unsigned int *sse
)
{
John Koleszar's avatar
John Koleszar committed
345
    unsigned short FData3[17*16];   /* Temp data bufffer used in filtering */
John Koleszar's avatar
John Koleszar committed
346
    unsigned char  temp2[20*16];
347
    const short *HFilter, *VFilter;
John Koleszar's avatar
John Koleszar committed
348

349
350
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
351

352
353
    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 16, HFilter);
    var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 16, 16, VFilter);
John Koleszar's avatar
John Koleszar committed
354
355
356
357

    return vp8_variance16x16_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse);
}

358

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
unsigned int vp8_variance_halfpixvar16x16_h_c(
    const unsigned char *src_ptr,
    int  source_stride,
    const unsigned char *ref_ptr,
    int  recon_stride,
    unsigned int *sse)
{
    return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 0,
                                         ref_ptr, recon_stride, sse);
}


unsigned int vp8_variance_halfpixvar16x16_v_c(
    const unsigned char *src_ptr,
    int  source_stride,
    const unsigned char *ref_ptr,
    int  recon_stride,
    unsigned int *sse)
{
    return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 0, 4,
                                         ref_ptr, recon_stride, sse);
}


unsigned int vp8_variance_halfpixvar16x16_hv_c(
384
385
386
387
388
389
390
391
392
393
394
    const unsigned char *src_ptr,
    int  source_stride,
    const unsigned char *ref_ptr,
    int  recon_stride,
    unsigned int *sse)
{
    return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 4,
                                         ref_ptr, recon_stride, sse);
}


John Koleszar's avatar
John Koleszar committed
395
396
unsigned int vp8_sub_pixel_mse16x16_c
(
397
    const unsigned char  *src_ptr,
John Koleszar's avatar
John Koleszar committed
398
399
400
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
401
    const unsigned char *dst_ptr,
John Koleszar's avatar
John Koleszar committed
402
403
404
405
406
407
408
409
410
411
    int dst_pixels_per_line,
    unsigned int *sse
)
{
    vp8_sub_pixel_variance16x16_c(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
    return *sse;
}

unsigned int vp8_sub_pixel_variance16x8_c
(
412
    const unsigned char  *src_ptr,
John Koleszar's avatar
John Koleszar committed
413
414
415
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
416
    const unsigned char *dst_ptr,
John Koleszar's avatar
John Koleszar committed
417
418
419
420
    int dst_pixels_per_line,
    unsigned int *sse
)
{
John Koleszar's avatar
John Koleszar committed
421
    unsigned short FData3[16*9];    /* Temp data bufffer used in filtering */
John Koleszar's avatar
John Koleszar committed
422
    unsigned char  temp2[20*16];
423
    const short *HFilter, *VFilter;
John Koleszar's avatar
John Koleszar committed
424

425
426
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
427

428
429
    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 16, HFilter);
    var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 8, 16, VFilter);
John Koleszar's avatar
John Koleszar committed
430
431
432
433
434
435

    return vp8_variance16x8_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse);
}

unsigned int vp8_sub_pixel_variance8x16_c
(
436
    const unsigned char  *src_ptr,
John Koleszar's avatar
John Koleszar committed
437
438
439
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
440
    const unsigned char *dst_ptr,
John Koleszar's avatar
John Koleszar committed
441
442
443
444
    int dst_pixels_per_line,
    unsigned int *sse
)
{
John Koleszar's avatar
John Koleszar committed
445
    unsigned short FData3[9*16];    /* Temp data bufffer used in filtering */
John Koleszar's avatar
John Koleszar committed
446
    unsigned char  temp2[20*16];
447
    const short *HFilter, *VFilter;
John Koleszar's avatar
John Koleszar committed
448
449


450
451
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
452
453


454
455
    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 8, HFilter);
    var_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 16, 8, VFilter);
John Koleszar's avatar
John Koleszar committed
456
457
458

    return vp8_variance8x16_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse);
}