mcomp.c 67.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
#include "vp8/encoder/onyx_int.h"
John Koleszar's avatar
John Koleszar committed
13 14
#include "mcomp.h"
#include "vpx_mem/vpx_mem.h"
15
#include "vpx_ports/config.h"
John Koleszar's avatar
John Koleszar committed
16 17 18
#include <stdio.h>
#include <limits.h>
#include <math.h>
19
#include "vp8/common/findnearmv.h"
John Koleszar's avatar
John Koleszar committed
20 21 22 23 24 25

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

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
void vp8_clamp_mv_min_max(MACROBLOCK *x, int_mv *ref_mv) {
  int col_min = (ref_mv->as_mv.col >> 3) - MAX_FULL_PEL_VAL +
      ((ref_mv->as_mv.col & 7) ? 1 : 0);
  int row_min = (ref_mv->as_mv.row >> 3) - MAX_FULL_PEL_VAL +
      ((ref_mv->as_mv.row & 7) ? 1 : 0);
  int col_max = (ref_mv->as_mv.col >> 3) + MAX_FULL_PEL_VAL;
  int row_max = (ref_mv->as_mv.row >> 3) + MAX_FULL_PEL_VAL;

  /* Get intersection of UMV window and valid MV window to reduce # of checks in diamond search. */
  if (x->mv_col_min < col_min)
    x->mv_col_min = col_min;
  if (x->mv_col_max > col_max)
    x->mv_col_max = col_max;
  if (x->mv_row_min < row_min)
    x->mv_row_min = row_min;
  if (x->mv_row_max > row_max)
    x->mv_row_max = row_max;
}

45 46 47 48 49 50 51 52 53 54 55
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
56 57
}

58 59
static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2],
                       int error_per_bit, int ishp) {
John Koleszar's avatar
John Koleszar committed
60 61 62 63 64 65
  // 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;
66 67
}

John Koleszar's avatar
John Koleszar committed
68

69 70
static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2],
                          int error_per_bit) {
John Koleszar's avatar
John Koleszar committed
71 72 73 74 75 76 77
  // 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
78 79
}

80

John Koleszar's avatar
John Koleszar committed
81 82 83
void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride) {
  int Len;
  int search_site_count = 0;
John Koleszar's avatar
John Koleszar committed
84 85


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

John Koleszar's avatar
John Koleszar committed
113 114 115 116 117
    // 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
118

John Koleszar's avatar
John Koleszar committed
119 120 121 122 123 124
    // Contract.
    Len /= 2;
  }

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

John Koleszar's avatar
John Koleszar committed
127 128 129 130 131 132 133 134 135 136 137 138
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
139

John Koleszar's avatar
John Koleszar committed
140
    // Compute offsets for search sites.
John Koleszar's avatar
John Koleszar committed
141
    x->ss[search_site_count].mv.col = 0;
John Koleszar's avatar
John Koleszar committed
142 143 144 145 146 147 148 149 150 151 152 153
    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
154
    x->ss[search_site_count].mv.row = 0;
John Koleszar's avatar
John Koleszar committed
155
    x->ss[search_site_count].offset = -Len;
John Koleszar's avatar
John Koleszar committed
156 157
    search_site_count++;

John Koleszar's avatar
John Koleszar committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    // 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
187

John Koleszar's avatar
John Koleszar committed
188 189 190 191 192 193 194

    // Contract.
    Len /= 2;
  }

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

197 198 199 200 201 202 203 204 205
/*
 * 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.
 */
206

207
#define PRE(r,c) (y + (((r)>>2) * y_stride + ((c)>>2) -(offset))) // pointer to predictor base of a motionvector
208
#define SP(x) (((x)&3)<<2) // convert motion vector component to offset for svf calc
209
#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)
210
#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
211
#define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost
212 213 214 215 216 217 218
#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;

#define PREHP(r,c) (y + (((r)>>3) * y_stride + ((c)>>3) -(offset))) // pointer to predictor base of a motionvector
#define SPHP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc
#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
219

