vp9_mbgraph.c 14.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 *  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 <limits.h>
12 13 14 15 16 17
#include <vp9/encoder/vp9_encodeintra.h>
#include <vp9/encoder/vp9_rdopt.h>
#include <vp9/common/vp9_setupintrarecon.h>
#include <vp9/common/vp9_blockd.h>
#include <vp9/common/vp9_reconinter.h>
#include <vp9/common/vp9_systemdependent.h>
18
#include <vpx_mem/vpx_mem.h>
19
#include <vp9/encoder/vp9_segmentation.h>
20

21 22 23
static unsigned int do_16x16_motion_iteration(VP9_COMP *cpi,
                                              int_mv *ref_mv,
                                              int_mv *dst_mv) {
John Koleszar's avatar
John Koleszar committed
24 25 26 27
  MACROBLOCK   *const x  = &cpi->mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  BLOCK *b  = &x->block[0];
  BLOCKD *d = &xd->block[0];
28
  vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[BLOCK_16X16];
John Koleszar's avatar
John Koleszar committed
29 30
  unsigned int best_err;
  int step_param, further_steps;
31

John Koleszar's avatar
John Koleszar committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
  int tmp_col_min = x->mv_col_min;
  int tmp_col_max = x->mv_col_max;
  int tmp_row_min = x->mv_row_min;
  int tmp_row_max = x->mv_row_max;
  int_mv ref_full;

  // Further step/diamond searches as necessary
  if (cpi->Speed < 8) {
    step_param = cpi->sf.first_step + ((cpi->Speed > 5) ? 1 : 0);
    further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
  } else {
    step_param = cpi->sf.first_step + 2;
    further_steps = 0;
  }

47
  vp9_clamp_mv_min_max(x, ref_mv);
John Koleszar's avatar
John Koleszar committed
48 49 50 51 52

  ref_full.as_mv.col = ref_mv->as_mv.col >> 3;
  ref_full.as_mv.row = ref_mv->as_mv.row >> 3;

  /*cpi->sf.search_method == HEX*/
53
  best_err = vp9_hex_search(
54 55 56 57 58
      x, b, d,
      &ref_full, dst_mv,
      step_param,
      x->errorperbit,
      &v_fn_ptr,
59 60
      NULL, NULL,
      NULL, NULL,
61
      ref_mv);
John Koleszar's avatar
John Koleszar committed
62 63 64 65 66 67

  // Try sub-pixel MC
  // if (bestsme > error_thresh && bestsme < INT_MAX)
  {
    int distortion;
    unsigned int sse;
68 69 70 71
    best_err = cpi->find_fractional_mv_step(
        x, b, d,
        dst_mv, ref_mv,
        x->errorperbit, &v_fn_ptr,
72
        NULL, NULL,
73
        & distortion, &sse);
John Koleszar's avatar
John Koleszar committed
74
  }
75

76
#if CONFIG_PRED_FILTER
John Koleszar's avatar
John Koleszar committed
77 78
  // Disable the prediction filter
  xd->mode_info_context->mbmi.pred_filter_enabled = 0;
79 80
#endif

81
  vp9_set_mbmode_and_mvs(x, NEWMV, dst_mv);
82
  vp9_build_1st_inter16x16_predictors_mby(xd, xd->predictor, 16, 0);
83
  best_err = vp9_sad16x16(xd->dst.y_buffer, xd->dst.y_stride,
84
                          xd->predictor, 16, INT_MAX);
85

John Koleszar's avatar
John Koleszar committed
86 87 88 89 90
  /* restore UMV window */
  x->mv_col_min = tmp_col_min;
  x->mv_col_max = tmp_col_max;
  x->mv_row_min = tmp_row_min;
  x->mv_row_max = tmp_row_max;
91

John Koleszar's avatar
John Koleszar committed
92
  return best_err;
93 94 95 96
}

