mcomp.c 61.4 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
13
14
15
16
17
18
19
20
21
22
23
 */


#include "mcomp.h"
#include "vpx_mem/vpx_mem.h"

#include <stdio.h>
#include <limits.h>
#include <math.h>

#ifdef ENTROPY_STATS
static int mv_ref_ct [31] [4] [2];
static int mv_mode_cts [4] [2];
#endif

Scott LaVarnway's avatar
Scott LaVarnway committed
24
int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight)
John Koleszar's avatar
John Koleszar committed
25
26
27
28
29
{
    // MV costing is based on the distribution of vectors in the previous frame and as such will tend to
    // over state the cost of vectors. In addition coding a new vector can have a knock on effect on the
    // cost of subsequent vectors and the quality of prediction from NEAR and NEAREST for subsequent blocks.
    // The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors.
Scott LaVarnway's avatar
Scott LaVarnway committed
30
    return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1]) * Weight) >> 7;
John Koleszar's avatar
John Koleszar committed
31
32
}

Scott LaVarnway's avatar
Scott LaVarnway committed
33
static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit)
John Koleszar's avatar
John Koleszar committed
34
{
Scott LaVarnway's avatar
Scott LaVarnway committed
35
36
37
    return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] +
        mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1])
        * error_per_bit + 128) >> 8;
John Koleszar's avatar
John Koleszar committed
38
39
}

Scott LaVarnway's avatar
Scott LaVarnway committed
40
static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_per_bit)
41
42
{
    /* Calculate sad error cost on full pixel basis. */
Scott LaVarnway's avatar
Scott LaVarnway committed
43
44
45
    return ((mvsadcost[0][(mv->as_mv.row - ref->as_mv.row)] +
        mvsadcost[1][(mv->as_mv.col - ref->as_mv.col)])
        * error_per_bit + 128) >> 8;
John Koleszar's avatar
John Koleszar committed
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
}

void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride)
{
    int Len;
    int search_site_count = 0;


    // Generate offsets for 4 search sites per step.
    Len = MAX_FIRST_STEP;
    x->ss[search_site_count].mv.col = 0;
    x->ss[search_site_count].mv.row = 0;
    x->ss[search_site_count].offset = 0;
    search_site_count++;

    while (Len > 0)
    {

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = 0;
        x->ss[search_site_count].mv.row = -Len;
        x->ss[search_site_count].offset = -Len * stride;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = 0;
        x->ss[search_site_count].mv.row = Len;
        x->ss[search_site_count].offset = Len * stride;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = -Len;
        x->ss[search_site_count].mv.row = 0;
        x->ss[search_site_count].offset = -Len;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = Len;
        x->ss[search_site_count].mv.row = 0;
        x->ss[search_site_count].offset = Len;
        search_site_count++;

        // Contract.
        Len /= 2;
    }

    x->ss_count = search_site_count;
    x->searches_per_step = 4;
}

void vp8_init3smotion_compensation(MACROBLOCK *x, int stride)
{
    int Len;
    int search_site_count = 0;

    // Generate offsets for 8 search sites per step.
    Len = MAX_FIRST_STEP;
    x->ss[search_site_count].mv.col = 0;
    x->ss[search_site_count].mv.row = 0;
    x->ss[search_site_count].offset = 0;
    search_site_count++;

    while (Len > 0)
    {

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = 0;
        x->ss[search_site_count].mv.row = -Len;
        x->ss[search_site_count].offset = -Len * stride;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = 0;
        x->ss[search_site_count].mv.row = Len;
        x->ss[search_site_count].offset = Len * stride;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = -Len;
        x->ss[search_site_count].mv.row = 0;
        x->ss[search_site_count].offset = -Len;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = Len;
        x->ss[search_site_count].mv.row = 0;
        x->ss[search_site_count].offset = Len;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = -Len;
        x->ss[search_site_count].mv.row = -Len;
        x->ss[search_site_count].offset = -Len * stride - Len;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = Len;
        x->ss[search_site_count].mv.row = -Len;
        x->ss[search_site_count].offset = -Len * stride + Len;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = -Len;
        x->ss[search_site_count].mv.row = Len;
        x->ss[search_site_count].offset = Len * stride - Len;
        search_site_count++;

        // Compute offsets for search sites.
        x->ss[search_site_count].mv.col = Len;
        x->ss[search_site_count].mv.row = Len;
        x->ss[search_site_count].offset = Len * stride + Len;
        search_site_count++;


        // Contract.
        Len /= 2;
    }

    x->ss_count = search_site_count;
    x->searches_per_step = 8;
}


#define MVC(r,c) (((mvcost[0][(r)-rr] + mvcost[1][(c) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
#define PRE(r,c) (*(d->base_pre) + d->pre + ((r)>>2) * d->pre_stride + ((c)>>2)) // pointer to predictor base of a motionvector
#define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc
172
#define DIST(r,c) vfp->svf( PRE(r,c), d->pre_stride, SP(c),SP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
John Koleszar's avatar
John Koleszar committed
173
174
#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;
#define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost
175
#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{thismse = DIST(r,c); if((v = (MVC(r,c)+thismse)) < besterr) { besterr = v; br=r; bc=c; *distortion = thismse; *sse1 = sse; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best
John Koleszar's avatar
John Koleszar committed
176
177
178
179
180
#define MIN(x,y) (((x)<(y))?(x):(y))
#define MAX(x,y) (((x)>(y))?(x):(y))

//#define CHECK_BETTER(v,r,c) if((v = ERR(r,c)) < besterr) { besterr = v; br=r; bc=c; }

