mcomp.c 68.2 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

25
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
26 27 28 29 30 31
int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight, int ishp) {
  // 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.
  return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> (ishp == 0)] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> (ishp == 0)]) * Weight) >> 7;
John Koleszar's avatar
John Koleszar committed
32
}
33
#else
John Koleszar's avatar
John Koleszar committed
34 35 36 37 38 39
int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight) {
  // 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.
  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;
40 41
}
#endif
John Koleszar's avatar
John Koleszar committed
42

43
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
44 45 46 47 48 49 50
static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit, int ishp) {
  // Ignore costing if mvcost is NULL
  if (mvcost)
    return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> (ishp == 0)] +
             mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> (ishp == 0)])
            * error_per_bit + 128) >> 8;
  return 0;
51 52
}
#else
John Koleszar's avatar
John Koleszar committed
53 54 55 56 57 58 59
static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit) {
  // Ignore costing if mvcost is NULL
  if (mvcost)
    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;
  return 0;
John Koleszar's avatar
John Koleszar committed
60
}
61 62
#endif

John Koleszar's avatar
John Koleszar committed
63

John Koleszar's avatar
John Koleszar committed
64 65 66 67 68 69 70 71
static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_per_bit) {
  // Calculate sad error cost on full pixel basis.
  // Ignore costing if mvcost is NULL
  if (mvsadcost)
    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;
  return 0;
John Koleszar's avatar
John Koleszar committed
72 73
}

74

John Koleszar's avatar
John Koleszar committed
75 76 77
void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride) {
  int Len;
  int search_site_count = 0;
John Koleszar's avatar
John Koleszar committed
78 79


John Koleszar's avatar
John Koleszar committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  // 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.
John Koleszar's avatar
John Koleszar committed
96
    x->ss[search_site_count].mv.col = 0;
John Koleszar's avatar
John Koleszar committed
97 98 99 100 101 102
    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;
John Koleszar's avatar
John Koleszar committed
103
    x->ss[search_site_count].mv.row = 0;
John Koleszar's avatar
John Koleszar committed
104
    x->ss[search_site_count].offset = -Len;
John Koleszar's avatar
John Koleszar committed
105 106
    search_site_count++;

John Koleszar's avatar
John Koleszar committed
107 108 109 110 111
    // 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++;
John Koleszar's avatar
John Koleszar committed
112

John Koleszar's avatar
John Koleszar committed
113 114 115 116 117 118
    // Contract.
    Len /= 2;
  }

  x->ss_count = search_site_count;
  x->searches_per_step = 4;
John Koleszar's avatar
John Koleszar committed
119 120
}

John Koleszar's avatar
John Koleszar committed
121 122 123 124 125 126 127 128 129 130 131 132
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) {
John Koleszar's avatar
John Koleszar committed
133

John Koleszar's avatar
John Koleszar committed
134
    // Compute offsets for search sites.
John Koleszar's avatar
John Koleszar committed
135
    x->ss[search_site_count].mv.col = 0;
John Koleszar's avatar
John Koleszar committed
136 137 138 139 140 141 142 143 144 145 146 147
    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;
John Koleszar's avatar
John Koleszar committed
148
    x->ss[search_site_count].mv.row = 0;
John Koleszar's avatar
John Koleszar committed
149
    x->ss[search_site_count].offset = -Len;
John Koleszar's avatar
John Koleszar committed
150 151
    search_site_count++;

John Koleszar's avatar
John Koleszar committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    // 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++;
John Koleszar's avatar
John Koleszar committed
181

John Koleszar's avatar
John Koleszar committed
182 183 184 185 186 187 188

    // Contract.
    Len /= 2;
  }

  x->ss_count = search_site_count;
  x->searches_per_step = 8;
John Koleszar's avatar
John Koleszar committed
189 190
}

191 192 193 194 195 196 197 198 199
/*
 * 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.
 */
200