John Koleszar's avatar
John Koleszar committed
220 221 222
#define MIN(x,y) (((x)<(y))?(x):(y))
#define MAX(x,y) (((x)>(y))?(x):(y))

Scott LaVarnway's avatar
Scott LaVarnway committed
223 224 225 226 227
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
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
                                             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;
  unsigned int eighthiters = 4;
  int thismse;
  int maxc, minc, maxr, minr;
  int y_stride;
  int offset;
John Koleszar's avatar
John Koleszar committed
245

Ronald S. Bultje's avatar
Ronald S. Bultje committed
246
#if !CONFIG_SUPERBLOCKS && (ARCH_X86 || ARCH_X86_64)
John Koleszar's avatar
John Koleszar committed
247 248 249 250 251
  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
252 253 254 255 256 257 258 259
  buf_r1 = ((bestmv->as_mv.row - INTERP_EXTEND) < x->mv_row_min) ?
      (bestmv->as_mv.row - x->mv_row_min) : INTERP_EXTEND - 1;
  buf_r2 = ((bestmv->as_mv.row + INTERP_EXTEND) > x->mv_row_max) ?
      (x->mv_row_max - bestmv->as_mv.row) : INTERP_EXTEND - 1;
  buf_c1 = ((bestmv->as_mv.col - INTERP_EXTEND) < x->mv_col_min) ?
      (bestmv->as_mv.col - x->mv_col_min) : INTERP_EXTEND - 1;
  buf_c2 = ((bestmv->as_mv.col + INTERP_EXTEND) > x->mv_col_max) ?
      (x->mv_col_max - bestmv->as_mv.col) : INTERP_EXTEND - 1;
John Koleszar's avatar
John Koleszar committed
260 261 262 263 264
  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;
265
#else
John Koleszar's avatar
John Koleszar committed
266 267
  unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
  y_stride = d->pre_stride;
268 269 270
#endif


John Koleszar's avatar
John Koleszar committed
271 272 273 274 275 276 277 278 279 280
  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));
281
  } else {
John Koleszar's avatar
John Koleszar committed
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
    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;
306 307
  besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit,
                         xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
308

309 310
  // TODO: Each subsequent iteration checks at least one point in
  // common with the last iteration could be 2 ( if diag selected)
John Koleszar's avatar
John Koleszar committed
311 312 313 314 315 316
  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);
317

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

John Koleszar's avatar
John Koleszar committed
320 321 322 323 324 325 326 327 328 329 330 331 332 333
    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;
    }
334

John Koleszar's avatar
John Koleszar committed
335 336 337
    // no reason to check the same one again.
    if (tr == br && tc == bc)
      break;
John Koleszar's avatar
John Koleszar committed
338

John Koleszar's avatar
John Koleszar committed
339 340 341
    tr = br;
    tc = bc;
  }
John Koleszar's avatar
John Koleszar committed
342

343 344
  // TODO: Each subsequent iteration checks at least one point in common with
  // the last iteration could be 2 ( if diag selected) 1/4 pel
John Koleszar's avatar
John Koleszar committed
345 346 347 348 349 350
  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
351

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

John Koleszar's avatar
John Koleszar committed
354 355 356 357 358 359 360 361 362 363 364 365 366 367
    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
368

John Koleszar's avatar
John Koleszar committed
369 370 371
    // no reason to check the same one again.
    if (tr == br && tc == bc)
      break;
John Koleszar's avatar
John Koleszar committed
372

John Koleszar's avatar
John Koleszar committed
373 374 375
    tr = br;
    tc = bc;
  }
John Koleszar's avatar
John Koleszar committed
376