Scott LaVarnway's avatar
Scott LaVarnway committed
181
182
183
184
185
186
int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
                                             int_mv *bestmv, int_mv *ref_mv,
                                             int error_per_bit,
                                             const vp8_variance_fn_ptr_t *vfp,
                                             int *mvcost[2], int *distortion,
                                             unsigned int *sse1)
John Koleszar's avatar
John Koleszar committed
187
{
Scott LaVarnway's avatar
Scott LaVarnway committed
188
    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
John Koleszar's avatar
John Koleszar committed
189
190
    unsigned char *z = (*(b->base_src) + b->src);

Scott LaVarnway's avatar
Scott LaVarnway committed
191
192
    int rr = ref_mv->as_mv.row >> 1, rc = ref_mv->as_mv.col >> 1;
    int br = bestmv->as_mv.row << 2, bc = bestmv->as_mv.col << 2;
John Koleszar's avatar
John Koleszar committed
193
194
195
196
197
198
199
    int tr = br, tc = bc;
    unsigned int besterr = INT_MAX;
    unsigned int left, right, up, down, diag;
    unsigned int sse;
    unsigned int whichdir;
    unsigned int halfiters = 4;
    unsigned int quarteriters = 4;
200
    int thismse;
John Koleszar's avatar
John Koleszar committed
201

Scott LaVarnway's avatar
Scott LaVarnway committed
202
203
204
205
    int minc = MAX(x->mv_col_min << 2, (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1));
    int maxc = MIN(x->mv_col_max << 2, (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1));
    int minr = MAX(x->mv_row_min << 2, (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1));
    int maxr = MIN(x->mv_row_max << 2, (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1));
John Koleszar's avatar
John Koleszar committed
206
207

    // central mv
Scott LaVarnway's avatar
Scott LaVarnway committed
208
209
    bestmv->as_mv.row <<= 3;
    bestmv->as_mv.col <<= 3;
John Koleszar's avatar
John Koleszar committed
210
211

    // calculate central point error
212
    besterr = vfp->vf(y, d->pre_stride, z, b->src_stride, sse1);
213
    *distortion = besterr;
214
    besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
215
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
    while (--halfiters)
    {
        // 1/2 pel
        CHECK_BETTER(left, tr, tc - 2);
        CHECK_BETTER(right, tr, tc + 2);
        CHECK_BETTER(up, tr - 2, tc);
        CHECK_BETTER(down, tr + 2, tc);

        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);

        switch (whichdir)
        {
        case 0:
            CHECK_BETTER(diag, tr - 2, tc - 2);
            break;
        case 1:
            CHECK_BETTER(diag, tr - 2, tc + 2);
            break;
        case 2:
            CHECK_BETTER(diag, tr + 2, tc - 2);
            break;
        case 3:
            CHECK_BETTER(diag, tr + 2, tc + 2);
            break;
        }

        // no reason to check the same one again.
        if (tr == br && tc == bc)
            break;

        tr = br;
        tc = bc;
    }

    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
    // 1/4 pel
    while (--quarteriters)
    {
        CHECK_BETTER(left, tr, tc - 1);
        CHECK_BETTER(right, tr, tc + 1);
        CHECK_BETTER(up, tr - 1, tc);
        CHECK_BETTER(down, tr + 1, tc);

        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);

        switch (whichdir)
        {
        case 0:
            CHECK_BETTER(diag, tr - 1, tc - 1);
            break;
        case 1:
            CHECK_BETTER(diag, tr - 1, tc + 1);
            break;
        case 2:
            CHECK_BETTER(diag, tr + 1, tc - 1);
            break;
        case 3:
            CHECK_BETTER(diag, tr + 1, tc + 1);
            break;
        }

        // no reason to check the same one again.
        if (tr == br && tc == bc)
            break;

        tr = br;
        tc = bc;
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
286
287
    bestmv->as_mv.row = br << 1;
    bestmv->as_mv.col = bc << 1;
John Koleszar's avatar
John Koleszar committed
288

Scott LaVarnway's avatar
Scott LaVarnway committed
289
290
    if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > MAX_FULL_PEL_VAL) ||
        (abs(bestmv->as_mv.row - ref_mv->as_mv.row) > MAX_FULL_PEL_VAL))
John Koleszar's avatar
John Koleszar committed
291
292
293
294
295
296
297
298
299
300
301
302
        return INT_MAX;

    return besterr;
}
#undef MVC
#undef PRE
#undef SP
#undef DIST
#undef ERR
#undef CHECK_BETTER
#undef MIN
#undef MAX
Scott LaVarnway's avatar
Scott LaVarnway committed
303
304
305
306
307
308
int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
                                 int_mv *bestmv, int_mv *ref_mv,
                                 int error_per_bit,
                                 const vp8_variance_fn_ptr_t *vfp,
                                 int *mvcost[2], int *distortion,
                                 unsigned int *sse1)
John Koleszar's avatar
John Koleszar committed
309
310
{
    int bestmse = INT_MAX;
Scott LaVarnway's avatar
Scott LaVarnway committed
311
312
313
    int_mv startmv;
    int_mv this_mv;
    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
John Koleszar's avatar
John Koleszar committed
314
315
316
317
    unsigned char *z = (*(b->base_src) + b->src);
    int left, right, up, down, diag;
    unsigned int sse;
    int whichdir ;
318
    int thismse;
John Koleszar's avatar
John Koleszar committed
319
320
321


    // Trap uncodable vectors
Scott LaVarnway's avatar
Scott LaVarnway committed
322
323
    if ((abs((bestmv->as_mv.col << 3) - ref_mv->as_mv.col) > MAX_FULL_PEL_VAL)
        || (abs((bestmv->as_mv.row << 3) - ref_mv->as_mv.row) > MAX_FULL_PEL_VAL))
John Koleszar's avatar
John Koleszar committed
324
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
325
326
        bestmv->as_mv.row <<= 3;
        bestmv->as_mv.col <<= 3;
327
        *distortion = INT_MAX;
John Koleszar's avatar
John Koleszar committed
328
329
330
331
        return INT_MAX;
    }

    // central mv