201
#define PRE(r,c) (y + (((r)>>2) * y_stride + ((c)>>2) -(offset))) // pointer to predictor base of a motionvector
202 203 204
#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
205
#define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc
206
#endif  /* CONFIG_SIXTEENTH_SUBPEL_UV */
207
#define MVC(r,c) (mvcost ? ((mvcost[0][(r)-rr] + mvcost[1][(c)-rc]) * error_per_bit + 128 )>>8 : 0) // estimated cost of a motion vector (r,c)
208
#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
209
#define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost
210 211 212 213 214 215 216 217 218 219 220 221 222
#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;

#if CONFIG_HIGH_PRECISION_MV
#define PREHP(r,c) (y + (((r)>>3) * y_stride + ((c)>>3) -(offset))) // pointer to predictor base of a motionvector
#if CONFIG_SIXTEENTH_SUBPEL_UV
#define SPHP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc
#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
#define SPHP(x) ((x)&7) // convert motion vector component to offset for svf calc
#endif  /* CONFIG_SIXTEENTH_SUBPEL_UV */
#define DISTHP(r,c) vfp->svf( PREHP(r,c), y_stride, SPHP(c),SPHP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
#define ERRHP(r,c) (MVC(r,c)+DISTHP(r,c)) // returns distortion + motion vector cost
#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{thismse = ((xd->allow_high_precision_mv)?DISTHP(r,c):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
#else
223
#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
224
#endif /* CONFIG_HIGH_PRECISION_MV */
225

John Koleszar's avatar
John Koleszar committed
226 227 228
#define MIN(x,y) (((x)<(y))?(x):(y))
#define MAX(x,y) (((x)>(y))?(x):(y))

Scott LaVarnway's avatar
Scott LaVarnway committed
229 230 231 232 233
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,
John Koleszar's avatar
John Koleszar committed
234 235 236 237 238 239 240 241 242 243 244 245
                                             unsigned int *sse1) {
  unsigned char *z = (*(b->base_src) + b->src);
  MACROBLOCKD *xd = &x->e_mbd;

  int rr, rc, br, bc, hstep;
  int tr, tc;
  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;
246
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
247
  unsigned int eighthiters = 4;
248
#endif
John Koleszar's avatar
John Koleszar committed
249 250 251 252
  int thismse;
  int maxc, minc, maxr, minr;
  int y_stride;
  int offset;
John Koleszar's avatar
John Koleszar committed
253

254
#if ARCH_X86 || ARCH_X86_64
John Koleszar's avatar
John Koleszar committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268
  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
  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;
  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;
269
#else
John Koleszar's avatar
John Koleszar committed
270 271
  unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
  y_stride = d->pre_stride;
272 273 274
#endif


275
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
  if (xd->allow_high_precision_mv) {
    rr = ref_mv->as_mv.row;
    rc = ref_mv->as_mv.col;
    br = bestmv->as_mv.row << 3;
    bc = bestmv->as_mv.col << 3;
    hstep = 4;
    minc = MAX(x->mv_col_min << 3, (ref_mv->as_mv.col) - ((1 << mvlong_width_hp) - 1));
    maxc = MIN(x->mv_col_max << 3, (ref_mv->as_mv.col) + ((1 << mvlong_width_hp) - 1));
    minr = MAX(x->mv_row_min << 3, (ref_mv->as_mv.row) - ((1 << mvlong_width_hp) - 1));
    maxr = MIN(x->mv_row_max << 3, (ref_mv->as_mv.row) + ((1 << mvlong_width_hp) - 1));
  } else
#endif
  {
    rr = ref_mv->as_mv.row >> 1;
    rc = ref_mv->as_mv.col >> 1;
    br = bestmv->as_mv.row << 2;
    bc = bestmv->as_mv.col << 2;
    hstep = 2;
    minc = MAX(x->mv_col_min << 2, (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1));
    maxc = MIN(x->mv_col_max << 2, (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1));
    minr = MAX(x->mv_row_min << 2, (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1));
    maxr = MIN(x->mv_row_max << 2, (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1));
  }

  tr = br;
  tc = bc;


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

  // central mv
  bestmv->as_mv.row <<= 3;
  bestmv->as_mv.col <<= 3;

  // calculate central point error
  besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1);
  *distortion = besterr;
