vp9_encodeframe.c 81.6 KB
Newer Older
      printf("Mode %d skip %d tx_size %d ref %d ref2 %d mv %d %d interp %d\n",
             mbmi->mode, x->skip, mbmi->txfm_size,
             mbmi->ref_frame, mbmi->second_ref_frame,
             mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
             mbmi->interp_filter);
John Koleszar's avatar
John Koleszar committed

    assert(cm->frame_type != KEY_FRAME);

Paul Wilkins's avatar
Paul Wilkins committed
    if (mbmi->ref_frame == LAST_FRAME)
      ref_fb_idx = cpi->common.ref_frame_map[cpi->lst_fb_idx];
Paul Wilkins's avatar
Paul Wilkins committed
    else if (mbmi->ref_frame == GOLDEN_FRAME)
      ref_fb_idx = cpi->common.ref_frame_map[cpi->gld_fb_idx];
Adrian Grange's avatar
Adrian Grange committed
    else
      ref_fb_idx = cpi->common.ref_frame_map[cpi->alt_fb_idx];
John Koleszar's avatar
John Koleszar committed

    if (mbmi->second_ref_frame > 0) {
Paul Wilkins's avatar
Paul Wilkins committed
      if (mbmi->second_ref_frame == LAST_FRAME)
        second_ref_fb_idx = cpi->common.ref_frame_map[cpi->lst_fb_idx];
Paul Wilkins's avatar
Paul Wilkins committed
      else if (mbmi->second_ref_frame == GOLDEN_FRAME)
        second_ref_fb_idx = cpi->common.ref_frame_map[cpi->gld_fb_idx];
John Koleszar's avatar
John Koleszar committed
      else
        second_ref_fb_idx = cpi->common.ref_frame_map[cpi->alt_fb_idx];
    setup_pre_planes(xd,
        &cpi->common.yv12_fb[ref_fb_idx],
        mbmi->second_ref_frame > 0 ? &cpi->common.yv12_fb[second_ref_fb_idx]
                                   : NULL,
        mi_row, mi_col, xd->scale_factor, xd->scale_factor_uv);
John Koleszar's avatar
John Koleszar committed
    if (!x->skip) {
      vp9_encode_inter16x16(cm, x, mi_row, mi_col);
John Koleszar's avatar
John Koleszar committed
    } else {
      vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_SIZE_MB16X16);
#if CONFIG_COMP_INTERINTRA_PRED
      if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) {
        vp9_build_interintra_predictors(xd,
                                        xd->plane[0].dst.buf,
                                        xd->plane[1].dst.buf,
                                        xd->plane[2].dst.buf,
                                        xd->plane[0].dst.stride,
                                        xd->plane[1].dst.stride,
                                        BLOCK_SIZE_MB16X16);
John Koleszar's avatar
John Koleszar committed
    }
John Koleszar's avatar
John Koleszar committed
  }
John Koleszar's avatar
John Koleszar committed
  if (!x->skip) {
John Koleszar's avatar
John Koleszar committed
    if (enc_debug) {
      int i, j;
      printf("\n");
      printf("qcoeff\n");
      for (i = 0; i < 384; i++) {
John Koleszar's avatar
John Koleszar committed
        printf("%3d ", xd->qcoeff[i]);
        if (i % 16 == 15) printf("\n");
      }
      printf("\n");
      printf("predictor\n");
      for (i = 0; i < 384; i++) {
        printf("%3d ", xd->predictor[i]);
        if (i % 16 == 15) printf("\n");
      }
      printf("\n");
      printf("src_diff\n");
      for (i = 0; i < 384; i++) {
        printf("%3d ", x->src_diff[i]);
        if (i % 16 == 15) printf("\n");
      }
      printf("\n");
      printf("diff\n");
      for (i = 0; i < 384; i++) {
        printf("%3d ", xd->block[0].diff[i]);
        if (i % 16 == 15) printf("\n");
      }
      printf("\n");
      printf("final y\n");
      for (i = 0; i < 16; i++) {
        for (j = 0; j < 16; j++)
          printf("%3d ", xd->plane[0].dst.buf[i * xd->plane[0].dst.stride + j]);
        printf("\n");
      }
      printf("\n");
      printf("final u\n");
      for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++)
          printf("%3d ", xd->plane[1].dst.buf[i * xd->plane[1].dst.stride + j]);
John Koleszar's avatar
John Koleszar committed
      printf("\n");
      printf("final v\n");
      for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++)
          printf("%3d ", xd->plane[2].dst.buf[i * xd->plane[1].dst.stride + j]);
