Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  vp9_rdopt.c   Sprache: C

 
/*
 *  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 <assert.h>
#include <math.h>

#include "./vp9_rtcd.h"
#include "./vpx_dsp_rtcd.h"

#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/system_state.h"

#include "vp9/common/vp9_common.h"
#include "vp9/common/vp9_entropy.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_idct.h"
#include "vp9/common/vp9_mvref_common.h"
#include "vp9/common/vp9_pred_common.h"
#include "vp9/common/vp9_quant_common.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/common/vp9_reconintra.h"
#include "vp9/common/vp9_scan.h"
#include "vp9/common/vp9_seg_common.h"

#if !CONFIG_REALTIME_ONLY
#include "vp9/encoder/vp9_aq_variance.h"
#endif
#include "vp9/encoder/vp9_cost.h"
#include "vp9/encoder/vp9_encodemb.h"
#include "vp9/encoder/vp9_encodemv.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_mcomp.h"
#include "vp9/encoder/vp9_quantize.h"
#include "vp9/encoder/vp9_ratectrl.h"
#include "vp9/encoder/vp9_rd.h"
#include "vp9/encoder/vp9_rdopt.h"

#define LAST_FRAME_MODE_MASK \
  ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | (1 << INTRA_FRAME))
#define GOLDEN_FRAME_MODE_MASK \
  ((1 << LAST_FRAME) | (1 << ALTREF_FRAME) | (1 << INTRA_FRAME))
#define ALT_REF_MODE_MASK \
  ((1 << LAST_FRAME) | (1 << GOLDEN_FRAME) | (1 << INTRA_FRAME))

#define SECOND_REF_FRAME_MASK ((1 << ALTREF_FRAME) | 0x01)

#define MIN_EARLY_TERM_INDEX 3
#define NEW_MV_DISCOUNT_FACTOR 8

typedef struct {
  PREDICTION_MODE mode;
  MV_REFERENCE_FRAME ref_frame[2];
} MODE_DEFINITION;

typedef struct {
  MV_REFERENCE_FRAME ref_frame[2];
} REF_DEFINITION;

struct rdcost_block_args {
  const VP9_COMP *cpi;
  MACROBLOCK *x;
  ENTROPY_CONTEXT t_above[16];
  ENTROPY_CONTEXT t_left[16];
  int this_rate;
  int64_t this_dist;
  int64_t this_sse;
  int64_t this_rd;
  int64_t best_rd;
  int exit_early;
  int use_fast_coef_costing;
  const ScanOrder *so;
  uint8_t skippable;
  struct buf_2d *this_recon;
};

#define LAST_NEW_MV_INDEX 6

#if !CONFIG_REALTIME_ONLY
static const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
  { NEARESTMV, { LAST_FRAME, NO_REF_FRAME } },
  { NEARESTMV, { ALTREF_FRAME, NO_REF_FRAME } },
  { NEARESTMV, { GOLDEN_FRAME, NO_REF_FRAME } },

  { DC_PRED, { INTRA_FRAME, NO_REF_FRAME } },

  { NEWMV, { LAST_FRAME, NO_REF_FRAME } },
  { NEWMV, { ALTREF_FRAME, NO_REF_FRAME } },
  { NEWMV, { GOLDEN_FRAME, NO_REF_FRAME } },

  { NEARMV, { LAST_FRAME, NO_REF_FRAME } },
  { NEARMV, { ALTREF_FRAME, NO_REF_FRAME } },
  { NEARMV, { GOLDEN_FRAME, NO_REF_FRAME } },

  { ZEROMV, { LAST_FRAME, NO_REF_FRAME } },
  { ZEROMV, { GOLDEN_FRAME, NO_REF_FRAME } },
  { ZEROMV, { ALTREF_FRAME, NO_REF_FRAME } },

  { NEARESTMV, { LAST_FRAME, ALTREF_FRAME } },
  { NEARESTMV, { GOLDEN_FRAME, ALTREF_FRAME } },

  { TM_PRED, { INTRA_FRAME, NO_REF_FRAME } },

  { NEARMV, { LAST_FRAME, ALTREF_FRAME } },
  { NEWMV, { LAST_FRAME, ALTREF_FRAME } },
  { NEARMV, { GOLDEN_FRAME, ALTREF_FRAME } },
  { NEWMV, { GOLDEN_FRAME, ALTREF_FRAME } },

  { ZEROMV, { LAST_FRAME, ALTREF_FRAME } },
  { ZEROMV, { GOLDEN_FRAME, ALTREF_FRAME } },

  { H_PRED, { INTRA_FRAME, NO_REF_FRAME } },
  { V_PRED, { INTRA_FRAME, NO_REF_FRAME } },
  { D135_PRED, { INTRA_FRAME, NO_REF_FRAME } },
  { D207_PRED, { INTRA_FRAME, NO_REF_FRAME } },
  { D153_PRED, { INTRA_FRAME, NO_REF_FRAME } },
  { D63_PRED, { INTRA_FRAME, NO_REF_FRAME } },
  { D117_PRED, { INTRA_FRAME, NO_REF_FRAME } },
  { D45_PRED, { INTRA_FRAME, NO_REF_FRAME } },
};

static const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
  { { LAST_FRAME, NO_REF_FRAME } },   { { GOLDEN_FRAME, NO_REF_FRAME } },
  { { ALTREF_FRAME, NO_REF_FRAME } }, { { LAST_FRAME, ALTREF_FRAME } },
  { { GOLDEN_FRAME, ALTREF_FRAME } }, { { INTRA_FRAME, NO_REF_FRAME } },
};
#endif  // !CONFIG_REALTIME_ONLY

static void swap_block_ptr(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx, int m, int n,
                           int min_plane, int max_plane) {
  int i;

  for (i = min_plane; i < max_plane; ++i) {
    struct macroblock_plane *const p = &x->plane[i];
    struct macroblockd_plane *const pd = &x->e_mbd.plane[i];

    p->coeff = ctx->coeff_pbuf[i][m];
    p->qcoeff = ctx->qcoeff_pbuf[i][m];
    pd->dqcoeff = ctx->dqcoeff_pbuf[i][m];
    p->eobs = ctx->eobs_pbuf[i][m];

    ctx->coeff_pbuf[i][m] = ctx->coeff_pbuf[i][n];
    ctx->qcoeff_pbuf[i][m] = ctx->qcoeff_pbuf[i][n];
    ctx->dqcoeff_pbuf[i][m] = ctx->dqcoeff_pbuf[i][n];
    ctx->eobs_pbuf[i][m] = ctx->eobs_pbuf[i][n];

    ctx->coeff_pbuf[i][n] = p->coeff;
    ctx->qcoeff_pbuf[i][n] = p->qcoeff;
    ctx->dqcoeff_pbuf[i][n] = pd->dqcoeff;
    ctx->eobs_pbuf[i][n] = p->eobs;
  }
}

#if !CONFIG_REALTIME_ONLY
// Planewise build inter prediction and compute rdcost with early termination
// option
static int build_inter_pred_model_rd_earlyterm(
    VP9_COMP *cpi, int mi_row, int mi_col, BLOCK_SIZE bsize, MACROBLOCK *x,
    MACROBLOCKD *xd, int *out_rate_sum, int64_t *out_dist_sum,
    int *skip_txfm_sb, int64_t *skip_sse_sb, int do_earlyterm,
    int64_t best_rd) {
  // Note our transform coeffs are 8 times an orthogonal transform.
  // Hence quantizer step is also 8 times. To get effective quantizer
  // we need to divide by 8 before sending to modeling function.
  int i;
  int64_t rate_sum = 0;
  int64_t dist_sum = 0;
  const int ref = xd->mi[0]->ref_frame[0];
  unsigned int sse;
  unsigned int var = 0;
  int64_t total_sse = 0;
  int skip_flag = 1;
  const int shift = 6;
  const int dequant_shift =
#if CONFIG_VP9_HIGHBITDEPTH
      (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? xd->bd - 5 :
#endif  // CONFIG_VP9_HIGHBITDEPTH
                                                    3;

  x->pred_sse[ref] = 0;

  // Build prediction signal, compute stats and RD cost on per-plane basis
  for (i = 0; i < MAX_MB_PLANE; ++i) {
    struct macroblock_plane *const p = &x->plane[i];
    struct macroblockd_plane *const pd = &xd->plane[i];
    const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
    const TX_SIZE max_tx_size = max_txsize_lookup[bs];
    const BLOCK_SIZE unit_size = txsize_to_bsize[max_tx_size];
    const int64_t dc_thr = p->quant_thred[0] >> shift;
    const int64_t ac_thr = p->quant_thred[1] >> shift;
    unsigned int sum_sse = 0;
    // The low thresholds are used to measure if the prediction errors are
    // low enough so that we can skip the mode search.
    const int64_t low_dc_thr = VPXMIN(50, dc_thr >> 2);
    const int64_t low_ac_thr = VPXMIN(80, ac_thr >> 2);
    int bw = 1 << (b_width_log2_lookup[bs] - b_width_log2_lookup[unit_size]);
    int bh = 1 << (b_height_log2_lookup[bs] - b_width_log2_lookup[unit_size]);
    int idx, idy;
    int lw = b_width_log2_lookup[unit_size] + 2;
    int lh = b_height_log2_lookup[unit_size] + 2;
    unsigned int qstep;
    unsigned int nlog2;
    int64_t dist = 0;

    // Build inter predictor
    vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, i);

    // Compute useful stats
    for (idy = 0; idy < bh; ++idy) {
      for (idx = 0; idx < bw; ++idx) {
        uint8_t *src = p->src.buf + (idy * p->src.stride << lh) + (idx << lw);
        uint8_t *dst = pd->dst.buf + (idy * pd->dst.stride << lh) + (idx << lh);
        int block_idx = (idy << 1) + idx;
        int low_err_skip = 0;

        var = cpi->fn_ptr[unit_size].vf(src, p->src.stride, dst, pd->dst.stride,
                                        &sse);
        x->bsse[(i << 2) + block_idx] = sse;
        sum_sse += sse;

        x->skip_txfm[(i << 2) + block_idx] = SKIP_TXFM_NONE;
        if (!x->select_tx_size) {
          // Check if all ac coefficients can be quantized to zero.
          if (var < ac_thr || var == 0) {
            x->skip_txfm[(i << 2) + block_idx] = SKIP_TXFM_AC_ONLY;

            // Check if dc coefficient can be quantized to zero.
            if (sse - var < dc_thr || sse == var) {
              x->skip_txfm[(i << 2) + block_idx] = SKIP_TXFM_AC_DC;

              if (!sse || (var < low_ac_thr && sse - var < low_dc_thr))
                low_err_skip = 1;
            }
          }
        }

        if (skip_flag && !low_err_skip) skip_flag = 0;

        if (i == 0) x->pred_sse[ref] += sse;
      }
    }

    total_sse += sum_sse;
    qstep = pd->dequant[1] >> dequant_shift;
    nlog2 = num_pels_log2_lookup[bs];

    // Fast approximate the modelling function.
    if (cpi->sf.simple_model_rd_from_var) {
      int64_t rate;
      if (qstep < 120)
        rate = ((int64_t)sum_sse * (280 - qstep)) >> (16 - VP9_PROB_COST_SHIFT);
      else
        rate = 0;
      dist = ((int64_t)sum_sse * qstep) >> 8;
      rate_sum += rate;
    } else {
      int rate;
      vp9_model_rd_from_var_lapndz(sum_sse, nlog2, qstep, &rate, &dist);
      rate_sum += rate;
    }
    dist_sum += dist;
    if (do_earlyterm) {
      if (RDCOST(x->rdmult, x->rddiv, rate_sum,
                 dist_sum << VP9_DIST_SCALE_LOG2) >= best_rd)
        return 1;
    }
  }
  *skip_txfm_sb = skip_flag;
  *skip_sse_sb = total_sse << VP9_DIST_SCALE_LOG2;
  *out_rate_sum = (int)rate_sum;
  *out_dist_sum = dist_sum << VP9_DIST_SCALE_LOG2;

  return 0;
}
#endif  // !CONFIG_REALTIME_ONLY

#if CONFIG_VP9_HIGHBITDEPTH
int64_t vp9_highbd_block_error_c(const tran_low_t *coeff,
                                 const tran_low_t *dqcoeff, intptr_t block_size,
                                 int64_t *ssz, int bd) {
  int i;
  int64_t error = 0, sqcoeff = 0;
  int shift = 2 * (bd - 8);
  int rounding = shift > 0 ? 1 << (shift - 1) : 0;

  for (i = 0; i < block_size; i++) {
    const int64_t diff = coeff[i] - dqcoeff[i];
    error += diff * diff;
    sqcoeff += (int64_t)coeff[i] * (int64_t)coeff[i];
  }
  assert(error >= 0 && sqcoeff >= 0);
  error = (error + rounding) >> shift;
  sqcoeff = (sqcoeff + rounding) >> shift;

  *ssz = sqcoeff;
  return error;
}

static int64_t vp9_highbd_block_error_dispatch(const tran_low_t *coeff,
                                               const tran_low_t *dqcoeff,
                                               intptr_t block_size,
                                               int64_t *ssz, int bd) {
  if (bd == 8) {
    return vp9_block_error(coeff, dqcoeff, block_size, ssz);
  } else {
    return vp9_highbd_block_error(coeff, dqcoeff, block_size, ssz, bd);
  }
}
#endif  // CONFIG_VP9_HIGHBITDEPTH

int64_t vp9_block_error_c(const tran_low_t *coeff, const tran_low_t *dqcoeff,
                          intptr_t block_size, int64_t *ssz) {
  int i;
  int64_t error = 0, sqcoeff = 0;

  for (i = 0; i < block_size; i++) {
    const int diff = coeff[i] - dqcoeff[i];
    error += diff * diff;
    sqcoeff += coeff[i] * coeff[i];
  }

  *ssz = sqcoeff;
  return error;
}

int64_t vp9_block_error_fp_c(const tran_low_t *coeff, const tran_low_t *dqcoeff,
                             int block_size) {
  int i;
  int64_t error = 0;

  for (i = 0; i < block_size; i++) {
    const int diff = coeff[i] - dqcoeff[i];
    error += diff * diff;
  }

  return error;
}

/* The trailing '0' is a terminator which is used inside cost_coeffs() to
 * decide whether to include cost of a trailing EOB node or not (i.e. we
 * can skip this if the last coefficient in this transform block, e.g. the
 * 16th coefficient in a 4x4 block or the 64th coefficient in a 8x8 block,
 * were non-zero). */