#if CONFIG_HIGH_PRECISION_MV
  besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
#else
  besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
317
#endif
John Koleszar's avatar
John Koleszar committed
318

John Koleszar's avatar
John Koleszar committed
319 320 321 322 323 324 325
  // 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 - hstep);
    CHECK_BETTER(right, tr, tc + hstep);
    CHECK_BETTER(up, tr - hstep, tc);
    CHECK_BETTER(down, tr + hstep, tc);
326

John Koleszar's avatar
John Koleszar committed
327
    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
328

John Koleszar's avatar
John Koleszar committed
329 330 331 332 333 334 335 336 337 338 339 340 341 342
    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;
    }
343

John Koleszar's avatar
John Koleszar committed
344 345 346
    // no reason to check the same one again.
    if (tr == br && tc == bc)
      break;
John Koleszar's avatar
John Koleszar committed
347

John Koleszar's avatar
John Koleszar committed
348 349 350
    tr = br;
    tc = bc;
  }
John Koleszar's avatar
John Koleszar committed
351

John Koleszar's avatar
John Koleszar committed
352 353 354 355 356 357 358 359
  // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
  // 1/4 pel
  hstep >>= 1;
  while (--quarteriters) {
    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
360

John Koleszar's avatar
John Koleszar committed
361
    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
John Koleszar's avatar
John Koleszar committed
362

John Koleszar's avatar
John Koleszar committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376
    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;
    }
John Koleszar's avatar
John Koleszar committed
377

John Koleszar's avatar
John Koleszar committed
378 379 380
    // no reason to check the same one again.
    if (tr == br && tc == bc)
      break;
John Koleszar's avatar
John Koleszar committed
381

John Koleszar's avatar
John Koleszar committed
382 383 384
    tr = br;
    tc = bc;
  }
John Koleszar's avatar
John Koleszar committed
385

John Koleszar's avatar
John Koleszar committed
386 387
#if CONFIG_HIGH_PRECISION_MV
  if (x->e_mbd.allow_high_precision_mv) {
388
    hstep >>= 1;
John Koleszar's avatar
John Koleszar committed
389 390 391 392 393
    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);
John Koleszar's avatar
John Koleszar committed
394

John Koleszar's avatar
John Koleszar committed
395
      whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
John Koleszar's avatar
John Koleszar committed
396

John Koleszar's avatar
John Koleszar committed
397
      switch (whichdir) {
John Koleszar's avatar
John Koleszar committed
398
        case 0:
John Koleszar's avatar
John Koleszar committed
399 400
          CHECK_BETTER(diag, tr - hstep, tc - hstep);
          break;
John Koleszar's avatar
John Koleszar committed
401
        case 1:
John Koleszar's avatar
John Koleszar committed
402 403
          CHECK_BETTER(diag, tr - hstep, tc + hstep);
          break;
John Koleszar's avatar
John Koleszar committed
404
        case 2:
John Koleszar's avatar
John Koleszar committed
405 406
          CHECK_BETTER(diag, tr + hstep, tc - hstep);
          break;
John Koleszar's avatar
John Koleszar committed
407
        case 3:
John Koleszar's avatar
John Koleszar committed
408 409 410
          CHECK_BETTER(diag, tr + hstep, tc + hstep);
          break;
      }
John Koleszar's avatar
John Koleszar committed
411

John Koleszar's avatar
John Koleszar committed
412 413 414
      // no reason to check the same one again.
      if (tr == br && tc == bc)
        break;
415

John Koleszar's avatar
John Koleszar committed
416 417
      tr = br;
      tc = bc;
418
    }
John Koleszar's avatar
John Koleszar committed
419
  }
420 421
#endif
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
422 423 424 425
  if (x->e_mbd.allow_high_precision_mv) {
    bestmv->as_mv.row = br;
    bestmv->as_mv.col = bc;
  } else
426
#endif  /* CONFIG_HIGH_PRECISION_MV */
John Koleszar's avatar
John Koleszar committed
427 428 429 430
  {
    bestmv->as_mv.row = br << 1;
    bestmv->as_mv.col = bc << 1;
  }
John Koleszar's avatar
John Koleszar committed
431

John Koleszar's avatar
John Koleszar committed
432 433 434
  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)))
    return INT_MAX;
John Koleszar's avatar
John Koleszar committed
435

John Koleszar's avatar
John Koleszar committed
436
  return besterr;
John Koleszar's avatar
John Koleszar committed
437 438 439 440 441
}
#undef MVC
#undef PRE
#undef SP
#undef DIST
442
#undef IFMVCV
John Koleszar's avatar
John Koleszar committed
443 444 445 446
#undef ERR
#undef CHECK_BETTER
#undef MIN
#undef MAX
447

448 449 450 451 452 453 454
#if CONFIG_HIGH_PRECISION_MV
#undef PREHP
#undef DPHP
#undef DISTHP
#undef ERRHP
#endif

455 456 457 458
#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
459
#endif  /* CONFIG_SIXTEENTH_SUBPEL_UV */
Scott LaVarnway's avatar
Scott LaVarnway committed
460 461 462 463 464
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,
John Koleszar's avatar
John Koleszar committed
465 466 467 468
                                 unsigned int *sse1) {
  int bestmse = INT_MAX;
  int_mv startmv;
  int_mv this_mv;
469
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
470 471
  int_mv orig_mv;
  int yrow_movedback = 0, ycol_movedback = 0;
472
#endif
John Koleszar's avatar
John Koleszar committed
473 474 475 476 477 478 479
  unsigned char *z = (*(b->base_src) + b->src);
  int left, right, up, down, diag;
  unsigned int sse;
  int whichdir;
  int thismse;
  int y_stride;
  MACROBLOCKD *xd = &x->e_mbd;
480 481

#if ARCH_X86 || ARCH_X86_64
John Koleszar's avatar
John Koleszar committed
482 483
  unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
  unsigned char *y;
484

John Koleszar's avatar
John Koleszar committed
485 486 487 488
  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;
489
#else
John Koleszar's avatar
John Koleszar committed
490 491
  unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
  y_stride = d->pre_stride;
492
#endif
John Koleszar's avatar
John Koleszar committed
493

John Koleszar's avatar
John Koleszar committed
494 495 496 497
  // central mv
  bestmv->as_mv.row <<= 3;
  bestmv->as_mv.col <<= 3;
  startmv = *bestmv;
498
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
499
  orig_mv = *bestmv;
500
#endif
John Koleszar's avatar
John Koleszar committed
501

John Koleszar's avatar
John Koleszar committed
502 503 504
  // calculate central point error
  bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
  *distortion = bestmse;
505
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
506
  bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
507
#else
John Koleszar's avatar
John Koleszar committed
508
  bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
509
#endif
John Koleszar's avatar
John Koleszar committed
510

John Koleszar's avatar
John Koleszar committed
511 512 513 514
  // go left then right and check error
  this_mv.as_mv.row = startmv.as_mv.row;
  this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
  thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse);
515
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
516
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
517
#else
John Koleszar's avatar
John Koleszar committed
518
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
519
#endif
John Koleszar's avatar
John Koleszar committed
520

John Koleszar's avatar
John Koleszar committed
521 522 523 524 525 526
  if (left < bestmse) {
    *bestmv = this_mv;
    bestmse = left;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
527

John Koleszar's avatar
John Koleszar committed
528 529
  this_mv.as_mv.col += 8;
  thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
530
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
531
  right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
532
#else
John Koleszar's avatar
John Koleszar committed
533
  right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
534
#endif
John Koleszar's avatar
John Koleszar committed
535

John Koleszar's avatar
John Koleszar committed
536 537 538 539 540 541 542 543 544 545 546
  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;
  this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
  thismse =  vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse);
