1824 lines · 56.7 KB · C
RawDownload
/* *  Copyright (c) 2010 The WebM project authors. All Rights Reserved. * *  Use of this source code is governed by a BSD-style license *  that can be found in the LICENSE file in the root of the source *  tree. An additional intellectual property rights grant can be found *  in the file PATENTS.  All contributing project authors may *  be found in the AUTHORS file in the root of the source tree. */ #include "./vp8_rtcd.h"#include "./vpx_dsp_rtcd.h"#include "onyx_int.h"#include "mcomp.h"#include "vpx_mem/vpx_mem.h"#include "vpx_config.h"#include <stdio.h>#include <limits.h>#include <math.h>#include "vp8/common/findnearmv.h"#include "vp8/common/common.h"#include "vpx_dsp/vpx_dsp_common.h" 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.   */  const int mv_idx_row =      clamp((mv->as_mv.row - ref->as_mv.row) >> 1, 0, MVvals);  const int mv_idx_col =      clamp((mv->as_mv.col - ref->as_mv.col) >> 1, 0, MVvals);  return ((mvcost[0][mv_idx_row] + mvcost[1][mv_idx_col]) * Weight) >> 7;} static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2],                       int error_per_bit) {  /* Ignore mv costing if mvcost is NULL */  if (mvcost) {    const int mv_idx_row =        clamp((mv->as_mv.row - ref->as_mv.row) >> 1, 0, MVvals);    const int mv_idx_col =        clamp((mv->as_mv.col - ref->as_mv.col) >> 1, 0, MVvals);    return ((mvcost[0][mv_idx_row] + mvcost[1][mv_idx_col]) * error_per_bit +            128) >>           8;  }  return 0;} 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 mv costing if mvsadcost 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;} void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride) {  int Len;  int search_site_count = 0;   /* Generate offsets for 4 search sites per step. */  Len = MAX_FIRST_STEP;  x->ss[search_site_count].mv.col = 0;  x->ss[search_site_count].mv.row = 0;  x->ss[search_site_count].offset = 0;  search_site_count++;   while (Len > 0) {    /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = 0;    x->ss[search_site_count].mv.row = -Len;    x->ss[search_site_count].offset = -Len * stride;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = 0;    x->ss[search_site_count].mv.row = Len;    x->ss[search_site_count].offset = Len * stride;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = -Len;    x->ss[search_site_count].mv.row = 0;    x->ss[search_site_count].offset = -Len;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = Len;    x->ss[search_site_count].mv.row = 0;    x->ss[search_site_count].offset = Len;    search_site_count++;     /* Contract. */    Len /= 2;  }   x->ss_count = search_site_count;  x->searches_per_step = 4;} void vp8_init3smotion_compensation(MACROBLOCK *x, int stride) {  int Len;  int search_site_count = 0;   /* Generate offsets for 8 search sites per step. */  Len = MAX_FIRST_STEP;  x->ss[search_site_count].mv.col = 0;  x->ss[search_site_count].mv.row = 0;  x->ss[search_site_count].offset = 0;  search_site_count++;   while (Len > 0) {    /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = 0;    x->ss[search_site_count].mv.row = -Len;    x->ss[search_site_count].offset = -Len * stride;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = 0;    x->ss[search_site_count].mv.row = Len;    x->ss[search_site_count].offset = Len * stride;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = -Len;    x->ss[search_site_count].mv.row = 0;    x->ss[search_site_count].offset = -Len;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = Len;    x->ss[search_site_count].mv.row = 0;    x->ss[search_site_count].offset = Len;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = -Len;    x->ss[search_site_count].mv.row = -Len;    x->ss[search_site_count].offset = -Len * stride - Len;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = Len;    x->ss[search_site_count].mv.row = -Len;    x->ss[search_site_count].offset = -Len * stride + Len;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = -Len;    x->ss[search_site_count].mv.row = Len;    x->ss[search_site_count].offset = Len * stride - Len;    search_site_count++;     /* Compute offsets for search sites. */    x->ss[search_site_count].mv.col = Len;    x->ss[search_site_count].mv.row = Len;    x->ss[search_site_count].offset = Len * stride + Len;    search_site_count++;     /* Contract. */    Len /= 2;  }   x->ss_count = search_site_count;  x->searches_per_step = 8;} /* * 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. */ /* estimated cost of a motion vector (r,c) */#define MVC(r, c)                                                             \  (mvcost                                                                     \       ? ((mvcost[0][(r)-rr] + mvcost[1][(c)-rc]) * error_per_bit + 128) >> 8 \       : 0)/* pointer to predictor base of a motionvector */#define PRE(r, c) (y + (((r) >> 2) * y_stride + ((c) >> 2) - (offset)))/* convert motion vector component to offset for svf calc */#define SP(x) (((x)&3) << 1)/* returns subpixel variance error function. */#define DIST(r, c) \  vfp->svf(PRE(r, c), y_stride, SP(c), SP(r), z, b->src_stride, &sse)#define IFMVCV(r, c, s, e) \  if (c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;/* returns distortion + motion vector cost */#define ERR(r, c) (MVC(r, c) + DIST(r, c))/* checks if (r,c) has better score than previous best */#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 = UINT_MAX;) int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,                                             int_mv *bestmv, int_mv *ref_mv,                                             int error_per_bit,                                             const vp8_variance_fn_ptr_t *vfp,                                             int *mvcost[2], int *distortion,                                             unsigned int *sse1) {  unsigned char *z = (*(b->base_src) + b->src);   int rr = ref_mv->as_mv.row >> 1, rc = ref_mv->as_mv.col >> 1;  int br = bestmv->as_mv.row * 4, bc = bestmv->as_mv.col * 4;  int tr = br, tc = bc;  unsigned int besterr;  unsigned int left, right, up, down, diag;  unsigned int sse;  unsigned int whichdir;  unsigned int halfiters = 4;  unsigned int quarteriters = 4;  int thismse;   int minc = VPXMAX(x->mv_col_min * 4,                    (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1));  int maxc = VPXMIN(x->mv_col_max * 4,                    (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1));  int minr = VPXMAX(x->mv_row_min * 4,                    (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1));  int maxr = VPXMIN(x->mv_row_max * 4,                    (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1));   int y_stride;  int offset;  int pre_stride = x->e_mbd.pre.y_stride;  unsigned char *base_pre = x->e_mbd.pre.y_buffer; #if VPX_ARCH_X86 || VPX_ARCH_X86_64  MACROBLOCKD *xd = &x->e_mbd;  unsigned char *y_0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +                       bestmv->as_mv.col;  unsigned char *y;  int buf_r1, buf_r2, buf_c1;   /* Clamping to avoid out-of-range data access */  buf_r1 = ((bestmv->as_mv.row - 3) < x->mv_row_min)               ? (bestmv->as_mv.row - x->mv_row_min)               : 3;  buf_r2 = ((bestmv->as_mv.row + 3) > x->mv_row_max)               ? (x->mv_row_max - bestmv->as_mv.row)               : 3;  buf_c1 = ((bestmv->as_mv.col - 3) < x->mv_col_min)               ? (bestmv->as_mv.col - x->mv_col_min)               : 3;  y_stride = 32;   /* Copy to intermediate buffer before searching. */  vfp->copymem(y_0 - buf_c1 - pre_stride * buf_r1, pre_stride, xd->y_buf,               y_stride, 16 + buf_r1 + buf_r2);  y = xd->y_buf + y_stride * buf_r1 + buf_c1;#else  unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +                     bestmv->as_mv.col;  y_stride = pre_stride;#endif   offset = (bestmv->as_mv.row) * y_stride + bestmv->as_mv.col;   /* central mv */  bestmv->as_mv.row *= 8;  bestmv->as_mv.col *= 8;   /* calculate central point error */  besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1);  *distortion = besterr;  besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);   /* TODO: Each subsequent iteration checks at least one point in common   * with the last iteration could be 2 ( if diag selected)   */  while (--halfiters) {    /* 1/2 pel */    CHECK_BETTER(left, tr, tc - 2);    CHECK_BETTER(right, tr, tc + 2);    CHECK_BETTER(up, tr - 2, tc);    CHECK_BETTER(down, tr + 2, tc);     whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);     switch (whichdir) {      case 0: CHECK_BETTER(diag, tr - 2, tc - 2); break;      case 1: CHECK_BETTER(diag, tr - 2, tc + 2); break;      case 2: CHECK_BETTER(diag, tr + 2, tc - 2); break;      case 3: CHECK_BETTER(diag, tr + 2, tc + 2); break;    }     /* no reason to check the same one again. */    if (tr == br && tc == bc) break;     tr = br;    tc = bc;  }   /* TODO: Each subsequent iteration checks at least one point in common   * with the last iteration could be 2 ( if diag selected)   */   /* 1/4 pel */  while (--quarteriters) {    CHECK_BETTER(left, tr, tc - 1);    CHECK_BETTER(right, tr, tc + 1);    CHECK_BETTER(up, tr - 1, tc);    CHECK_BETTER(down, tr + 1, tc);     whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);     switch (whichdir) {      case 0: CHECK_BETTER(diag, tr - 1, tc - 1); break;      case 1: CHECK_BETTER(diag, tr - 1, tc + 1); break;      case 2: CHECK_BETTER(diag, tr + 1, tc - 1); break;      case 3: CHECK_BETTER(diag, tr + 1, tc + 1); break;    }     /* no reason to check the same one again. */    if (tr == br && tc == bc) break;     tr = br;    tc = bc;  }   bestmv->as_mv.row = br * 2;  bestmv->as_mv.col = bc * 2;   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;  }   return besterr;}#undef MVC#undef PRE#undef SP#undef DIST#undef IFMVCV#undef ERR#undef CHECK_BETTER int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,                                 int_mv *bestmv, int_mv *ref_mv,                                 int error_per_bit,                                 const vp8_variance_fn_ptr_t *vfp,                                 int *mvcost[2], int *distortion,                                 unsigned int *sse1) {  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;  int pre_stride = x->e_mbd.pre.y_stride;  unsigned char *base_pre = x->e_mbd.pre.y_buffer; #if VPX_ARCH_X86 || VPX_ARCH_X86_64  MACROBLOCKD *xd = &x->e_mbd;  unsigned char *y_0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +                       bestmv->as_mv.col;  unsigned char *y;   y_stride = 32;  /* Copy 18 rows x 32 cols area to intermediate buffer before searching. */  vfp->copymem(y_0 - 1 - pre_stride, pre_stride, xd->y_buf, y_stride, 18);  y = xd->y_buf + y_stride + 1;#else  unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +                     bestmv->as_mv.col;  y_stride = pre_stride;#endif   /* central mv */  bestmv->as_mv.row *= 8;  bestmv->as_mv.col *= 8;  startmv = *bestmv;   /* calculate central point error */  bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);  *distortion = bestmse;  bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);   /* 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);  /* "halfpix" horizontal variance */  thismse = vfp->svf(y - 1, y_stride, 4, 0, z, b->src_stride, &sse);  left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);   if (left < bestmse) {    *bestmv = this_mv;    bestmse = left;    *distortion = thismse;    *sse1 = sse;  }   this_mv.as_mv.col += 8;  /* "halfpix" horizontal variance */  thismse = vfp->svf(y, y_stride, 4, 0, z, b->src_stride, &sse);  right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);   if (right < bestmse) {    *bestmv = this_mv;    bestmse = right;    *distortion = thismse;    *sse1 = sse;  }   /* go up then down and check error */  this_mv.as_mv.col = startmv.as_mv.col;  this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);  /* "halfpix" vertical variance */  thismse = vfp->svf(y - y_stride, y_stride, 0, 4, z, b->src_stride, &sse);  up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);   if (up < bestmse) {    *bestmv = this_mv;    bestmse = up;    *distortion = thismse;    *sse1 = sse;  }   this_mv.as_mv.row += 8;  /* "halfpix" vertical variance */  thismse = vfp->svf(y, y_stride, 0, 4, z, b->src_stride, &sse);  down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);   if (down < bestmse) {    *bestmv = this_mv;    bestmse = down;    *distortion = thismse;    *sse1 = sse;  }   /* now check 1 more diagonal */  whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);  this_mv = startmv;   switch (whichdir) {    case 0:      this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;      this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;      /* "halfpix" horizontal/vertical variance */      thismse =          vfp->svf(y - 1 - y_stride, y_stride, 4, 4, z, b->src_stride, &sse);      break;    case 1:      this_mv.as_mv.col += 4;      this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;      /* "halfpix" horizontal/vertical variance */      thismse = vfp->svf(y - y_stride, y_stride, 4, 4, z, b->src_stride, &sse);      break;    case 2:      this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;      this_mv.as_mv.row += 4;      /* "halfpix" horizontal/vertical variance */      thismse = vfp->svf(y - 1, y_stride, 4, 4, z, b->src_stride, &sse);      break;    case 3:    default:      this_mv.as_mv.col += 4;      this_mv.as_mv.row += 4;      /* "halfpix" horizontal/vertical variance */      thismse = vfp->svf(y, y_stride, 4, 4, z, b->src_stride, &sse);      break;  }   diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);   if (diag < bestmse) {    *bestmv = this_mv;    bestmse = diag;    *distortion = thismse;    *sse1 = sse;

Lines 1–500 of 1824.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t