mcomp.c 68.1 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
 */


#include "mcomp.h"
#include "vpx_mem/vpx_mem.h"
14
#include "vpx_ports/config.h"
John Koleszar's avatar
John Koleszar committed
15 16 17
#include <stdio.h>
#include <limits.h>
#include <math.h>
18
#include "vp8/common/findnearmv.h"
John Koleszar's avatar
John Koleszar committed
19 20 21 22 23 24

#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
25
int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight)
John Koleszar's avatar
John Koleszar committed
26 27 28 29 30
{
    // 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.
31
    return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> MV_SHIFT] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> MV_SHIFT]) * Weight) >> 7;
John Koleszar's avatar
John Koleszar committed
32 33
}

Scott LaVarnway's avatar
Scott LaVarnway committed
34
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
35
{
36 37
    return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> MV_SHIFT] +
        mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> MV_SHIFT])
Scott LaVarnway's avatar
Scott LaVarnway committed
38
        * error_per_bit + 128) >> 8;
John Koleszar's avatar
John Koleszar committed
39 40
}

Scott LaVarnway's avatar
Scott LaVarnway committed
41
static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_per_bit)
42 43
{
    /* Calculate sad error cost on full pixel basis. */
Scott LaVarnway's avatar
Scott LaVarnway committed
44 45 46
    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
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
}

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;
}

169 170 171 172 173 174 175 176 177
/*
 * To avoid the penalty for crossing cache-line read, preload the reference
 * area in a small buffer, which is aligned to make sure there won't be crossing
 * cache-line read while reading from this buffer. This reduced the cpu
 * cycles spent on reading ref data in sub-pixel filter functions.
 * TODO: Currently, since sub-pixel search range here is -3 ~ 3, copy 22 rows x
 * 32 cols area that is enough for 16x16 macroblock. Later, for SPLITMV, we
 * could reduce the area.
 */
178 179 180 181 182 183 184 185 186 187 188 189

#if CONFIG_HIGH_PRECISION_MV

#define PRE(r,c) (y + (((r)>>3) * y_stride + ((c)>>3) -(offset))) // pointer to predictor base of a motionvector
#if CONFIG_SIXTEENTH_SUBPEL_UV
#define SP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc
#else
#define SP(x) ((x)&7) // convert motion vector component to offset for svf calc
#endif  /* CONFIG_SIXTEENTH_SUBPEL_UV */

#else   /* CONFIG_HIGH_PRECISION_MV */

190
#define PRE(r,c) (y + (((r)>>2) * y_stride + ((c)>>2) -(offset))) // pointer to predictor base of a motionvector
191 192 193
#if CONFIG_SIXTEENTH_SUBPEL_UV
#define SP(x) (((x)&3)<<2) // convert motion vector component to offset for svf calc
#else
John Koleszar's avatar
John Koleszar committed
194
#define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc
195 196 197 198 199
#endif  /* CONFIG_SIXTEENTH_SUBPEL_UV */

#endif  /* CONFIG_HIGH_PRECISION_MV */

#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)
200
#define DIST(r,c) vfp->svf( PRE(r,c), y_stride, SP(c),SP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
John Koleszar's avatar
John Koleszar committed
201 202
#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
203
#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
204

John Koleszar's avatar
John Koleszar committed
205 206 207
#define MIN(x,y) (((x)<(y))?(x):(y))
#define MAX(x,y) (((x)>(y))?(x):(y))