547
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
548
  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
549
#else
John Koleszar's avatar
John Koleszar committed
550
  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
551
#endif
John Koleszar's avatar
John Koleszar committed
552

John Koleszar's avatar
John Koleszar committed
553 554 555 556 557 558
  if (up < bestmse) {
    *bestmv = this_mv;
    bestmse = up;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
559

John Koleszar's avatar
John Koleszar committed
560 561
  this_mv.as_mv.row += 8;
  thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse);
562
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
563
  down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
564
#else
John Koleszar's avatar
John Koleszar committed
565
  down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
566
#endif
John Koleszar's avatar
John Koleszar committed
567

John Koleszar's avatar
John Koleszar committed
568 569 570 571 572 573
  if (down < bestmse) {
    *bestmv = this_mv;
    bestmse = down;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
574 575


John Koleszar's avatar
John Koleszar committed
576 577 578 579 580
  // now check 1 more diagonal
  whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
  // for(whichdir =0;whichdir<4;whichdir++)
  // {
  this_mv = startmv;
John Koleszar's avatar
John Koleszar committed
581

John Koleszar's avatar
John Koleszar committed
582
  switch (whichdir) {
John Koleszar's avatar
John Koleszar committed
583
    case 0:
John Koleszar's avatar
John Koleszar committed
584 585 586 587
      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);
      break;
John Koleszar's avatar
John Koleszar committed
588
    case 1:
John Koleszar's avatar
John Koleszar committed
589 590 591 592
      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);
      break;
John Koleszar's avatar
John Koleszar committed
593
    case 2:
John Koleszar's avatar
John Koleszar committed
594 595 596 597
      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);
      break;
John Koleszar's avatar
John Koleszar committed
598
    case 3:
599
    default:
John Koleszar's avatar
John Koleszar committed
600 601 602 603 604
      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);
      break;
  }
John Koleszar's avatar
John Koleszar committed
605

606
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
607
  diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
608
#else
John Koleszar's avatar
John Koleszar committed
609
  diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
610
#endif
John Koleszar's avatar
John Koleszar committed
611