John Koleszar's avatar
John Koleszar committed
377
  if (x->e_mbd.allow_high_precision_mv) {
378
    hstep >>= 1;
John Koleszar's avatar
John Koleszar committed
379 380 381 382 383
    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
384

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

John Koleszar's avatar
John Koleszar committed
387
      switch (whichdir) {
John Koleszar's avatar
John Koleszar committed
388
        case 0:
John Koleszar's avatar
John Koleszar committed
389 390
          CHECK_BETTER(diag, tr - hstep, tc - hstep);
          break;
John Koleszar's avatar
John Koleszar committed
391
        case 1:
John Koleszar's avatar
John Koleszar committed
392 393
          CHECK_BETTER(diag, tr - hstep, tc + hstep);
          break;
John Koleszar's avatar
John Koleszar committed
394
        case 2:
John Koleszar's avatar
John Koleszar committed
395 396
          CHECK_BETTER(diag, tr + hstep, tc - hstep);
          break;
John Koleszar's avatar
John Koleszar committed
397
        case 3:
John Koleszar's avatar
John Koleszar committed
398 399 400
          CHECK_BETTER(diag, tr + hstep, tc + hstep);
          break;
      }
John Koleszar's avatar
John Koleszar committed
401

John Koleszar's avatar
John Koleszar committed
402 403 404
      // no reason to check the same one again.
      if (tr == br && tc == bc)
        break;
405

John Koleszar's avatar
John Koleszar committed
406 407
      tr = br;
      tc = bc;
408
    }
John Koleszar's avatar
John Koleszar committed
409 410 411 412
  }
  if (x->e_mbd.allow_high_precision_mv) {
    bestmv->as_mv.row = br;
    bestmv->as_mv.col = bc;
413
  } else {
John Koleszar's avatar
John Koleszar committed
414 415 416
    bestmv->as_mv.row = br << 1;
    bestmv->as_mv.col = bc << 1;
  }
John Koleszar's avatar
John Koleszar committed
417

John Koleszar's avatar
John Koleszar committed
418 419 420
  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
421

John Koleszar's avatar
John Koleszar committed
422
  return besterr;
John Koleszar's avatar
John Koleszar committed
423 424 425 426 427
}
#undef MVC
#undef PRE
#undef SP
#undef DIST
428
#undef IFMVCV
John Koleszar's avatar
John Koleszar committed
429 430 431 432
#undef ERR
#undef CHECK_BETTER
#undef MIN
#undef MAX
433

434 435 436 437 438
#undef PREHP
#undef DPHP
#undef DISTHP
#undef ERRHP

439
#define SP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc
Scott LaVarnway's avatar
Scott LaVarnway committed
440 441 442 443 444
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
445 446 447 448 449 450 451 452 453 454 455 456 457
                                 unsigned int *sse1) {
  int bestmse = INT_MAX;
  int_mv startmv;
  int_mv this_mv;
  int_mv orig_mv;
  int yrow_movedback = 0, ycol_movedback = 0;
  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;
458 459

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

John Koleszar's avatar
John Koleszar committed
463 464 465 466
  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;
467
#else
John Koleszar's avatar
John Koleszar committed
468 469
  unsigned char *y = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
  y_stride = d->pre_stride;
470
#endif
John Koleszar's avatar
John Koleszar committed
471

John Koleszar's avatar
John Koleszar committed
472 473 474 475 476
  // central mv
  bestmv->as_mv.row <<= 3;
  bestmv->as_mv.col <<= 3;
  startmv = *bestmv;
  orig_mv = *bestmv;
John Koleszar's avatar
John Koleszar committed
477

John Koleszar's avatar
John Koleszar committed
478 479 480
  // calculate central point error
  bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
  *distortion = bestmse;
481 482
  bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit,
                         xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
483

John Koleszar's avatar
John Koleszar committed
484 485 486 487
  // 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);
488 489
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                               xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
490

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

John Koleszar's avatar
John Koleszar committed
498 499
  this_mv.as_mv.col += 8;
  thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
500 501
  right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                                xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
502

John Koleszar's avatar
John Koleszar committed
503 504 505 506 507 508 509 510 511 512 513
  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);