John Koleszar's avatar
John Koleszar committed
      fflush(stdout);
    }
    vp9_tokenize_mb(cpi, xd, t, !output_enabled);
John Koleszar's avatar
John Koleszar committed
  } else {
    // FIXME(rbultje): not tile-aware (mi - 1)
    int mb_skip_context =
      (mi - 1)->mbmi.mb_skip_coeff + (mi - mis)->mbmi.mb_skip_coeff;

    mbmi->mb_skip_coeff = 1;
    if (output_enabled)
      cpi->skip_true_count[mb_skip_context]++;
    vp9_reset_sb_tokens_context(xd, BLOCK_SIZE_MB16X16);
John Koleszar's avatar
John Koleszar committed
  }
#if CONFIG_SB8X8
  // copy skip flag on all mb_mode_info contexts in this SB
  // if this was a skip at this txfm size
  for (n = 1; n < 4; n++) {
    const int x_idx = n & 1, y_idx = n >> 1;
    if (mi_col + x_idx < cm->mi_cols && mi_row + y_idx < cm->mi_rows)
      mi[x_idx + y_idx * mis].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff;
  }
#endif

  if (output_enabled) {
    int segment_id = mbmi->segment_id;
    if (cpi->common.txfm_mode == TX_MODE_SELECT &&
        !(mbmi->mb_skip_coeff ||
          vp9_segfeature_active(&x->e_mbd, segment_id, SEG_LVL_SKIP))) {
      assert(mbmi->txfm_size <= TX_16X16);
Yaowu Xu's avatar
Yaowu Xu committed
      if (mbmi->mode != I4X4_PRED && mbmi->mode != I8X8_PRED &&
          mbmi->mode != SPLITMV) {
        cpi->txfm_count_16x16p[mbmi->txfm_size]++;
      } else if (mbmi->mode == I8X8_PRED ||
                 (mbmi->mode == SPLITMV &&
                  mbmi->partitioning != PARTITIONING_4X4)) {
        cpi->txfm_count_8x8p[mbmi->txfm_size]++;
#if CONFIG_SB8X8
      int y, x;
#endif

      if (mbmi->mode != I4X4_PRED && mbmi->mode != I8X8_PRED &&
          mbmi->mode != SPLITMV && cpi->common.txfm_mode >= ALLOW_16X16) {
        mbmi->txfm_size = TX_16X16;
      } else if (mbmi->mode != I4X4_PRED &&
                 !(mbmi->mode == SPLITMV &&
                   mbmi->partitioning == PARTITIONING_4X4) &&
                 cpi->common.txfm_mode >= ALLOW_8X8) {
        mbmi->txfm_size = TX_8X8;
      } else {
        mbmi->txfm_size = TX_4X4;
      }

#if CONFIG_SB8X8
      for (y = 0; y < 2; y++) {
        for (x = !y; x < 2; x++) {
          if (mi_col + x < cm->mi_cols && mi_row + y < cm->mi_rows) {
            mi[mis * y + x].mbmi.txfm_size = mbmi->txfm_size;
          }
        }
      }
#endif
John Koleszar's avatar
John Koleszar committed
}
static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t,
                              int output_enabled, int mi_row, int mi_col,
                              BLOCK_SIZE_TYPE bsize) {
  VP9_COMMON *const cm = &cpi->common;
  MACROBLOCK *const x = &cpi->mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  int n;
  MODE_INFO *mi = x->e_mbd.mode_info_context;
  unsigned int segment_id = mi->mbmi.segment_id;
  const int mis = cm->mode_info_stride;
  const int bwl = mi_width_log2(bsize);
  const int bw = 1 << bwl, bh = 1 << mi_height_log2(bsize);

  if (cm->frame_type == KEY_FRAME) {
    if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
      adjust_act_zbin(cpi, x);
      vp9_update_zbin_extra(cpi, x);
    }
  } else {
    vp9_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, cm);

    if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
      // Adjust the zbin based on this MB rate.
      adjust_act_zbin(cpi, x);
    }

    // Experimental code. Special case for gf and arf zeromv modes.
    // Increase zbin size to suppress noise
    cpi->zbin_mode_boost = 0;
    if (cpi->zbin_mode_boost_enabled) {
      if (xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME) {
        if (xd->mode_info_context->mbmi.mode == ZEROMV) {
          if (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME)
            cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
          else
            cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
        } else if (xd->mode_info_context->mbmi.mode == SPLITMV) {
Paul Wilkins's avatar
Paul Wilkins committed
          cpi->zbin_mode_boost = SPLIT_MV_ZBIN_BOOST;
        } else {
          cpi->zbin_mode_boost = MV_ZBIN_BOOST;
        }
Paul Wilkins's avatar
Paul Wilkins committed
      } else {
        cpi->zbin_mode_boost = INTRA_ZBIN_BOOST;
      }
    }

    vp9_update_zbin_extra(cpi, x);
  }

  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
    vp9_build_intra_predictors_sby_s(&x->e_mbd, bsize);
    vp9_build_intra_predictors_sbuv_s(&x->e_mbd, bsize);
    if (output_enabled)
      sum_intra_stats(cpi, x);
    int ref_fb_idx, second_ref_fb_idx;

    assert(cm->frame_type != KEY_FRAME);

    if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME)
      ref_fb_idx = cpi->common.ref_frame_map[cpi->lst_fb_idx];
    else if (xd->mode_info_context->mbmi.ref_frame == GOLDEN_FRAME)
      ref_fb_idx = cpi->common.ref_frame_map[cpi->gld_fb_idx];
      ref_fb_idx = cpi->common.ref_frame_map[cpi->alt_fb_idx];

    if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
      if (xd->mode_info_context->mbmi.second_ref_frame == LAST_FRAME)
        second_ref_fb_idx = cpi->common.ref_frame_map[cpi->lst_fb_idx];
      else if (xd->mode_info_context->mbmi.second_ref_frame == GOLDEN_FRAME)
        second_ref_fb_idx = cpi->common.ref_frame_map[cpi->gld_fb_idx];
        second_ref_fb_idx = cpi->common.ref_frame_map[cpi->alt_fb_idx];
    setup_pre_planes(xd,
        &cpi->common.yv12_fb[ref_fb_idx],
        xd->mode_info_context->mbmi.second_ref_frame > 0
            ? &cpi->common.yv12_fb[second_ref_fb_idx] : NULL,
        mi_row, mi_col, xd->scale_factor, xd->scale_factor_uv);
    vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
    vp9_subtract_sb(x, bsize);
    switch (xd->mode_info_context->mbmi.txfm_size) {
      case TX_32X32:
        vp9_transform_sby_32x32(x, bsize);
        vp9_quantize_sby_32x32(x, bsize);
        if (bsize == BLOCK_SIZE_SB64X64) {
          vp9_transform_sbuv_32x32(x, bsize);
          vp9_quantize_sbuv_32x32(x, bsize);
        } else {
          vp9_transform_sbuv_16x16(x, bsize);
          vp9_quantize_sbuv_16x16(x, bsize);
        }
          vp9_optimize_sby_32x32(cm, x, bsize);
          if (bsize == BLOCK_SIZE_SB64X64)
            vp9_optimize_sbuv_32x32(cm, x, bsize);
          else
            vp9_optimize_sbuv_16x16(cm, x, bsize);
        vp9_inverse_transform_sby_32x32(xd, bsize);
        if (bsize == BLOCK_SIZE_SB64X64)
          vp9_inverse_transform_sbuv_32x32(xd, bsize);
        else
          vp9_inverse_transform_sbuv_16x16(xd, bsize);
        vp9_transform_sby_16x16(x, bsize);
        vp9_quantize_sby_16x16(x, bsize);
        if (bsize >= BLOCK_SIZE_SB32X32) {
          vp9_transform_sbuv_16x16(x, bsize);
          vp9_quantize_sbuv_16x16(x, bsize);
        } else {
          vp9_transform_sbuv_8x8(x, bsize);
          vp9_quantize_sbuv_8x8(x, bsize);
        }
          vp9_optimize_sby_16x16(cm, x, bsize);
          if (bsize >= BLOCK_SIZE_SB32X32)
            vp9_optimize_sbuv_16x16(cm, x, bsize);
          else
            vp9_optimize_sbuv_8x8(cm, x, bsize);
        vp9_inverse_transform_sby_16x16(xd, bsize);
        if (bsize >= BLOCK_SIZE_SB32X32)
          vp9_inverse_transform_sbuv_16x16(xd, bsize);
        else
          vp9_inverse_transform_sbuv_8x8(xd, bsize);
        vp9_transform_sby_8x8(x, bsize);
        vp9_transform_sbuv_8x8(x, bsize);
        vp9_quantize_sby_8x8(x, bsize);
        vp9_quantize_sbuv_8x8(x, bsize);
          vp9_optimize_sby_8x8(cm, x, bsize);
          vp9_optimize_sbuv_8x8(cm, x, bsize);
        vp9_inverse_transform_sby_8x8(xd, bsize);
        vp9_inverse_transform_sbuv_8x8(xd, bsize);
        vp9_transform_sby_4x4(x, bsize);
        vp9_transform_sbuv_4x4(x, bsize);
        vp9_quantize_sby_4x4(x, bsize);
        vp9_quantize_sbuv_4x4(x, bsize);
          vp9_optimize_sby_4x4(cm, x, bsize);
          vp9_optimize_sbuv_4x4(cm, x, bsize);
        vp9_inverse_transform_sby_4x4(xd, bsize);
        vp9_inverse_transform_sbuv_4x4(xd, bsize);
    vp9_recon_sb_c(xd, bsize);
    vp9_tokenize_sb(cpi, &x->e_mbd, t, !output_enabled, bsize);
  } else {
    // FIXME(rbultje): not tile-aware (mi - 1)
    int mb_skip_context =
        (mi - 1)->mbmi.mb_skip_coeff + (mi - mis)->mbmi.mb_skip_coeff;

    xd->mode_info_context->mbmi.mb_skip_coeff = 1;
    if (output_enabled)
      cpi->skip_true_count[mb_skip_context]++;
    vp9_reset_sb_tokens_context(xd, bsize);
  // copy skip flag on all mb_mode_info contexts in this SB
  // if this was a skip at this txfm size
  for (n = 1; n < bw * bh; n++) {
    const int x_idx = n & (bw - 1), y_idx = n >> bwl;
    if (mi_col + x_idx < cm->mi_cols && mi_row + y_idx < cm->mi_rows)
      mi[x_idx + y_idx * mis].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff;
  }

  if (output_enabled) {
    if (cm->txfm_mode == TX_MODE_SELECT &&
        !(mi->mbmi.mb_skip_coeff ||
          vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))) {
      if (bsize >= BLOCK_SIZE_SB32X32) {
        cpi->txfm_count_32x32p[mi->mbmi.txfm_size]++;
      } else {
        cpi->txfm_count_16x16p[mi->mbmi.txfm_size]++;
      }
    } else {
      int x, y;
      TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? TX_32X32 : cm->txfm_mode;

      if (sz == TX_32X32 && bsize < BLOCK_SIZE_SB32X32)
        sz = TX_16X16;

      for (y = 0; y < bh; y++) {
        for (x = 0; x < bw; x++) {
          if (mi_col + x < cm->mi_cols && mi_row + y < cm->mi_rows) {
            mi[mis * y + x].mbmi.txfm_size = sz;
          }
        }
      }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
}