John Koleszar's avatar
John Koleszar committed
612 613 614 615 616 617
  if (diag < bestmse) {
    *bestmv = this_mv;
    bestmse = diag;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
618 619 620 621

//  }


John Koleszar's avatar
John Koleszar committed
622 623 624
  // time to check quarter pels.
  if (bestmv->as_mv.row < startmv.as_mv.row) {
    y -= y_stride;
625
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
626
    yrow_movedback = 1;
627
#endif
John Koleszar's avatar
John Koleszar committed
628
  }
John Koleszar's avatar
John Koleszar committed
629

John Koleszar's avatar
John Koleszar committed
630 631
  if (bestmv->as_mv.col < startmv.as_mv.col) {
    y--;
632
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
633
    ycol_movedback = 1;
634
#endif
John Koleszar's avatar
John Koleszar committed
635
  }
John Koleszar's avatar
John Koleszar committed
636

John Koleszar's avatar
John Koleszar committed
637
  startmv = *bestmv;
John Koleszar's avatar
John Koleszar committed
638 639 640



John Koleszar's avatar
John Koleszar committed
641 642
  // go left then right and check error
  this_mv.as_mv.row = startmv.as_mv.row;
John Koleszar's avatar
John Koleszar committed
643

John Koleszar's avatar
John Koleszar committed
644 645 646 647 648 649 650
  if (startmv.as_mv.col & 7) {
    this_mv.as_mv.col = startmv.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);
  } else {
    this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
    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
651

652
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
653
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
654
#else
John Koleszar's avatar
John Koleszar committed
655
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
656
#endif
John Koleszar's avatar
John Koleszar committed
657

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

John Koleszar's avatar
John Koleszar committed
665 666
  this_mv.as_mv.col += 4;
  thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
667
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
668
  right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
669
#else
John Koleszar's avatar
John Koleszar committed
670
  right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
671
#endif
John Koleszar's avatar
John Koleszar committed
672

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

John Koleszar's avatar
John Koleszar committed
680 681
  // go up then down and check error
  this_mv.as_mv.col = startmv.as_mv.col;
John Koleszar's avatar
John Koleszar committed
682

John Koleszar's avatar
John Koleszar committed
683 684 685 686 687 688 689
  if (startmv.as_mv.row & 7) {
    this_mv.as_mv.row = startmv.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);
  } else {
    this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
    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
690

691
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
692
  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
693
#else
John Koleszar's avatar
John Koleszar committed
694
  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
695
#endif
John Koleszar's avatar
John Koleszar committed
696

John Koleszar's avatar
John Koleszar committed
697 698 699 700 701 702
  if (up < bestmse) {
    *bestmv = this_mv;
    bestmse = up;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
703

John Koleszar's avatar
John Koleszar committed
704 705
  this_mv.as_mv.row += 4;
  thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
706
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
707
  down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
708
#else
John Koleszar's avatar
John Koleszar committed
709
  down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
710
#endif
John Koleszar's avatar
John Koleszar committed
711

John Koleszar's avatar
John Koleszar committed
712 713 714 715 716 717
  if (down < bestmse) {
    *bestmv = this_mv;
    bestmse = down;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
718 719


John Koleszar's avatar
John Koleszar committed
720 721
  // now check 1 more diagonal
  whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
John Koleszar's avatar
John Koleszar committed
722 723 724

//  for(whichdir=0;whichdir<4;whichdir++)
//  {
John Koleszar's avatar
John Koleszar committed
725
  this_mv = startmv;
John Koleszar's avatar
John Koleszar committed
726

John Koleszar's avatar
John Koleszar committed
727
  switch (whichdir) {
John Koleszar's avatar
John Koleszar committed
728 729
    case 0:

John Koleszar's avatar
John Koleszar committed
730 731
      if (startmv.as_mv.row & 7) {
        this_mv.as_mv.row -= 2;
John Koleszar's avatar
John Koleszar committed
732

John Koleszar's avatar
John Koleszar committed
733 734 735 736 737 738
        if (startmv.as_mv.col & 7) {
          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);
        } else {
          this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
          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
739
        }
John Koleszar's avatar
John Koleszar committed
740 741 742 743 744 745 746 747 748
      } else {
        this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;

        if (startmv.as_mv.col & 7) {
          this_mv.as_mv.col -= 2;
          thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse);
        } else {
          this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
          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
749
        }
John Koleszar's avatar
John Koleszar committed
750
      }
John Koleszar's avatar
John Koleszar committed
751

John Koleszar's avatar
John Koleszar committed
752
      break;
John Koleszar's avatar
John Koleszar committed
753
    case 1:
John Koleszar's avatar
John Koleszar committed
754
      this_mv.as_mv.col += 2;
John Koleszar's avatar
John Koleszar committed
755

John Koleszar's avatar
John Koleszar committed
756 757 758 759 760 761 762
      if (startmv.as_mv.row & 7) {
        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);
      } else {
        this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
        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
763

John Koleszar's avatar
John Koleszar committed
764
      break;
John Koleszar's avatar
John Koleszar committed
765
    case 2:
John Koleszar's avatar
John Koleszar committed
766
      this_mv.as_mv.row += 2;
John Koleszar's avatar
John Koleszar committed
767

John Koleszar's avatar
John Koleszar committed
768 769 770 771 772 773 774
      if (startmv.as_mv.col & 7) {
        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);
      } else {
        this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
        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
775

John Koleszar's avatar
John Koleszar committed
776
      break;
John Koleszar's avatar
John Koleszar committed
777
    case 3:
John Koleszar's avatar
John Koleszar committed
778 779 780 781 782
      this_mv.as_mv.col += 2;
      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);
      break;
  }