static int do_16x16_motion_search
(
97
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
  int_mv *ref_mv,
  int_mv *dst_mv,
  YV12_BUFFER_CONFIG *buf,
  int buf_mb_y_offset,
  YV12_BUFFER_CONFIG *ref,
  int mb_y_offset
) {
  MACROBLOCK   *const x  = &cpi->mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  unsigned int err, tmp_err;
  int_mv tmp_mv;
  int n;

  for (n = 0; n < 16; n++) {
    BLOCKD *d = &xd->block[n];
    BLOCK *b  = &x->block[n];

    b->base_src   = &buf->y_buffer;
    b->src_stride = buf->y_stride;
    b->src        = buf->y_stride * (n & 12) + (n & 3) * 4 + buf_mb_y_offset;

    d->base_pre   = &ref->y_buffer;
    d->pre_stride = ref->y_stride;
    d->pre        = ref->y_stride * (n & 12) + (n & 3) * 4 + mb_y_offset;
  }

  // Try zero MV first
  // FIXME should really use something like near/nearest MV and/or MV prediction
  xd->pre.y_buffer = ref->y_buffer + mb_y_offset;
  xd->pre.y_stride = ref->y_stride;
128
  err = vp9_sad16x16(ref->y_buffer + mb_y_offset, ref->y_stride,
129
                     xd->dst.y_buffer, xd->dst.y_stride, INT_MAX);
John Koleszar's avatar
John Koleszar committed
130 131 132 133 134 135 136 137 138 139 140 141
  dst_mv->as_int = 0;

  // Test last reference frame using the previous best mv as the
  // starting point (best reference) for the search
  tmp_err = do_16x16_motion_iteration(cpi, ref_mv, &tmp_mv);
  if (tmp_err < err) {
    err            = tmp_err;
    dst_mv->as_int = tmp_mv.as_int;
  }

  // If the current best reference mv is not centred on 0,0 then do a 0,0 based search as well
  if (ref_mv->as_int) {
142
    unsigned int tmp_err;
John Koleszar's avatar
John Koleszar committed
143 144 145 146 147 148 149
    int_mv zero_ref_mv, tmp_mv;

    zero_ref_mv.as_int = 0;
    tmp_err = do_16x16_motion_iteration(cpi, &zero_ref_mv, &tmp_mv);
    if (tmp_err < err) {
      dst_mv->as_int = tmp_mv.as_int;
      err = tmp_err;
150
    }
John Koleszar's avatar
John Koleszar committed
151
  }
152

John Koleszar's avatar
John Koleszar committed
153
  return err;
154 155
}

Paul Wilkins's avatar
Paul Wilkins committed
156 157
static int do_16x16_zerozero_search
(
158
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
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
  int_mv *dst_mv,
  YV12_BUFFER_CONFIG *buf,
  int buf_mb_y_offset,
  YV12_BUFFER_CONFIG *ref,
  int mb_y_offset
) {
  MACROBLOCK   *const x  = &cpi->mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  unsigned int err;
  int n;

  for (n = 0; n < 16; n++) {
    BLOCKD *d = &xd->block[n];
    BLOCK *b  = &x->block[n];

    b->base_src   = &buf->y_buffer;
    b->src_stride = buf->y_stride;
    b->src        = buf->y_stride * (n & 12) + (n & 3) * 4 + buf_mb_y_offset;

    d->base_pre   = &ref->y_buffer;
    d->pre_stride = ref->y_stride;
    d->pre        = ref->y_stride * (n & 12) + (n & 3) * 4 + mb_y_offset;
  }

  // Try zero MV first
  // FIXME should really use something like near/nearest MV and/or MV prediction
  xd->pre.y_buffer = ref->y_buffer + mb_y_offset;
  xd->pre.y_stride = ref->y_stride;
187
  err = vp9_sad16x16(ref->y_buffer + mb_y_offset, ref->y_stride,
188
                     xd->dst.y_buffer, xd->dst.y_stride, INT_MAX);
John Koleszar's avatar
John Koleszar committed
189 190 191 192

  dst_mv->as_int = 0;

  return err;
Paul Wilkins's avatar
Paul Wilkins committed
193
}
194 195
static int find_best_16x16_intra
(
196
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
197 198 199 200 201 202 203
  YV12_BUFFER_CONFIG *buf,
  int mb_y_offset,
  MB_PREDICTION_MODE *pbest_mode
) {
  MACROBLOCK   *const x  = &cpi->mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  MB_PREDICTION_MODE best_mode = -1, mode;
204
  unsigned int best_err = INT_MAX;
John Koleszar's avatar
John Koleszar committed
205 206 207 208 209 210 211

  // calculate SATD for each intra prediction mode;
  // we're intentionally not doing 4x4, we just want a rough estimate
  for (mode = DC_PRED; mode <= TM_PRED; mode++) {
    unsigned int err;

    xd->mode_info_context->mbmi.mode = mode;
212
    vp9_build_intra_predictors_mby(xd);
213
    err = vp9_sad16x16(xd->predictor, 16, buf->y_buffer + mb_y_offset,
214
                       buf->y_stride, best_err);
John Koleszar's avatar
John Koleszar committed
215 216 217 218
    // find best
    if (err < best_err) {
      best_err  = err;
      best_mode = mode;
219
    }
John Koleszar's avatar
John Koleszar committed
220
  }
221

John Koleszar's avatar
John Koleszar committed
222 223
  if (pbest_mode)
    *pbest_mode = best_mode;
224

John Koleszar's avatar
John Koleszar committed
225
  return best_err;
226 227 228 229
}

static void update_mbgraph_mb_stats
(
230
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
  MBGRAPH_MB_STATS *stats,
  YV12_BUFFER_CONFIG *buf,
  int mb_y_offset,
  YV12_BUFFER_CONFIG *golden_ref,
  int_mv *prev_golden_ref_mv,
  int gld_y_offset,
  YV12_BUFFER_CONFIG *alt_ref,
  int_mv *prev_alt_ref_mv,
  int arf_y_offset
) {
  MACROBLOCK   *const x  = &cpi->mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  int intra_error;

  // FIXME in practice we're completely ignoring chroma here
  xd->dst.y_buffer = buf->y_buffer + mb_y_offset;

  // do intra 16x16 prediction
  intra_error = find_best_16x16_intra(cpi, buf, mb_y_offset, &stats->ref[INTRA_FRAME].m.mode);
  if (intra_error <= 0)
    intra_error = 1;
  stats->ref[INTRA_FRAME].err = intra_error;

  // Golden frame MV search, if it exists and is different than last frame
  if (golden_ref) {
    int g_motion_error = do_16x16_motion_search(cpi, prev_golden_ref_mv,
                                                &stats->ref[GOLDEN_FRAME].m.mv,
                                                buf, mb_y_offset,
                                                golden_ref, gld_y_offset);
    stats->ref[GOLDEN_FRAME].err = g_motion_error;
  } else {
    stats->ref[GOLDEN_FRAME].err = INT_MAX;
    stats->ref[GOLDEN_FRAME].m.mv.as_int = 0;
  }

  // Alt-ref frame MV search, if it exists and is different than last/golden frame
  if (alt_ref) {
    // int a_motion_error = do_16x16_motion_search(cpi, prev_alt_ref_mv,
    //                                            &stats->ref[ALTREF_FRAME].m.mv,
    //                                            buf, mb_y_offset,
    //                                            alt_ref, arf_y_offset);

    int a_motion_error =
      do_16x16_zerozero_search(cpi,
                               &stats->ref[ALTREF_FRAME].m.mv,
                               buf, mb_y_offset,
                               alt_ref, arf_y_offset);

    stats->ref[ALTREF_FRAME].err = a_motion_error;
  } else {
    stats->ref[ALTREF_FRAME].err = INT_MAX;
    stats->ref[ALTREF_FRAME].m.mv.as_int = 0;
  }
284 285 286 287
}