Scott LaVarnway's avatar
Scott LaVarnway committed
208 209 210 211 212 213
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
214 215 216
{
    unsigned char *z = (*(b->base_src) + b->src);

217 218 219 220 221
#if CONFIG_HIGH_PRECISION_MV
    int rr = ref_mv->as_mv.row, rc = ref_mv->as_mv.col;
    int br = bestmv->as_mv.row << 3, bc = bestmv->as_mv.col << 3;
    int hstep = 4;
#else
Scott LaVarnway's avatar
Scott LaVarnway committed
222 223
    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;
224 225
    int hstep = 2;
#endif
John Koleszar's avatar
John Koleszar committed
226 227 228 229 230 231 232
    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;
233 234 235
#if CONFIG_HIGH_PRECISION_MV
    unsigned int eighthiters = 4;
#endif
236
    int thismse;
John Koleszar's avatar
John Koleszar committed
237

238 239 240 241 242 243
#if CONFIG_HIGH_PRECISION_MV
    int minc = MAX(x->mv_col_min << 3, (ref_mv->as_mv.col) - ((1 << mvlong_width) - 1));
    int maxc = MIN(x->mv_col_max << 3, (ref_mv->as_mv.col) + ((1 << mvlong_width) - 1));
    int minr = MAX(x->mv_row_min << 3, (ref_mv->as_mv.row) - ((1 << mvlong_width) - 1));
    int maxr = MIN(x->mv_row_max << 3, (ref_mv->as_mv.row) + ((1 << mvlong_width) - 1));
#else
Scott LaVarnway's avatar
Scott LaVarnway committed
244 245 246 247
    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));
248
#endif
John Koleszar's avatar
John Koleszar committed
249

250 251 252 253 254 255 256 257 258 259
    int y_stride;
    int offset;

#if ARCH_X86 || ARCH_X86_64
    MACROBLOCKD *xd = &x->e_mbd;
    unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
    unsigned char *y;
    int buf_r1, buf_r2, buf_c1, buf_c2;

    // Clamping to avoid out-of-range data access
260 261 262 263
    buf_r1 = ((bestmv->as_mv.row - INTERP_EXTEND) < x->mv_row_min)?(bestmv->as_mv.row - x->mv_row_min):INTERP_EXTEND;
    buf_r2 = ((bestmv->as_mv.row + INTERP_EXTEND) > x->mv_row_max)?(x->mv_row_max - bestmv->as_mv.row):INTERP_EXTEND;
    buf_c1 = ((bestmv->as_mv.col - INTERP_EXTEND) < x->mv_col_min)?(bestmv->as_mv.col - x->mv_col_min):INTERP_EXTEND;
    buf_c2 = ((bestmv->as_mv.col + INTERP_EXTEND) > x->mv_col_max)?(x->mv_col_max - bestmv->as_mv.col):INTERP_EXTEND;
264 265 266 267 268 269 270 271 272 273 274 275
    y_stride = 32;

    /* Copy to intermediate buffer before searching. */
    vfp->copymem(y0 - buf_c1 - d->pre_stride*buf_r1, d->pre_stride, xd->y_buf, y_stride, 16+buf_r1+buf_r2);
    y = xd->y_buf + y_stride*buf_r1 +buf_c1;
#else
    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
    y_stride = d->pre_stride;
#endif

    offset = (bestmv->as_mv.row) * y_stride + bestmv->as_mv.col;

John Koleszar's avatar
John Koleszar committed
276
    // central mv
Scott LaVarnway's avatar
Scott LaVarnway committed
277 278
    bestmv->as_mv.row <<= 3;
    bestmv->as_mv.col <<= 3;
John Koleszar's avatar
John Koleszar committed
279 280

    // calculate central point error
281
    besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1);
282
    *distortion = besterr;
283
    besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
284 285 286 287 288

    // 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
289 290 291 292
        CHECK_BETTER(left, tr, tc - hstep);
        CHECK_BETTER(right, tr, tc + hstep);
        CHECK_BETTER(up, tr - hstep, tc);
        CHECK_BETTER(down, tr + hstep, tc);
John Koleszar's avatar
John Koleszar committed
293 294 295 296 297 298

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

        switch (whichdir)
        {
        case 0:
299
            CHECK_BETTER(diag, tr - hstep, tc - hstep);
John Koleszar's avatar
John Koleszar committed
300 301
            break;
        case 1:
302
            CHECK_BETTER(diag, tr - hstep, tc + hstep);
John Koleszar's avatar
John Koleszar committed
303 304
            break;
        case 2:
305
            CHECK_BETTER(diag, tr + hstep, tc - hstep);
John Koleszar's avatar
John Koleszar committed
306 307
            break;
        case 3:
308
            CHECK_BETTER(diag, tr + hstep, tc + hstep);
John Koleszar's avatar
John Koleszar committed
309 310 311 312 313 314 315 316 317 318 319 320 321
            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
322
    hstep >>= 1;
John Koleszar's avatar
John Koleszar committed
323 324
    while (--quarteriters)
    {
325 326 327 328
        CHECK_BETTER(left, tr, tc - hstep);
        CHECK_BETTER(right, tr, tc + hstep);
        CHECK_BETTER(up, tr - hstep, tc);
        CHECK_BETTER(down, tr + hstep, tc);
John Koleszar's avatar
John Koleszar committed
329 330 331 332 333 334

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

        switch (whichdir)
        {
        case 0:
335
            CHECK_BETTER(diag, tr - hstep, tc - hstep);
John Koleszar's avatar
John Koleszar committed
336 337
            break;
        case 1:
338
            CHECK_BETTER(diag, tr - hstep, tc + hstep);
John Koleszar's avatar
John Koleszar committed
339 340
            break;
        case 2:
341
            CHECK_BETTER(diag, tr + hstep, tc - hstep);
John Koleszar's avatar
John Koleszar committed
342 343
            break;
        case 3:
344
            CHECK_BETTER(diag, tr + hstep, tc + hstep);
John Koleszar's avatar
John Koleszar committed
345 346 347 348 349 350 351 352 353 354 355
            break;
        }

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

        tr = br;
        tc = bc;
    }

356 357 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 384 385 386 387 388 389 390 391 392 393 394 395
#if CONFIG_HIGH_PRECISION_MV
    if (x->e_mbd.allow_high_precision_mv)
    {
        hstep >>= 1;
        while (--eighthiters)
        {
            CHECK_BETTER(left, tr, tc - hstep);
            CHECK_BETTER(right, tr, tc + hstep);
            CHECK_BETTER(up, tr - hstep, tc);
            CHECK_BETTER(down, tr + hstep, tc);

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

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

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

            tr = br;
            tc = bc;
        }
    }
    bestmv->as_mv.row = br;
    bestmv->as_mv.col = bc;
#else
Scott LaVarnway's avatar
Scott LaVarnway committed
396 397
    bestmv->as_mv.row = br << 1;
    bestmv->as_mv.col = bc << 1;
398
#endif  /* CONFIG_HIGH_PRECISION_MV */
John Koleszar's avatar
John Koleszar committed
399

400 401
    if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > (MAX_FULL_PEL_VAL<<3)) ||
        (abs(bestmv->as_mv.row - ref_mv->as_mv.row) > (MAX_FULL_PEL_VAL<<3)))
John Koleszar's avatar
John Koleszar committed
402 403 404 405 406 407 408 409
        return INT_MAX;

    return besterr;
}
#undef MVC
#undef PRE
#undef SP
#undef DIST
410
#undef IFMVCV
John Koleszar's avatar
John Koleszar committed
411 412 413 414
#undef ERR
#undef CHECK_BETTER
#undef MIN
#undef MAX
415 416 417 418 419 420