John Koleszar's avatar
John Koleszar committed
783

784
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
785
  diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
786
#else
John Koleszar's avatar
John Koleszar committed
787
  diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
788
#endif
John Koleszar's avatar
John Koleszar committed
789

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

797
#if CONFIG_HIGH_PRECISION_MV
John Koleszar's avatar
John Koleszar committed
798 799
  if (!x->e_mbd.allow_high_precision_mv)
    return bestmse;
800

John Koleszar's avatar
John Koleszar committed
801 802 803 804 805
  /* Now do 1/8th pixel */
  if (bestmv->as_mv.row < orig_mv.as_mv.row && !yrow_movedback) {
    y -= y_stride;
    yrow_movedback = 1;
  }
806

John Koleszar's avatar
John Koleszar committed
807 808 809 810
  if (bestmv->as_mv.col < orig_mv.as_mv.col && !ycol_movedback) {
    y--;
    ycol_movedback = 1;
  }
811

John Koleszar's avatar
John Koleszar committed
812
  startmv = *bestmv;
813

John Koleszar's avatar
John Koleszar committed
814 815
  // go left then right and check error
  this_mv.as_mv.row = startmv.as_mv.row;
816

John Koleszar's avatar
John Koleszar committed
817 818
  if (startmv.as_mv.col & 7) {
    this_mv.as_mv.col = startmv.as_mv.col - 1;
819
    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
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
  } 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, xd->allow_high_precision_mv);

  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, xd->allow_high_precision_mv);

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

John Koleszar's avatar
John Koleszar committed
856
  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
857

John Koleszar's avatar
John Koleszar committed
858 859 860 861 862 863
  if (up < bestmse) {
    *bestmv = this_mv;
    bestmse = up;
    *distortion = thismse;
    *sse1 = sse;
  }
864

John Koleszar's avatar
John Koleszar committed
865 866 867
  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, xd->allow_high_precision_mv);
868

John Koleszar's avatar
John Koleszar committed
869 870 871 872 873 874
  if (down < bestmse) {
    *bestmv = this_mv;
    bestmse = down;
    *distortion = thismse;
    *sse1 = sse;
  }
875 876


John Koleszar's avatar
John Koleszar committed
877 878
  // now check 1 more diagonal
  whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
879 880 881

//  for(whichdir=0;whichdir<4;whichdir++)
//  {
John Koleszar's avatar
John Koleszar committed
882
  this_mv = startmv;
883

John Koleszar's avatar
John Koleszar committed
884
  switch (whichdir) {
885 886
    case 0:

John Koleszar's avatar
John Koleszar committed
887 888
      if (startmv.as_mv.row & 7) {
        this_mv.as_mv.row -= 1;
889

John Koleszar's avatar
John Koleszar committed
890 891 892 893 894 895
        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);;
896
        }
John Koleszar's avatar
John Koleszar committed
897 898 899 900 901 902 903 904 905
      } 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);
906
        }
John Koleszar's avatar
John Koleszar committed
907
      }
908

John Koleszar's avatar
John Koleszar committed
909
      break;
910
    case 1:
John Koleszar's avatar
John Koleszar committed
911
      this_mv.as_mv.col += 1;
912

John Koleszar's avatar
John Koleszar committed
913 914 915 916 917 918 919
      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);
      }
920

John Koleszar's avatar
John Koleszar committed
921
      break;
922
    case 2:
John Koleszar's avatar
John Koleszar committed
923
      this_mv.as_mv.row += 1;
924

John Koleszar's avatar
John Koleszar committed
925 926 927 928 929 930 931
      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);
      }
932

John Koleszar's avatar
John Koleszar committed
933
      break;
934
    case 3: