tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

encodemb.c (35947B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #include "config/aom_config.h"
     13 #include "config/av1_rtcd.h"
     14 #include "config/aom_dsp_rtcd.h"
     15 
     16 #include "aom_dsp/bitwriter.h"
     17 #include "aom_dsp/quantize.h"
     18 #include "aom_mem/aom_mem.h"
     19 #include "aom_ports/mem.h"
     20 
     21 #if CONFIG_BITSTREAM_DEBUG || CONFIG_MISMATCH_DEBUG
     22 #include "aom_util/debug_util.h"
     23 #endif  // CONFIG_BITSTREAM_DEBUG || CONFIG_MISMATCH_DEBUG
     24 
     25 #include "av1/common/cfl.h"
     26 #include "av1/common/idct.h"
     27 #include "av1/common/reconinter.h"
     28 #include "av1/common/reconintra.h"
     29 #include "av1/common/scan.h"
     30 
     31 #include "av1/encoder/av1_quantize.h"
     32 #include "av1/encoder/encodemb.h"
     33 #include "av1/encoder/hybrid_fwd_txfm.h"
     34 #include "av1/encoder/txb_rdopt.h"
     35 #include "av1/encoder/rd.h"
     36 #include "av1/encoder/rdopt.h"
     37 
     38 void av1_subtract_block(BitDepthInfo bd_info, int rows, int cols, int16_t *diff,
     39                        ptrdiff_t diff_stride, const uint8_t *src8,
     40                        ptrdiff_t src_stride, const uint8_t *pred8,
     41                        ptrdiff_t pred_stride) {
     42  assert(rows >= 4 && cols >= 4);
     43 #if CONFIG_AV1_HIGHBITDEPTH
     44  if (bd_info.use_highbitdepth_buf) {
     45    aom_highbd_subtract_block(rows, cols, diff, diff_stride, src8, src_stride,
     46                              pred8, pred_stride);
     47    return;
     48  }
     49 #endif
     50  (void)bd_info;
     51  aom_subtract_block(rows, cols, diff, diff_stride, src8, src_stride, pred8,
     52                     pred_stride);
     53 }
     54 
     55 void av1_subtract_txb(MACROBLOCK *x, int plane, BLOCK_SIZE plane_bsize,
     56                      int blk_col, int blk_row, TX_SIZE tx_size) {
     57  MACROBLOCKD *const xd = &x->e_mbd;
     58  const BitDepthInfo bd_info = get_bit_depth_info(xd);
     59  struct macroblock_plane *const p = &x->plane[plane];
     60  const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
     61  const int diff_stride = block_size_wide[plane_bsize];
     62  const int src_stride = p->src.stride;
     63  const int dst_stride = pd->dst.stride;
     64  const int tx1d_width = tx_size_wide[tx_size];
     65  const int tx1d_height = tx_size_high[tx_size];
     66  uint8_t *dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << MI_SIZE_LOG2];
     67  uint8_t *src = &p->src.buf[(blk_row * src_stride + blk_col) << MI_SIZE_LOG2];
     68  int16_t *src_diff =
     69      &p->src_diff[(blk_row * diff_stride + blk_col) << MI_SIZE_LOG2];
     70  av1_subtract_block(bd_info, tx1d_height, tx1d_width, src_diff, diff_stride,
     71                     src, src_stride, dst, dst_stride);
     72 }
     73 
     74 void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE plane_bsize, int plane) {
     75  struct macroblock_plane *const p = &x->plane[plane];
     76  const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
     77  assert(plane_bsize < BLOCK_SIZES_ALL);
     78  const int bw = block_size_wide[plane_bsize];
     79  const int bh = block_size_high[plane_bsize];
     80  const MACROBLOCKD *xd = &x->e_mbd;
     81  const BitDepthInfo bd_info = get_bit_depth_info(xd);
     82 
     83  av1_subtract_block(bd_info, bh, bw, p->src_diff, bw, p->src.buf,
     84                     p->src.stride, pd->dst.buf, pd->dst.stride);
     85 }
     86 
     87 int av1_optimize_b(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
     88                   int block, TX_SIZE tx_size, TX_TYPE tx_type,
     89                   const TXB_CTX *const txb_ctx, int *rate_cost) {
     90  MACROBLOCKD *const xd = &x->e_mbd;
     91  struct macroblock_plane *const p = &x->plane[plane];
     92  const int eob = p->eobs[block];
     93  const int segment_id = xd->mi[0]->segment_id;
     94 
     95  if (eob == 0 || !cpi->optimize_seg_arr[segment_id] ||
     96      xd->lossless[segment_id]) {
     97    *rate_cost = av1_cost_skip_txb(&x->coeff_costs, txb_ctx, plane, tx_size);
     98    return eob;
     99  }
    100 
    101  return av1_optimize_txb(cpi, x, plane, block, tx_size, tx_type, txb_ctx,
    102                          rate_cost, cpi->oxcf.algo_cfg.sharpness);
    103 }
    104 
    105 // Hyper-parameters for dropout optimization, based on following logics.
    106 // TODO(yjshen): These settings are tuned by experiments. They may still be
    107 // optimized for better performance.
    108 // (1) Coefficients which are large enough will ALWAYS be kept.
    109 static const tran_low_t DROPOUT_COEFF_MAX = 2;  // Max dropout-able coefficient.
    110 // (2) Continuous coefficients will ALWAYS be kept. Here rigorous continuity is
    111 //     NOT required. For example, `5 0 0 0 7` is treated as two continuous
    112 //     coefficients if three zeros do not fulfill the dropout condition.
    113 static const int DROPOUT_CONTINUITY_MAX =
    114    2;  // Max dropout-able continuous coeff.
    115 // (3) Dropout operation is NOT applicable to blocks with large or small
    116 //     quantization index.
    117 static const int DROPOUT_Q_MAX = 128;
    118 static const int DROPOUT_Q_MIN = 16;
    119 // (4) Recall that dropout optimization will forcibly set some quantized
    120 //     coefficients to zero. The key logic on determining whether a coefficient
    121 //     should be dropped is to check the number of continuous zeros before AND
    122 //     after this coefficient. The exact number of zeros for judgement depends
    123 //     on block size and quantization index. More concretely, block size
    124 //     determines the base number of zeros, while quantization index determines
    125 //     the multiplier. Intuitively, larger block requires more zeros and larger
    126 //     quantization index also requires more zeros (more information is lost
    127 //     when using larger quantization index).
    128 static const int DROPOUT_BEFORE_BASE_MAX =
    129    32;  // Max base number for leading zeros.
    130 static const int DROPOUT_BEFORE_BASE_MIN =
    131    16;  // Min base number for leading zeros.
    132 static const int DROPOUT_AFTER_BASE_MAX =
    133    32;  // Max base number for trailing zeros.
    134 static const int DROPOUT_AFTER_BASE_MIN =
    135    16;  // Min base number for trailing zeros.
    136 static const int DROPOUT_MULTIPLIER_MAX =
    137    8;  // Max multiplier on number of zeros.
    138 static const int DROPOUT_MULTIPLIER_MIN =
    139    2;  // Min multiplier on number of zeros.
    140 static const int DROPOUT_MULTIPLIER_Q_BASE =
    141    32;  // Base Q to compute multiplier.
    142 
    143 void av1_dropout_qcoeff(MACROBLOCK *mb, int plane, int block, TX_SIZE tx_size,
    144                        TX_TYPE tx_type, int qindex) {
    145  const int tx_width = tx_size_wide[tx_size];
    146  const int tx_height = tx_size_high[tx_size];
    147 
    148  // Early return if `qindex` is out of range.
    149  if (qindex > DROPOUT_Q_MAX || qindex < DROPOUT_Q_MIN) {
    150    return;
    151  }
    152 
    153  // Compute number of zeros used for dropout judgement.
    154  const int base_size = AOMMAX(tx_width, tx_height);
    155  const int multiplier = CLIP(qindex / DROPOUT_MULTIPLIER_Q_BASE,
    156                              DROPOUT_MULTIPLIER_MIN, DROPOUT_MULTIPLIER_MAX);
    157  const int dropout_num_before =
    158      multiplier *
    159      CLIP(base_size, DROPOUT_BEFORE_BASE_MIN, DROPOUT_BEFORE_BASE_MAX);
    160  const int dropout_num_after =
    161      multiplier *
    162      CLIP(base_size, DROPOUT_AFTER_BASE_MIN, DROPOUT_AFTER_BASE_MAX);
    163 
    164  av1_dropout_qcoeff_num(mb, plane, block, tx_size, tx_type, dropout_num_before,
    165                         dropout_num_after);
    166 }
    167 
    168 void av1_dropout_qcoeff_num(MACROBLOCK *mb, int plane, int block,
    169                            TX_SIZE tx_size, TX_TYPE tx_type,
    170                            int dropout_num_before, int dropout_num_after) {
    171  const struct macroblock_plane *const p = &mb->plane[plane];
    172  tran_low_t *const qcoeff = p->qcoeff + BLOCK_OFFSET(block);
    173  tran_low_t *const dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
    174  const int max_eob = av1_get_max_eob(tx_size);
    175  const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
    176 
    177  // Early return if there are not enough non-zero coefficients.
    178  if (p->eobs[block] == 0 || p->eobs[block] <= dropout_num_before ||
    179      max_eob <= dropout_num_before + dropout_num_after) {
    180    return;
    181  }
    182 
    183  int count_zeros_before = 0;
    184  int count_zeros_after = 0;
    185  int count_nonzeros = 0;
    186  // Index of the first non-zero coefficient after sufficient number of
    187  // continuous zeros. If equals to `-1`, it means number of leading zeros
    188  // hasn't reach `dropout_num_before`.
    189  int idx = -1;
    190  int eob = 0;  // New end of block.
    191 
    192  for (int i = 0; i < p->eobs[block]; ++i) {
    193    const int scan_idx = scan_order->scan[i];
    194    if (abs(qcoeff[scan_idx]) > DROPOUT_COEFF_MAX) {
    195      // Keep large coefficients.
    196      count_zeros_before = 0;
    197      count_zeros_after = 0;
    198      idx = -1;
    199      eob = i + 1;
    200    } else if (qcoeff[scan_idx] == 0) {  // Count zeros.
    201      if (idx == -1) {
    202        ++count_zeros_before;
    203      } else {
    204        ++count_zeros_after;
    205      }
    206    } else {  // Count non-zeros.
    207      if (count_zeros_before >= dropout_num_before) {
    208        idx = (idx == -1) ? i : idx;
    209        ++count_nonzeros;
    210      } else {
    211        count_zeros_before = 0;
    212        eob = i + 1;
    213      }
    214    }
    215 
    216    // Handle continuity.
    217    if (count_nonzeros > DROPOUT_CONTINUITY_MAX) {
    218      count_zeros_before = 0;
    219      count_zeros_after = 0;
    220      count_nonzeros = 0;
    221      idx = -1;
    222      eob = i + 1;
    223    }
    224 
    225    // Handle the trailing zeros after original end of block.
    226    if (idx != -1 && i == p->eobs[block] - 1) {
    227      count_zeros_after += (max_eob - p->eobs[block]);
    228    }
    229 
    230    // Set redundant coefficients to zeros if needed.
    231    if (count_zeros_after >= dropout_num_after) {
    232      for (int j = idx; j <= i; ++j) {
    233        qcoeff[scan_order->scan[j]] = 0;
    234        dqcoeff[scan_order->scan[j]] = 0;
    235      }
    236      count_zeros_before += (i - idx + 1);
    237      count_zeros_after = 0;
    238      count_nonzeros = 0;
    239    } else if (i == p->eobs[block] - 1) {
    240      eob = i + 1;
    241    }
    242  }
    243 
    244  if (eob != p->eobs[block]) {
    245    p->eobs[block] = eob;
    246    p->txb_entropy_ctx[block] =
    247        av1_get_txb_entropy_context(qcoeff, scan_order, eob);
    248  }
    249 }
    250 
    251 // Settings for optimization type. NOTE: To set optimization type for all intra
    252 // frames, both `KEY_BLOCK_OPT_TYPE` and `INTRA_BLOCK_OPT_TYPE` should be set.
    253 // TODO(yjshen): These settings are hard-coded and look okay for now. They
    254 // should be made configurable later.
    255 // Blocks of key frames ONLY.
    256 static const OPT_TYPE KEY_BLOCK_OPT_TYPE = TRELLIS_DROPOUT_OPT;
    257 // Blocks of intra frames (key frames EXCLUSIVE).
    258 static const OPT_TYPE INTRA_BLOCK_OPT_TYPE = TRELLIS_DROPOUT_OPT;
    259 // Blocks of inter frames. (NOTE: Dropout optimization is DISABLED by default
    260 // if trellis optimization is on for inter frames.)
    261 static const OPT_TYPE INTER_BLOCK_OPT_TYPE = TRELLIS_DROPOUT_OPT;
    262 
    263 enum {
    264  QUANT_FUNC_LOWBD = 0,
    265  QUANT_FUNC_HIGHBD = 1,
    266  QUANT_FUNC_TYPES = 2
    267 } UENUM1BYTE(QUANT_FUNC);
    268 
    269 #if CONFIG_AV1_HIGHBITDEPTH
    270 static AV1_QUANT_FACADE
    271    quant_func_list[AV1_XFORM_QUANT_TYPES][QUANT_FUNC_TYPES] = {
    272      { av1_quantize_fp_facade, av1_highbd_quantize_fp_facade },
    273      { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
    274      { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
    275      { NULL, NULL }
    276    };
    277 #else
    278 static AV1_QUANT_FACADE quant_func_list[AV1_XFORM_QUANT_TYPES] = {
    279  av1_quantize_fp_facade, av1_quantize_b_facade, av1_quantize_dc_facade, NULL
    280 };
    281 #endif
    282 
    283 // Computes the transform for DC only blocks
    284 void av1_xform_dc_only(MACROBLOCK *x, int plane, int block,
    285                       TxfmParam *txfm_param, int64_t per_px_mean) {
    286  assert(per_px_mean != INT64_MAX);
    287  const struct macroblock_plane *const p = &x->plane[plane];
    288  const int block_offset = BLOCK_OFFSET(block);
    289  tran_low_t *const coeff = p->coeff + block_offset;
    290  const int n_coeffs = av1_get_max_eob(txfm_param->tx_size);
    291  memset(coeff, 0, sizeof(*coeff) * n_coeffs);
    292  coeff[0] =
    293      (tran_low_t)((per_px_mean * dc_coeff_scale[txfm_param->tx_size]) >> 12);
    294 }
    295 
    296 void av1_xform_quant(MACROBLOCK *x, int plane, int block, int blk_row,
    297                     int blk_col, BLOCK_SIZE plane_bsize, TxfmParam *txfm_param,
    298                     const QUANT_PARAM *qparam) {
    299  av1_xform(x, plane, block, blk_row, blk_col, plane_bsize, txfm_param);
    300  av1_quant(x, plane, block, txfm_param, qparam);
    301 }
    302 
    303 void av1_xform(MACROBLOCK *x, int plane, int block, int blk_row, int blk_col,
    304               BLOCK_SIZE plane_bsize, TxfmParam *txfm_param) {
    305  const struct macroblock_plane *const p = &x->plane[plane];
    306  const int block_offset = BLOCK_OFFSET(block);
    307  tran_low_t *const coeff = p->coeff + block_offset;
    308  const int diff_stride = block_size_wide[plane_bsize];
    309 
    310  const int src_offset = (blk_row * diff_stride + blk_col);
    311  const int16_t *src_diff = &p->src_diff[src_offset << MI_SIZE_LOG2];
    312 
    313  av1_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
    314 }
    315 
    316 void av1_quant(MACROBLOCK *x, int plane, int block, TxfmParam *txfm_param,
    317               const QUANT_PARAM *qparam) {
    318  const struct macroblock_plane *const p = &x->plane[plane];
    319  const SCAN_ORDER *const scan_order =
    320      get_scan(txfm_param->tx_size, txfm_param->tx_type);
    321  const int block_offset = BLOCK_OFFSET(block);
    322  tran_low_t *const coeff = p->coeff + block_offset;
    323  tran_low_t *const qcoeff = p->qcoeff + block_offset;
    324  tran_low_t *const dqcoeff = p->dqcoeff + block_offset;
    325  uint16_t *const eob = &p->eobs[block];
    326 
    327  if (qparam->xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
    328    const int n_coeffs = av1_get_max_eob(txfm_param->tx_size);
    329    if (LIKELY(!x->seg_skip_block)) {
    330 #if CONFIG_AV1_HIGHBITDEPTH
    331      quant_func_list[qparam->xform_quant_idx][txfm_param->is_hbd](
    332          coeff, n_coeffs, p, qcoeff, dqcoeff, eob, scan_order, qparam);
    333 #else
    334      quant_func_list[qparam->xform_quant_idx](
    335          coeff, n_coeffs, p, qcoeff, dqcoeff, eob, scan_order, qparam);
    336 #endif
    337    } else {
    338      av1_quantize_skip(n_coeffs, qcoeff, dqcoeff, eob);
    339    }
    340  }
    341  // use_optimize_b is true means av1_optimze_b will be called,
    342  // thus cannot update entropy ctx now (performed in optimize_b)
    343  if (qparam->use_optimize_b) {
    344    p->txb_entropy_ctx[block] = 0;
    345  } else {
    346    p->txb_entropy_ctx[block] =
    347        av1_get_txb_entropy_context(qcoeff, scan_order, *eob);
    348  }
    349 }
    350 
    351 void av1_setup_xform(const AV1_COMMON *cm, MACROBLOCK *x, TX_SIZE tx_size,
    352                     TX_TYPE tx_type, TxfmParam *txfm_param) {
    353  MACROBLOCKD *const xd = &x->e_mbd;
    354  MB_MODE_INFO *const mbmi = xd->mi[0];
    355 
    356  txfm_param->tx_type = tx_type;
    357  txfm_param->tx_size = tx_size;
    358  txfm_param->lossless = xd->lossless[mbmi->segment_id];
    359  txfm_param->tx_set_type = av1_get_ext_tx_set_type(
    360      tx_size, is_inter_block(mbmi), cm->features.reduced_tx_set_used);
    361 
    362  txfm_param->bd = xd->bd;
    363  txfm_param->is_hbd = is_cur_buf_hbd(xd);
    364 }
    365 void av1_setup_quant(TX_SIZE tx_size, int use_optimize_b, int xform_quant_idx,
    366                     int use_quant_b_adapt, QUANT_PARAM *qparam) {
    367  qparam->log_scale = av1_get_tx_scale(tx_size);
    368  qparam->tx_size = tx_size;
    369 
    370  qparam->use_quant_b_adapt = use_quant_b_adapt;
    371 
    372  // TODO(bohanli): optimize_b and quantization idx has relationship,
    373  // but is kind of buried and complicated in different encoding stages.
    374  // Should have a unified function to derive quant_idx, rather than
    375  // determine and pass in the quant_idx
    376  qparam->use_optimize_b = use_optimize_b;
    377  qparam->xform_quant_idx = xform_quant_idx;
    378 
    379  qparam->qmatrix = NULL;
    380  qparam->iqmatrix = NULL;
    381 }
    382 void av1_setup_qmatrix(const CommonQuantParams *quant_params,
    383                       const MACROBLOCKD *xd, int plane, TX_SIZE tx_size,
    384                       TX_TYPE tx_type, QUANT_PARAM *qparam) {
    385  qparam->qmatrix = av1_get_qmatrix(quant_params, xd, plane, tx_size, tx_type);
    386  qparam->iqmatrix =
    387      av1_get_iqmatrix(quant_params, xd, plane, tx_size, tx_type);
    388 }
    389 
    390 static void encode_block(int plane, int block, int blk_row, int blk_col,
    391                         BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg,
    392                         RUN_TYPE dry_run) {
    393  (void)dry_run;
    394  struct encode_b_args *const args = arg;
    395  const AV1_COMP *const cpi = args->cpi;
    396  const AV1_COMMON *const cm = &cpi->common;
    397  MACROBLOCK *const x = args->x;
    398  MACROBLOCKD *const xd = &x->e_mbd;
    399  MB_MODE_INFO *mbmi = xd->mi[0];
    400  struct macroblock_plane *const p = &x->plane[plane];
    401  struct macroblockd_plane *const pd = &xd->plane[plane];
    402  tran_low_t *const dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
    403  uint8_t *dst;
    404  ENTROPY_CONTEXT *a, *l;
    405  int dummy_rate_cost = 0;
    406 
    407  const int bw = mi_size_wide[plane_bsize];
    408  dst = &pd->dst.buf[(blk_row * pd->dst.stride + blk_col) << MI_SIZE_LOG2];
    409 
    410  a = &args->ta[blk_col];
    411  l = &args->tl[blk_row];
    412 
    413  TX_TYPE tx_type = DCT_DCT;
    414  const int blk_skip_idx = blk_row * bw + blk_col;
    415  if (!is_blk_skip(x->txfm_search_info.blk_skip, plane, blk_skip_idx) &&
    416      !mbmi->skip_mode) {
    417    tx_type = av1_get_tx_type(xd, pd->plane_type, blk_row, blk_col, tx_size,
    418                              cm->features.reduced_tx_set_used);
    419    TxfmParam txfm_param;
    420    QUANT_PARAM quant_param;
    421    const int use_trellis = is_trellis_used(args->enable_optimize_b, dry_run);
    422    int quant_idx;
    423    if (use_trellis)
    424      quant_idx = AV1_XFORM_QUANT_FP;
    425    else
    426      quant_idx =
    427          USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
    428    av1_setup_xform(cm, x, tx_size, tx_type, &txfm_param);
    429    av1_setup_quant(tx_size, use_trellis, quant_idx,
    430                    cpi->oxcf.q_cfg.quant_b_adapt, &quant_param);
    431    av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, tx_type,
    432                      &quant_param);
    433    av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
    434                    &quant_param);
    435 
    436    // Whether trellis or dropout optimization is required for inter frames.
    437    const bool do_trellis = INTER_BLOCK_OPT_TYPE == TRELLIS_OPT ||
    438                            INTER_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT;
    439    const bool do_dropout = INTER_BLOCK_OPT_TYPE == DROPOUT_OPT ||
    440                            INTER_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT;
    441 
    442    if (quant_param.use_optimize_b && do_trellis) {
    443      TXB_CTX txb_ctx;
    444      get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
    445      av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, &txb_ctx,
    446                     &dummy_rate_cost);
    447    }
    448    if (!quant_param.use_optimize_b && do_dropout) {
    449      av1_dropout_qcoeff(x, plane, block, tx_size, tx_type,
    450                         cm->quant_params.base_qindex);
    451    }
    452  } else {
    453    p->eobs[block] = 0;
    454    p->txb_entropy_ctx[block] = 0;
    455  }
    456 
    457  av1_set_txb_context(x, plane, block, tx_size, a, l);
    458 
    459  if (p->eobs[block]) {
    460    // As long as any YUV plane has non-zero quantized transform coefficients,
    461    // mbmi->skip_txfm flag is set to 0.
    462    mbmi->skip_txfm = 0;
    463    av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, dst,
    464                                pd->dst.stride, p->eobs[block],
    465                                cm->features.reduced_tx_set_used);
    466  } else {
    467    // Only when YUV planes all have zero quantized transform coefficients,
    468    // mbmi->skip_txfm flag is set to 1.
    469    mbmi->skip_txfm &= 1;
    470  }
    471 
    472  // TODO(debargha, jingning): Temporarily disable txk_type check for eob=0
    473  // case. It is possible that certain collision in hash index would cause
    474  // the assertion failure. To further optimize the rate-distortion
    475  // performance, we need to re-visit this part and enable this assert
    476  // again.
    477  if (p->eobs[block] == 0 && plane == 0) {
    478 #if 0
    479    if (args->cpi->oxcf.q_cfg.aq_mode == NO_AQ &&
    480        args->cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q) {
    481      // TODO(jingning,angiebird,huisu@google.com): enable txk_check when
    482      // enable_optimize_b is true to detect potential RD bug.
    483      const uint8_t disable_txk_check = args->enable_optimize_b;
    484      if (!disable_txk_check) {
    485        assert(xd->tx_type_map[blk_row * xd->tx_type_map_stride + blk_col)] ==
    486            DCT_DCT);
    487      }
    488    }
    489 #endif
    490    update_txk_array(xd, blk_row, blk_col, tx_size, DCT_DCT);
    491  }
    492 
    493 #if CONFIG_MISMATCH_DEBUG
    494  if (dry_run == OUTPUT_ENABLED) {
    495    int pixel_c, pixel_r;
    496    BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
    497    int blk_w = block_size_wide[bsize];
    498    int blk_h = block_size_high[bsize];
    499    mi_to_pixel_loc(&pixel_c, &pixel_r, xd->mi_col, xd->mi_row, blk_col,
    500                    blk_row, pd->subsampling_x, pd->subsampling_y);
    501    mismatch_record_block_tx(dst, pd->dst.stride, cm->current_frame.order_hint,
    502                             plane, pixel_c, pixel_r, blk_w, blk_h,
    503                             xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH);
    504  }
    505 #endif
    506 }
    507 
    508 static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
    509                               BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
    510                               void *arg, RUN_TYPE dry_run) {
    511  struct encode_b_args *const args = arg;
    512  MACROBLOCK *const x = args->x;
    513  MACROBLOCKD *const xd = &x->e_mbd;
    514  MB_MODE_INFO *const mbmi = xd->mi[0];
    515  const struct macroblockd_plane *const pd = &xd->plane[plane];
    516  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
    517  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
    518 
    519  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
    520 
    521  const TX_SIZE plane_tx_size =
    522      plane ? av1_get_max_uv_txsize(mbmi->bsize, pd->subsampling_x,
    523                                    pd->subsampling_y)
    524            : mbmi->inter_tx_size[av1_get_txb_size_index(plane_bsize, blk_row,
    525                                                         blk_col)];
    526  if (!plane) {
    527    assert(tx_size_wide[tx_size] >= tx_size_wide[plane_tx_size] &&
    528           tx_size_high[tx_size] >= tx_size_high[plane_tx_size]);
    529  }
    530 
    531  if (tx_size == plane_tx_size || plane) {
    532    encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg,
    533                 dry_run);
    534  } else {
    535    assert(tx_size < TX_SIZES_ALL);
    536    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    537    assert(IMPLIES(tx_size <= TX_4X4, sub_txs == tx_size));
    538    assert(IMPLIES(tx_size > TX_4X4, sub_txs < tx_size));
    539    // This is the square transform block partition entry point.
    540    const int bsw = tx_size_wide_unit[sub_txs];
    541    const int bsh = tx_size_high_unit[sub_txs];
    542    const int step = bsh * bsw;
    543    const int row_end =
    544        AOMMIN(tx_size_high_unit[tx_size], max_blocks_high - blk_row);
    545    const int col_end =
    546        AOMMIN(tx_size_wide_unit[tx_size], max_blocks_wide - blk_col);
    547    assert(bsw > 0 && bsh > 0);
    548 
    549    for (int row = 0; row < row_end; row += bsh) {
    550      const int offsetr = blk_row + row;
    551      for (int col = 0; col < col_end; col += bsw) {
    552        const int offsetc = blk_col + col;
    553 
    554        encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
    555                           arg, dry_run);
    556        block += step;
    557      }
    558    }
    559  }
    560 }
    561 
    562 void av1_foreach_transformed_block_in_plane(
    563    const MACROBLOCKD *const xd, BLOCK_SIZE plane_bsize, int plane,
    564    foreach_transformed_block_visitor visit, void *arg) {
    565  const struct macroblockd_plane *const pd = &xd->plane[plane];
    566  // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
    567  // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
    568  // transform size varies per plane, look it up in a common way.
    569  const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
    570  const BLOCK_SIZE tx_bsize = txsize_to_bsize[tx_size];
    571  // Call visit() directly with zero offsets if the current block size is the
    572  // same as the transform block size.
    573  if (plane_bsize == tx_bsize) {
    574    visit(plane, 0, 0, 0, plane_bsize, tx_size, arg);
    575    return;
    576  }
    577  const uint8_t txw_unit = tx_size_wide_unit[tx_size];
    578  const uint8_t txh_unit = tx_size_high_unit[tx_size];
    579  const int step = txw_unit * txh_unit;
    580 
    581  // If mb_to_right_edge is < 0 we are in a situation in which
    582  // the current block size extends into the UMV and we won't
    583  // visit the sub blocks that are wholly within the UMV.
    584  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
    585  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
    586  const BLOCK_SIZE max_unit_bsize =
    587      get_plane_block_size(BLOCK_64X64, pd->subsampling_x, pd->subsampling_y);
    588  const int mu_blocks_wide =
    589      AOMMIN(mi_size_wide[max_unit_bsize], max_blocks_wide);
    590  const int mu_blocks_high =
    591      AOMMIN(mi_size_high[max_unit_bsize], max_blocks_high);
    592 
    593  // Keep track of the row and column of the blocks we use so that we know
    594  // if we are in the unrestricted motion border.
    595  int i = 0;
    596  for (int r = 0; r < max_blocks_high; r += mu_blocks_high) {
    597    const int unit_height = AOMMIN(mu_blocks_high + r, max_blocks_high);
    598    // Skip visiting the sub blocks that are wholly within the UMV.
    599    for (int c = 0; c < max_blocks_wide; c += mu_blocks_wide) {
    600      const int unit_width = AOMMIN(mu_blocks_wide + c, max_blocks_wide);
    601      for (int blk_row = r; blk_row < unit_height; blk_row += txh_unit) {
    602        for (int blk_col = c; blk_col < unit_width; blk_col += txw_unit) {
    603          visit(plane, i, blk_row, blk_col, plane_bsize, tx_size, arg);
    604          i += step;
    605        }
    606      }
    607    }
    608  }
    609  // Check if visit() is invoked at least once.
    610  assert(i >= 1);
    611 }
    612 
    613 typedef struct encode_block_pass1_args {
    614  AV1_COMP *cpi;
    615  MACROBLOCK *x;
    616 } encode_block_pass1_args;
    617 
    618 static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
    619                               BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
    620                               void *arg) {
    621  encode_block_pass1_args *args = (encode_block_pass1_args *)arg;
    622  AV1_COMP *cpi = args->cpi;
    623  AV1_COMMON *cm = &cpi->common;
    624  MACROBLOCK *const x = args->x;
    625  MACROBLOCKD *const xd = &x->e_mbd;
    626  struct macroblock_plane *const p = &x->plane[plane];
    627  struct macroblockd_plane *const pd = &xd->plane[plane];
    628  tran_low_t *const dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
    629 
    630  uint8_t *dst;
    631  dst = &pd->dst.buf[(blk_row * pd->dst.stride + blk_col) << MI_SIZE_LOG2];
    632 
    633  TxfmParam txfm_param;
    634  QUANT_PARAM quant_param;
    635 
    636  av1_setup_xform(cm, x, tx_size, DCT_DCT, &txfm_param);
    637  av1_setup_quant(tx_size, 0, AV1_XFORM_QUANT_B, cpi->oxcf.q_cfg.quant_b_adapt,
    638                  &quant_param);
    639  av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, DCT_DCT,
    640                    &quant_param);
    641 
    642  av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
    643                  &quant_param);
    644 
    645  if (p->eobs[block] > 0) {
    646    txfm_param.eob = p->eobs[block];
    647    if (txfm_param.is_hbd) {
    648      av1_highbd_inv_txfm_add(dqcoeff, dst, pd->dst.stride, &txfm_param);
    649      return;
    650    }
    651    av1_inv_txfm_add(dqcoeff, dst, pd->dst.stride, &txfm_param);
    652  }
    653 }
    654 
    655 void av1_encode_sby_pass1(AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize) {
    656  encode_block_pass1_args args = { cpi, x };
    657  av1_subtract_plane(x, bsize, 0);
    658  av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
    659                                         encode_block_pass1, &args);
    660 }
    661 
    662 void av1_encode_sb(const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
    663                   RUN_TYPE dry_run) {
    664  assert(bsize < BLOCK_SIZES_ALL);
    665  MACROBLOCKD *const xd = &x->e_mbd;
    666  MB_MODE_INFO *mbmi = xd->mi[0];
    667  // In the current encoder implementation, for inter blocks,
    668  // only when YUV planes all have zero quantized transform coefficients,
    669  // mbmi->skip_txfm flag is set to 1.
    670  // For intra blocks, this flag is set to 0 since skipped blocks are so rare
    671  // that transmitting skip_txfm = 1 is very expensive.
    672  // mbmi->skip_txfm is init to 1, and will be modified in encode_block() based
    673  // on transform, quantization, and (if exists) trellis optimization.
    674  mbmi->skip_txfm = 1;
    675  if (x->txfm_search_info.skip_txfm) return;
    676 
    677  struct optimize_ctx ctx;
    678  struct encode_b_args arg = {
    679    cpi, x, &ctx, NULL, NULL, dry_run, cpi->optimize_seg_arr[mbmi->segment_id]
    680  };
    681  const AV1_COMMON *const cm = &cpi->common;
    682  const int num_planes = av1_num_planes(cm);
    683  for (int plane = 0; plane < num_planes; ++plane) {
    684    const struct macroblockd_plane *const pd = &xd->plane[plane];
    685    const int subsampling_x = pd->subsampling_x;
    686    const int subsampling_y = pd->subsampling_y;
    687    if (plane && !xd->is_chroma_ref) break;
    688    const BLOCK_SIZE plane_bsize =
    689        get_plane_block_size(bsize, subsampling_x, subsampling_y);
    690    assert(plane_bsize < BLOCK_SIZES_ALL);
    691    const int mi_width = mi_size_wide[plane_bsize];
    692    const int mi_height = mi_size_high[plane_bsize];
    693    const TX_SIZE max_tx_size = get_vartx_max_txsize(xd, plane_bsize, plane);
    694    const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
    695    const int bw = mi_size_wide[txb_size];
    696    const int bh = mi_size_high[txb_size];
    697    int block = 0;
    698    const int step =
    699        tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
    700    av1_get_entropy_contexts(plane_bsize, pd, ctx.ta[plane], ctx.tl[plane]);
    701    av1_subtract_plane(x, plane_bsize, plane);
    702    arg.ta = ctx.ta[plane];
    703    arg.tl = ctx.tl[plane];
    704    const BLOCK_SIZE max_unit_bsize =
    705        get_plane_block_size(BLOCK_64X64, subsampling_x, subsampling_y);
    706    int mu_blocks_wide = mi_size_wide[max_unit_bsize];
    707    int mu_blocks_high = mi_size_high[max_unit_bsize];
    708    mu_blocks_wide = AOMMIN(mi_width, mu_blocks_wide);
    709    mu_blocks_high = AOMMIN(mi_height, mu_blocks_high);
    710 
    711    for (int idy = 0; idy < mi_height; idy += mu_blocks_high) {
    712      for (int idx = 0; idx < mi_width; idx += mu_blocks_wide) {
    713        int blk_row, blk_col;
    714        const int unit_height = AOMMIN(mu_blocks_high + idy, mi_height);
    715        const int unit_width = AOMMIN(mu_blocks_wide + idx, mi_width);
    716        for (blk_row = idy; blk_row < unit_height; blk_row += bh) {
    717          for (blk_col = idx; blk_col < unit_width; blk_col += bw) {
    718            encode_block_inter(plane, block, blk_row, blk_col, plane_bsize,
    719                               max_tx_size, &arg, dry_run);
    720            block += step;
    721          }
    722        }
    723      }
    724    }
    725  }
    726 }
    727 
    728 static void encode_block_intra(int plane, int block, int blk_row, int blk_col,
    729                               BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
    730                               void *arg) {
    731  struct encode_b_args *const args = arg;
    732  const AV1_COMP *const cpi = args->cpi;
    733  const AV1_COMMON *const cm = &cpi->common;
    734  MACROBLOCK *const x = args->x;
    735  MACROBLOCKD *const xd = &x->e_mbd;
    736  MB_MODE_INFO *mbmi = xd->mi[0];
    737  struct macroblock_plane *const p = &x->plane[plane];
    738  struct macroblockd_plane *const pd = &xd->plane[plane];
    739  tran_low_t *dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
    740  PLANE_TYPE plane_type = get_plane_type(plane);
    741  uint16_t *eob = &p->eobs[block];
    742  const int dst_stride = pd->dst.stride;
    743  uint8_t *dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << MI_SIZE_LOG2];
    744  int dummy_rate_cost = 0;
    745 
    746  av1_predict_intra_block_facade(cm, xd, plane, blk_col, blk_row, tx_size);
    747 
    748  TX_TYPE tx_type = DCT_DCT;
    749  const int bw = mi_size_wide[plane_bsize];
    750  if (plane == 0 && is_blk_skip(x->txfm_search_info.blk_skip, plane,
    751                                blk_row * bw + blk_col)) {
    752    *eob = 0;
    753    p->txb_entropy_ctx[block] = 0;
    754  } else {
    755    av1_subtract_txb(x, plane, plane_bsize, blk_col, blk_row, tx_size);
    756 
    757    const ENTROPY_CONTEXT *a = &args->ta[blk_col];
    758    const ENTROPY_CONTEXT *l = &args->tl[blk_row];
    759    tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
    760                              cm->features.reduced_tx_set_used);
    761    TxfmParam txfm_param;
    762    QUANT_PARAM quant_param;
    763    const int use_trellis =
    764        is_trellis_used(args->enable_optimize_b, args->dry_run);
    765    int quant_idx;
    766    if (use_trellis)
    767      quant_idx = AV1_XFORM_QUANT_FP;
    768    else
    769      quant_idx =
    770          USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
    771 
    772    av1_setup_xform(cm, x, tx_size, tx_type, &txfm_param);
    773    av1_setup_quant(tx_size, use_trellis, quant_idx,
    774                    cpi->oxcf.q_cfg.quant_b_adapt, &quant_param);
    775    av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, tx_type,
    776                      &quant_param);
    777 
    778    av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
    779                    &quant_param);
    780 
    781    // Whether trellis or dropout optimization is required for key frames and
    782    // intra frames.
    783    const bool do_trellis = (frame_is_intra_only(cm) &&
    784                             (KEY_BLOCK_OPT_TYPE == TRELLIS_OPT ||
    785                              KEY_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT)) ||
    786                            (!frame_is_intra_only(cm) &&
    787                             (INTRA_BLOCK_OPT_TYPE == TRELLIS_OPT ||
    788                              INTRA_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT));
    789    const bool do_dropout = (frame_is_intra_only(cm) &&
    790                             (KEY_BLOCK_OPT_TYPE == DROPOUT_OPT ||
    791                              KEY_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT)) ||
    792                            (!frame_is_intra_only(cm) &&
    793                             (INTRA_BLOCK_OPT_TYPE == DROPOUT_OPT ||
    794                              INTRA_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT));
    795 
    796    if (quant_param.use_optimize_b && do_trellis) {
    797      TXB_CTX txb_ctx;
    798      get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
    799      av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, &txb_ctx,
    800                     &dummy_rate_cost);
    801    }
    802    if (do_dropout) {
    803      av1_dropout_qcoeff(x, plane, block, tx_size, tx_type,
    804                         cm->quant_params.base_qindex);
    805    }
    806  }
    807 
    808  if (*eob) {
    809    av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, dst,
    810                                dst_stride, *eob,
    811                                cm->features.reduced_tx_set_used);
    812  }
    813 
    814  // TODO(jingning): Temporarily disable txk_type check for eob=0 case.
    815  // It is possible that certain collision in hash index would cause
    816  // the assertion failure. To further optimize the rate-distortion
    817  // performance, we need to re-visit this part and enable this assert
    818  // again.
    819  if (*eob == 0 && plane == 0) {
    820 #if 0
    821    if (args->cpi->oxcf.q_cfg.aq_mode == NO_AQ
    822        && args->cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q) {
    823      assert(xd->tx_type_map[blk_row * xd->tx_type_map_stride + blk_col)] ==
    824          DCT_DCT);
    825    }
    826 #endif
    827    update_txk_array(xd, blk_row, blk_col, tx_size, DCT_DCT);
    828  }
    829 
    830  // For intra mode, skipped blocks are so rare that transmitting
    831  // skip_txfm = 1 is very expensive.
    832  mbmi->skip_txfm = 0;
    833 
    834 #if !CONFIG_REALTIME_ONLY
    835  if (plane == AOM_PLANE_Y && xd->cfl.store_y) {
    836    cfl_store_tx(xd, blk_row, blk_col, tx_size, plane_bsize);
    837  }
    838 #endif
    839 }
    840 
    841 static void encode_block_intra_and_set_context(int plane, int block,
    842                                               int blk_row, int blk_col,
    843                                               BLOCK_SIZE plane_bsize,
    844                                               TX_SIZE tx_size, void *arg) {
    845  encode_block_intra(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
    846 
    847  struct encode_b_args *const args = arg;
    848  MACROBLOCK *x = args->x;
    849  ENTROPY_CONTEXT *a = &args->ta[blk_col];
    850  ENTROPY_CONTEXT *l = &args->tl[blk_row];
    851  av1_set_txb_context(x, plane, block, tx_size, a, l);
    852 }
    853 
    854 void av1_encode_intra_block_plane(const struct AV1_COMP *cpi, MACROBLOCK *x,
    855                                  BLOCK_SIZE bsize, int plane, RUN_TYPE dry_run,
    856                                  TRELLIS_OPT_TYPE enable_optimize_b) {
    857  assert(bsize < BLOCK_SIZES_ALL);
    858  const MACROBLOCKD *const xd = &x->e_mbd;
    859  if (plane && !xd->is_chroma_ref) return;
    860 
    861  const struct macroblockd_plane *const pd = &xd->plane[plane];
    862  const int ss_x = pd->subsampling_x;
    863  const int ss_y = pd->subsampling_y;
    864  ENTROPY_CONTEXT ta[MAX_MIB_SIZE] = { 0 };
    865  ENTROPY_CONTEXT tl[MAX_MIB_SIZE] = { 0 };
    866  struct encode_b_args arg = {
    867    cpi, x, NULL, ta, tl, dry_run, enable_optimize_b
    868  };
    869  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
    870  if (enable_optimize_b) {
    871    av1_get_entropy_contexts(plane_bsize, pd, ta, tl);
    872  }
    873  av1_foreach_transformed_block_in_plane(
    874      xd, plane_bsize, plane, encode_block_intra_and_set_context, &arg);
    875 }