514 515
  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                             xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
516

John Koleszar's avatar
John Koleszar committed
517 518 519 520 521 522
  if (up < bestmse) {
    *bestmv = this_mv;
    bestmse = up;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
523

John Koleszar's avatar
John Koleszar committed
524 525
  this_mv.as_mv.row += 8;
  thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse);
526 527
  down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                               xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
528

John Koleszar's avatar
John Koleszar committed
529 530 531 532 533 534
  if (down < bestmse) {
    *bestmv = this_mv;
    bestmse = down;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
535 536


John Koleszar's avatar
John Koleszar committed
537 538 539 540 541
  // 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
542

John Koleszar's avatar
John Koleszar committed
543
  switch (whichdir) {
John Koleszar's avatar
John Koleszar committed
544
    case 0:
John Koleszar's avatar
John Koleszar committed
545 546 547 548
      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
549
    case 1:
John Koleszar's avatar
John Koleszar committed
550 551 552 553
      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
554
    case 2:
John Koleszar's avatar
John Koleszar committed
555 556 557 558
      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
559
    case 3:
560
    default:
John Koleszar's avatar
John Koleszar committed
561 562 563 564 565
      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
566

567 568
  diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                               xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
569

John Koleszar's avatar
John Koleszar committed
570 571 572 573 574 575
  if (diag < bestmse) {
    *bestmv = this_mv;
    bestmse = diag;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
576 577 578 579

//  }


John Koleszar's avatar
John Koleszar committed
580 581 582 583 584
  // time to check quarter pels.
  if (bestmv->as_mv.row < startmv.as_mv.row) {
    y -= y_stride;
    yrow_movedback = 1;
  }
John Koleszar's avatar
John Koleszar committed
585

John Koleszar's avatar
John Koleszar committed
586 587 588 589
  if (bestmv->as_mv.col < startmv.as_mv.col) {
    y--;
    ycol_movedback = 1;
  }
John Koleszar's avatar
John Koleszar committed
590

John Koleszar's avatar
John Koleszar committed
591
  startmv = *bestmv;
John Koleszar's avatar
John Koleszar committed
592 593 594



John Koleszar's avatar
John Koleszar committed
595 596
  // go left then right and check error
  this_mv.as_mv.row = startmv.as_mv.row;
John Koleszar's avatar
John Koleszar committed
597

John Koleszar's avatar
John Koleszar committed
598 599
  if (startmv.as_mv.col & 7) {
    this_mv.as_mv.col = startmv.as_mv.col - 2;
600 601 602
    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
603 604
  } else {
    this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
605 606
    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
607
  }
John Koleszar's avatar
John Koleszar committed
608

609 610
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                               xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
611

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

John Koleszar's avatar
John Koleszar committed
619
  this_mv.as_mv.col += 4;
620 621 622 623 624
  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);
John Koleszar's avatar
John Koleszar committed
625

John Koleszar's avatar
John Koleszar committed
626 627 628 629 630 631
  if (right < bestmse) {
    *bestmv = this_mv;
    bestmse = right;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
632

John Koleszar's avatar
John Koleszar committed
633 634
  // go up then down and check error
  this_mv.as_mv.col = startmv.as_mv.col;
John Koleszar's avatar
John Koleszar committed
635

John Koleszar's avatar
John Koleszar committed
636 637
  if (startmv.as_mv.row & 7) {
    this_mv.as_mv.row = startmv.as_mv.row - 2;
638 639 640
    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
641 642
  } else {
    this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
643 644
    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
645
  }
John Koleszar's avatar
John Koleszar committed
646

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

John Koleszar's avatar
John Koleszar committed
650 651 652 653 654 655
  if (up < bestmse) {
    *bestmv = this_mv;
    bestmse = up;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
656

John Koleszar's avatar
John Koleszar committed
657
  this_mv.as_mv.row += 4;
658 659 660 661
  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);
John Koleszar's avatar
John Koleszar committed
662

John Koleszar's avatar
John Koleszar committed
663 664 665 666 667 668
  if (down < bestmse) {
    *bestmv = this_mv;
    bestmse = down;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
669 670


John Koleszar's avatar
John Koleszar committed
671 672
  // now check 1 more diagonal
  whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
John Koleszar's avatar
John Koleszar committed
673 674 675

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

John Koleszar's avatar
John Koleszar committed
678
  switch (whichdir) {
John Koleszar's avatar
John Koleszar committed
679 680
    case 0:

John Koleszar's avatar
John Koleszar committed
681 682
      if (startmv.as_mv.row & 7) {
        this_mv.as_mv.row -= 2;
John Koleszar's avatar
John Koleszar committed
683

John Koleszar's avatar
John Koleszar committed
684 685 686 687 688 689
        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
690
        }
John Koleszar's avatar
John Koleszar committed
691 692 693 694 695 696 697 698 699
      } 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
700
        }
John Koleszar's avatar
John Koleszar committed
701
      }
John Koleszar's avatar
John Koleszar committed
702

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

John Koleszar's avatar
John Koleszar committed
707 708 709 710 711 712 713
      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
714

John Koleszar's avatar
John Koleszar committed
715
      break;
John Koleszar's avatar
John Koleszar committed
716
    case 2:
John Koleszar's avatar
John Koleszar committed
717
      this_mv.as_mv.row += 2;
John Koleszar's avatar
John Koleszar committed
718

John Koleszar's avatar
John Koleszar committed
719 720
      if (startmv.as_mv.col & 7) {
        this_mv.as_mv.col -= 2;
721 722
        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
723 724
      } else {
        this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
725 726
        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
727
      }
John Koleszar's avatar
John Koleszar committed
728

John Koleszar's avatar
John Koleszar committed
729
      break;
John Koleszar's avatar
John Koleszar committed
730
    case 3:
John Koleszar's avatar
John Koleszar committed
731 732
      this_mv.as_mv.col += 2;
      this_mv.as_mv.row += 2;
733 734 735
      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
736 737
      break;
  }
John Koleszar's avatar
John Koleszar committed
738

739 740
  diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                               xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
741

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

John Koleszar's avatar
John Koleszar committed
749 750
  if (!x->e_mbd.allow_high_precision_mv)
    return bestmse;
751

John Koleszar's avatar
John Koleszar committed
752 753 754 755 756
  /* Now do 1/8th pixel */
  if (bestmv->as_mv.row < orig_mv.as_mv.row && !yrow_movedback) {
    y -= y_stride;
    yrow_movedback = 1;
  }
757

John Koleszar's avatar
John Koleszar committed
758 759 760 761
  if (bestmv->as_mv.col < orig_mv.as_mv.col && !ycol_movedback) {
    y--;
    ycol_movedback = 1;
  }
762

John Koleszar's avatar
John Koleszar committed
763
  startmv = *bestmv;
764

John Koleszar's avatar
John Koleszar committed
765 766
  // go left then right and check error
  this_mv.as_mv.row = startmv.as_mv.row;
767

John Koleszar's avatar
John Koleszar committed
768 769
  if (startmv.as_mv.col & 7) {
    this_mv.as_mv.col = startmv.as_mv.col - 1;
770 771 772
    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
773 774
  } else {
    this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
775 776
    thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row),
                       z, b->src_stride, &sse);