Scott LaVarnway's avatar
Scott LaVarnway committed
332
333
    bestmv->as_mv.row <<= 3;
    bestmv->as_mv.col <<= 3;
John Koleszar's avatar
John Koleszar committed
334
335
336
    startmv = *bestmv;

    // calculate central point error
337
    bestmse = vfp->vf(y, d->pre_stride, z, b->src_stride, sse1);
338
    *distortion = bestmse;
339
    bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
340
341

    // go left then right and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
342
343
    this_mv.as_mv.row = startmv.as_mv.row;
    this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
344
345
    thismse = vfp->svf_halfpix_h(y - 1, d->pre_stride, z, b->src_stride, &sse);
    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
346
347
348
349
350

    if (left < bestmse)
    {
        *bestmv = this_mv;
        bestmse = left;
351
        *distortion = thismse;
352
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
353
354
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
355
    this_mv.as_mv.col += 8;
356
357
    thismse = vfp->svf_halfpix_h(y, d->pre_stride, z, b->src_stride, &sse);
    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
358
359
360
361
362

    if (right < bestmse)
    {
        *bestmv = this_mv;
        bestmse = right;
363
        *distortion = thismse;
364
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
365
366
367
    }

    // go up then down and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
368
369
    this_mv.as_mv.col = startmv.as_mv.col;
    this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
370
371
    thismse =  vfp->svf_halfpix_v(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
372
373
374
375
376

    if (up < bestmse)
    {
        *bestmv = this_mv;
        bestmse = up;
377
        *distortion = thismse;
378
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
379
380
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
381
    this_mv.as_mv.row += 8;
382
383
    thismse = vfp->svf_halfpix_v(y, d->pre_stride, z, b->src_stride, &sse);
    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
384
385
386
387
388

    if (down < bestmse)
    {
        *bestmv = this_mv;
        bestmse = down;
389
        *distortion = thismse;
390
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
391
392
393
394
395
396
397
398
399
400
401
402
    }


    // now check 1 more diagonal
    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
    //for(whichdir =0;whichdir<4;whichdir++)
    //{
    this_mv = startmv;

    switch (whichdir)
    {
    case 0:
Scott LaVarnway's avatar
Scott LaVarnway committed
403
404
        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
405
        thismse = vfp->svf_halfpix_hv(y - 1 - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
406
407
        break;
    case 1:
Scott LaVarnway's avatar
Scott LaVarnway committed
408
409
        this_mv.as_mv.col += 4;
        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
410
        thismse = vfp->svf_halfpix_hv(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
411
412
        break;
    case 2:
Scott LaVarnway's avatar
Scott LaVarnway committed
413
414
        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
        this_mv.as_mv.row += 4;
415
        thismse = vfp->svf_halfpix_hv(y - 1, d->pre_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
416
417
        break;
    case 3:
418
    default:
Scott LaVarnway's avatar
Scott LaVarnway committed
419
420
        this_mv.as_mv.col += 4;
        this_mv.as_mv.row += 4;
421
        thismse = vfp->svf_halfpix_hv(y, d->pre_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
422
423
424
        break;
    }

425
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
426
427
428
429
430

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
431
        *distortion = thismse;
432
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
433
434
435
436
437
438
    }

//  }


    // time to check quarter pels.
Scott LaVarnway's avatar
Scott LaVarnway committed
439
    if (bestmv->as_mv.row < startmv.as_mv.row)
John Koleszar's avatar
John Koleszar committed
440
441
        y -= d->pre_stride;

Scott LaVarnway's avatar
Scott LaVarnway committed
442
    if (bestmv->as_mv.col < startmv.as_mv.col)
John Koleszar's avatar
John Koleszar committed
443
444
445
446
447
448
449
        y--;

    startmv = *bestmv;



    // go left then right and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
450
    this_mv.as_mv.row = startmv.as_mv.row;
John Koleszar's avatar
John Koleszar committed
451

Scott LaVarnway's avatar
Scott LaVarnway committed
452
    if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
453
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
454
455
        this_mv.as_mv.col = startmv.as_mv.col - 2;
        thismse = vfp->svf(y, d->pre_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
456
457
458
    }
    else
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
459
460
        this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
        thismse = vfp->svf(y - 1, d->pre_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
461
462
    }

463
    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
464
465
466
467
468

    if (left < bestmse)
    {
        *bestmv = this_mv;
        bestmse = left;
469
        *distortion = thismse;
470
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
471
472
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
473
474
    this_mv.as_mv.col += 4;
    thismse = vfp->svf(y, d->pre_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
475
    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
476
477
478
479
480

    if (right < bestmse)
    {
        *bestmv = this_mv;
        bestmse = right;
481
        *distortion = thismse;
482
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
483
484
485
    }

    // go up then down and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
486
    this_mv.as_mv.col = startmv.as_mv.col;
John Koleszar's avatar
John Koleszar committed
487

Scott LaVarnway's avatar
Scott LaVarnway committed
488
    if (startmv.as_mv.row & 7)
John Koleszar's avatar
John Koleszar committed
489
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
490
491
        this_mv.as_mv.row = startmv.as_mv.row - 2;
        thismse = vfp->svf(y, d->pre_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
492
493
494
    }
    else
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
495
496
        this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
        thismse = vfp->svf(y - d->pre_stride, d->pre_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
497
498
    }

499
    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
500
501
502
503
504

    if (up < bestmse)
    {
        *bestmv = this_mv;
        bestmse = up;
505
        *distortion = thismse;
506
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
507
508
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
509
510
    this_mv.as_mv.row += 4;
    thismse = vfp->svf(y, d->pre_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
511
    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
512
513
514
515
516

    if (down < bestmse)
    {
        *bestmv = this_mv;
        bestmse = down;
517
        *distortion = thismse;
518
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    }


    // now check 1 more diagonal
    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);

//  for(whichdir=0;whichdir<4;whichdir++)
//  {
    this_mv = startmv;

    switch (whichdir)
    {
    case 0:

Scott LaVarnway's avatar
Scott LaVarnway committed
533
        if (startmv.as_mv.row & 7)
John Koleszar's avatar
John Koleszar committed
534
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
535
            this_mv.as_mv.row -= 2;
John Koleszar's avatar
John Koleszar committed
536

Scott LaVarnway's avatar
Scott LaVarnway committed
537
            if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
538
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
539
540
                this_mv.as_mv.col -= 2;
                thismse = vfp->svf(y, d->pre_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
541
542
543
            }
            else
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
544
545
                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
                thismse = vfp->svf(y - 1, d->pre_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);;
John Koleszar's avatar
John Koleszar committed
546
547
548
549
            }
        }
        else
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
550
            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
John Koleszar's avatar
John Koleszar committed
551

Scott LaVarnway's avatar
Scott LaVarnway committed
552
            if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
553
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
554
555
                this_mv.as_mv.col -= 2;
                thismse = vfp->svf(y - d->pre_stride, d->pre_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
556
557
558
            }
            else
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
559
                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
560
                thismse = vfp->svf(y - d->pre_stride - 1, d->pre_stride, 6, 6, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
561
562
563
564
565
            }
        }

        break;
    case 1:
Scott LaVarnway's avatar
Scott LaVarnway committed
566
        this_mv.as_mv.col += 2;
John Koleszar's avatar
John Koleszar committed
567

Scott LaVarnway's avatar
Scott LaVarnway committed
568
        if (startmv.as_mv.row & 7)
John Koleszar's avatar
John Koleszar committed
569
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
570
571
            this_mv.as_mv.row -= 2;
            thismse = vfp->svf(y, d->pre_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
572
573
574
        }
        else
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
575
576
            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
            thismse = vfp->svf(y - d->pre_stride, d->pre_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
577
578
579
580
        }

        break;
    case 2:
Scott LaVarnway's avatar
Scott LaVarnway committed
581
        this_mv.as_mv.row += 2;
John Koleszar's avatar
John Koleszar committed
582

Scott LaVarnway's avatar
Scott LaVarnway committed
583
        if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
584
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
585
586
            this_mv.as_mv.col -= 2;
            thismse = vfp->svf(y, d->pre_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
587
588
589
        }
        else
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
590
591
            this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
            thismse = vfp->svf(y - 1, d->pre_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
592
593
594
595
        }

        break;
    case 3:
Scott LaVarnway's avatar
Scott LaVarnway committed
596
597
598
        this_mv.as_mv.col += 2;
        this_mv.as_mv.row += 2;
        thismse = vfp->svf(y, d->pre_stride,  this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
599
600
601
        break;
    }

602
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
603
604
605
606
607

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
608
        *distortion = thismse;
609
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
610
611
612
613
614
    }

    return bestmse;
}

Scott LaVarnway's avatar
Scott LaVarnway committed
615
616
617
618
619
620
int vp8_find_best_half_pixel_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d,
                                  int_mv *bestmv, int_mv *ref_mv,
                                  int error_per_bit,
                                  const vp8_variance_fn_ptr_t *vfp,
                                  int *mvcost[2], int *distortion,
                                  unsigned int *sse1)
John Koleszar's avatar
John Koleszar committed
621
622
{
    int bestmse = INT_MAX;
Scott LaVarnway's avatar
Scott LaVarnway committed
623
624
625
    int_mv startmv;
    int_mv this_mv;
    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
John Koleszar's avatar
John Koleszar committed
626
627
628
    unsigned char *z = (*(b->base_src) + b->src);
    int left, right, up, down, diag;
    unsigned int sse;
629
    int thismse;
John Koleszar's avatar
John Koleszar committed
630
631

    // Trap uncodable vectors
Scott LaVarnway's avatar
Scott LaVarnway committed
632
633
    if ((abs((bestmv->as_mv.col << 3) - ref_mv->as_mv.col) > MAX_FULL_PEL_VAL)
        || (abs((bestmv->as_mv.row << 3) - ref_mv->as_mv.row) > MAX_FULL_PEL_VAL))
John Koleszar's avatar
John Koleszar committed
634
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
635
636
        bestmv->as_mv.row <<= 3;
        bestmv->as_mv.col <<= 3;
637
        *distortion = INT_MAX;
John Koleszar's avatar
John Koleszar committed
638
639
640
641
        return INT_MAX;
    }

    // central mv
Scott LaVarnway's avatar
Scott LaVarnway committed
642
643
    bestmv->as_mv.row <<= 3;
    bestmv->as_mv.col <<= 3;
John Koleszar's avatar
John Koleszar committed
644
645
646
    startmv = *bestmv;

    // calculate central point error
647
    bestmse = vfp->vf(y, d->pre_stride, z, b->src_stride, sse1);
648
    *distortion = bestmse;
649
    bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
650
651

    // go left then right and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
652
653
    this_mv.as_mv.row = startmv.as_mv.row;
    this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
654
655
    thismse = vfp->svf_halfpix_h(y - 1, d->pre_stride, z, b->src_stride, &sse);
    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
656
657
658
659
660

    if (left < bestmse)
    {
        *bestmv = this_mv;
        bestmse = left;
661
        *distortion = thismse;
662
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
663
664
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
665
    this_mv.as_mv.col += 8;
666
667
    thismse = vfp->svf_halfpix_h(y, d->pre_stride, z, b->src_stride, &sse);
    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
668
669
670
671
672

    if (right < bestmse)
    {
        *bestmv = this_mv;
        bestmse = right;
673
        *distortion = thismse;
674
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
675
676
677
    }

    // go up then down and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
678
679
    this_mv.as_mv.col = startmv.as_mv.col;
    this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
680
681
    thismse = vfp->svf_halfpix_v(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
682
683
684
685
686

    if (up < bestmse)
    {
        *bestmv = this_mv;
        bestmse = up;
687
        *distortion = thismse;
688
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
689
690
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
691
    this_mv.as_mv.row += 8;
692
693
    thismse = vfp->svf_halfpix_v(y, d->pre_stride, z, b->src_stride, &sse);
    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
694
695
696
697
698

    if (down < bestmse)
    {
        *bestmv = this_mv;
        bestmse = down;
699
        *distortion = thismse;
700
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
701
702
703
704
705
706
707
708
709
710
711
712
713
    }

    // somewhat strangely not doing all the diagonals for half pel is slower than doing them.
#if 0
    // now check 1 more diagonal -
    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
    this_mv = startmv;

    switch (whichdir)
    {
    case 0:
        this_mv.col = (this_mv.col - 8) | 4;
        this_mv.row = (this_mv.row - 8) | 4;
714
        diag = vfp->svf(y - 1 - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
715
716
717
718
        break;
    case 1:
        this_mv.col += 4;
        this_mv.row = (this_mv.row - 8) | 4;
719
        diag = vfp->svf(y - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
720
721
722
723
        break;
    case 2:
        this_mv.col = (this_mv.col - 8) | 4;
        this_mv.row += 4;
724
        diag = vfp->svf(y - 1, d->pre_stride, 4, 4, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
725
726
727
728
        break;
    case 3:
        this_mv.col += 4;
        this_mv.row += 4;
729
        diag = vfp->svf(y, d->pre_stride, 4, 4, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
730
731
732
        break;
    }

733
    diag += mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
734
735
736
737
738
739
740
741

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
    }

#else
Scott LaVarnway's avatar
Scott LaVarnway committed
742
743
    this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
    this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
744
745
    thismse = vfp->svf_halfpix_hv(y - 1 - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
746
747
748
749
750

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
751
        *distortion = thismse;
752
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
753
754
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
755
    this_mv.as_mv.col += 8;
756
757
    thismse = vfp->svf_halfpix_hv(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
758
759
760
761
762

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
763
        *distortion = thismse;
764
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
765
766
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
767
768
    this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
    this_mv.as_mv.row = startmv.as_mv.row + 4;
769
770
    thismse = vfp->svf_halfpix_hv(y - 1, d->pre_stride, z, b->src_stride, &sse);
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
771
772
773
774
775

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
776
        *distortion = thismse;
777
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
778
779
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
780
    this_mv.as_mv.col += 8;
781
782
    thismse = vfp->svf_halfpix_hv(y, d->pre_stride, z, b->src_stride, &sse);
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
783
784
785
786
787

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
788
        *distortion = thismse;
789
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
790
791
792
793
794
795
    }

#endif
    return bestmse;
}

Yunqing Wang's avatar
Yunqing Wang committed
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
#define CHECK_BOUNDS(range) \
{\
    all_in = 1;\
    all_in &= ((br-range) >= x->mv_row_min);\
    all_in &= ((br+range) <= x->mv_row_max);\
    all_in &= ((bc-range) >= x->mv_col_min);\
    all_in &= ((bc+range) <= x->mv_col_max);\
}

#define CHECK_POINT \
{\
    if (this_mv.as_mv.col < x->mv_col_min) continue;\
    if (this_mv.as_mv.col > x->mv_col_max) continue;\
    if (this_mv.as_mv.row < x->mv_row_min) continue;\
    if (this_mv.as_mv.row > x->mv_row_max) continue;\
}

#define CHECK_BETTER \
{\
    if (thissad < bestsad)\
    {\
817
        thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);\
Yunqing Wang's avatar
Yunqing Wang committed
818
819
820
821
822
823
824
        if (thissad < bestsad)\
        {\
            bestsad = thissad;\
            best_site = i;\
        }\
    }\
}
John Koleszar's avatar
John Koleszar committed
825

826
827
828
829
830
831
832
833
834
static const MV next_chkpts[6][3] =
{
    {{ -2, 0}, { -1, -2}, {1, -2}},
    {{ -1, -2}, {1, -2}, {2, 0}},
    {{1, -2}, {2, 0}, {1, 2}},
    {{2, 0}, {1, 2}, { -1, 2}},
    {{1, 2}, { -1, 2}, { -2, 0}},
    {{ -1, 2}, { -2, 0}, { -1, -2}}
};
Yunqing Wang's avatar
Yunqing Wang committed
835

John Koleszar's avatar
John Koleszar committed
836
837
838
839
840
int vp8_hex_search
(
    MACROBLOCK *x,
    BLOCK *b,
    BLOCKD *d,
Scott LaVarnway's avatar
Scott LaVarnway committed
841
842
    int_mv *ref_mv,
    int_mv *best_mv,
John Koleszar's avatar
John Koleszar committed
843
    int search_param,
844
    int sad_per_bit,
845
    const vp8_variance_fn_ptr_t *vfp,
John Koleszar's avatar
John Koleszar committed
846
    int *mvsadcost[2],
847
    int *mvcost[2],
Scott LaVarnway's avatar
Scott LaVarnway committed
848
    int_mv *center_mv
John Koleszar's avatar
John Koleszar committed
849
850
)
{
851
    MV hex[6] = { { -1, -2}, {1, -2}, {2, 0}, {1, 2}, { -1, 2}, { -2, 0} } ;
Yunqing Wang's avatar
Yunqing Wang committed
852
    MV neighbors[4] = {{0, -1}, { -1, 0}, {1, 0}, {0, 1}} ;
John Koleszar's avatar
John Koleszar committed
853
854
    int i, j;

Yunqing Wang's avatar
Yunqing Wang committed
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
    unsigned char *what = (*(b->base_src) + b->src);
    int what_stride = b->src_stride;
    int in_what_stride = d->pre_stride;
    int br = ref_mv->as_mv.row >> 3, bc = ref_mv->as_mv.col >> 3;
    int_mv this_mv;
    unsigned int bestsad = 0x7fffffff;
    unsigned int thissad;
    unsigned char *base_offset;
    unsigned char *this_offset;
    int k = -1;
    int all_in;
    int best_site = -1;

    int_mv fcenter_mv;
    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;

    // Work out the start point for the search
    base_offset = (unsigned char *)(*(d->base_pre) + d->pre);
    this_offset = base_offset + (br * (d->pre_stride)) + bc;
    this_mv.as_mv.row = br;
    this_mv.as_mv.col = bc;
877
878
879
    bestsad = vfp->sdf( what, what_stride, this_offset,
                        in_what_stride, 0x7fffffff)
            + mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);
John Koleszar's avatar
John Koleszar committed
880

881
882
    // hex search
    //j=0
Yunqing Wang's avatar
Yunqing Wang committed
883
    CHECK_BOUNDS(2)
884

Yunqing Wang's avatar
Yunqing Wang committed
885
    if(all_in)
886
    {
Yunqing Wang's avatar
Yunqing Wang committed
887
        for (i = 0; i < 6; i++)
888
        {
Yunqing Wang's avatar
Yunqing Wang committed
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
            this_mv.as_mv.row = br + hex[i].row;
            this_mv.as_mv.col = bc + hex[i].col;
            this_offset = base_offset + (this_mv.as_mv.row * in_what_stride) + this_mv.as_mv.col;
            thissad=vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
            CHECK_BETTER
        }
    }else
    {
        for (i = 0; i < 6; i++)
        {
            this_mv.as_mv.row = br + hex[i].row;
            this_mv.as_mv.col = bc + hex[i].col;
            CHECK_POINT
            this_offset = base_offset + (this_mv.as_mv.row * in_what_stride) + this_mv.as_mv.col;
            thissad=vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
            CHECK_BETTER
905
906
907
        }
    }

Yunqing Wang's avatar
Yunqing Wang committed
908
    if (best_site == -1)
909
        goto cal_neighbors;
Yunqing Wang's avatar
Yunqing Wang committed
910
911
912
913
914
915
    else
    {
        br += hex[best_site].row;
        bc += hex[best_site].col;
        k = best_site;
    }
916
917

    for (j = 1; j < 127; j++)
John Koleszar's avatar
John Koleszar committed
918
    {
Yunqing Wang's avatar
Yunqing Wang committed
919
920
        best_site = -1;
        CHECK_BOUNDS(2)
John Koleszar's avatar
John Koleszar committed
921

Yunqing Wang's avatar
Yunqing Wang committed
922
        if(all_in)
John Koleszar's avatar
John Koleszar committed
923
        {
Yunqing Wang's avatar
Yunqing Wang committed
924
            for (i = 0; i < 3; i++)
925
            {
Yunqing Wang's avatar
Yunqing Wang committed
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
                this_mv.as_mv.row = br + next_chkpts[k][i].row;
                this_mv.as_mv.col = bc + next_chkpts[k][i].col;
                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
                CHECK_BETTER
            }
        }else
        {
            for (i = 0; i < 3; i++)
            {
                this_mv.as_mv.row = br + next_chkpts[k][i].row;
                this_mv.as_mv.col = bc + next_chkpts[k][i].col;
                CHECK_POINT
                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
                CHECK_BETTER
942
            }
John Koleszar's avatar
John Koleszar committed
943
944
        }

Yunqing Wang's avatar
Yunqing Wang committed
945
        if (best_site == -1)
John Koleszar's avatar
John Koleszar committed
946
            break;
Yunqing Wang's avatar
Yunqing Wang committed
947
948
949
950
951
952
953
954
        else
        {
            br += next_chkpts[k][best_site].row;
            bc += next_chkpts[k][best_site].col;
            k += 5 + best_site;
            if (k >= 12) k -= 12;
            else if (k >= 6) k -= 6;
        }
John Koleszar's avatar
John Koleszar committed
955
956
    }

Yunqing Wang's avatar
Yunqing Wang committed
957
    // check 4 1-away neighbors
958
cal_neighbors:
Yunqing Wang's avatar
Yunqing Wang committed
959
    for (j = 0; j < 32; j++)
John Koleszar's avatar
John Koleszar committed
960
    {
Yunqing Wang's avatar
Yunqing Wang committed
961
962
        best_site = -1;
        CHECK_BOUNDS(1)
John Koleszar's avatar
John Koleszar committed
963

Yunqing Wang's avatar
Yunqing Wang committed
964
        if(all_in)
Yunqing Wang's avatar
Yunqing Wang committed
965
        {
Yunqing Wang's avatar
Yunqing Wang committed
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
            for (i = 0; i < 4; i++)
            {
                this_mv.as_mv.row = br + neighbors[i].row;
                this_mv.as_mv.col = bc + neighbors[i].col;
                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
                CHECK_BETTER
            }
        }else
        {
            for (i = 0; i < 4; i++)
            {
                this_mv.as_mv.row = br + neighbors[i].row;
                this_mv.as_mv.col = bc + neighbors[i].col;
                CHECK_POINT
                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
                CHECK_BETTER
            }
Yunqing Wang's avatar
Yunqing Wang committed
985
986
        }

Yunqing Wang's avatar
Yunqing Wang committed
987
        if (best_site == -1)
Yunqing Wang's avatar
Yunqing Wang committed
988
            break;
Yunqing Wang's avatar
Yunqing Wang committed
989
990
991
992
993
        else
        {
            br += neighbors[best_site].row;
            bc += neighbors[best_site].col;
        }
John Koleszar's avatar
John Koleszar committed
994
995
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
996
997
    best_mv->as_mv.row = br;
    best_mv->as_mv.col = bc;
John Koleszar's avatar
John Koleszar committed
998

999
    return bestsad;
John Koleszar's avatar
John Koleszar committed
1000
}
Yunqing Wang's avatar
Yunqing Wang committed
1001
1002
#undef CHECK_BOUNDS
#undef CHECK_POINT
John Koleszar's avatar
John Koleszar committed
1003
#undef CHECK_BETTER
1004

John Koleszar's avatar
John Koleszar committed
1005
1006
1007
1008
1009
int vp8_diamond_search_sad
(
    MACROBLOCK *x,
    BLOCK *b,
    BLOCKD *d,
Scott LaVarnway's avatar
Scott LaVarnway committed
1010
1011
    int_mv *ref_mv,
    int_mv *best_mv,
John Koleszar's avatar
John Koleszar committed
1012
    int search_param,
1013
    int sad_per_bit,
John Koleszar's avatar
John Koleszar committed
1014
1015
    int *num00,
    vp8_variance_fn_ptr_t *fn_ptr,
1016
    int *mvcost[2],
Scott LaVarnway's avatar
Scott LaVarnway committed
1017
    int_mv *center_mv
John Koleszar's avatar
John Koleszar committed
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
)
{
    int i, j, step;

    unsigned char *what = (*(b->base_src) + b->src);
    int what_stride = b->src_stride;
    unsigned char *in_what;
    int in_what_stride = d->pre_stride;
    unsigned char *best_address;

    int tot_steps;
Scott LaVarnway's avatar
Scott LaVarnway committed
1029
    int_mv this_mv;
John Koleszar's avatar
John Koleszar committed
1030
1031
1032
1033
1034

    int bestsad = INT_MAX;
    int best_site = 0;
    int last_site = 0;

Scott LaVarnway's avatar
Scott LaVarnway committed
1035
1036
    int ref_row = ref_mv->as_mv.row >> 3;
    int ref_col = ref_mv->as_mv.col >> 3;
John Koleszar's avatar
John Koleszar committed
1037
1038
1039
1040
1041
1042
1043
    int this_row_offset;
    int this_col_offset;
    search_site *ss;

    unsigned char *check_here;
    int thissad;

1044
    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
Scott LaVarnway's avatar
Scott LaVarnway committed
1045
1046
1047
    int_mv fcenter_mv;
    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
1048

Yunqing Wang's avatar
Yunqing Wang committed
1049
1050
    *num00 = 0;

Scott LaVarnway's avatar
Scott LaVarnway committed
1051
1052
    best_mv->as_mv.row = ref_row;
    best_mv->as_mv.col = ref_col;
1053

John Koleszar's avatar
John Koleszar committed
1054
1055
1056
1057
1058
1059
1060
1061
1062
    // Work out the start point for the search
    in_what = (unsigned char *)(*(d->base_pre) + d->pre + (ref_row * (d->pre_stride)) + ref_col);
    best_address = in_what;

    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
    {
        // Check the starting position
1063
1064
1065
        bestsad = fn_ptr->sdf(what, what_stride, in_what,
                              in_what_stride, 0x7fffffff)
                + mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
John Koleszar's avatar
John Koleszar committed
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
    }

    // search_param determines the length of the initial step and hence the number of iterations
    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
    ss = &x->ss[search_param * x->searches_per_step];
    tot_steps = (x->ss_count / x->searches_per_step) - search_param;

    i = 1;

    for (step = 0; step < tot_steps ; step++)
    {
        for (j = 0 ; j < x->searches_per_step ; j++)
        {
            // Trap illegal vectors
Scott LaVarnway's avatar
Scott LaVarnway committed
1080
1081
            this_row_offset = best_mv->as_mv.row + ss[i].mv.row;
            this_col_offset = best_mv->as_mv.col + ss[i].mv.col;
John Koleszar's avatar
John Koleszar committed
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091

            if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) &&
            (this_row_offset > x->mv_row_min) && (this_row_offset < x->mv_row_max))

            {
                check_here = ss[i].offset + best_address;
                thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);

                if (thissad < bestsad)
                {
Scott LaVarnway's avatar
Scott LaVarnway committed
1092
1093
                    this_mv.as_mv.row = this_row_offset;
                    this_mv.as_mv.col = this_col_offset;
1094
1095
                    thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
                                                mvsadcost, sad_per_bit);
John Koleszar's avatar
John Koleszar committed
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109

                    if (thissad < bestsad)
                    {
                        bestsad = thissad;
                        best_site = i;
                    }
                }
            }

            i++;
        }

        if (best_site != last_site)
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
1110
1111
            best_mv->as_mv.row += ss[best_site].mv.row;
            best_mv->as_mv.col += ss[best_site].mv.col;
John Koleszar's avatar
John Koleszar committed
1112
1113
1114
1115
1116
1117
1118
            best_address += ss[best_site].offset;
            last_site = best_site;
        }
        else if (best_address == in_what)
            (*num00)++;
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
1119
1120
    this_mv.as_mv.row = best_mv->as_mv.row << 3;
    this_mv.as_mv.col = best_mv->as_mv.col << 3;
John Koleszar's avatar
John Koleszar committed
1121
1122
1123
1124
1125

    if (bestsad == INT_MAX)
        return INT_MAX;

    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
1126
        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
John Koleszar's avatar
John Koleszar committed
1127
1128
1129
1130
1131
1132
1133
}

int vp8_diamond_search_sadx4
(
    MACROBLOCK *x,
    BLOCK *b,
    BLOCKD *d,
Scott LaVarnway's avatar
Scott LaVarnway committed
1134
1135
    int_mv *ref_mv,
    int_mv *best_mv,
John Koleszar's avatar
John Koleszar committed
1136
    int search_param,
1137
    int sad_per_bit,
John Koleszar's avatar
John Koleszar committed
1138
1139
    int *num00,
    vp8_variance_fn_ptr_t *fn_ptr,
1140
    int *mvcost[2],
Scott LaVarnway's avatar
Scott LaVarnway committed
1141
    int_mv *center_mv
John Koleszar's avatar
John Koleszar committed
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
)
{
    int i, j, step;

    unsigned char *what = (*(b->base_src) + b->src);
    int what_stride = b->src_stride;
    unsigned char *in_what;
    int in_what_stride = d->pre_stride;
    unsigned char *best_address;

    int tot_steps;
Scott LaVarnway's avatar
Scott LaVarnway committed
1153
    int_mv this_mv;
John Koleszar's avatar
John Koleszar committed
1154

1155
    int bestsad = INT_MAX;
John Koleszar's avatar
John Koleszar committed
1156
1157
1158
    int best_site = 0;
    int last_site = 0;

Scott LaVarnway's avatar
Scott LaVarnway committed
1159
1160
    int ref_row = ref_mv->as_mv.row >> 3;
    int ref_col = ref_mv->as_mv.col >> 3;
John Koleszar's avatar
John Koleszar committed
1161
1162
1163
1164
1165
1166
1167
    int this_row_offset;
    int this_col_offset;
    search_site *ss;

    unsigned char *check_here;
    unsigned int thissad;

1168
    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
Scott LaVarnway's avatar
Scott LaVarnway committed
1169
1170
1171
    int_mv fcenter_mv;
    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
1172

Yunqing Wang's avatar
Yunqing Wang committed
1173
    *num00 = 0;
Scott LaVarnway's avatar
Scott LaVarnway committed
1174
1175
    best_mv->as_mv.row = ref_row;
    best_mv->as_mv.col = ref_col;
Yunqing Wang's avatar
Yunqing Wang committed
1176

John Koleszar's avatar
John Koleszar committed
1177
1178
1179
1180
1181
1182
1183
1184
1185
    // Work out the start point for the search
    in_what = (unsigned char *)(*(d->base_pre) + d->pre + (ref_row * (d->pre_stride)) + ref_col);
    best_address = in_what;

    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
    {
        // Check the starting position
1186
1187
1188
        bestsad = fn_ptr->sdf(what, what_stride,
                              in_what, in_what_stride, 0x7fffffff)
                + mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
John Koleszar's avatar
John Koleszar committed
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
    }

    // search_param determines the length of the initial step and hence the number of iterations
    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
    ss = &x->ss[search_param * x->searches_per_step];
    tot_steps = (x->ss_count / x->searches_per_step) - search_param;

    i = 1;

    for (step = 0; step < tot_steps ; step++)
    {
1200
        int all_in = 1, t;
John Koleszar's avatar
John Koleszar committed
1201

1202
1203
        // To know if all neighbor points are within the bounds, 4 bounds checking are enough instead of
        // checking 4 bounds for each points.
Scott LaVarnway's avatar
Scott LaVarnway committed
1204
1205
1206
1207
        all_in &= ((best_mv->as_mv.row + ss[i].mv.row)> x->mv_row_min);
        all_in &= ((best_mv->as_mv.row + ss[i+1].mv.row) < x->mv_row_max);
        all_in &= ((best_mv->as_mv.col + ss[i+2].mv.col) > x->mv_col_min);
        all_in &= ((best_mv->as_mv.col + ss[i+3].mv.col) < x->mv_col_max);
John Koleszar's avatar
John Koleszar committed
1208

1209
        if (all_in)
John Koleszar's avatar
John Koleszar committed
1210
        {
1211
            unsigned int sad_array[4];
John Koleszar's avatar
John Koleszar committed
1212

1213
            for (j = 0 ; j < x->searches_per_step ; j += 4)
John Koleszar's avatar
John Koleszar committed
1214
            {
1215
                unsigned char *block_offset[4];
John Koleszar's avatar
John Koleszar committed
1216

1217
1218
                for (t = 0; t < 4; t++)
                    block_offset[t] = ss[i+t].offset + best_address;
John Koleszar's avatar
John Koleszar committed
1219
1220
1221
1222
1223

                fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride, sad_array);

                for (t = 0; t < 4; t++, i++)
                {
1224
                    if (sad_array[t] < bestsad)
John Koleszar's avatar
John Koleszar committed