#if CONFIG_SIXTEENTH_SUBPEL_UV
#define SP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc
#else
#define SP(x) ((x)&7) // convert motion vector component to offset for svf calc
#endif  /* CONFIG_HIGH_PRECISION_MV */
Scott LaVarnway's avatar
Scott LaVarnway committed
421 422 423 424 425 426
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
427 428
{
    int bestmse = INT_MAX;
Scott LaVarnway's avatar
Scott LaVarnway committed
429 430
    int_mv startmv;
    int_mv this_mv;
431 432 433 434
#if CONFIG_HIGH_PRECISION_MV
    int_mv orig_mv;
    int yrow_movedback=0, ycol_movedback=0;
#endif
John Koleszar's avatar
John Koleszar committed
435 436 437 438
    unsigned char *z = (*(b->base_src) + b->src);
    int left, right, up, down, diag;
    unsigned int sse;
    int whichdir ;
439
    int thismse;
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    int y_stride;

#if ARCH_X86 || ARCH_X86_64
    MACROBLOCKD *xd = &x->e_mbd;
    unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
    unsigned char *y;

    y_stride = 32;
    /* Copy 18 rows x 32 cols area to intermediate buffer before searching. */
     vfp->copymem(y0 - 1 - d->pre_stride, d->pre_stride, xd->y_buf, y_stride, 18);
     y = xd->y_buf + y_stride + 1;
#else
     unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
     y_stride = d->pre_stride;
#endif
John Koleszar's avatar
John Koleszar committed
455 456

    // central mv
Scott LaVarnway's avatar
Scott LaVarnway committed
457 458
    bestmv->as_mv.row <<= 3;
    bestmv->as_mv.col <<= 3;
John Koleszar's avatar
John Koleszar committed
459
    startmv = *bestmv;
460 461 462
#if CONFIG_HIGH_PRECISION_MV
    orig_mv = *bestmv;
#endif
John Koleszar's avatar
John Koleszar committed
463 464

    // calculate central point error
465
    bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
466
    *distortion = bestmse;
467
    bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
468 469

    // go left then right and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
470 471
    this_mv.as_mv.row = startmv.as_mv.row;
    this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
472
    thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse);
473
    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
474 475 476 477 478

    if (left < bestmse)
    {
        *bestmv = this_mv;
        bestmse = left;
479
        *distortion = thismse;
480
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
481 482
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
483
    this_mv.as_mv.col += 8;
484
    thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
485
    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
486 487 488 489 490

    if (right < bestmse)
    {
        *bestmv = this_mv;
        bestmse = right;
491
        *distortion = thismse;
492
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
493 494 495
    }

    // go up then down and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
496 497
    this_mv.as_mv.col = startmv.as_mv.col;
    this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
498
    thismse =  vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse);
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
    this_mv.as_mv.row += 8;
510
    thismse = vfp->svf_halfpix_v(y, y_stride, 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
    }


    // 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
531 532
        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