John Koleszar's avatar
John Koleszar committed
777 778
  }

779 780
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                               xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
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

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

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

John Koleszar's avatar
John Koleszar committed
813 814 815 816 817 818
  if (up < bestmse) {
    *bestmv = this_mv;
    bestmse = up;
    *distortion = thismse;
    *sse1 = sse;
  }
819

John Koleszar's avatar
John Koleszar committed
820 821 822
  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);
823

John Koleszar's avatar
John Koleszar committed
824 825 826 827 828 829
  if (down < bestmse) {
    *bestmv = this_mv;
    bestmse = down;
    *distortion = thismse;
    *sse1 = sse;
  }
830

John Koleszar's avatar
John Koleszar committed
831 832
  // now check 1 more diagonal
  whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
833 834 835

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

John Koleszar's avatar
John Koleszar committed
838
  switch (whichdir) {
839 840
    case 0:

John Koleszar's avatar
John Koleszar committed
841 842
      if (startmv.as_mv.row & 7) {
        this_mv.as_mv.row -= 1;
843

John Koleszar's avatar
John Koleszar committed
844 845 846 847 848 849
        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);;
850
        }
John Koleszar's avatar
John Koleszar committed
851 852 853 854 855 856 857 858 859
      } 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);
860
        }
John Koleszar's avatar
John Koleszar committed
861
      }