static void update_mbgraph_frame_stats
(
288
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
289 290 291 292 293 294
  MBGRAPH_FRAME_STATS *stats,
  YV12_BUFFER_CONFIG *buf,
  YV12_BUFFER_CONFIG *golden_ref,
  YV12_BUFFER_CONFIG *alt_ref
) {
  MACROBLOCK   *const x  = &cpi->mb;
295
  VP9_COMMON   *const cm = &cpi->common;
John Koleszar's avatar
John Koleszar committed
296 297 298 299 300 301 302 303 304
  MACROBLOCKD *const xd = &x->e_mbd;
  int mb_col, mb_row, offset = 0;
  int mb_y_offset = 0, arf_y_offset = 0, gld_y_offset = 0;
  int_mv arf_top_mv, gld_top_mv;
  MODE_INFO mi_local;

  // Set up limit values for motion vectors to prevent them extending outside the UMV borders
  arf_top_mv.as_int = 0;
  gld_top_mv.as_int = 0;
John Koleszar's avatar
John Koleszar committed
305 306 307
  x->mv_row_min     = -(VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND);
  x->mv_row_max     = (cm->mb_rows - 1) * 16 + VP9BORDERINPIXELS
                      - 16 - VP9_INTERP_EXTEND;
John Koleszar's avatar
John Koleszar committed
308 309 310 311 312 313 314 315 316 317 318
  xd->up_available  = 0;
  xd->dst.y_stride  = buf->y_stride;
  xd->pre.y_stride  = buf->y_stride;
  xd->dst.uv_stride = buf->uv_stride;
  xd->mode_info_context = &mi_local;

  for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
    int_mv arf_left_mv, gld_left_mv;
    int mb_y_in_offset  = mb_y_offset;
    int arf_y_in_offset = arf_y_offset;
    int gld_y_in_offset = gld_y_offset;
319 320

    // Set up limit values for motion vectors to prevent them extending outside the UMV borders
John Koleszar's avatar
John Koleszar committed
321 322
    arf_left_mv.as_int = arf_top_mv.as_int;
    gld_left_mv.as_int = gld_top_mv.as_int;
John Koleszar's avatar
John Koleszar committed
323 324 325
    x->mv_col_min      = -(VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND);
    x->mv_col_max      = (cm->mb_cols - 1) * 16 + VP9BORDERINPIXELS
                         - 16 - VP9_INTERP_EXTEND;
John Koleszar's avatar
John Koleszar committed
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    xd->left_available = 0;

    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
      MBGRAPH_MB_STATS *mb_stats = &stats->mb_stats[offset + mb_col];

      update_mbgraph_mb_stats(cpi, mb_stats, buf, mb_y_in_offset,
                              golden_ref, &gld_left_mv, gld_y_in_offset,
                              alt_ref,    &arf_left_mv, arf_y_in_offset);
      arf_left_mv.as_int = mb_stats->ref[ALTREF_FRAME].m.mv.as_int;
      gld_left_mv.as_int = mb_stats->ref[GOLDEN_FRAME].m.mv.as_int;
      if (mb_col == 0) {
        arf_top_mv.as_int = arf_left_mv.as_int;
        gld_top_mv.as_int = gld_left_mv.as_int;
      }
      xd->left_available = 1;
      mb_y_in_offset    += 16;
      gld_y_in_offset   += 16;
      arf_y_in_offset   += 16;
      x->mv_col_min     -= 16;
      x->mv_col_max     -= 16;
346
    }
John Koleszar's avatar
John Koleszar committed
347 348 349 350 351 352 353 354 355
    xd->up_available = 1;
    mb_y_offset     += buf->y_stride * 16;
    gld_y_offset    += golden_ref->y_stride * 16;
    if (alt_ref)
      arf_y_offset    += alt_ref->y_stride * 16;
    x->mv_row_min   -= 16;
    x->mv_row_max   -= 16;
    offset          += cm->mb_cols;
  }
356 357
}

John Koleszar's avatar
John Koleszar committed
358
// void separate_arf_mbs_byzz
359 360
static void separate_arf_mbs(VP9_COMP *cpi) {
  VP9_COMMON *const cm = &cpi->common;
John Koleszar's avatar
John Koleszar committed
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
  int mb_col, mb_row, offset, i;
  int ncnt[4];
  int n_frames = cpi->mbgraph_n_frames;

  int *arf_not_zz;

  CHECK_MEM_ERROR(arf_not_zz,
                  vpx_calloc(cm->mb_rows * cm->mb_cols * sizeof(*arf_not_zz), 1));

  // We are not interested in results beyond the alt ref itself.
  if (n_frames > cpi->frames_till_gf_update_due)
    n_frames = cpi->frames_till_gf_update_due;

  // defer cost to reference frames
  for (i = n_frames - 1; i >= 0; i--) {
    MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i];
377 378

    for (offset = 0, mb_row = 0; mb_row < cm->mb_rows;
John Koleszar's avatar
John Koleszar committed
379 380 381 382 383 384 385 386 387 388 389 390 391 392
         offset += cm->mb_cols, mb_row++) {
      for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
        MBGRAPH_MB_STATS *mb_stats =
          &frame_stats->mb_stats[offset + mb_col];

        int altref_err = mb_stats->ref[ALTREF_FRAME].err;
        int intra_err  = mb_stats->ref[INTRA_FRAME ].err;
        int golden_err = mb_stats->ref[GOLDEN_FRAME].err;

        // Test for altref vs intra and gf and that its mv was 0,0.
        if ((altref_err > 1000) ||
            (altref_err > intra_err) ||
            (altref_err > golden_err)) {
          arf_not_zz[offset + mb_col]++;
393
        }
John Koleszar's avatar
John Koleszar committed
394
      }
395
    }
John Koleszar's avatar
John Koleszar committed
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
  }

  vpx_memset(ncnt, 0, sizeof(ncnt));
  for (offset = 0, mb_row = 0; mb_row < cm->mb_rows;
       offset += cm->mb_cols, mb_row++) {
    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
      // If any of the blocks in the sequence failed then the MB
      // goes in segment 0
      if (arf_not_zz[offset + mb_col]) {
        ncnt[0]++;
        cpi->segmentation_map[offset + mb_col] = 0;
      } else {
        ncnt[1]++;
        cpi->segmentation_map[offset + mb_col] = 1;
      }
411
    }
John Koleszar's avatar
John Koleszar committed
412 413 414 415 416 417 418 419 420 421 422
  }

  // Only bother with segmentation if over 10% of the MBs in static segment
  // if ( ncnt[1] && (ncnt[0] / ncnt[1] < 10) )
  if (1) {
    // Note % of blocks that are marked as static
    if (cm->MBs)
      cpi->static_mb_pct = (ncnt[1] * 100) / cm->MBs;

    // This error case should not be reachable as this function should
    // never be called with the common data structure unititialized.
423
    else
John Koleszar's avatar
John Koleszar committed
424 425 426
      cpi->static_mb_pct = 0;

    cpi->seg0_cnt = ncnt[0];
427
    vp9_enable_segmentation((VP9_PTR) cpi);
John Koleszar's avatar
John Koleszar committed
428 429
  } else {
    cpi->static_mb_pct = 0;
430
    vp9_disable_segmentation((VP9_PTR) cpi);
John Koleszar's avatar
John Koleszar committed
431
  }
432

John Koleszar's avatar
John Koleszar committed
433 434
  // Free localy allocated storage
  vpx_free(arf_not_zz);
435 436
}

437
void vp9_update_mbgraph_stats
438
(
439
  VP9_COMP *cpi
John Koleszar's avatar
John Koleszar committed
440
) {
441
  VP9_COMMON *const cm = &cpi->common;
442
  int i, n_frames = vp9_lookahead_depth(cpi->lookahead);
John Koleszar's avatar
John Koleszar committed
443 444 445 446 447 448
  YV12_BUFFER_CONFIG *golden_ref = &cm->yv12_fb[cm->gld_fb_idx];

  // we need to look ahead beyond where the ARF transitions into
  // being a GF - so exit if we don't look ahead beyond that
  if (n_frames <= cpi->frames_till_gf_update_due)
    return;
449
  if (n_frames > (int)cpi->common.frames_till_alt_ref_frame)
John Koleszar's avatar
John Koleszar committed
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
    n_frames = cpi->common.frames_till_alt_ref_frame;
  if (n_frames > MAX_LAG_BUFFERS)
    n_frames = MAX_LAG_BUFFERS;

  cpi->mbgraph_n_frames = n_frames;
  for (i = 0; i < n_frames; i++) {
    MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i];
    vpx_memset(frame_stats->mb_stats, 0,
               cm->mb_rows * cm->mb_cols * sizeof(*cpi->mbgraph_stats[i].mb_stats));
  }

  // do motion search to find contribution of each reference to data
  // later on in this GF group
  // FIXME really, the GF/last MC search should be done forward, and
  // the ARF MC search backwards, to get optimal results for MV caching
  for (i = 0; i < n_frames; i++) {
    MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i];
    struct lookahead_entry *q_cur =
468
      vp9_lookahead_peek(cpi->lookahead, i);
John Koleszar's avatar
John Koleszar committed
469 470 471 472 473 474 475

    assert(q_cur != NULL);

    update_mbgraph_frame_stats(cpi, frame_stats, &q_cur->img,
                               golden_ref, cpi->Source);
  }

476
  vp9_clear_system_state();  // __asm emms;
John Koleszar's avatar
John Koleszar committed
477 478

  separate_arf_mbs(cpi);
479
}