533
        thismse = vfp->svf_halfpix_hv(y - 1 - y_stride, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
534 535
        break;
    case 1:
Scott LaVarnway's avatar
Scott LaVarnway committed
536 537
        this_mv.as_mv.col += 4;
        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
538
        thismse = vfp->svf_halfpix_hv(y - y_stride, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
539 540
        break;
    case 2:
Scott LaVarnway's avatar
Scott LaVarnway committed
541 542
        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
        this_mv.as_mv.row += 4;
543
        thismse = vfp->svf_halfpix_hv(y - 1, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
544 545
        break;
    case 3:
546
    default:
Scott LaVarnway's avatar
Scott LaVarnway committed
547 548
        this_mv.as_mv.col += 4;
        this_mv.as_mv.row += 4;
549
        thismse = vfp->svf_halfpix_hv(y, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
550 551 552
        break;
    }

553
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
554 555 556 557 558

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
559
        *distortion = thismse;
560
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
561 562 563 564 565 566
    }

//  }


    // time to check quarter pels.
Scott LaVarnway's avatar
Scott LaVarnway committed
567
    if (bestmv->as_mv.row < startmv.as_mv.row)
568
    {
569
        y -= y_stride;
570 571 572 573
#if CONFIG_HIGH_PRECISION_MV
        yrow_movedback = 1;
#endif
    }
John Koleszar's avatar
John Koleszar committed
574

Scott LaVarnway's avatar
Scott LaVarnway committed
575
    if (bestmv->as_mv.col < startmv.as_mv.col)
576
    {
John Koleszar's avatar
John Koleszar committed
577
        y--;
578 579 580 581
#if CONFIG_HIGH_PRECISION_MV
        ycol_movedback = 1;
#endif
    }
John Koleszar's avatar
John Koleszar committed
582 583 584 585 586 587

    startmv = *bestmv;



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

Scott LaVarnway's avatar
Scott LaVarnway committed
590
    if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
591
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
592
        this_mv.as_mv.col = startmv.as_mv.col - 2;
593
        thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
594 595 596
    }
    else
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
597
        this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
598
        thismse = vfp->svf(y - 1, y_stride, SP(6), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
599 600
    }

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

    if (left < bestmse)
    {
        *bestmv = this_mv;
        bestmse = left;
607
        *distortion = thismse;
608
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
609 610
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
611
    this_mv.as_mv.col += 4;
612
    thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
613
    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
614 615 616 617 618

    if (right < bestmse)
    {
        *bestmv = this_mv;
        bestmse = right;
619
        *distortion = thismse;
620
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
621 622 623
    }

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

Scott LaVarnway's avatar
Scott LaVarnway committed
626
    if (startmv.as_mv.row & 7)
John Koleszar's avatar
John Koleszar committed
627
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
628
        this_mv.as_mv.row = startmv.as_mv.row - 2;
629
        thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
630 631 632
    }
    else
    {
Scott LaVarnway's avatar
Scott LaVarnway committed
633
        this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
634
        thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
635 636
    }

637
    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
638 639 640 641 642

    if (up < bestmse)
    {
        *bestmv = this_mv;
        bestmse = up;
643
        *distortion = thismse;
644
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
645 646
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
647
    this_mv.as_mv.row += 4;
648
    thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
649
    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
650 651 652 653 654

    if (down < bestmse)
    {
        *bestmv = this_mv;
        bestmse = down;
655
        *distortion = thismse;
656
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
657 658 659 660 661 662 663 664 665 666 667 668 669 670
    }


    // 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
671
        if (startmv.as_mv.row & 7)
John Koleszar's avatar
John Koleszar committed
672
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
673
            this_mv.as_mv.row -= 2;
John Koleszar's avatar
John Koleszar committed
674

Scott LaVarnway's avatar
Scott LaVarnway committed
675
            if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
676
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
677
                this_mv.as_mv.col -= 2;
678
                thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
679 680 681
            }
            else
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
682
                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
683
                thismse = vfp->svf(y - 1, y_stride, SP(6), SP(this_mv.as_mv.row), z, b->src_stride, &sse);;
John Koleszar's avatar
John Koleszar committed
684 685 686 687
            }
        }
        else
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
688
            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
John Koleszar's avatar
John Koleszar committed
689

Scott LaVarnway's avatar
Scott LaVarnway committed
690
            if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
691
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
692
                this_mv.as_mv.col -= 2;
693
                thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
694 695 696
            }
            else
            {
Scott LaVarnway's avatar
Scott LaVarnway committed
697
                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
698
                thismse = vfp->svf(y - y_stride - 1, y_stride, SP(6), SP(6), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
699 700 701 702 703
            }
        }

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

Scott LaVarnway's avatar
Scott LaVarnway committed
706
        if (startmv.as_mv.row & 7)
John Koleszar's avatar
John Koleszar committed
707
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
708
            this_mv.as_mv.row -= 2;
709
            thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
710 711 712
        }
        else
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
713
            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
714
            thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
715 716 717 718
        }

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

Scott LaVarnway's avatar
Scott LaVarnway committed
721
        if (startmv.as_mv.col & 7)
John Koleszar's avatar
John Koleszar committed
722
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
723
            this_mv.as_mv.col -= 2;
724
            thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
725 726 727
        }
        else
        {
Scott LaVarnway's avatar
Scott LaVarnway committed
728
            this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
729
            thismse = vfp->svf(y - 1, y_stride, SP(6), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
730 731 732 733
        }

        break;
    case 3:
Scott LaVarnway's avatar
Scott LaVarnway committed
734 735
        this_mv.as_mv.col += 2;
        this_mv.as_mv.row += 2;
736
        thismse = vfp->svf(y, y_stride,  SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
737 738 739
        break;
    }

740
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
741 742 743 744 745

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
746
        *distortion = thismse;
747
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
748 749
    }

750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
#if CONFIG_HIGH_PRECISION_MV
    if (!x->e_mbd.allow_high_precision_mv)
        return bestmse;

    /* Now do 1/8th pixel */
    if (bestmv->as_mv.row < orig_mv.as_mv.row && !yrow_movedback)
    {
        y -= y_stride;
        yrow_movedback = 1;
    }

    if (bestmv->as_mv.col < orig_mv.as_mv.col && !ycol_movedback)
    {
        y--;
        ycol_movedback = 1;
    }

    startmv = *bestmv;

    // go left then right and check error
    this_mv.as_mv.row = startmv.as_mv.row;

    if (startmv.as_mv.col & 7)
    {
        this_mv.as_mv.col = startmv.as_mv.col - 1;
        thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
    }
    else
    {
        this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
        thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
    }

    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);

    if (left < bestmse)
    {
        *bestmv = this_mv;
        bestmse = left;
        *distortion = thismse;
        *sse1 = sse;
    }

    this_mv.as_mv.col += 2;
    thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);

    if (right < bestmse)
    {
        *bestmv = this_mv;
        bestmse = right;
        *distortion = thismse;
        *sse1 = sse;
    }

    // go up then down and check error
    this_mv.as_mv.col = startmv.as_mv.col;

    if (startmv.as_mv.row & 7)
    {
        this_mv.as_mv.row = startmv.as_mv.row - 1;
        thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
    }
    else
    {
        this_mv.as_mv.row = (startmv.as_mv.row - 8) | 7;
        thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(7), z, b->src_stride, &sse);
    }

    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);

    if (up < bestmse)
    {
        *bestmv = this_mv;
        bestmse = up;
        *distortion = thismse;
        *sse1 = sse;
    }

    this_mv.as_mv.row += 2;
    thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);

    if (down < bestmse)
    {
        *bestmv = this_mv;
        bestmse = down;
        *distortion = thismse;
        *sse1 = sse;
    }


    // 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:

        if (startmv.as_mv.row & 7)
        {
            this_mv.as_mv.row -= 1;

            if (startmv.as_mv.col & 7)
            {
                this_mv.as_mv.col -= 1;
                thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
            }
            else
            {
                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
                thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row), z, b->src_stride, &sse);;
            }
        }
        else
        {
            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 7;

            if (startmv.as_mv.col & 7)
            {
                this_mv.as_mv.col -= 1;
                thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(7), z, b->src_stride, &sse);
            }
            else
            {
                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
                thismse = vfp->svf(y - y_stride - 1, y_stride, SP(7), SP(7), z, b->src_stride, &sse);
            }
        }

        break;
    case 1:
        this_mv.as_mv.col += 1;

        if (startmv.as_mv.row & 7)
        {
            this_mv.as_mv.row -= 1;
            thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
        }
        else
        {
            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 7;
            thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(7), z, b->src_stride, &sse);
        }

        break;
    case 2:
        this_mv.as_mv.row += 1;

        if (startmv.as_mv.col & 7)
        {
            this_mv.as_mv.col -= 1;
            thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
        }
        else
        {
            this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
            thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
        }

        break;
    case 3:
        this_mv.as_mv.col += 1;
        this_mv.as_mv.row += 1;
        thismse = vfp->svf(y, y_stride,  SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
        break;
    }

    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
        *distortion = thismse;
        *sse1 = sse;
    }

#endif  /* CONFIG_HIGH_PRECISION_MV */

John Koleszar's avatar
John Koleszar committed
934 935 936
    return bestmse;
}

937 938
#undef SP

939
int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
Scott LaVarnway's avatar
Scott LaVarnway committed
940 941 942 943 944
                                  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
945 946
{
    int bestmse = INT_MAX;
Scott LaVarnway's avatar
Scott LaVarnway committed
947 948
    int_mv startmv;
    int_mv this_mv;
John Koleszar's avatar
John Koleszar committed
949 950 951
    unsigned char *z = (*(b->base_src) + b->src);
    int left, right, up, down, diag;
    unsigned int sse;
Yunqing Wang's avatar
Yunqing Wang committed
952
    int whichdir ;
953
    int thismse;
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
    int y_stride;

#if ARCH_X86 || ARCH_X86_64
    MACROBLOCKD *xd = &x->e_mbd;
    unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
    unsigned char *y;

    y_stride = 32;
    /* Copy 18 rows x 32 cols area to intermediate buffer before searching. */
    vfp->copymem(y0 - 1 - d->pre_stride, d->pre_stride, xd->y_buf, y_stride, 18);
    y = xd->y_buf + y_stride + 1;
#else
    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
    y_stride = d->pre_stride;
#endif
John Koleszar's avatar
John Koleszar committed
969 970

    // central mv
Scott LaVarnway's avatar
Scott LaVarnway committed
971 972
    bestmv->as_mv.row <<= 3;
    bestmv->as_mv.col <<= 3;
John Koleszar's avatar
John Koleszar committed
973 974 975
    startmv = *bestmv;

    // calculate central point error
976
    bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
977
    *distortion = bestmse;
978
    bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
979 980

    // go left then right and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
981 982
    this_mv.as_mv.row = startmv.as_mv.row;
    this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
983
    thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse);
984
    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
985 986 987 988 989

    if (left < bestmse)
    {
        *bestmv = this_mv;
        bestmse = left;
990
        *distortion = thismse;
991
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
992 993
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
994
    this_mv.as_mv.col += 8;
995
    thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
996
    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
997 998 999 1000 1001

    if (right < bestmse)
    {
        *bestmv = this_mv;
        bestmse = right;
1002
        *distortion = thismse;
1003
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
1004 1005 1006
    }

    // go up then down and check error
Scott LaVarnway's avatar
Scott LaVarnway committed
1007 1008
    this_mv.as_mv.col = startmv.as_mv.col;
    this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
1009
    thismse = vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse);
1010
    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
1011 1012 1013 1014 1015

    if (up < bestmse)
    {
        *bestmv = this_mv;
        bestmse = up;
1016
        *distortion = thismse;
1017
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
1018 1019
    }

Scott LaVarnway's avatar
Scott LaVarnway committed
1020
    this_mv.as_mv.row += 8;
1021
    thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse);
1022
    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
1023 1024 1025 1026 1027

    if (down < bestmse)
    {
        *bestmv = this_mv;
        bestmse = down;
1028
        *distortion = thismse;
1029
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
1030 1031 1032 1033 1034 1035 1036 1037 1038
    }

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

    switch (whichdir)
    {
    case 0:
Yunqing Wang's avatar
Yunqing Wang committed
1039 1040 1041
        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
        thismse = vfp->svf_halfpix_hv(y - 1 - y_stride, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
1042 1043
        break;
    case 1:
Yunqing Wang's avatar
Yunqing Wang committed
1044 1045 1046
        this_mv.as_mv.col += 4;
        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
        thismse = vfp->svf_halfpix_hv(y - y_stride, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
1047 1048
        break;
    case 2:
Yunqing Wang's avatar
Yunqing Wang committed
1049 1050 1051
        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
        this_mv.as_mv.row += 4;
        thismse = vfp->svf_halfpix_hv(y - 1, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
1052 1053
        break;
    case 3:
Yunqing Wang's avatar
Yunqing Wang committed
1054 1055 1056 1057
    default:
        this_mv.as_mv.col += 4;
        this_mv.as_mv.row += 4;
        thismse = vfp->svf_halfpix_hv(y, y_stride, z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
1058 1059 1060
        break;
    }

1061
    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
John Koleszar's avatar
John Koleszar committed
1062 1063 1064 1065 1066

    if (diag < bestmse)
    {
        *bestmv = this_mv;
        bestmse = diag;
1067
        *distortion = thismse;
1068
        *sse1 = sse;
John Koleszar's avatar
John Koleszar committed
1069 1070 1071 1072 1073
    }

    return bestmse;
}

Yunqing Wang's avatar
Yunqing Wang committed
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
#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)\
    {\
1095
        thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);\
Yunqing Wang's avatar
Yunqing Wang committed
1096 1097 1098 1099 1100 1101 1102
        if (thissad < bestsad)\
        {\
            bestsad = thissad;\
            best_site = i;\
        }\
    }\
}
John Koleszar's avatar
John Koleszar committed
1103

John Koleszar's avatar