862

John Koleszar's avatar
John Koleszar committed
863
      break;
864
    case 1:
John Koleszar's avatar
John Koleszar committed
865
      this_mv.as_mv.col += 1;
866

John Koleszar's avatar
John Koleszar committed
867 868 869 870 871 872 873
      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);
      }
874

John Koleszar's avatar
John Koleszar committed
875
      break;
876
    case 2:
John Koleszar's avatar
John Koleszar committed
877
      this_mv.as_mv.row += 1;
878

John Koleszar's avatar
John Koleszar committed
879 880 881 882 883 884 885
      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);
      }
886

John Koleszar's avatar
John Koleszar committed
887
      break;
888
    case 3:
John Koleszar's avatar
John Koleszar committed
889 890 891 892 893
      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;
  }
894

John Koleszar's avatar
John Koleszar committed
895
  diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
896

John Koleszar's avatar
John Koleszar committed
897 898 899 900 901 902
  if (diag < bestmse) {
    *bestmv = this_mv;
    bestmse = diag;
    *distortion = thismse;
    *sse1 = sse;
  }
903

John Koleszar's avatar
John Koleszar committed
904
  return bestmse;
John Koleszar's avatar
John Koleszar committed
905 906
}

907 908
#undef SP

909
int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
Scott LaVarnway's avatar
Scott LaVarnway committed
910 911 912 913
                                  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
914 915 916 917 918 919 920 921 922 923 924
                                  unsigned int *sse1) {
  int bestmse = INT_MAX;
  int_mv startmv;
  int_mv this_mv;
  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;
925 926

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

John Koleszar's avatar
John Koleszar committed
931 932 933 934
  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;
935
#else
936 937
  unsigned char *y = *(d->base_pre) + d->pre +
      (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
John Koleszar's avatar
John Koleszar committed
938
  y_stride = d->pre_stride;
939
#endif
John Koleszar's avatar
John Koleszar committed
940

John Koleszar's avatar
John Koleszar committed
941 942 943 944
  // central mv
  bestmv->as_mv.row <<= 3;
  bestmv->as_mv.col <<= 3;
  startmv = *bestmv;
John Koleszar's avatar
John Koleszar committed
945

John Koleszar's avatar
John Koleszar committed
946 947 948
  // calculate central point error
  bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
  *distortion = bestmse;
949 950
  bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit,
                         xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
951

John Koleszar's avatar
John Koleszar committed
952 953 954 955
  // 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);
956 957
  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                               xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
958

John Koleszar's avatar
John Koleszar committed
959 960 961 962 963 964
  if (left < bestmse) {
    *bestmv = this_mv;
    bestmse = left;
    *distortion = thismse;
    *sse1 = sse;
  }
John Koleszar's avatar
John Koleszar committed
965

John Koleszar's avatar
John Koleszar committed
966 967
  this_mv.as_mv.col += 8;
  thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
968 969
  right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                                xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
970

John Koleszar's avatar
John Koleszar committed
971 972 973 974 975 976 977 978 979 980 981
  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);
982 983
  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit,
                             xd->allow_hig