static const int16_t band_counts[TX_SIZES][8] = {
  { 1, 2, 3, 4, 3, 16 - 13, 0 },
  { 1, 2, 3, 4, 11, 64 - 21, 0 },
  { 1, 2, 3, 4, 11, 256 - 21, 0 },
  { 1, 2, 3, 4, 11, 1024 - 21, 0 },
};
static int cost_coeffs(MACROBLOCK *x, int plane, int block, TX_SIZE tx_size,
                       int pt, const int16_t *scan, const int16_t *nb,
                       int use_fast_coef_costing) {
  MACROBLOCKD *const xd = &x->e_mbd;
  MODE_INFO *mi = xd->mi[0];
  const struct macroblock_plane *p = &x->plane[plane];
  const PLANE_TYPE type = get_plane_type(plane);
  const int16_t *band_count = &band_counts[tx_size][1];
  const int eob = p->eobs[block];
  const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
  unsigned int(*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
      x->token_costs[tx_size][type][is_inter_block(mi)];
  uint8_t token_cache[32 * 32];
  int cost;
#if CONFIG_VP9_HIGHBITDEPTH
  const uint16_t *cat6_high_cost = vp9_get_high_cost_table(xd->bd);
#else
  const uint16_t *cat6_high_cost = vp9_get_high_cost_table(8);
#endif

  // Check for consistency of tx_size with mode info
  assert(type == PLANE_TYPE_Y
             ? mi->tx_size == tx_size
             : get_uv_tx_size(mi, &xd->plane[plane]) == tx_size);

  if (eob == 0) {
    // single eob token
    cost = token_costs[0][0][pt][EOB_TOKEN];
  } else {
    if (use_fast_coef_costing) {
      int band_left = *band_count++;
      int c;

      // dc token
      int v = qcoeff[0];
      int16_t prev_t;
      cost = vp9_get_token_cost(v, &prev_t, cat6_high_cost);
      cost += (*token_costs)[0][pt][prev_t];

      token_cache[0] = vp9_pt_energy_class[prev_t];
      ++token_costs;

      // ac tokens
      for (c = 1; c < eob; c++) {
        const int rc = scan[c];
        int16_t t;

        v = qcoeff[rc];
        cost += vp9_get_token_cost(v, &t, cat6_high_cost);
        cost += (*token_costs)[!prev_t][!prev_t][t];
        prev_t = t;
        if (!--band_left) {
          band_left = *band_count++;
          ++token_costs;
        }
      }

      // eob token
      if (band_left) cost += (*token_costs)[0][!prev_t][EOB_TOKEN];

    } else {  // !use_fast_coef_costing
      int band_left = *band_count++;
      int c;

      // dc token
      int v = qcoeff[0];
      int16_t tok;
      unsigned int(*tok_cost_ptr)[COEFF_CONTEXTS][ENTROPY_TOKENS];
      cost = vp9_get_token_cost(v, &tok, cat6_high_cost);
      cost += (*token_costs)[0][pt][tok];

      token_cache[0] = vp9_pt_energy_class[tok];
      ++token_costs;

      tok_cost_ptr = &((*token_costs)[!tok]);

      // ac tokens
      for (c = 1; c < eob; c++) {
        const int rc = scan[c];

        v = qcoeff[rc];
        cost += vp9_get_token_cost(v, &tok, cat6_high_cost);
        pt = get_coef_context(nb, token_cache, c);
        cost += (*tok_cost_ptr)[pt][tok];
        token_cache[rc] = vp9_pt_energy_class[tok];
        if (!--band_left) {
          band_left = *band_count++;
          ++token_costs;
        }
        tok_cost_ptr = &((*token_costs)[!tok]);
      }

      // eob token
      if (band_left) {
        pt = get_coef_context(nb, token_cache, c);
        cost += (*token_costs)[0][pt][EOB_TOKEN];
      }
    }
  }

  return cost;
}

// Copy all visible 4x4s in the transform block.
static void copy_block_visible(const MACROBLOCKD *xd,
                               const struct macroblockd_plane *const pd,
                               const uint8_t *src, const int src_stride,
                               uint8_t *dst, const int dst_stride, int blk_row,
                               int blk_col, const BLOCK_SIZE plane_bsize,
                               const BLOCK_SIZE tx_bsize) {
  const int plane_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
  const int plane_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
  const int tx_4x4_w = num_4x4_blocks_wide_lookup[tx_bsize];
  const int tx_4x4_h = num_4x4_blocks_high_lookup[tx_bsize];
  int b4x4s_to_right_edge = num_4x4_to_edge(plane_4x4_w, xd->mb_to_right_edge,
                                            pd->subsampling_x, blk_col);
  int b4x4s_to_bottom_edge = num_4x4_to_edge(plane_4x4_h, xd->mb_to_bottom_edge,
                                             pd->subsampling_y, blk_row);
  const int is_highbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
  if (tx_bsize == BLOCK_4X4 ||
      (b4x4s_to_right_edge >= tx_4x4_w && b4x4s_to_bottom_edge >= tx_4x4_h)) {
    const int w = tx_4x4_w << 2;
    const int h = tx_4x4_h << 2;
#if CONFIG_VP9_HIGHBITDEPTH
    if (is_highbd) {
      vpx_highbd_convolve_copy(CONVERT_TO_SHORTPTR(src), src_stride,
                               CONVERT_TO_SHORTPTR(dst), dst_stride, NULL, 0, 0,
                               0, 0, w, h, xd->bd);
    } else {
#endif
      vpx_convolve_copy(src, src_stride, dst, dst_stride, NULL, 0, 0, 0, 0, w,
                        h);
#if CONFIG_VP9_HIGHBITDEPTH
    }
#endif
  } else {
    int r, c;
    int max_r = VPXMIN(b4x4s_to_bottom_edge, tx_4x4_h);
    int max_c = VPXMIN(b4x4s_to_right_edge, tx_4x4_w);
    // if we are in the unrestricted motion border.
    for (r = 0; r < max_r; ++r) {
      // Skip visiting the sub blocks that are wholly within the UMV.
      for (c = 0; c < max_c; ++c) {
        const uint8_t *src_ptr = src + r * src_stride * 4 + c * 4;
        uint8_t *dst_ptr = dst + r * dst_stride * 4 + c * 4;
#if CONFIG_VP9_HIGHBITDEPTH
        if (is_highbd) {
          vpx_highbd_convolve_copy(CONVERT_TO_SHORTPTR(src_ptr), src_stride,
                                   CONVERT_TO_SHORTPTR(dst_ptr), dst_stride,
                                   NULL, 0, 0, 0, 0, 4, 4, xd->bd);
        } else {
#endif
          vpx_convolve_copy(src_ptr, src_stride, dst_ptr, dst_stride, NULL, 0,
                            0, 0, 0, 4, 4);
#if CONFIG_VP9_HIGHBITDEPTH
        }
#endif
      }
    }
  }
  (void)is_highbd;
}

// Compute the pixel domain sum square error on all visible 4x4s in the
// transform block.
static unsigned pixel_sse(const VP9_COMP *const cpi, const MACROBLOCKD *xd,
                          const struct macroblockd_plane *const pd,
                          const uint8_t *src, const int src_stride,
                          const uint8_t *dst, const int dst_stride, int blk_row,
                          int blk_col, const BLOCK_SIZE plane_bsize,
                          const BLOCK_SIZE tx_bsize) {
  unsigned int sse = 0;
  const int plane_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
  const int plane_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
  const int tx_4x4_w = num_4x4_blocks_wide_lookup[tx_bsize];
  const int tx_4x4_h = num_4x4_blocks_high_lookup[tx_bsize];
  int b4x4s_to_right_edge = num_4x4_to_edge(plane_4x4_w, xd->mb_to_right_edge,
                                            pd->subsampling_x, blk_col);
  int b4x4s_to_bottom_edge = num_4x4_to_edge(plane_4x4_h, xd->mb_to_bottom_edge,
                                             pd->subsampling_y, blk_row);
  if (tx_bsize == BLOCK_4X4 ||
      (b4x4s_to_right_edge >= tx_4x4_w && b4x4s_to_bottom_edge >= tx_4x4_h)) {
    cpi->fn_ptr[tx_bsize].vf(src, src_stride, dst, dst_stride, &sse);
  } else {
    const vpx_variance_fn_t vf_4x4 = cpi->fn_ptr[BLOCK_4X4].vf;
    int r, c;
    unsigned this_sse = 0;
    int max_r = VPXMIN(b4x4s_to_bottom_edge, tx_4x4_h);
    int max_c = VPXMIN(b4x4s_to_right_edge, tx_4x4_w);
    sse = 0;
    // if we are in the unrestricted motion border.
    for (r = 0; r < max_r; ++r) {
      // Skip visiting the sub blocks that are wholly within the UMV.
      for (c = 0; c < max_c; ++c) {
        vf_4x4(src + r * src_stride * 4 + c * 4, src_stride,
               dst + r * dst_stride * 4 + c * 4, dst_stride, &this_sse);
        sse += this_sse;
      }
    }
  }
  return sse;
}

static void dist_block(const VP9_COMP *cpi, MACROBLOCK *x, int plane,
                       BLOCK_SIZE plane_bsize, int block, int blk_row,
                       int blk_col, TX_SIZE tx_size, int64_t *out_dist,
                       int64_t *out_sse, struct buf_2d *out_recon,
                       int sse_calc_done) {
  MACROBLOCKD *const xd = &x->e_mbd;
  const struct macroblock_plane *const p = &x->plane[plane];
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const int eob = p->eobs[block];

  if (!out_recon && x->block_tx_domain && eob) {
    const int ss_txfrm_size = tx_size << 1;
    int64_t this_sse;
    const int shift = tx_size == TX_32X32 ? 0 : 2;
    const tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
    const tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
#if CONFIG_VP9_HIGHBITDEPTH
    const int bd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? xd->bd : 8;
    *out_dist = vp9_highbd_block_error_dispatch(
                    coeff, dqcoeff, 16 << ss_txfrm_size, &this_sse, bd) >>
                shift;
#else
    *out_dist =
        vp9_block_error(coeff, dqcoeff, 16 << ss_txfrm_size, &this_sse) >>
        shift;
#endif  // CONFIG_VP9_HIGHBITDEPTH
    *out_sse = this_sse >> shift;

    if (x->skip_encode && !is_inter_block(xd->mi[0])) {
      // TODO(jingning): tune the model to better capture the distortion.
      const int64_t mean_quant_error =
          (pd->dequant[1] * pd->dequant[1] * (1 << ss_txfrm_size)) >>
#if CONFIG_VP9_HIGHBITDEPTH
          (shift + 2 + (bd - 8) * 2);
#else
          (shift + 2);
#endif  // CONFIG_VP9_HIGHBITDEPTH
      *out_dist += (mean_quant_error >> 4);
      *out_sse += mean_quant_error;
    }
  } else {
    const BLOCK_SIZE tx_bsize = txsize_to_bsize[tx_size];
    const int bs = 4 * num_4x4_blocks_wide_lookup[tx_bsize];
    const int src_stride = p->src.stride;
    const int dst_stride = pd->dst.stride;
    const int src_idx = 4 * (blk_row * src_stride + blk_col);
    const int dst_idx = 4 * (blk_row * dst_stride + blk_col);
    const uint8_t *src = &p->src.buf[src_idx];
    const uint8_t *dst = &pd->dst.buf[dst_idx];
    uint8_t *out_recon_ptr = 0;

    const tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
    unsigned int tmp;

    if (sse_calc_done) {
      tmp = (unsigned int)(*out_sse);
    } else {
      tmp = pixel_sse(cpi, xd, pd, src, src_stride, dst, dst_stride, blk_row,
                      blk_col, plane_bsize, tx_bsize);
    }
    *out_sse = (int64_t)tmp * 16;
    if (out_recon) {
      const int out_recon_idx = 4 * (blk_row * out_recon->stride + blk_col);
      out_recon_ptr = &out_recon->buf[out_recon_idx];
      copy_block_visible(xd, pd, dst, dst_stride, out_recon_ptr,
                         out_recon->stride, blk_row, blk_col, plane_bsize,
                         tx_bsize);
    }

    if (eob) {
#if CONFIG_VP9_HIGHBITDEPTH
      DECLARE_ALIGNED(16, uint16_t, recon16[1024]);
      uint8_t *recon = (uint8_t *)recon16;
#else
      DECLARE_ALIGNED(16, uint8_t, recon[1024]);
#endif  // CONFIG_VP9_HIGHBITDEPTH

#if CONFIG_VP9_HIGHBITDEPTH
      if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
        vpx_highbd_convolve_copy(CONVERT_TO_SHORTPTR(dst), dst_stride, recon16,
                                 32, NULL, 0, 0, 0, 0, bs, bs, xd->bd);
        if (xd->lossless) {
          vp9_highbd_iwht4x4_add(dqcoeff, recon16, 32, eob, xd->bd);
        } else {
          switch (tx_size) {
            case TX_4X4:
              vp9_highbd_idct4x4_add(dqcoeff, recon16, 32, eob, xd->bd);
              break;
            case TX_8X8:
              vp9_highbd_idct8x8_add(dqcoeff, recon16, 32, eob, xd->bd);
              break;
            case TX_16X16:
              vp9_highbd_idct16x16_add(dqcoeff, recon16, 32, eob, xd->bd);
              break;
            default:
              assert(tx_size == TX_32X32);
              vp9_highbd_idct32x32_add(dqcoeff, recon16, 32, eob, xd->bd);
              break;
          }
        }
        recon = CONVERT_TO_BYTEPTR(recon16);
      } else {
#endif  // CONFIG_VP9_HIGHBITDEPTH
        vpx_convolve_copy(dst, dst_stride, recon, 32, NULL, 0, 0, 0, 0, bs, bs);
        switch (tx_size) {
          case TX_32X32: vp9_idct32x32_add(dqcoeff, recon, 32, eob); break;
          case TX_16X16: vp9_idct16x16_add(dqcoeff, recon, 32, eob); break;
          case TX_8X8: vp9_idct8x8_add(dqcoeff, recon, 32, eob); break;
          default:
            assert(tx_size == TX_4X4);
            // this is like vp9_short_idct4x4 but has a special case around
            // eob<=1, which is significant (not just an optimization) for
            // the lossless case.
            x->inv_txfm_add(dqcoeff, recon, 32, eob);
            break;
        }
#if CONFIG_VP9_HIGHBITDEPTH
      }
#endif  // CONFIG_VP9_HIGHBITDEPTH

      tmp = pixel_sse(cpi, xd, pd, src, src_stride, recon, 32, blk_row, blk_col,
                      plane_bsize, tx_bsize);
      if (out_recon) {
        copy_block_visible(xd, pd, recon, 32, out_recon_ptr, out_recon->stride,
                           blk_row, blk_col, plane_bsize, tx_bsize);
      }
    }

    *out_dist = (int64_t)tmp * 16;
  }
}

static int rate_block(int plane, int block, TX_SIZE tx_size, int coeff_ctx,
                      struct rdcost_block_args *args) {
  return cost_coeffs(args->x, plane, block, tx_size, coeff_ctx, args->so->scan,
                     args->so->neighbors, args->use_fast_coef_costing);
}

static void block_rd_txfm(int plane, int block, int blk_row, int blk_col,
                          BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
  struct rdcost_block_args *args = arg;
  MACROBLOCK *const x = args->x;
  MACROBLOCKD *const xd = &x->e_mbd;
  MODE_INFO *const mi = xd->mi[0];
  int64_t rd1, rd2, rd;
  int rate;
  int64_t dist = INT64_MAX;
  int64_t sse = INT64_MAX;
  const int coeff_ctx =
      combine_entropy_contexts(args->t_left[blk_row], args->t_above[blk_col]);
  struct buf_2d *recon = args->this_recon;
  const BLOCK_SIZE tx_bsize = txsize_to_bsize[tx_size];
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const int dst_stride = pd->dst.stride;
  const uint8_t *dst = &pd->dst.buf[4 * (blk_row * dst_stride + blk_col)];
  const int enable_trellis_opt = args->cpi->sf.trellis_opt_tx_rd.method;
  const double trellis_opt_thresh = args->cpi->sf.trellis_opt_tx_rd.thresh;
  int sse_calc_done = 0;
#if CONFIG_MISMATCH_DEBUG
  struct encode_b_args encode_b_arg = {
    x,    enable_trellis_opt, trellis_opt_thresh, &sse_calc_done,
    &sse, args->t_above,      args->t_left,       &mi->skip,
    0,  // mi_row
    0,  // mi_col
    0   // output_enabled
  };
#else
  struct encode_b_args encode_b_arg = {
    x,    enable_trellis_opt, trellis_opt_thresh, &sse_calc_done,
    &sse, args->t_above,      args->t_left,       &mi->skip
  };
#endif

  if (args->exit_early) return;

  if (!is_inter_block(mi)) {
    vp9_encode_block_intra(plane, block, blk_row, blk_col, plane_bsize, tx_size,
                           &encode_b_arg);
    if (recon) {
      uint8_t *rec_ptr = &recon->buf[4 * (blk_row * recon->stride + blk_col)];
      copy_block_visible(xd, pd, dst, dst_stride, rec_ptr, recon->stride,
                         blk_row, blk_col, plane_bsize, tx_bsize);
    }
    if (x->block_tx_domain) {
      dist_block(args->cpi, x, plane, plane_bsize, block, blk_row, blk_col,
                 tx_size, &dist, &sse, /*out_recon=*/NULL, sse_calc_done);
    } else {
      const struct macroblock_plane *const p = &x->plane[plane];
      const int src_stride = p->src.stride;
      const uint8_t *src = &p->src.buf[4 * (blk_row * src_stride + blk_col)];
      unsigned int tmp;
      if (!sse_calc_done) {
        const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
        const int16_t *diff =
            &p->src_diff[4 * (blk_row * diff_stride + blk_col)];
        int visible_width, visible_height;
        sse = sum_squares_visible(xd, pd, diff, diff_stride, blk_row, blk_col,
                                  plane_bsize, tx_bsize, &visible_width,
                                  &visible_height);
      }
#if CONFIG_VP9_HIGHBITDEPTH
      if ((xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) && (xd->bd > 8))
        sse = ROUND64_POWER_OF_TWO(sse, (xd->bd - 8) * 2);
#endif  // CONFIG_VP9_HIGHBITDEPTH
      sse = sse * 16;
      tmp = pixel_sse(args->cpi, xd, pd, src, src_stride, dst, dst_stride,
                      blk_row, blk_col, plane_bsize, tx_bsize);
      dist = (int64_t)tmp * 16;
    }
  } else {
    int skip_txfm_flag = SKIP_TXFM_NONE;
    if (max_txsize_lookup[plane_bsize] == tx_size)
      skip_txfm_flag = x->skip_txfm[(plane << 2) + (block >> (tx_size << 1))];

    // This reduces the risk of bad perceptual quality due to bad prediction.
    // We always force the encoder to perform transform and quantization.
    if (!args->cpi->sf.allow_skip_txfm_ac_dc &&
        skip_txfm_flag == SKIP_TXFM_AC_DC) {
      skip_txfm_flag = SKIP_TXFM_NONE;
    }

    if (skip_txfm_flag == SKIP_TXFM_NONE ||
        (recon && skip_txfm_flag == SKIP_TXFM_AC_ONLY)) {
      const struct macroblock_plane *const p = &x->plane[plane];
      const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
      const int16_t *const diff =
          &p->src_diff[4 * (blk_row * diff_stride + blk_col)];
      const int use_trellis_opt =
          do_trellis_opt(pd, diff, diff_stride, blk_row, blk_col, plane_bsize,
                         tx_size, &encode_b_arg);
      // full forward transform and quantization
      vp9_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, tx_size);
      if (use_trellis_opt) vp9_optimize_b(x, plane, block, tx_size, coeff_ctx);
      dist_block(args->cpi, x, plane, plane_bsize, block, blk_row, blk_col,
                 tx_size, &dist, &sse, recon, sse_calc_done);
    } else if (skip_txfm_flag == SKIP_TXFM_AC_ONLY) {
      // compute DC coefficient
      tran_low_t *const coeff = BLOCK_OFFSET(x->plane[plane].coeff, block);
      tran_low_t *const dqcoeff = BLOCK_OFFSET(xd->plane[plane].dqcoeff, block);
      vp9_xform_quant_dc(x, plane, block, blk_row, blk_col, plane_bsize,
                         tx_size);
      sse = x->bsse[(plane << 2) + (block >> (tx_size << 1))] << 4;
      dist = sse;
      if (x->plane[plane].eobs[block]) {
        const int64_t orig_sse = (int64_t)coeff[0] * coeff[0];
        const int64_t resd_sse = coeff[0] - dqcoeff[0];
        int64_t dc_correct = orig_sse - resd_sse * resd_sse;
#if CONFIG_VP9_HIGHBITDEPTH
        dc_correct >>= ((xd->bd - 8) * 2);
#endif
        if (tx_size != TX_32X32) dc_correct >>= 2;

        dist = VPXMAX(0, sse - dc_correct);
      }
    } else {
      assert(0 && "allow_skip_txfm_ac_dc does not allow SKIP_TXFM_AC_DC.");
    }
  }

  rd = RDCOST(x->rdmult, x->rddiv, 0, dist);
  if (args->this_rd + rd > args->best_rd) {
    args->exit_early = 1;
    return;
  }

  rate = rate_block(plane, block, tx_size, coeff_ctx, args);
  args->t_above[blk_col] = (x->plane[plane].eobs[block] > 0) ? 1 : 0;
  args->t_left[blk_row] = (x->plane[plane].eobs[block] > 0) ? 1 : 0;
  rd1 = RDCOST(x->rdmult, x->rddiv, rate, dist);
  rd2 = RDCOST(x->rdmult, x->rddiv, 0, sse);

  // TODO(jingning): temporarily enabled only for luma component
  rd = VPXMIN(rd1, rd2);
  if (plane == 0) {
    x->zcoeff_blk[tx_size][block] =
        !x->plane[plane].eobs[block] ||
        (x->sharpness == 0 && rd1 > rd2 && !xd->lossless);
    x->sum_y_eobs[tx_size] += x->plane[plane].eobs[block];
  }

  args->this_rate += rate;
  args->this_dist += dist;
  args->this_sse += sse;
  args->this_rd += rd;

  if (args->this_rd > args->best_rd) {
    args->exit_early = 1;
    return;
  }

  args->skippable &= !x->plane[plane].eobs[block];
}

static void txfm_rd_in_plane(const VP9_COMP *cpi, MACROBLOCK *x, int *rate,
                             int64_t *distortion, int *skippable, int64_t *sse,
                             int64_t ref_best_rd, int plane, BLOCK_SIZE bsize,
                             TX_SIZE tx_size, int use_fast_coef_costing,
                             struct buf_2d *recon) {
  MACROBLOCKD *const xd = &x->e_mbd;
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  struct rdcost_block_args args;
  vp9_zero(args);
  args.cpi = cpi;
  args.x = x;
  args.best_rd = ref_best_rd;
  args.use_fast_coef_costing = use_fast_coef_costing;
  args.skippable = 1;
  args.this_recon = recon;

  if (plane == 0) xd->mi[0]->tx_size = tx_size;

  vp9_get_entropy_contexts(bsize, tx_size, pd, args.t_above, args.t_left);

  args.so = get_scan(xd, tx_size, get_plane_type(plane), 0);

  vp9_foreach_transformed_block_in_plane(xd, bsize, plane, block_rd_txfm,
                                         &args);
  if (args.exit_early) {
    *rate = INT_MAX;
    *distortion = INT64_MAX;
    *sse = INT64_MAX;
    *skippable = 0;
  } else {
    *distortion = args.this_dist;
    *rate = args.this_rate;
    *sse = args.this_sse;
    *skippable = args.skippable;
  }
}

static void choose_largest_tx_size(VP9_COMP *cpi, MACROBLOCK *x, int *rate,
                                   int64_t *distortion, int *skip, int64_t *sse,
                                   int64_t ref_best_rd, BLOCK_SIZE bs,
                                   struct buf_2d *recon) {
  const TX_SIZE max_tx_size = max_txsize_lookup[bs];
  VP9_COMMON *const cm = &cpi->common;
  const TX_SIZE largest_tx_size = tx_mode_to_biggest_tx_size[cm->tx_mode];
  MACROBLOCKD *const xd = &x->e_mbd;
  MODE_INFO *const mi = xd->mi[0];

  mi->tx_size = VPXMIN(max_tx_size, largest_tx_size);

  txfm_rd_in_plane(cpi, x, rate, distortion, skip, sse, ref_best_rd, 0, bs,
                   mi->tx_size, cpi->sf.use_fast_coef_costing, recon);
}

static void choose_tx_size_from_rd(VP9_COMP *cpi, MACROBLOCK *x, int *rate,
                                   int64_t *distortion, int *skip,
                                   int64_t *psse, int64_t ref_best_rd,
                                   BLOCK_SIZE bs, struct buf_2d *recon) {
  const TX_SIZE max_tx_size = max_txsize_lookup[bs];
  VP9_COMMON *const cm = &cpi->common;
  MACROBLOCKD *const xd = &x->e_mbd;
  MODE_INFO *const mi = xd->mi[0];
  vpx_prob skip_prob = vp9_get_skip_prob(cm, xd);
  int r[TX_SIZES][2], s[TX_SIZES];
  int64_t d[TX_SIZES], sse[TX_SIZES];
  int64_t rd[TX_SIZES][2] = { { INT64_MAX, INT64_MAX },
                              { INT64_MAX, INT64_MAX },
                              { INT64_MAX, INT64_MAX },
                              { INT64_MAX, INT64_MAX } };
  int n;
  int s0, s1;
  int64_t best_rd = ref_best_rd;
  TX_SIZE best_tx = max_tx_size;
  int start_tx, end_tx;
  const int tx_size_ctx = get_tx_size_context(xd);
#if CONFIG_VP9_HIGHBITDEPTH
  DECLARE_ALIGNED(16, uint16_t, recon_buf16[TX_SIZES][64 * 64]);
  uint8_t *recon_buf[TX_SIZES];
  for (n = 0; n < TX_SIZES; ++n) {
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
      recon_buf[n] = CONVERT_TO_BYTEPTR(recon_buf16[n]);
    } else {
      recon_buf[n] = (uint8_t *)recon_buf16[n];
    }
  }
#else
  DECLARE_ALIGNED(16, uint8_t, recon_buf[TX_SIZES][64 * 64]);
#endif  // CONFIG_VP9_HIGHBITDEPTH

  assert(skip_prob > 0);
  s0 = vp9_cost_bit(skip_prob, 0);
  s1 = vp9_cost_bit(skip_prob, 1);

  if (cm->tx_mode == TX_MODE_SELECT) {
    start_tx = max_tx_size;
    end_tx = VPXMAX(start_tx - cpi->sf.tx_size_search_depth, 0);
    if (bs > BLOCK_32X32) end_tx = VPXMIN(end_tx + 1, start_tx);
  } else {
    TX_SIZE chosen_tx_size =
        VPXMIN(max_tx_size, tx_mode_to_biggest_tx_size[cm->tx_mode]);
    start_tx = chosen_tx_size;
    end_tx = chosen_tx_size;
  }

  for (n = start_tx; n >= end_tx; n--) {
    const int r_tx_size = cpi->tx_size_cost[max_tx_size - 1][tx_size_ctx][n];
    if (recon) {
      struct buf_2d this_recon;
      this_recon.buf = recon_buf[n];
      this_recon.stride = recon->stride;
      txfm_rd_in_plane(cpi, x, &r[n][0], &d[n], &s[n], &sse[n], best_rd, 0, bs,
                       n, cpi->sf.use_fast_coef_costing, &this_recon);
    } else {
      txfm_rd_in_plane(cpi, x, &r[n][0], &d[n], &s[n], &sse[n], best_rd, 0, bs,
                       n, cpi->sf.use_fast_coef_costing, 0);
    }
    r[n][1] = r[n][0];
    if (r[n][0] < INT_MAX) {
      r[n][1] += r_tx_size;
    }
    if (d[n] == INT64_MAX || r[n][0] == INT_MAX) {
      rd[n][0] = rd[n][1] = INT64_MAX;
    } else if (s[n]) {
      if (is_inter_block(mi)) {
        rd[n][0] = rd[n][1] = RDCOST(x->rdmult, x->rddiv, s1, sse[n]);
        r[n][1] -= r_tx_size;
      } else {
        rd[n][0] = RDCOST(x->rdmult, x->rddiv, s1, sse[n]);
        rd[n][1] = RDCOST(x->rdmult, x->rddiv, s1 + r_tx_size, sse[n]);
      }
    } else {
      rd[n][0] = RDCOST(x->rdmult, x->rddiv, r[n][0] + s0, d[n]);
      rd[n][1] = RDCOST(x->rdmult, x->rddiv, r[n][1] + s0, d[n]);
    }

    if (is_inter_block(mi) && !xd->lossless && !s[n] && sse[n] != INT64_MAX) {
      rd[n][0] = VPXMIN(rd[n][0], RDCOST(x->rdmult, x->rddiv, s1, sse[n]));
      rd[n][1] = VPXMIN(rd[n][1], RDCOST(x->rdmult, x->rddiv, s1, sse[n]));
    }

    // Early termination in transform size search.
    if (cpi->sf.tx_size_search_breakout &&
        (rd[n][1] == INT64_MAX ||
         (n < (int)max_tx_size && rd[n][1] > rd[n + 1][1]) || s[n] == 1))
      break;

    if (rd[n][1] < best_rd) {
      best_tx = n;
      best_rd = rd[n][1];
    }
  }
  mi->tx_size = best_tx;

  *distortion = d[mi->tx_size];
  *rate = r[mi->tx_size][cm->tx_mode == TX_MODE_SELECT];
  *skip = s[mi->tx_size];
  *psse = sse[mi->tx_size];
  if (recon) {
#if CONFIG_VP9_HIGHBITDEPTH
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
      memcpy(CONVERT_TO_SHORTPTR(recon->buf),
             CONVERT_TO_SHORTPTR(recon_buf[mi->tx_size]),
             64 * 64 * sizeof(uint16_t));
    } else {
#endif
      memcpy(recon->buf, recon_buf[mi->tx_size], 64 * 64);
#if CONFIG_VP9_HIGHBITDEPTH
    }
#endif
  }
}

static void super_block_yrd(VP9_COMP *cpi, MACROBLOCK *x, int *rate,
                            int64_t *distortion, int *skip, int64_t *psse,
                            BLOCK_SIZE bs, int64_t ref_best_rd,
                            struct buf_2d *recon) {
  MACROBLOCKD *xd = &x->e_mbd;
  int64_t sse;
  int64_t *ret_sse = psse ? psse : &sse;

  assert(bs == xd->mi[0]->sb_type);

  if (cpi->sf.tx_size_search_method == USE_LARGESTALL || xd->lossless) {
    choose_largest_tx_size(cpi, x, rate, distortion, skip, ret_sse, ref_best_rd,
                           bs, recon);
  } else {
    choose_tx_size_from_rd(cpi, x, rate, distortion, skip, ret_sse, ref_best_rd,
                           bs, recon);
  }
}

static int conditional_skipintra(PREDICTION_MODE mode,
                                 PREDICTION_MODE best_intra_mode) {
  if (mode == D117_PRED && best_intra_mode != V_PRED &&
      best_intra_mode != D135_PRED)
    return 1;
  if (mode == D63_PRED && best_intra_mode != V_PRED &&
      best_intra_mode != D45_PRED)
    return 1;
  if (mode == D207_PRED && best_intra_mode != H_PRED &&
      best_intra_mode != D45_PRED)
    return 1;
  if (mode == D153_PRED && best_intra_mode != H_PRED &&
      best_intra_mode != D135_PRED)
    return 1;
  return 0;
}

static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int row,
                                     int col, PREDICTION_MODE *best_mode,
                                     const int *bmode_costs, ENTROPY_CONTEXT *a,
                                     ENTROPY_CONTEXT *l, int *bestrate,
                                     int *bestratey, int64_t *bestdistortion,
                                     BLOCK_SIZE bsize, int64_t rd_thresh) {
  PREDICTION_MODE mode;
  MACROBLOCKD *const xd = &x->e_mbd;
  int64_t best_rd = rd_thresh;
  struct macroblock_plane *p = &x->plane[0];
  struct macroblockd_plane *pd = &xd->plane[0];
  const int src_stride = p->src.stride;
  const int dst_stride = pd->dst.stride;
  const uint8_t *src_init = &p->src.buf[row * 4 * src_stride + col * 4];
  uint8_t *dst_init = &pd->dst.buf[row * 4 * src_stride + col * 4];
  ENTROPY_CONTEXT ta[2], tempa[2];
  ENTROPY_CONTEXT tl[2], templ[2];
  const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
  const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
  int idx, idy;
  uint8_t best_dst[8 * 8];
#if CONFIG_VP9_HIGHBITDEPTH
  uint16_t best_dst16[8 * 8];
#endif
  memcpy(ta, a, num_4x4_blocks_wide * sizeof(a[0]));
  memcpy(tl, l, num_4x4_blocks_high * sizeof(l[0]));

  xd->mi[0]->tx_size = TX_4X4;

  assert(!x->skip_block);

#if CONFIG_VP9_HIGHBITDEPTH
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
      int64_t this_rd;
      int ratey = 0;
      int64_t distortion = 0;
      int rate = bmode_costs[mode];

      if (!(cpi->sf.intra_y_mode_mask[TX_4X4] & (1 << mode))) continue;

      // Only do the oblique modes if the best so far is
      // one of the neighboring directional modes
      if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
        if (conditional_skipintra(mode, *best_mode)) continue;
      }

      memcpy(tempa, ta, num_4x4_blocks_wide * sizeof(ta[0]));
      memcpy(templ, tl, num_4x4_blocks_high * sizeof(tl[0]));

      for (idy = 0; idy < num_4x4_blocks_high; ++idy) {
        for (idx = 0; idx < num_4x4_blocks_wide; ++idx) {
          const int block = (row + idy) * 2 + (col + idx);
          const uint8_t *const src = &src_init[idx * 4 + idy * 4 * src_stride];
          uint8_t *const dst = &dst_init[idx * 4 + idy * 4 * dst_stride];
          uint16_t *const dst16 = CONVERT_TO_SHORTPTR(dst);
          int16_t *const src_diff =
              vp9_raster_block_offset_int16(BLOCK_8X8, block, p->src_diff);
          tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
          tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
          tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
          uint16_t *const eob = &p->eobs[block];
          xd->mi[0]->bmi[block].as_mode = mode;
          vp9_predict_intra_block(xd, 1, TX_4X4, mode,
                                  x->skip_encode ? src : dst,
                                  x->skip_encode ? src_stride : dst_stride, dst,
                                  dst_stride, col + idx, row + idy, 0);
          vpx_highbd_subtract_block(4, 4, src_diff, 8, src, src_stride, dst,
                                    dst_stride, xd->bd);
          if (xd->lossless) {
            const ScanOrder *so = &vp9_default_scan_orders[TX_4X4];
            const int coeff_ctx =
                combine_entropy_contexts(tempa[idx], templ[idy]);
            vp9_highbd_fwht4x4(src_diff, coeff, 8);
            vpx_highbd_quantize_b(coeff, 4 * 4, p, qcoeff, dqcoeff, pd->dequant,
                                  eob, so);
            ratey += cost_coeffs(x, 0, block, TX_4X4, coeff_ctx, so->scan,
                                 so->neighbors, cpi->sf.use_fast_coef_costing);
            tempa[idx] = templ[idy] = (x->plane[0].eobs[block] > 0 ? 1 : 0);
            if (RDCOST(x->rdmult, x->rddiv, ratey, distortion) >= best_rd)
              goto next_highbd;
            vp9_highbd_iwht4x4_add(BLOCK_OFFSET(pd->dqcoeff, block), dst16,
                                   dst_stride, p->eobs[block], xd->bd);
          } else {
            int64_t unused;
            const TX_TYPE tx_type = get_tx_type_4x4(PLANE_TYPE_Y, xd, block);
            const ScanOrder *so = &vp9_scan_orders[TX_4X4][tx_type];
            const int coeff_ctx =
                combine_entropy_contexts(tempa[idx], templ[idy]);
            if (tx_type == DCT_DCT)
              vpx_highbd_fdct4x4(src_diff, coeff, 8);
            else
              vp9_highbd_fht4x4(src_diff, coeff, 8, tx_type);
            vpx_highbd_quantize_b(coeff, 4 * 4, p, qcoeff, dqcoeff, pd->dequant,
                                  eob, so);
            ratey += cost_coeffs(x, 0, block, TX_4X4, coeff_ctx, so->scan,
                                 so->neighbors, cpi->sf.use_fast_coef_costing);
            distortion += vp9_highbd_block_error_dispatch(
                              coeff, BLOCK_OFFSET(pd->dqcoeff, block), 16,
                              &unused, xd->bd) >>
                          2;
            tempa[idx] = templ[idy] = (x->plane[0].eobs[block] > 0 ? 1 : 0);
            if (RDCOST(x->rdmult, x->rddiv, ratey, distortion) >= best_rd)
              goto next_highbd;
            vp9_highbd_iht4x4_add(tx_type, BLOCK_OFFSET(pd->dqcoeff, block),
                                  dst16, dst_stride, p->eobs[block], xd->bd);
          }
        }
      }

      rate += ratey;
      this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);

      if (this_rd < best_rd) {
        *bestrate = rate;
        *bestratey = ratey;
        *bestdistortion = distortion;
        best_rd = this_rd;
        *best_mode = mode;
        memcpy(a, tempa, num_4x4_blocks_wide * sizeof(tempa[0]));
        memcpy(l, templ, num_4x4_blocks_high * sizeof(templ[0]));
        for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy) {
          memcpy(best_dst16 + idy * 8,
                 CONVERT_TO_SHORTPTR(dst_init + idy * dst_stride),
                 num_4x4_blocks_wide * 4 * sizeof(uint16_t));
        }
      }
    next_highbd : {}
    }
    if (best_rd >= rd_thresh || x->skip_encode) return best_rd;

    for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy) {
      memcpy(CONVERT_TO_SHORTPTR(dst_init + idy * dst_stride),
             best_dst16 + idy * 8, num_4x4_blocks_wide * 4 * sizeof(uint16_t));
    }

    return best_rd;
  }
#endif  // CONFIG_VP9_HIGHBITDEPTH

  for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
    int64_t this_rd;
    int ratey = 0;
    int64_t distortion = 0;
    int rate = bmode_costs[mode];

    if (!(cpi->sf.intra_y_mode_mask[TX_4X4] & (1 << mode))) continue;

    // Only do the oblique modes if the best so far is
    // one of the neighboring directional modes
    if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
      if (conditional_skipintra(mode, *best_mode)) continue;
    }

    memcpy(tempa, ta, num_4x4_blocks_wide * sizeof(ta[0]));
    memcpy(templ, tl, num_4x4_blocks_high * sizeof(tl[0]));

    for (idy = 0; idy < num_4x4_blocks_high; ++idy) {
      for (idx = 0; idx < num_4x4_blocks_wide; ++idx) {
        const int block = (row + idy) * 2 + (col + idx);
        const uint8_t *const src = &src_init[idx * 4 + idy * 4 * src_stride];
        uint8_t *const dst = &dst_init[idx * 4 + idy * 4 * dst_stride];
        int16_t *const src_diff =
            vp9_raster_block_offset_int16(BLOCK_8X8, block, p->src_diff);
        tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
        tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
        tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
        uint16_t *const eob = &p->eobs[block];
        xd->mi[0]->bmi[block].as_mode = mode;
        vp9_predict_intra_block(xd, 1, TX_4X4, mode, x->skip_encode ? src : dst,
                                x->skip_encode ? src_stride : dst_stride, dst,
                                dst_stride, col + idx, row + idy, 0);
        vpx_subtract_block(4, 4, src_diff, 8, src, src_stride, dst, dst_stride);

        if (xd->lossless) {
          const ScanOrder *so = &vp9_default_scan_orders[TX_4X4];
          const int coeff_ctx =
              combine_entropy_contexts(tempa[idx], templ[idy]);
          vp9_fwht4x4(src_diff, coeff, 8);
          vpx_quantize_b(coeff, 4 * 4, p, qcoeff, dqcoeff, pd->dequant, eob,
                         so);
          ratey += cost_coeffs(x, 0, block, TX_4X4, coeff_ctx, so->scan,
                               so->neighbors, cpi->sf.use_fast_coef_costing);
          tempa[idx] = templ[idy] = (x->plane[0].eobs[block] > 0) ? 1 : 0;
          if (RDCOST(x->rdmult, x->rddiv, ratey, distortion) >= best_rd)
            goto next;
          vp9_iwht4x4_add(BLOCK_OFFSET(pd->dqcoeff, block), dst, dst_stride,
                          p->eobs[block]);
        } else {
          int64_t unused;
          const TX_TYPE tx_type = get_tx_type_4x4(PLANE_TYPE_Y, xd, block);
          const ScanOrder *so = &vp9_scan_orders[TX_4X4][tx_type];
          const int coeff_ctx =
              combine_entropy_contexts(tempa[idx], templ[idy]);
          vp9_fht4x4(src_diff, coeff, 8, tx_type);
          vpx_quantize_b(coeff, 4 * 4, p, qcoeff, dqcoeff, pd->dequant, eob,
                         so);
          ratey += cost_coeffs(x, 0, block, TX_4X4, coeff_ctx, so->scan,
                               so->neighbors, cpi->sf.use_fast_coef_costing);
          tempa[idx] = templ[idy] = (x->plane[0].eobs[block] > 0) ? 1 : 0;
          distortion += vp9_block_error(coeff, BLOCK_OFFSET(pd->dqcoeff, block),
                                        16, &unused) >>
                        2;
          if (RDCOST(x->rdmult, x->rddiv, ratey, distortion) >= best_rd)
            goto next;
          vp9_iht4x4_add(tx_type, BLOCK_OFFSET(pd->dqcoeff, block), dst,
                         dst_stride, p->eobs[block]);
        }
      }
    }

    rate += ratey;
    this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);

    if (this_rd < best_rd) {
      *bestrate = rate;
      *bestratey = ratey;
      *bestdistortion = distortion;
      best_rd = this_rd;
      *best_mode = mode;
      memcpy(a, tempa, num_4x4_blocks_wide * sizeof(tempa[0]));
      memcpy(l, templ, num_4x4_blocks_high * sizeof(templ[0]));
      for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy)
        memcpy(best_dst + idy * 8, dst_init + idy * dst_stride,
               num_4x4_blocks_wide * 4);
    }
  next : {}
  }

  if (best_rd >= rd_thresh || x->skip_encode) return best_rd;

  for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy)
    memcpy(dst_init + idy * dst_stride, best_dst + idy * 8,
           num_4x4_blocks_wide * 4);

  return best_rd;
}

static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP *cpi, MACROBLOCK *mb,
                                            int *rate, int *rate_y,
                                            int64_t *distortion,
                                            int64_t best_rd) {
  int i, j;
  const MACROBLOCKD *const xd = &mb->e_mbd;
  MODE_INFO *const mic = xd->mi[0];
  const MODE_INFO *above_mi = xd->above_mi;
  const MODE_INFO *left_mi = xd->left_mi;
  const BLOCK_SIZE bsize = xd->mi[0]->sb_type;
  const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
  const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
  int idx, idy;
  int cost = 0;
  int64_t total_distortion = 0;
  int tot_rate_y = 0;
  int64_t total_rd = 0;
  const int *bmode_costs = cpi->mbmode_cost;

  // Pick modes for each sub-block (of size 4x4, 4x8, or 8x4) in an 8x8 block.
  for (idy = 0; idy < 2; idy += num_4x4_blocks_high) {
    for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
      PREDICTION_MODE best_mode = DC_PRED;
      int r = INT_MAX, ry = INT_MAX;
      int64_t d = INT64_MAX, this_rd = INT64_MAX;
      i = idy * 2 + idx;
      if (cpi->common.frame_type == KEY_FRAME) {
        const PREDICTION_MODE A = vp9_above_block_mode(mic, above_mi, i);
        const PREDICTION_MODE L = vp9_left_block_mode(mic, left_mi, i);

        bmode_costs = cpi->y_mode_costs[A][L];
      }

      this_rd = rd_pick_intra4x4block(
          cpi, mb, idy, idx, &best_mode, bmode_costs,
          xd->plane[0].above_context + idx, xd->plane[0].left_context + idy, &r,
          &ry, &d, bsize, best_rd - total_rd);

      if (this_rd >= best_rd - total_rd) return INT64_MAX;

      total_rd += this_rd;
      cost += r;
      total_distortion += d;
      tot_rate_y += ry;

      mic->bmi[i].as_mode = best_mode;
      for (j = 1; j < num_4x4_blocks_high; ++j)
        mic->bmi[i + j * 2].as_mode = best_mode;
      for (j = 1; j < num_4x4_blocks_wide; ++j)
        mic->bmi[i + j].as_mode = best_mode;

      if (total_rd >= best_rd) return INT64_MAX;
    }
  }

  *rate = cost;
  *rate_y = tot_rate_y;
  *distortion = total_distortion;
  mic->mode = mic->bmi[3].as_mode;

  return RDCOST(mb->rdmult, mb->rddiv, cost, total_distortion);
}

// This function is used only for intra_only frames
static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x, int *rate,
                                      int *rate_tokenonly, int64_t *distortion,
                                      int *skippable, BLOCK_SIZE bsize,
                                      int64_t best_rd) {
  PREDICTION_MODE mode;
  PREDICTION_MODE mode_selected = DC_PRED;
  MACROBLOCKD *const xd = &x->e_mbd;
  MODE_INFO *const mic = xd->mi[0];
  int this_rate, this_rate_tokenonly, s;
  int64_t this_distortion, this_rd;
  TX_SIZE best_tx = TX_4X4;
  int *bmode_costs;
  const MODE_INFO *above_mi = xd->above_mi;
  const MODE_INFO *left_mi = xd->left_mi;
  const PREDICTION_MODE A = vp9_above_block_mode(mic, above_mi, 0);
  const PREDICTION_MODE L = vp9_left_block_mode(mic, left_mi, 0);
  bmode_costs = cpi->y_mode_costs[A][L];

  memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm));
  /* Y Search for intra prediction mode */
  for (mode = DC_PRED; mode <= TM_PRED; mode++) {
    if (cpi->sf.use_nonrd_pick_mode) {
      // These speed features are turned on in hybrid non-RD and RD mode
      // for key frame coding in the context of real-time setting.
      if (conditional_skipintra(mode, mode_selected)) continue;
      if (*skippable) break;
    }

    mic->mode = mode;

    super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, &s, NULL,
                    bsize, best_rd, /*recon=*/NULL);

    if (this_rate_tokenonly == INT_MAX) continue;

    this_rate = this_rate_tokenonly + bmode_costs[mode];
    this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);

    if (this_rd < best_rd) {
      mode_selected = mode;
      best_rd = this_rd;
      best_tx = mic->tx_size;
      *rate = this_rate;
      *rate_tokenonly = this_rate_tokenonly;
      *distortion = this_distortion;
      *skippable = s;
    }
  }

  mic->mode = mode_selected;
  mic->tx_size = best_tx;

  return best_rd;
}

// Return value 0: early termination triggered, no valid rd cost available;
//              1: rd cost values are valid.
static int super_block_uvrd(const VP9_COMP *cpi, MACROBLOCK *x, int *rate,
                            int64_t *distortion, int *skippable, int64_t *sse,
                            BLOCK_SIZE bsize, int64_t ref_best_rd) {
  MACROBLOCKD *const xd = &x->e_mbd;
  MODE_INFO *const mi = xd->mi[0];
  const TX_SIZE uv_tx_size = get_uv_tx_size(mi, &xd->plane[1]);
  int plane;
  int pnrate = 0, pnskip = 1;
  int64_t pndist = 0, pnsse = 0;
  int is_cost_valid = 1;

  if (ref_best_rd < 0) is_cost_valid = 0;

  if (is_inter_block(mi) && is_cost_valid) {
    for (plane = 1; plane < MAX_MB_PLANE; ++plane)
      vp9_subtract_plane(x, bsize, plane);
  }

  *rate = 0;
  *distortion = 0;
  *sse = 0;
  *skippable = 1;

  for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
    txfm_rd_in_plane(cpi, x, &pnrate, &pndist, &pnskip, &pnsse, ref_best_rd,
                     plane, bsize, uv_tx_size, cpi->sf.use_fast_coef_costing,
                     /*recon=*/NULL);
    if (pnrate == INT_MAX) {
      is_cost_valid = 0;
      break;
    }
    *rate += pnrate;
    *distortion += pndist;
    *sse += pnsse;
    *skippable &= pnskip;
  }

  if (!is_cost_valid) {
    // reset cost value
    *rate = INT_MAX;
    *distortion = INT64_MAX;
    *sse = INT64_MAX;
    *skippable = 0;
  }

  return is_cost_valid;
}

static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                       PICK_MODE_CONTEXT *ctx, int *rate,
                                       int *rate_tokenonly, int64_t *distortion,
                                       int *skippable, BLOCK_SIZE bsize,
                                       TX_SIZE max_tx_size) {
  MACROBLOCKD *xd = &x->e_mbd;
  PREDICTION_MODE mode;
  PREDICTION_MODE mode_selected = DC_PRED;
  int64_t best_rd = INT64_MAX, this_rd;
  int this_rate_tokenonly, this_rate, s;
  int64_t this_distortion, this_sse;

  memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm));
  for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
    if (!(cpi->sf.intra_uv_mode_mask[max_tx_size] & (1 << mode))) continue;
#if CONFIG_BETTER_HW_COMPATIBILITY && CONFIG_VP9_HIGHBITDEPTH
    if ((xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) &&
        (xd->above_mi == NULL || xd->left_mi == NULL) && need_top_left[mode])
      continue;
#endif  // CONFIG_BETTER_HW_COMPATIBILITY && CONFIG_VP9_HIGHBITDEPTH

    xd->mi[0]->uv_mode = mode;

    if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, &this_distortion, &s,
                          &this_sse, bsize, best_rd))
      continue;
    this_rate =
        this_rate_tokenonly +
        cpi->intra_uv_mode_cost[cpi->common.frame_type][xd->mi[0]->mode][mode];
    this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);

    if (this_rd < best_rd) {
      mode_selected = mode;
      best_rd = this_rd;
      *rate = this_rate;
      *rate_tokenonly = this_rate_tokenonly;
      *distortion = this_distortion;
      *skippable = s;
      if (!x->select_tx_size) swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
    }
  }

  xd->mi[0]->uv_mode = mode_selected;
  return best_rd;
}

#if !CONFIG_REALTIME_ONLY
static int64_t rd_sbuv_dcpred(const VP9_COMP *cpi, MACROBLOCK *x, int *rate,
                              int *rate_tokenonly, int64_t *distortion,
                              int *skippable, BLOCK_SIZE bsize) {
  const VP9_COMMON *cm = &cpi->common;
  int64_t unused;

  x->e_mbd.mi[0]->uv_mode = DC_PRED;
  memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm));
  super_block_uvrd(cpi, x, rate_tokenonly, distortion, skippable, &unused,
                   bsize, INT64_MAX);
  *rate =
      *rate_tokenonly +
      cpi->intra_uv_mode_cost[cm->frame_type][x->e_mbd.mi[0]->mode][DC_PRED];
  return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
}

static void choose_intra_uv_mode(VP9_COMP *cpi, MACROBLOCK *const x,
                                 PICK_MODE_CONTEXT *ctx, BLOCK_SIZE bsize,
                                 TX_SIZE max_tx_size, int *rate_uv,
                                 int *rate_uv_tokenonly, int64_t *dist_uv,
                                 int *skip_uv, PREDICTION_MODE *mode_uv) {
  // Use an estimated rd for uv_intra based on DC_PRED if the
  // appropriate speed flag is set.
  if (cpi->sf.use_uv_intra_rd_estimate) {
    rd_sbuv_dcpred(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
                   bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize);
    // Else do a proper rd search for each possible transform size that may
    // be considered in the main rd loop.
  } else {
    rd_pick_intra_sbuv_mode(cpi, x, ctx, rate_uv, rate_uv_tokenonly, dist_uv,
                            skip_uv, bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize,
                            max_tx_size);
  }
  *mode_uv = x->e_mbd.mi[0]->uv_mode;
}

static int cost_mv_ref(const VP9_COMP *cpi, PREDICTION_MODE mode,
                       int mode_context) {
  assert(is_inter_mode(mode));
  return cpi->inter_mode_cost[mode_context][INTER_OFFSET(mode)];
}

static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
                                int i, PREDICTION_MODE mode, int_mv this_mv[2],
                                int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES],
                                int_mv seg_mvs[MAX_REF_FRAMES],
                                int_mv *best_ref_mv[2], const int *mvjcost,
                                int *mvcost[2]) {
  MODE_INFO *const mi = xd->mi[0];
  const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
  int thismvcost = 0;
  int idx, idy;
  const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[mi->sb_type];
  const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[mi->sb_type];
  const int is_compound = has_second_ref(mi);

  switch (mode) {
    case NEWMV:
      this_mv[0].as_int = seg_mvs[mi->ref_frame[0]].as_int;
      thismvcost += vp9_mv_bit_cost(&this_mv[0].as_mv, &best_ref_mv[0]->as_mv,
                                    mvjcost, mvcost, MV_COST_WEIGHT_SUB);
      if (is_compound) {
        this_mv[1].as_int = seg_mvs[mi->ref_frame[1]].as_int;
        thismvcost += vp9_mv_bit_cost(&this_mv[1].as_mv, &best_ref_mv[1]->as_mv,
                                      mvjcost, mvcost, MV_COST_WEIGHT_SUB);
      }
      break;
    case NEARMV:
    case NEARESTMV:
      this_mv[0].as_int = frame_mv[mode][mi->ref_frame[0]].as_int;
      if (is_compound)
        this_mv[1].as_int = frame_mv[mode][mi->ref_frame[1]].as_int;
      break;
    default:
      assert(mode == ZEROMV);
      this_mv[0].as_int = 0;
      if (is_compound) this_mv[1].as_int = 0;
      break;
  }

  mi->bmi[i].as_mv[0].as_int = this_mv[0].as_int;
  if (is_compound) mi->bmi[i].as_mv[1].as_int = this_mv[1].as_int;

  mi->bmi[i].as_mode = mode;

  for (idy = 0; idy < num_4x4_blocks_high; ++idy)
    for (idx = 0; idx < num_4x4_blocks_wide; ++idx)
      memmove(&mi->bmi[i + idy * 2 + idx], &mi->bmi[i], sizeof(mi->bmi[i]));

  return cost_mv_ref(cpi, mode, mbmi_ext->mode_context[mi->ref_frame[0]]) +
         thismvcost;
}

static int64_t encode_inter_mb_segment(VP9_COMP *cpi, MACROBLOCK *x,
                                       int64_t best_yrd, int i, int *labelyrate,
                                       int64_t *distortion, int64_t *sse,
                                       ENTROPY_CONTEXT *ta, ENTROPY_CONTEXT *tl,
                                       int mi_row, int mi_col) {
  int k;
  MACROBLOCKD *xd = &x->e_mbd;
  struct macroblockd_plane *const pd = &xd->plane[0];
  struct macroblock_plane *const p = &x->plane[0];
  MODE_INFO *const mi = xd->mi[0];
  const BLOCK_SIZE plane_bsize = get_plane_block_size(mi->sb_type, pd);
  const int width = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
  const int height = 4 * num_4x4_blocks_high_lookup[plane_bsize];
  int idx, idy;

  const uint8_t *const src =
      &p->src.buf[vp9_raster_block_offset(BLOCK_8X8, i, p->src.stride)];
  uint8_t *const dst =
      &pd->dst.buf[vp9_raster_block_offset(BLOCK_8X8, i, pd->dst.stride)];
  int64_t thisdistortion = 0, thissse = 0;
  int thisrate = 0, ref;
  const ScanOrder *so = &vp9_default_scan_orders[TX_4X4];
  const int is_compound = has_second_ref(mi);
  const InterpKernel *kernel = vp9_filter_kernels[mi->interp_filter];

  assert(!x->skip_block);

  for (ref = 0; ref < 1 + is_compound; ++ref) {
    const int bw = b_width_log2_lookup[BLOCK_8X8];
    const int h = 4 * (i >> bw);
    const int w = 4 * (i & ((1 << bw) - 1));
    const struct scale_factors *sf = &xd->block_refs[ref]->sf;
    int y_stride = pd->pre[ref].stride;
    uint8_t *pre = pd->pre[ref].buf + (h * pd->pre[ref].stride + w);

    if (vp9_is_scaled(sf)) {
      const int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x));
      const int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y));

      y_stride = xd->block_refs[ref]->buf->y_stride;
      pre = xd->block_refs[ref]->buf->y_buffer;
      pre += scaled_buffer_offset(x_start + w, y_start + h, y_stride, sf);
    }
#if CONFIG_VP9_HIGHBITDEPTH
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
      vp9_highbd_build_inter_predictor(
          CONVERT_TO_SHORTPTR(pre), y_stride, CONVERT_TO_SHORTPTR(dst),
          pd->dst.stride, &mi->bmi[i].as_mv[ref].as_mv,
          &xd->block_refs[ref]->sf, width, height, ref, kernel, MV_PRECISION_Q3,
          mi_col * MI_SIZE + 4 * (i % 2), mi_row * MI_SIZE + 4 * (i / 2),
          xd->bd);
    } else {
      vp9_build_inter_predictor(
          pre, y_stride, dst, pd->dst.stride, &mi->bmi[i].as_mv[ref].as_mv,
          &xd->block_refs[ref]->sf, width, height, ref, kernel, MV_PRECISION_Q3,
          mi_col * MI_SIZE + 4 * (i % 2), mi_row * MI_SIZE + 4 * (i / 2));
    }
#else
    vp9_build_inter_predictor(
        pre, y_stride, dst, pd->dst.stride, &mi->bmi[i].as_mv[ref].as_mv,
        &xd->block_refs[ref]->sf, width, height, ref, kernel, MV_PRECISION_Q3,
        mi_col * MI_SIZE + 4 * (i % 2), mi_row * MI_SIZE + 4 * (i / 2));
#endif  // CONFIG_VP9_HIGHBITDEPTH
  }

#if CONFIG_VP9_HIGHBITDEPTH
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    vpx_highbd_subtract_block(
        height, width, vp9_raster_block_offset_int16(BLOCK_8X8, i, p->src_diff),
        8, src, p->src.stride, dst, pd->dst.stride, xd->bd);
  } else {
    vpx_subtract_block(height, width,
                       vp9_raster_block_offset_int16(BLOCK_8X8, i, p->src_diff),
                       8, src, p->src.stride, dst, pd->dst.stride);
  }
#else
  vpx_subtract_block(height, width,
                     vp9_raster_block_offset_int16(BLOCK_8X8, i, p->src_diff),
                     8, src, p->src.stride, dst, pd->dst.stride);
#endif  // CONFIG_VP9_HIGHBITDEPTH

  k = i;
  for (idy = 0; idy < height / 4; ++idy) {
    for (idx = 0; idx < width / 4; ++idx) {
#if CONFIG_VP9_HIGHBITDEPTH
      const int bd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? xd->bd : 8;
#endif
      int64_t ssz, rd, rd1, rd2;
      tran_low_t *coeff, *qcoeff, *dqcoeff;
      uint16_t *eob;
      int coeff_ctx;
      k += (idy * 2 + idx);
      coeff_ctx = combine_entropy_contexts(ta[k & 1], tl[k >> 1]);
      coeff = BLOCK_OFFSET(p->coeff, k);
      qcoeff = BLOCK_OFFSET(p->qcoeff, k);
      dqcoeff = BLOCK_OFFSET(pd->dqcoeff, k);
      eob = &p->eobs[k];

      x->fwd_txfm4x4(vp9_raster_block_offset_int16(BLOCK_8X8, k, p->src_diff),
                     coeff, 8);
#if CONFIG_VP9_HIGHBITDEPTH
      vpx_highbd_quantize_b(coeff, 4 * 4, p, qcoeff, dqcoeff, pd->dequant, eob,
                            so);
      thisdistortion += vp9_highbd_block_error_dispatch(
          coeff, BLOCK_OFFSET(pd->dqcoeff, k), 16, &ssz, bd);
#else
      vpx_quantize_b(coeff, 4 * 4, p, qcoeff, dqcoeff, pd->dequant, eob, so);
      thisdistortion +=
          vp9_block_error(coeff, BLOCK_OFFSET(pd->dqcoeff, k), 16, &ssz);
#endif  // CONFIG_VP9_HIGHBITDEPTH
      thissse += ssz;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=91 G=92

¤ Dauer der Verarbeitung: 0.34 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge