mbgraph.c 13.5 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11 12 13
 */

#include <limits.h>

Yaowu Xu's avatar
Yaowu Xu committed
14
#include "./av1_rtcd.h"
Jingning Han's avatar
Jingning Han committed
15 16
#include "./vpx_dsp_rtcd.h"

Yaowu Xu's avatar
Yaowu Xu committed
17 18 19
#include "aom_dsp/vpx_dsp_common.h"
#include "aom_mem/vpx_mem.h"
#include "aom_ports/system_state.h"
Yaowu Xu's avatar
Yaowu Xu committed
20 21 22 23 24
#include "av1/encoder/segmentation.h"
#include "av1/encoder/mcomp.h"
#include "av1/common/blockd.h"
#include "av1/common/reconinter.h"
#include "av1/common/reconintra.h"
Jingning Han's avatar
Jingning Han committed
25

clang-format's avatar
clang-format committed
26 27
static unsigned int do_16x16_motion_iteration(VP10_COMP *cpi, const MV *ref_mv,
                                              MV *dst_mv, int mb_row,
Jingning Han's avatar
Jingning Han committed
28 29 30 31
                                              int mb_col) {
  MACROBLOCK *const x = &cpi->td.mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  const MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv;
Yaowu Xu's avatar
Yaowu Xu committed
32
  const vpx_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[BLOCK_16X16];
Jingning Han's avatar
Jingning Han committed
33 34 35 36 37 38 39 40 41 42

  const int tmp_col_min = x->mv_col_min;
  const int tmp_col_max = x->mv_col_max;
  const int tmp_row_min = x->mv_row_min;
  const int tmp_row_max = x->mv_row_max;
  MV ref_full;
  int cost_list[5];

  // Further step/diamond searches as necessary
  int step_param = mv_sf->reduce_first_step_size;
43
  step_param = VPXMIN(step_param, MAX_MVSEARCH_STEPS - 2);
Jingning Han's avatar
Jingning Han committed
44 45 46 47 48 49 50 51

  vp10_set_mv_search_range(x, ref_mv);

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

  /*cpi->sf.search_method == HEX*/
  vp10_hex_search(x, &ref_full, step_param, x->errorperbit, 0,
clang-format's avatar
clang-format committed
52
                  cond_cost_list(cpi, cost_list), &v_fn_ptr, 0, ref_mv, dst_mv);
Jingning Han's avatar
Jingning Han committed
53 54 55 56 57 58 59 60 61

  // Try sub-pixel MC
  // if (bestsme > error_thresh && bestsme < INT_MAX)
  {
    int distortion;
    unsigned int sse;
    cpi->find_fractional_mv_step(
        x, dst_mv, ref_mv, cpi->common.allow_high_precision_mv, x->errorperbit,
        &v_fn_ptr, 0, mv_sf->subpel_iters_per_step,
clang-format's avatar
clang-format committed
62 63
        cond_cost_list(cpi, cost_list), NULL, NULL, &distortion, &sse, NULL, 0,
        0);
Jingning Han's avatar
Jingning Han committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  }

  xd->mi[0]->mbmi.mode = NEWMV;
  xd->mi[0]->mbmi.mv[0].as_mv = *dst_mv;

  vp10_build_inter_predictors_sby(xd, mb_row, mb_col, BLOCK_16X16);

  /* 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;

  return vpx_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
                      xd->plane[0].dst.buf, xd->plane[0].dst.stride);
}

Yaowu Xu's avatar
Yaowu Xu committed
81
static int do_16x16_motion_search(VP10_COMP *cpi, const MV *ref_mv,
Jingning Han's avatar
Jingning Han committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
                                  int_mv *dst_mv, int mb_row, int mb_col) {
  MACROBLOCK *const x = &cpi->td.mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  unsigned int err, tmp_err;
  MV tmp_mv;

  // Try zero MV first
  // FIXME should really use something like near/nearest MV and/or MV prediction
  err = vpx_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
                     xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride);
  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, mb_row, mb_col);
  if (tmp_err < err) {
    err = tmp_err;
    dst_mv->as_mv = tmp_mv;
  }

  // If the current best reference mv is not centered on 0,0 then do a 0,0
  // based search as well.
  if (ref_mv->row != 0 || ref_mv->col != 0) {
    unsigned int tmp_err;
clang-format's avatar
clang-format committed
106
    MV zero_ref_mv = { 0, 0 }, tmp_mv;
Jingning Han's avatar
Jingning Han committed
107

clang-format's avatar
clang-format committed
108 109
    tmp_err =
        do_16x16_motion_iteration(cpi, &zero_ref_mv, &tmp_mv, mb_row, mb_col);
Jingning Han's avatar
Jingning Han committed
110 111 112 113 114 115 116 117 118
    if (tmp_err < err) {
      dst_mv->as_mv = tmp_mv;
      err = tmp_err;
    }
  }

  return err;
}

Yaowu Xu's avatar
Yaowu Xu committed
119
static int do_16x16_zerozero_search(VP10_COMP *cpi, int_mv *dst_mv) {
Jingning Han's avatar
Jingning Han committed
120 121 122 123 124 125 126 127 128 129 130 131 132
  MACROBLOCK *const x = &cpi->td.mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  unsigned int err;

  // Try zero MV first
  // FIXME should really use something like near/nearest MV and/or MV prediction
  err = vpx_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
                     xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride);

  dst_mv->as_int = 0;

  return err;
}
Yaowu Xu's avatar
Yaowu Xu committed
133
static int find_best_16x16_intra(VP10_COMP *cpi, PREDICTION_MODE *pbest_mode) {
clang-format's avatar
clang-format committed
134
  MACROBLOCK *const x = &cpi->td.mb;
Jingning Han's avatar
Jingning Han committed
135 136 137 138 139 140 141 142 143 144
  MACROBLOCKD *const xd = &x->e_mbd;
  PREDICTION_MODE best_mode = -1, mode;
  unsigned int best_err = INT_MAX;

  // 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->mi[0]->mbmi.mode = mode;
clang-format's avatar
clang-format committed
145 146 147
    vp10_predict_intra_block(xd, 2, 2, TX_16X16, mode, x->plane[0].src.buf,
                             x->plane[0].src.stride, xd->plane[0].dst.buf,
                             xd->plane[0].dst.stride, 0, 0, 0);
Jingning Han's avatar
Jingning Han committed
148 149 150 151 152
    err = vpx_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
                       xd->plane[0].dst.buf, xd->plane[0].dst.stride);

    // find best
    if (err < best_err) {
clang-format's avatar
clang-format committed
153
      best_err = err;
Jingning Han's avatar
Jingning Han committed
154 155 156 157
      best_mode = mode;
    }
  }

clang-format's avatar
clang-format committed
158
  if (pbest_mode) *pbest_mode = best_mode;
Jingning Han's avatar
Jingning Han committed
159 160 161 162

  return best_err;
}

clang-format's avatar
clang-format committed
163 164 165 166 167 168
static void update_mbgraph_mb_stats(VP10_COMP *cpi, MBGRAPH_MB_STATS *stats,
                                    YV12_BUFFER_CONFIG *buf, int mb_y_offset,
                                    YV12_BUFFER_CONFIG *golden_ref,
                                    const MV *prev_golden_ref_mv,
                                    YV12_BUFFER_CONFIG *alt_ref, int mb_row,
                                    int mb_col) {
Jingning Han's avatar
Jingning Han committed
169 170 171
  MACROBLOCK *const x = &cpi->td.mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  int intra_error;
Yaowu Xu's avatar
Yaowu Xu committed
172
  VP10_COMMON *cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
173 174 175 176 177 178 179 180 181

  // FIXME in practice we're completely ignoring chroma here
  x->plane[0].src.buf = buf->y_buffer + mb_y_offset;
  x->plane[0].src.stride = buf->y_stride;

  xd->plane[0].dst.buf = get_frame_new_buffer(cm)->y_buffer + mb_y_offset;
  xd->plane[0].dst.stride = get_frame_new_buffer(cm)->y_stride;

  // do intra 16x16 prediction
clang-format's avatar
clang-format committed
182 183
  intra_error = find_best_16x16_intra(cpi, &stats->ref[INTRA_FRAME].m.mode);
  if (intra_error <= 0) intra_error = 1;
Jingning Han's avatar
Jingning Han committed
184 185 186 187 188 189 190
  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;
    xd->plane[0].pre[0].buf = golden_ref->y_buffer + mb_y_offset;
    xd->plane[0].pre[0].stride = golden_ref->y_stride;
clang-format's avatar
clang-format committed
191 192 193
    g_motion_error =
        do_16x16_motion_search(cpi, prev_golden_ref_mv,
                               &stats->ref[GOLDEN_FRAME].m.mv, mb_row, mb_col);
Jingning Han's avatar
Jingning Han committed
194 195 196 197 198 199 200 201 202 203 204 205
    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;
  }

  // Do an Alt-ref frame MV search, if it exists and is different than
  // last/golden frame.
  if (alt_ref) {
    int a_motion_error;
    xd->plane[0].pre[0].buf = alt_ref->y_buffer + mb_y_offset;
    xd->plane[0].pre[0].stride = alt_ref->y_stride;
clang-format's avatar
clang-format committed
206 207
    a_motion_error =
        do_16x16_zerozero_search(cpi, &stats->ref[ALTREF_FRAME].m.mv);
Jingning Han's avatar
Jingning Han committed
208 209 210 211 212 213 214 215

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

Yaowu Xu's avatar
Yaowu Xu committed
216
static void update_mbgraph_frame_stats(VP10_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
217 218 219 220 221 222
                                       MBGRAPH_FRAME_STATS *stats,
                                       YV12_BUFFER_CONFIG *buf,
                                       YV12_BUFFER_CONFIG *golden_ref,
                                       YV12_BUFFER_CONFIG *alt_ref) {
  MACROBLOCK *const x = &cpi->td.mb;
  MACROBLOCKD *const xd = &x->e_mbd;
Yaowu Xu's avatar
Yaowu Xu committed
223
  VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
224 225 226

  int mb_col, mb_row, offset = 0;
  int mb_y_offset = 0, arf_y_offset = 0, gld_y_offset = 0;
clang-format's avatar
clang-format committed
227
  MV gld_top_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
228 229 230 231 232
  MODE_INFO mi_local;

  vp10_zero(mi_local);
  // Set up limit values for motion vectors to prevent them extending outside
  // the UMV borders.
clang-format's avatar
clang-format committed
233 234 235 236 237
  x->mv_row_min = -BORDER_MV_PIXELS_B16;
  x->mv_row_max = (cm->mb_rows - 1) * 8 + BORDER_MV_PIXELS_B16;
  xd->up_available = 0;
  xd->plane[0].dst.stride = buf->y_stride;
  xd->plane[0].pre[0].stride = buf->y_stride;
Jingning Han's avatar
Jingning Han committed
238 239 240 241 242 243 244 245
  xd->plane[1].dst.stride = buf->uv_stride;
  xd->mi[0] = &mi_local;
  mi_local.mbmi.sb_type = BLOCK_16X16;
  mi_local.mbmi.ref_frame[0] = LAST_FRAME;
  mi_local.mbmi.ref_frame[1] = NONE;

  for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
    MV gld_left_mv = gld_top_mv;
clang-format's avatar
clang-format committed
246
    int mb_y_in_offset = mb_y_offset;
Jingning Han's avatar
Jingning Han committed
247 248 249 250 251
    int arf_y_in_offset = arf_y_offset;
    int gld_y_in_offset = gld_y_offset;

    // Set up limit values for motion vectors to prevent them extending outside
    // the UMV borders.
clang-format's avatar
clang-format committed
252 253
    x->mv_col_min = -BORDER_MV_PIXELS_B16;
    x->mv_col_max = (cm->mb_cols - 1) * 8 + BORDER_MV_PIXELS_B16;
Jingning Han's avatar
Jingning Han committed
254 255 256 257 258
    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];

clang-format's avatar
clang-format committed
259 260
      update_mbgraph_mb_stats(cpi, mb_stats, buf, mb_y_in_offset, golden_ref,
                              &gld_left_mv, alt_ref, mb_row, mb_col);
Jingning Han's avatar
Jingning Han committed
261 262 263 264 265
      gld_left_mv = mb_stats->ref[GOLDEN_FRAME].m.mv.as_mv;
      if (mb_col == 0) {
        gld_top_mv = gld_left_mv;
      }
      xd->left_available = 1;
clang-format's avatar
clang-format committed
266 267 268 269 270
      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;
Jingning Han's avatar
Jingning Han committed
271 272
    }
    xd->up_available = 1;
clang-format's avatar
clang-format committed
273 274 275 276 277 278
    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;
Jingning Han's avatar
Jingning Han committed
279 280 281 282
  }
}

// void separate_arf_mbs_byzz
Yaowu Xu's avatar
Yaowu Xu committed
283
static void separate_arf_mbs(VP10_COMP *cpi) {
Yaowu Xu's avatar
Yaowu Xu committed
284
  VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
285 286 287 288 289 290 291
  int mb_col, mb_row, offset, i;
  int mi_row, mi_col;
  int ncnt[4] = { 0 };
  int n_frames = cpi->mbgraph_n_frames;

  int *arf_not_zz;

clang-format's avatar
clang-format committed
292 293 294
  CHECK_MEM_ERROR(
      cm, arf_not_zz,
      vpx_calloc(cm->mb_rows * cm->mb_cols * sizeof(*arf_not_zz), 1));
Jingning Han's avatar
Jingning Han committed
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

  // We are not interested in results beyond the alt ref itself.
  if (n_frames > cpi->rc.frames_till_gf_update_due)
    n_frames = cpi->rc.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];

    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++) {
        MBGRAPH_MB_STATS *mb_stats = &frame_stats->mb_stats[offset + mb_col];

        int altref_err = mb_stats->ref[ALTREF_FRAME].err;
clang-format's avatar
clang-format committed
310
        int intra_err = mb_stats->ref[INTRA_FRAME].err;
Jingning Han's avatar
Jingning Han committed
311 312 313
        int golden_err = mb_stats->ref[GOLDEN_FRAME].err;

        // Test for altref vs intra and gf and that its mv was 0,0.
clang-format's avatar
clang-format committed
314
        if (altref_err > 1000 || altref_err > intra_err ||
Jingning Han's avatar
Jingning Han committed
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
            altref_err > golden_err) {
          arf_not_zz[offset + mb_col]++;
        }
      }
    }
  }

  // arf_not_zz is indexed by MB, but this loop is indexed by MI to avoid out
  // of bound access in segmentation_map
  for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) {
    for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) {
      // If any of the blocks in the sequence failed then the MB
      // goes in segment 0
      if (arf_not_zz[mi_row / 2 * cm->mb_cols + mi_col / 2]) {
        ncnt[0]++;
        cpi->segmentation_map[mi_row * cm->mi_cols + mi_col] = 0;
      } else {
        cpi->segmentation_map[mi_row * cm->mi_cols + mi_col] = 1;
        ncnt[1]++;
      }
    }
  }

  // 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->mi_rows * cm->mi_cols);

    // This error case should not be reachable as this function should
    // never be called with the common data structure uninitialized.
    else
      cpi->static_mb_pct = 0;

    vp10_enable_segmentation(&cm->seg);
  } else {
    cpi->static_mb_pct = 0;
    vp10_disable_segmentation(&cm->seg);
  }

  // Free localy allocated storage
  vpx_free(arf_not_zz);
}

Yaowu Xu's avatar
Yaowu Xu committed
360
void vp10_update_mbgraph_stats(VP10_COMP *cpi) {
Yaowu Xu's avatar
Yaowu Xu committed
361
  VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
362 363 364 365 366 367 368
  int i, n_frames = vp10_lookahead_depth(cpi->lookahead);
  YV12_BUFFER_CONFIG *golden_ref = get_ref_frame_buffer(cpi, GOLDEN_FRAME);

  assert(golden_ref != NULL);

  // we need to look ahead beyond where the ARF transitions into
  // being a GF - so exit if we don't look ahead beyond that
clang-format's avatar
clang-format committed
369
  if (n_frames <= cpi->rc.frames_till_gf_update_due) return;
Jingning Han's avatar
Jingning Han committed
370

clang-format's avatar
clang-format committed
371
  if (n_frames > MAX_LAG_BUFFERS) n_frames = MAX_LAG_BUFFERS;
Jingning Han's avatar
Jingning Han committed
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389

  cpi->mbgraph_n_frames = n_frames;
  for (i = 0; i < n_frames; i++) {
    MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i];
    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 = vp10_lookahead_peek(cpi->lookahead, i);

    assert(q_cur != NULL);

clang-format's avatar
clang-format committed
390 391
    update_mbgraph_frame_stats(cpi, frame_stats, &q_cur->img, golden_ref,
                               cpi->Source);
Jingning Han's avatar
Jingning Han committed
392 393 394 395 396 397
  }

  vpx_clear_system_state();

  separate_arf_mbs(cpi);
}