LCOV - code coverage report
Current view: top level - third_party/aom/av1/encoder - encodeframe.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1631 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 52 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <limits.h>
      13             : #include <math.h>
      14             : #include <stdio.h>
      15             : 
      16             : #include "./av1_rtcd.h"
      17             : #include "./aom_dsp_rtcd.h"
      18             : #include "./aom_config.h"
      19             : 
      20             : #include "aom_dsp/aom_dsp_common.h"
      21             : #include "aom_dsp/binary_codes_writer.h"
      22             : #include "aom_ports/mem.h"
      23             : #include "aom_ports/aom_timer.h"
      24             : #include "aom_ports/system_state.h"
      25             : 
      26             : #include "av1/common/common.h"
      27             : #include "av1/common/entropy.h"
      28             : #include "av1/common/entropymode.h"
      29             : #include "av1/common/idct.h"
      30             : #include "av1/common/mv.h"
      31             : #include "av1/common/mvref_common.h"
      32             : #include "av1/common/pred_common.h"
      33             : #include "av1/common/quant_common.h"
      34             : #include "av1/common/reconintra.h"
      35             : #include "av1/common/reconinter.h"
      36             : #include "av1/common/seg_common.h"
      37             : #include "av1/common/tile_common.h"
      38             : 
      39             : #include "av1/encoder/aq_complexity.h"
      40             : #include "av1/encoder/aq_cyclicrefresh.h"
      41             : #include "av1/encoder/aq_variance.h"
      42             : #if CONFIG_SUPERTX
      43             : #include "av1/encoder/cost.h"
      44             : #endif
      45             : #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
      46             : #include "av1/common/warped_motion.h"
      47             : #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
      48             : #if CONFIG_GLOBAL_MOTION
      49             : #include "av1/encoder/global_motion.h"
      50             : #endif  // CONFIG_GLOBAL_MOTION
      51             : #include "av1/encoder/encodeframe.h"
      52             : #include "av1/encoder/encodemb.h"
      53             : #include "av1/encoder/encodemv.h"
      54             : #if CONFIG_LV_MAP
      55             : #include "av1/encoder/encodetxb.h"
      56             : #endif
      57             : #include "av1/encoder/ethread.h"
      58             : #include "av1/encoder/extend.h"
      59             : #include "av1/encoder/rd.h"
      60             : #include "av1/encoder/rdopt.h"
      61             : #include "av1/encoder/segmentation.h"
      62             : #include "av1/encoder/tokenize.h"
      63             : #if CONFIG_PVQ
      64             : #include "av1/common/pvq.h"
      65             : #include "av1/encoder/pvq_encoder.h"
      66             : #endif
      67             : #if CONFIG_HIGHBITDEPTH
      68             : #define IF_HBD(...) __VA_ARGS__
      69             : #else
      70             : #define IF_HBD(...)
      71             : #endif  // CONFIG_HIGHBITDEPTH
      72             : 
      73             : static void encode_superblock(const AV1_COMP *const cpi, ThreadData *td,
      74             :                               TOKENEXTRA **t, RUN_TYPE dry_run, int mi_row,
      75             :                               int mi_col, BLOCK_SIZE bsize, int *rate);
      76             : 
      77             : #if CONFIG_SUPERTX
      78             : static int check_intra_b(PICK_MODE_CONTEXT *ctx);
      79             : 
      80             : static int check_intra_sb(const AV1_COMP *cpi, const TileInfo *const tile,
      81             :                           int mi_row, int mi_col, BLOCK_SIZE bsize,
      82             :                           PC_TREE *pc_tree);
      83             : static void predict_superblock(const AV1_COMP *const cpi, ThreadData *td,
      84             : #if CONFIG_EXT_INTER
      85             :                                int mi_row_ori, int mi_col_ori,
      86             : #endif  // CONFIG_EXT_INTER
      87             :                                int mi_row_pred, int mi_col_pred,
      88             :                                BLOCK_SIZE bsize_pred, int b_sub8x8, int block);
      89             : static int check_supertx_sb(BLOCK_SIZE bsize, TX_SIZE supertx_size,
      90             :                             PC_TREE *pc_tree);
      91             : static void predict_sb_complex(const AV1_COMP *const cpi, ThreadData *td,
      92             :                                const TileInfo *const tile, int mi_row,
      93             :                                int mi_col, int mi_row_ori, int mi_col_ori,
      94             :                                RUN_TYPE dry_run, BLOCK_SIZE bsize,
      95             :                                BLOCK_SIZE top_bsize, uint8_t *dst_buf[3],
      96             :                                int dst_stride[3], PC_TREE *pc_tree);
      97             : static void update_state_sb_supertx(const AV1_COMP *const cpi, ThreadData *td,
      98             :                                     const TileInfo *const tile, int mi_row,
      99             :                                     int mi_col, BLOCK_SIZE bsize,
     100             :                                     RUN_TYPE dry_run, PC_TREE *pc_tree);
     101             : static void rd_supertx_sb(const AV1_COMP *const cpi, ThreadData *td,
     102             :                           const TileInfo *const tile, int mi_row, int mi_col,
     103             :                           BLOCK_SIZE bsize, int *tmp_rate, int64_t *tmp_dist,
     104             :                           TX_TYPE *best_tx, PC_TREE *pc_tree);
     105             : #endif  // CONFIG_SUPERTX
     106             : 
     107             : // This is used as a reference when computing the source variance for the
     108             : //  purposes of activity masking.
     109             : // Eventually this should be replaced by custom no-reference routines,
     110             : //  which will be faster.
     111             : static const uint8_t AV1_VAR_OFFS[MAX_SB_SIZE] = {
     112             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     113             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     114             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     115             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     116             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     117             : #if CONFIG_EXT_PARTITION
     118             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     119             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     120             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     121             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     122             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
     123             : #endif  // CONFIG_EXT_PARTITION
     124             : };
     125             : 
     126             : #if CONFIG_HIGHBITDEPTH
     127             : static const uint16_t AV1_HIGH_VAR_OFFS_8[MAX_SB_SIZE] = {
     128             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     129             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     130             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     131             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     132             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     133             : #if CONFIG_EXT_PARTITION
     134             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     135             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     136             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     137             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
     138             :   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
     139             : #endif  // CONFIG_EXT_PARTITION
     140             : };
     141             : 
     142             : static const uint16_t AV1_HIGH_VAR_OFFS_10[MAX_SB_SIZE] = {
     143             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     144             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     145             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     146             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     147             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     148             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     149             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     150             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     151             : #if CONFIG_EXT_PARTITION
     152             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     153             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     154             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     155             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     156             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     157             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     158             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
     159             :   128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4
     160             : #endif  // CONFIG_EXT_PARTITION
     161             : };
     162             : 
     163             : static const uint16_t AV1_HIGH_VAR_OFFS_12[MAX_SB_SIZE] = {
     164             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     165             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     166             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     167             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     168             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     169             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     170             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     171             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     172             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     173             :   128 * 16,
     174             : #if CONFIG_EXT_PARTITION
     175             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     176             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     177             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     178             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     179             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     180             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     181             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     182             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     183             :   128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
     184             :   128 * 16
     185             : #endif  // CONFIG_EXT_PARTITION
     186             : };
     187             : #endif  // CONFIG_HIGHBITDEPTH
     188             : 
     189           0 : unsigned int av1_get_sby_perpixel_variance(const AV1_COMP *cpi,
     190             :                                            const struct buf_2d *ref,
     191             :                                            BLOCK_SIZE bs) {
     192             :   unsigned int sse;
     193           0 :   const unsigned int var =
     194           0 :       cpi->fn_ptr[bs].vf(ref->buf, ref->stride, AV1_VAR_OFFS, 0, &sse);
     195           0 :   return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
     196             : }
     197             : 
     198             : #if CONFIG_HIGHBITDEPTH
     199           0 : unsigned int av1_high_get_sby_perpixel_variance(const AV1_COMP *cpi,
     200             :                                                 const struct buf_2d *ref,
     201             :                                                 BLOCK_SIZE bs, int bd) {
     202             :   unsigned int var, sse;
     203           0 :   switch (bd) {
     204             :     case 10:
     205           0 :       var =
     206           0 :           cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
     207           0 :                              CONVERT_TO_BYTEPTR(AV1_HIGH_VAR_OFFS_10), 0, &sse);
     208           0 :       break;
     209             :     case 12:
     210           0 :       var =
     211           0 :           cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
     212           0 :                              CONVERT_TO_BYTEPTR(AV1_HIGH_VAR_OFFS_12), 0, &sse);
     213           0 :       break;
     214             :     case 8:
     215             :     default:
     216           0 :       var =
     217           0 :           cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
     218           0 :                              CONVERT_TO_BYTEPTR(AV1_HIGH_VAR_OFFS_8), 0, &sse);
     219           0 :       break;
     220             :   }
     221           0 :   return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
     222             : }
     223             : #endif  // CONFIG_HIGHBITDEPTH
     224             : 
     225           0 : static unsigned int get_sby_perpixel_diff_variance(const AV1_COMP *const cpi,
     226             :                                                    const struct buf_2d *ref,
     227             :                                                    int mi_row, int mi_col,
     228             :                                                    BLOCK_SIZE bs) {
     229             :   unsigned int sse, var;
     230             :   uint8_t *last_y;
     231           0 :   const YV12_BUFFER_CONFIG *last = get_ref_frame_buffer(cpi, LAST_FRAME);
     232             : 
     233           0 :   assert(last != NULL);
     234           0 :   last_y =
     235           0 :       &last->y_buffer[mi_row * MI_SIZE * last->y_stride + mi_col * MI_SIZE];
     236           0 :   var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride, last_y, last->y_stride, &sse);
     237           0 :   return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
     238             : }
     239             : 
     240           0 : static BLOCK_SIZE get_rd_var_based_fixed_partition(AV1_COMP *cpi, MACROBLOCK *x,
     241             :                                                    int mi_row, int mi_col) {
     242           0 :   unsigned int var = get_sby_perpixel_diff_variance(
     243           0 :       cpi, &x->plane[0].src, mi_row, mi_col, BLOCK_64X64);
     244           0 :   if (var < 8)
     245           0 :     return BLOCK_64X64;
     246           0 :   else if (var < 128)
     247           0 :     return BLOCK_32X32;
     248           0 :   else if (var < 2048)
     249           0 :     return BLOCK_16X16;
     250             :   else
     251           0 :     return BLOCK_8X8;
     252             : }
     253             : 
     254             : // Lighter version of set_offsets that only sets the mode info
     255             : // pointers.
     256           0 : static void set_mode_info_offsets(const AV1_COMP *const cpi,
     257             :                                   MACROBLOCK *const x, MACROBLOCKD *const xd,
     258             :                                   int mi_row, int mi_col) {
     259           0 :   const AV1_COMMON *const cm = &cpi->common;
     260           0 :   const int idx_str = xd->mi_stride * mi_row + mi_col;
     261           0 :   xd->mi = cm->mi_grid_visible + idx_str;
     262           0 :   xd->mi[0] = cm->mi + idx_str;
     263           0 :   x->mbmi_ext = cpi->mbmi_ext_base + (mi_row * cm->mi_cols + mi_col);
     264           0 : }
     265             : 
     266           0 : static void set_offsets_without_segment_id(const AV1_COMP *const cpi,
     267             :                                            const TileInfo *const tile,
     268             :                                            MACROBLOCK *const x, int mi_row,
     269             :                                            int mi_col, BLOCK_SIZE bsize) {
     270           0 :   const AV1_COMMON *const cm = &cpi->common;
     271           0 :   MACROBLOCKD *const xd = &x->e_mbd;
     272           0 :   const int mi_width = mi_size_wide[bsize];
     273           0 :   const int mi_height = mi_size_high[bsize];
     274             : 
     275           0 :   set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
     276           0 :   set_skip_context(xd, mi_row, mi_col);
     277             : #if CONFIG_VAR_TX
     278           0 :   xd->above_txfm_context =
     279           0 :       cm->above_txfm_context + (mi_col << TX_UNIT_WIDE_LOG2);
     280           0 :   xd->left_txfm_context = xd->left_txfm_context_buffer +
     281           0 :                           ((mi_row & MAX_MIB_MASK) << TX_UNIT_HIGH_LOG2);
     282           0 :   xd->max_tx_size = max_txsize_lookup[bsize];
     283             : #endif
     284             : 
     285             :   // Set up destination pointers.
     286           0 :   av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
     287             :                        mi_col);
     288             : 
     289             :   // Set up limit values for MV components.
     290             :   // Mv beyond the range do not produce new/different prediction block.
     291           0 :   x->mv_limits.row_min =
     292           0 :       -(((mi_row + mi_height) * MI_SIZE) + AOM_INTERP_EXTEND);
     293           0 :   x->mv_limits.col_min = -(((mi_col + mi_width) * MI_SIZE) + AOM_INTERP_EXTEND);
     294           0 :   x->mv_limits.row_max = (cm->mi_rows - mi_row) * MI_SIZE + AOM_INTERP_EXTEND;
     295           0 :   x->mv_limits.col_max = (cm->mi_cols - mi_col) * MI_SIZE + AOM_INTERP_EXTEND;
     296             : 
     297           0 :   set_plane_n4(xd, mi_width, mi_height);
     298             : 
     299             :   // Set up distance of MB to edge of frame in 1/8th pel units.
     300           0 :   assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
     301           0 :   set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width,
     302             : #if CONFIG_DEPENDENT_HORZTILES
     303             :                  cm->dependent_horz_tiles,
     304             : #endif  // CONFIG_DEPENDENT_HORZTILES
     305             :                  cm->mi_rows, cm->mi_cols);
     306             : 
     307             :   // Set up source buffers.
     308           0 :   av1_setup_src_planes(x, cpi->source, mi_row, mi_col);
     309             : 
     310             :   // R/D setup.
     311           0 :   x->rddiv = cpi->rd.RDDIV;
     312           0 :   x->rdmult = cpi->rd.RDMULT;
     313             : 
     314             :   // required by av1_append_sub8x8_mvs_for_idx() and av1_find_best_ref_mvs()
     315           0 :   xd->tile = *tile;
     316           0 : }
     317             : 
     318           0 : static void set_offsets(const AV1_COMP *const cpi, const TileInfo *const tile,
     319             :                         MACROBLOCK *const x, int mi_row, int mi_col,
     320             :                         BLOCK_SIZE bsize) {
     321           0 :   const AV1_COMMON *const cm = &cpi->common;
     322           0 :   MACROBLOCKD *const xd = &x->e_mbd;
     323             :   MB_MODE_INFO *mbmi;
     324           0 :   const struct segmentation *const seg = &cm->seg;
     325             : 
     326           0 :   set_offsets_without_segment_id(cpi, tile, x, mi_row, mi_col, bsize);
     327             : 
     328           0 :   mbmi = &xd->mi[0]->mbmi;
     329             : 
     330             :   // Setup segment ID.
     331           0 :   if (seg->enabled) {
     332           0 :     if (!cpi->vaq_refresh) {
     333           0 :       const uint8_t *const map =
     334           0 :           seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
     335           0 :       mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
     336             :     }
     337           0 :     av1_init_plane_quantizers(cpi, x, mbmi->segment_id);
     338             :   } else {
     339           0 :     mbmi->segment_id = 0;
     340             :   }
     341             : 
     342             : #if CONFIG_SUPERTX
     343             :   mbmi->segment_id_supertx = MAX_SEGMENTS;
     344             : #endif  // CONFIG_SUPERTX
     345           0 : }
     346             : 
     347             : #if CONFIG_SUPERTX
     348             : static void set_offsets_supertx(const AV1_COMP *const cpi, ThreadData *td,
     349             :                                 const TileInfo *const tile, int mi_row,
     350             :                                 int mi_col, BLOCK_SIZE bsize) {
     351             :   MACROBLOCK *const x = &td->mb;
     352             :   const AV1_COMMON *const cm = &cpi->common;
     353             :   MACROBLOCKD *const xd = &x->e_mbd;
     354             :   const int mi_width = mi_size_wide[bsize];
     355             :   const int mi_height = mi_size_high[bsize];
     356             : #if CONFIG_DEPENDENT_HORZTILES
     357             :   set_mode_info_offsets(cpi, x, xd, mi_row, mi_col, cm->dependent_horz_tiles);
     358             : #else
     359             :   set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
     360             : #endif
     361             : 
     362             :   // Set up distance of MB to edge of frame in 1/8th pel units.
     363             :   assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
     364             :   set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width,
     365             : #if CONFIG_DEPENDENT_HORZTILES
     366             :                  cm->dependent_horz_tiles,
     367             : #endif  // CONFIG_DEPENDENT_HORZTILES
     368             :                  cm->mi_rows, cm->mi_cols);
     369             : }
     370             : 
     371             : static void set_offsets_extend(const AV1_COMP *const cpi, ThreadData *td,
     372             :                                const TileInfo *const tile, int mi_row_pred,
     373             :                                int mi_col_pred, int mi_row_ori, int mi_col_ori,
     374             :                                BLOCK_SIZE bsize_pred) {
     375             :   // Used in supertx
     376             :   // (mi_row_ori, mi_col_ori, bsize_ori): region for mv
     377             :   // (mi_row_pred, mi_col_pred, bsize_pred): region to predict
     378             :   MACROBLOCK *const x = &td->mb;
     379             :   const AV1_COMMON *const cm = &cpi->common;
     380             :   MACROBLOCKD *const xd = &x->e_mbd;
     381             :   const int mi_width = mi_size_wide[bsize_pred];
     382             :   const int mi_height = mi_size_high[bsize_pred];
     383             : 
     384             : #if CONFIG_DEPENDENT_HORZTILES
     385             :   set_mode_info_offsets(cpi, x, xd, mi_row_ori, mi_col_ori,
     386             :                         cm->dependent_horz_tiles);
     387             : #else
     388             :   set_mode_info_offsets(cpi, x, xd, mi_row_ori, mi_col_ori);
     389             : #endif
     390             : 
     391             :   // Set up limit values for MV components.
     392             :   // Mv beyond the range do not produce new/different prediction block.
     393             :   x->mv_limits.row_min =
     394             :       -(((mi_row_pred + mi_height) * MI_SIZE) + AOM_INTERP_EXTEND);
     395             :   x->mv_limits.col_min =
     396             :       -(((mi_col_pred + mi_width) * MI_SIZE) + AOM_INTERP_EXTEND);
     397             :   x->mv_limits.row_max =
     398             :       (cm->mi_rows - mi_row_pred) * MI_SIZE + AOM_INTERP_EXTEND;
     399             :   x->mv_limits.col_max =
     400             :       (cm->mi_cols - mi_col_pred) * MI_SIZE + AOM_INTERP_EXTEND;
     401             : 
     402             : // Set up distance of MB to edge of frame in 1/8th pel units.
     403             : #if !CONFIG_CB4X4
     404             :   assert(!(mi_col_pred & (mi_width - mi_size_wide[BLOCK_8X8])) &&
     405             :          !(mi_row_pred & (mi_height - mi_size_high[BLOCK_8X8])));
     406             : #endif
     407             :   set_mi_row_col(xd, tile, mi_row_pred, mi_height, mi_col_pred, mi_width,
     408             : #if CONFIG_DEPENDENT_HORZTILES
     409             :                  cm->dependent_horz_tiles,
     410             : #endif  // CONFIG_DEPENDENT_HORZTILES
     411             :                  cm->mi_rows, cm->mi_cols);
     412             :   xd->up_available = (mi_row_ori > tile->mi_row_start);
     413             :   xd->left_available = (mi_col_ori > tile->mi_col_start);
     414             : 
     415             :   // R/D setup.
     416             :   x->rddiv = cpi->rd.RDDIV;
     417             :   x->rdmult = cpi->rd.RDMULT;
     418             : }
     419             : 
     420             : static void set_segment_id_supertx(const AV1_COMP *const cpi,
     421             :                                    MACROBLOCK *const x, const int mi_row,
     422             :                                    const int mi_col, const BLOCK_SIZE bsize) {
     423             :   const AV1_COMMON *cm = &cpi->common;
     424             :   const struct segmentation *seg = &cm->seg;
     425             :   const int miw = AOMMIN(mi_size_wide[bsize], cm->mi_cols - mi_col);
     426             :   const int mih = AOMMIN(mi_size_high[bsize], cm->mi_rows - mi_row);
     427             :   const int mi_offset = mi_row * cm->mi_stride + mi_col;
     428             :   MODE_INFO **const mip = cm->mi_grid_visible + mi_offset;
     429             :   int r, c;
     430             :   int seg_id_supertx = MAX_SEGMENTS;
     431             : 
     432             :   if (!seg->enabled) {
     433             :     seg_id_supertx = 0;
     434             :   } else {
     435             :     // Find the minimum segment_id
     436             :     for (r = 0; r < mih; r++)
     437             :       for (c = 0; c < miw; c++)
     438             :         seg_id_supertx =
     439             :             AOMMIN(mip[r * cm->mi_stride + c]->mbmi.segment_id, seg_id_supertx);
     440             :     assert(0 <= seg_id_supertx && seg_id_supertx < MAX_SEGMENTS);
     441             : 
     442             :     // Initialize plane quantisers
     443             :     av1_init_plane_quantizers(cpi, x, seg_id_supertx);
     444             :   }
     445             : 
     446             :   // Assign the the segment_id back to segment_id_supertx
     447             :   for (r = 0; r < mih; r++)
     448             :     for (c = 0; c < miw; c++)
     449             :       mip[r * cm->mi_stride + c]->mbmi.segment_id_supertx = seg_id_supertx;
     450             : }
     451             : #endif  // CONFIG_SUPERTX
     452             : 
     453             : #if CONFIG_DUAL_FILTER
     454           0 : static void reset_intmv_filter_type(const AV1_COMMON *const cm, MACROBLOCKD *xd,
     455             :                                     MB_MODE_INFO *mbmi) {
     456             :   int dir;
     457           0 :   for (dir = 0; dir < 2; ++dir) {
     458           0 :     if (!has_subpel_mv_component(xd->mi[0], xd, dir) &&
     459           0 :         (mbmi->ref_frame[1] == NONE_FRAME ||
     460           0 :          !has_subpel_mv_component(xd->mi[0], xd, dir + 2)))
     461           0 :       mbmi->interp_filter[dir] = (cm->interp_filter == SWITCHABLE)
     462             :                                      ? EIGHTTAP_REGULAR
     463           0 :                                      : cm->interp_filter;
     464           0 :     mbmi->interp_filter[dir + 2] = mbmi->interp_filter[dir];
     465             :   }
     466           0 : }
     467             : 
     468           0 : static void update_filter_type_count(FRAME_COUNTS *counts,
     469             :                                      const MACROBLOCKD *xd,
     470             :                                      const MB_MODE_INFO *mbmi) {
     471             :   int dir;
     472           0 :   for (dir = 0; dir < 2; ++dir) {
     473           0 :     if (has_subpel_mv_component(xd->mi[0], xd, dir) ||
     474           0 :         (mbmi->ref_frame[1] > INTRA_FRAME &&
     475           0 :          has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
     476           0 :       const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
     477           0 :       ++counts->switchable_interp[ctx][mbmi->interp_filter[dir]];
     478             :     }
     479             :   }
     480           0 : }
     481             : #endif
     482             : #if CONFIG_GLOBAL_MOTION
     483           0 : static void update_global_motion_used(PREDICTION_MODE mode, BLOCK_SIZE bsize,
     484             :                                       const MB_MODE_INFO *mbmi,
     485             :                                       RD_COUNTS *rdc) {
     486           0 :   if (mode == ZEROMV
     487             : #if CONFIG_EXT_INTER
     488           0 :       || mode == ZERO_ZEROMV
     489             : #endif
     490             :       ) {
     491           0 :     const int num_4x4s =
     492           0 :         num_4x4_blocks_wide_lookup[bsize] * num_4x4_blocks_high_lookup[bsize];
     493             :     int ref;
     494           0 :     for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
     495           0 :       rdc->global_motion_used[mbmi->ref_frame[ref]] += num_4x4s;
     496             :     }
     497             :   }
     498           0 : }
     499             : #endif  // CONFIG_GLOBAL_MOTION
     500             : 
     501           0 : static void reset_tx_size(MACROBLOCKD *xd, MB_MODE_INFO *mbmi,
     502             :                           const TX_MODE tx_mode) {
     503           0 :   if (xd->lossless[mbmi->segment_id]) {
     504           0 :     mbmi->tx_size = TX_4X4;
     505           0 :   } else if (tx_mode != TX_MODE_SELECT) {
     506           0 :     mbmi->tx_size =
     507           0 :         tx_size_from_tx_mode(mbmi->sb_type, tx_mode, is_inter_block(mbmi));
     508             :   }
     509           0 : }
     510             : 
     511           0 : static void set_ref_and_pred_mvs(MACROBLOCK *const x, int_mv *const mi_pred_mv,
     512             :                                  int8_t rf_type) {
     513           0 :   MACROBLOCKD *const xd = &x->e_mbd;
     514           0 :   MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
     515             : 
     516           0 :   const int bw = xd->n8_w << MI_SIZE_LOG2;
     517           0 :   const int bh = xd->n8_h << MI_SIZE_LOG2;
     518           0 :   int ref_mv_idx = mbmi->ref_mv_idx;
     519           0 :   MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
     520           0 :   CANDIDATE_MV *const curr_ref_mv_stack = mbmi_ext->ref_mv_stack[rf_type];
     521             : 
     522             : #if CONFIG_EXT_INTER
     523           0 :   if (has_second_ref(mbmi)) {
     524             :     // Special case: NEAR_NEWMV and NEW_NEARMV modes use 1 + mbmi->ref_mv_idx
     525             :     // (like NEARMV) instead
     526           0 :     if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV) ref_mv_idx += 1;
     527             : 
     528           0 :     if (compound_ref0_mode(mbmi->mode) == NEWMV) {
     529           0 :       int_mv this_mv = curr_ref_mv_stack[ref_mv_idx].this_mv;
     530           0 :       clamp_mv_ref(&this_mv.as_mv, bw, bh, xd);
     531           0 :       mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
     532           0 :       mbmi->pred_mv[0] = this_mv;
     533           0 :       mi_pred_mv[0] = this_mv;
     534             :     }
     535           0 :     if (compound_ref1_mode(mbmi->mode) == NEWMV) {
     536           0 :       int_mv this_mv = curr_ref_mv_stack[ref_mv_idx].comp_mv;
     537           0 :       clamp_mv_ref(&this_mv.as_mv, bw, bh, xd);
     538           0 :       mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0] = this_mv;
     539           0 :       mbmi->pred_mv[1] = this_mv;
     540           0 :       mi_pred_mv[1] = this_mv;
     541             :     }
     542             :   } else {
     543             : #endif  // CONFIG_EXT_INTER
     544           0 :     if (mbmi->mode == NEWMV) {
     545             :       int i;
     546           0 :       for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
     547           0 :         int_mv this_mv = (i == 0) ? curr_ref_mv_stack[ref_mv_idx].this_mv
     548           0 :                                   : curr_ref_mv_stack[ref_mv_idx].comp_mv;
     549           0 :         clamp_mv_ref(&this_mv.as_mv, bw, bh, xd);
     550           0 :         mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0] = this_mv;
     551           0 :         mbmi->pred_mv[i] = this_mv;
     552           0 :         mi_pred_mv[i] = this_mv;
     553             :       }
     554             :     }
     555             : #if CONFIG_EXT_INTER
     556             :   }
     557             : #endif  // CONFIG_EXT_INTER
     558           0 : }
     559             : 
     560           0 : static void update_state(const AV1_COMP *const cpi, ThreadData *td,
     561             :                          PICK_MODE_CONTEXT *ctx, int mi_row, int mi_col,
     562             :                          BLOCK_SIZE bsize, RUN_TYPE dry_run) {
     563             :   int i, x_idx, y;
     564           0 :   const AV1_COMMON *const cm = &cpi->common;
     565           0 :   RD_COUNTS *const rdc = &td->rd_counts;
     566           0 :   MACROBLOCK *const x = &td->mb;
     567           0 :   MACROBLOCKD *const xd = &x->e_mbd;
     568           0 :   struct macroblock_plane *const p = x->plane;
     569           0 :   struct macroblockd_plane *const pd = xd->plane;
     570           0 :   MODE_INFO *mi = &ctx->mic;
     571           0 :   MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
     572           0 :   MODE_INFO *mi_addr = xd->mi[0];
     573           0 :   const struct segmentation *const seg = &cm->seg;
     574           0 :   const int bw = mi_size_wide[mi->mbmi.sb_type];
     575           0 :   const int bh = mi_size_high[mi->mbmi.sb_type];
     576           0 :   const int x_mis = AOMMIN(bw, cm->mi_cols - mi_col);
     577           0 :   const int y_mis = AOMMIN(bh, cm->mi_rows - mi_row);
     578           0 :   MV_REF *const frame_mvs = cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
     579             :   int w, h;
     580             : 
     581           0 :   const int mis = cm->mi_stride;
     582           0 :   const int mi_width = mi_size_wide[bsize];
     583           0 :   const int mi_height = mi_size_high[bsize];
     584           0 :   const int unify_bsize = CONFIG_CB4X4;
     585             : 
     586             :   int8_t rf_type;
     587             : 
     588             : #if !CONFIG_SUPERTX
     589           0 :   assert(mi->mbmi.sb_type == bsize);
     590             : #endif
     591             : 
     592           0 :   *mi_addr = *mi;
     593           0 :   *x->mbmi_ext = ctx->mbmi_ext;
     594             : 
     595             : #if CONFIG_DUAL_FILTER
     596           0 :   reset_intmv_filter_type(cm, xd, mbmi);
     597             : #endif
     598             : 
     599           0 :   rf_type = av1_ref_frame_type(mbmi->ref_frame);
     600           0 :   if (x->mbmi_ext->ref_mv_count[rf_type] > 1 &&
     601           0 :       (mbmi->sb_type >= BLOCK_8X8 || unify_bsize)) {
     602           0 :     set_ref_and_pred_mvs(x, mi->mbmi.pred_mv, rf_type);
     603             :   }
     604             : 
     605             :   // If segmentation in use
     606           0 :   if (seg->enabled) {
     607             :     // For in frame complexity AQ copy the segment id from the segment map.
     608           0 :     if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
     609           0 :       const uint8_t *const map =
     610           0 :           seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
     611           0 :       mi_addr->mbmi.segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
     612           0 :       reset_tx_size(xd, &mi_addr->mbmi, cm->tx_mode);
     613             :     }
     614             :     // Else for cyclic refresh mode update the segment map, set the segment id
     615             :     // and then update the quantizer.
     616           0 :     if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
     617           0 :       av1_cyclic_refresh_update_segment(cpi, &xd->mi[0]->mbmi, mi_row, mi_col,
     618           0 :                                         bsize, ctx->rate, ctx->dist, x->skip);
     619           0 :       reset_tx_size(xd, &mi_addr->mbmi, cm->tx_mode);
     620             :     }
     621             :   }
     622             : 
     623           0 :   for (i = 0; i < MAX_MB_PLANE; ++i) {
     624           0 :     p[i].coeff = ctx->coeff[i];
     625           0 :     p[i].qcoeff = ctx->qcoeff[i];
     626           0 :     pd[i].dqcoeff = ctx->dqcoeff[i];
     627             : #if CONFIG_PVQ
     628             :     pd[i].pvq_ref_coeff = ctx->pvq_ref_coeff[i];
     629             : #endif
     630           0 :     p[i].eobs = ctx->eobs[i];
     631             : #if CONFIG_LV_MAP
     632             :     p[i].txb_entropy_ctx = ctx->txb_entropy_ctx[i];
     633             : #endif  // CONFIG_LV_MAP
     634             :   }
     635             : #if CONFIG_PALETTE
     636           0 :   for (i = 0; i < 2; ++i) pd[i].color_index_map = ctx->color_index_map[i];
     637             : #endif  // CONFIG_PALETTE
     638             : 
     639             :   // Restore the coding context of the MB to that that was in place
     640             :   // when the mode was picked for it
     641           0 :   for (y = 0; y < mi_height; y++)
     642           0 :     for (x_idx = 0; x_idx < mi_width; x_idx++)
     643           0 :       if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width > x_idx &&
     644           0 :           (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > y) {
     645           0 :         xd->mi[x_idx + y * mis] = mi_addr;
     646             :       }
     647             : 
     648             : #if CONFIG_DELTA_Q && !CONFIG_EXT_DELTA_Q
     649             :   if (cpi->oxcf.aq_mode > NO_AQ && cpi->oxcf.aq_mode < DELTA_AQ)
     650             :     av1_init_plane_quantizers(cpi, x, xd->mi[0]->mbmi.segment_id);
     651             : #else
     652           0 :   if (cpi->oxcf.aq_mode)
     653           0 :     av1_init_plane_quantizers(cpi, x, xd->mi[0]->mbmi.segment_id);
     654             : #endif
     655             : 
     656           0 :   if (is_inter_block(mbmi) && mbmi->sb_type < BLOCK_8X8 && !unify_bsize) {
     657           0 :     mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
     658           0 :     mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
     659             :   }
     660             : 
     661           0 :   x->skip = ctx->skip;
     662             : 
     663             : #if CONFIG_VAR_TX
     664           0 :   for (i = 0; i < 1; ++i)
     665           0 :     memcpy(x->blk_skip[i], ctx->blk_skip[i],
     666           0 :            sizeof(uint8_t) * ctx->num_4x4_blk);
     667             : #endif
     668             : 
     669           0 :   if (dry_run) return;
     670             : 
     671             : #if CONFIG_INTERNAL_STATS
     672             :   {
     673             :     unsigned int *const mode_chosen_counts =
     674             :         (unsigned int *)cpi->mode_chosen_counts;  // Cast const away.
     675             :     if (frame_is_intra_only(cm)) {
     676             :       static const int kf_mode_index[] = {
     677             :         THR_DC /*DC_PRED*/,
     678             :         THR_V_PRED /*V_PRED*/,
     679             :         THR_H_PRED /*H_PRED*/,
     680             :         THR_D45_PRED /*D45_PRED*/,
     681             :         THR_D135_PRED /*D135_PRED*/,
     682             :         THR_D117_PRED /*D117_PRED*/,
     683             :         THR_D153_PRED /*D153_PRED*/,
     684             :         THR_D207_PRED /*D207_PRED*/,
     685             :         THR_D63_PRED /*D63_PRED*/,
     686             : #if CONFIG_ALT_INTRA
     687             :         THR_SMOOTH, /*SMOOTH_PRED*/
     688             : #if CONFIG_SMOOTH_HV
     689             :         THR_SMOOTH_V, /*SMOOTH_V_PRED*/
     690             :         THR_SMOOTH_H, /*SMOOTH_H_PRED*/
     691             : #endif                // CONFIG_SMOOTH_HV
     692             : #endif                // CONFIG_ALT_INTRA
     693             :         THR_TM /*TM_PRED*/,
     694             :       };
     695             :       ++mode_chosen_counts[kf_mode_index[mbmi->mode]];
     696             :     } else {
     697             :       // Note how often each mode chosen as best
     698             :       ++mode_chosen_counts[ctx->best_mode_index];
     699             :     }
     700             :   }
     701             : #endif
     702           0 :   if (!frame_is_intra_only(cm)) {
     703           0 :     if (is_inter_block(mbmi)) {
     704           0 :       av1_update_mv_count(td);
     705             : #if CONFIG_GLOBAL_MOTION
     706           0 :       if (bsize >= BLOCK_8X8) {
     707             :         // TODO(sarahparker): global motion stats need to be handled per-tile
     708             :         // to be compatible with tile-based threading.
     709           0 :         update_global_motion_used(mbmi->mode, bsize, mbmi, rdc);
     710             :       } else {
     711           0 :         const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
     712           0 :         const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
     713             :         int idx, idy;
     714           0 :         for (idy = 0; idy < 2; idy += num_4x4_h) {
     715           0 :           for (idx = 0; idx < 2; idx += num_4x4_w) {
     716           0 :             const int j = idy * 2 + idx;
     717           0 :             update_global_motion_used(mi->bmi[j].as_mode, bsize, mbmi, rdc);
     718             :           }
     719             :         }
     720             :       }
     721             : #endif  // CONFIG_GLOBAL_MOTION
     722           0 :       if (cm->interp_filter == SWITCHABLE
     723             : #if CONFIG_WARPED_MOTION
     724           0 :           && mbmi->motion_mode != WARPED_CAUSAL
     725             : #endif  // CONFIG_WARPED_MOTION
     726             : #if CONFIG_GLOBAL_MOTION
     727           0 :           && !is_nontrans_global_motion(xd)
     728             : #endif  // CONFIG_GLOBAL_MOTION
     729             :               ) {
     730             : #if CONFIG_DUAL_FILTER
     731           0 :         update_filter_type_count(td->counts, xd, mbmi);
     732             : #else
     733             :         const int switchable_ctx = av1_get_pred_context_switchable_interp(xd);
     734             :         ++td->counts->switchable_interp[switchable_ctx][mbmi->interp_filter];
     735             : #endif
     736             :       }
     737             :     }
     738             : 
     739           0 :     rdc->comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
     740           0 :     rdc->comp_pred_diff[COMPOUND_REFERENCE] += ctx->comp_pred_diff;
     741           0 :     rdc->comp_pred_diff[REFERENCE_MODE_SELECT] += ctx->hybrid_pred_diff;
     742             :   }
     743             : 
     744           0 :   for (h = 0; h < y_mis; ++h) {
     745           0 :     MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
     746           0 :     for (w = 0; w < x_mis; ++w) {
     747           0 :       MV_REF *const mv = frame_mv + w;
     748           0 :       mv->ref_frame[0] = mi->mbmi.ref_frame[0];
     749           0 :       mv->ref_frame[1] = mi->mbmi.ref_frame[1];
     750           0 :       mv->mv[0].as_int = mi->mbmi.mv[0].as_int;
     751           0 :       mv->mv[1].as_int = mi->mbmi.mv[1].as_int;
     752             :     }
     753             :   }
     754             : }
     755             : 
     756             : #if CONFIG_SUPERTX
     757             : static void update_state_supertx(const AV1_COMP *const cpi, ThreadData *td,
     758             :                                  PICK_MODE_CONTEXT *ctx, int mi_row, int mi_col,
     759             :                                  BLOCK_SIZE bsize, RUN_TYPE dry_run) {
     760             :   int y, x_idx;
     761             : #if CONFIG_VAR_TX
     762             :   int i;
     763             : #endif
     764             :   const AV1_COMMON *const cm = &cpi->common;
     765             :   RD_COUNTS *const rdc = &td->rd_counts;
     766             :   MACROBLOCK *const x = &td->mb;
     767             :   MACROBLOCKD *const xd = &x->e_mbd;
     768             :   MODE_INFO *mi = &ctx->mic;
     769             :   MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
     770             :   MODE_INFO *mi_addr = xd->mi[0];
     771             :   const struct segmentation *const seg = &cm->seg;
     772             :   const int mis = cm->mi_stride;
     773             :   const int mi_width = mi_size_wide[bsize];
     774             :   const int mi_height = mi_size_high[bsize];
     775             :   const int x_mis = AOMMIN(mi_width, cm->mi_cols - mi_col);
     776             :   const int y_mis = AOMMIN(mi_height, cm->mi_rows - mi_row);
     777             :   const int unify_bsize = CONFIG_CB4X4;
     778             :   MV_REF *const frame_mvs = cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
     779             :   int w, h;
     780             : 
     781             :   int8_t rf_type;
     782             : 
     783             :   *mi_addr = *mi;
     784             :   *x->mbmi_ext = ctx->mbmi_ext;
     785             :   assert(is_inter_block(mbmi));
     786             :   assert(mbmi->tx_size == ctx->mic.mbmi.tx_size);
     787             : 
     788             : #if CONFIG_DUAL_FILTER
     789             :   reset_intmv_filter_type(cm, xd, mbmi);
     790             : #endif
     791             : 
     792             :   rf_type = av1_ref_frame_type(mbmi->ref_frame);
     793             :   if (x->mbmi_ext->ref_mv_count[rf_type] > 1 &&
     794             :       (mbmi->sb_type >= BLOCK_8X8 || unify_bsize)) {
     795             :     set_ref_and_pred_mvs(x, mi->mbmi.pred_mv, rf_type);
     796             :   }
     797             : 
     798             :   // If segmentation in use
     799             :   if (seg->enabled) {
     800             :     if (cpi->vaq_refresh) {
     801             :       const int energy =
     802             :           bsize <= BLOCK_16X16 ? x->mb_energy : av1_block_energy(cpi, x, bsize);
     803             :       mi_addr->mbmi.segment_id = av1_vaq_segment_id(energy);
     804             :     } else if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
     805             :       // For cyclic refresh mode, now update the segment map
     806             :       // and set the segment id.
     807             :       av1_cyclic_refresh_update_segment(cpi, &xd->mi[0]->mbmi, mi_row, mi_col,
     808             :                                         bsize, ctx->rate, ctx->dist, 1);
     809             :     } else {
     810             :       // Otherwise just set the segment id based on the current segment map
     811             :       const uint8_t *const map =
     812             :           seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
     813             :       mi_addr->mbmi.segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
     814             :     }
     815             :     mi_addr->mbmi.segment_id_supertx = MAX_SEGMENTS;
     816             :   }
     817             : 
     818             :   // Restore the coding context of the MB to that that was in place
     819             :   // when the mode was picked for it
     820             :   for (y = 0; y < mi_height; y++)
     821             :     for (x_idx = 0; x_idx < mi_width; x_idx++)
     822             :       if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width > x_idx &&
     823             :           (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > y) {
     824             :         xd->mi[x_idx + y * mis] = mi_addr;
     825             :       }
     826             : 
     827             : #if !CONFIG_CB4X4
     828             :   if (is_inter_block(mbmi) && mbmi->sb_type < BLOCK_8X8) {
     829             :     mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
     830             :     mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
     831             :   }
     832             : #endif
     833             : 
     834             :   x->skip = ctx->skip;
     835             : 
     836             : #if CONFIG_VAR_TX
     837             :   for (i = 0; i < 1; ++i)
     838             :     memcpy(x->blk_skip[i], ctx->blk_skip[i],
     839             :            sizeof(uint8_t) * ctx->num_4x4_blk);
     840             : 
     841             :   if (!is_inter_block(mbmi) || mbmi->skip)
     842             :     mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
     843             : #endif  // CONFIG_VAR_TX
     844             : 
     845             : #if CONFIG_VAR_TX
     846             :   {
     847             :     const TX_SIZE mtx = mbmi->tx_size;
     848             :     const int num_4x4_blocks_wide = tx_size_wide_unit[mtx] >> 1;
     849             :     const int num_4x4_blocks_high = tx_size_high_unit[mtx] >> 1;
     850             :     int idy, idx;
     851             :     mbmi->inter_tx_size[0][0] = mtx;
     852             :     for (idy = 0; idy < num_4x4_blocks_high; ++idy)
     853             :       for (idx = 0; idx < num_4x4_blocks_wide; ++idx)
     854             :         mbmi->inter_tx_size[idy][idx] = mtx;
     855             :   }
     856             : #endif  // CONFIG_VAR_TX
     857             :   // Turn motion variation off for supertx
     858             :   mbmi->motion_mode = SIMPLE_TRANSLATION;
     859             : 
     860             :   if (dry_run) return;
     861             : 
     862             :   if (!frame_is_intra_only(cm)) {
     863             :     av1_update_mv_count(td);
     864             : 
     865             : #if CONFIG_GLOBAL_MOTION
     866             :     if (is_inter_block(mbmi)) {
     867             :       if (bsize >= BLOCK_8X8) {
     868             :         // TODO(sarahparker): global motion stats need to be handled per-tile
     869             :         // to be compatible with tile-based threading.
     870             :         update_global_motion_used(mbmi->mode, bsize, mbmi, rdc);
     871             :       } else {
     872             :         const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
     873             :         const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
     874             :         int idx, idy;
     875             :         for (idy = 0; idy < 2; idy += num_4x4_h) {
     876             :           for (idx = 0; idx < 2; idx += num_4x4_w) {
     877             :             const int j = idy * 2 + idx;
     878             :             update_global_motion_used(mi->bmi[j].as_mode, bsize, mbmi, rdc);
     879             :           }
     880             :         }
     881             :       }
     882             :     }
     883             : #endif  // CONFIG_GLOBAL_MOTION
     884             : 
     885             :     if (cm->interp_filter == SWITCHABLE
     886             : #if CONFIG_GLOBAL_MOTION
     887             :         && !is_nontrans_global_motion(xd)
     888             : #endif  // CONFIG_GLOBAL_MOTION
     889             :             ) {
     890             : #if CONFIG_DUAL_FILTER
     891             :       update_filter_type_count(td->counts, xd, mbmi);
     892             : #else
     893             :       const int pred_ctx = av1_get_pred_context_switchable_interp(xd);
     894             :       ++td->counts->switchable_interp[pred_ctx][mbmi->interp_filter];
     895             : #endif
     896             :     }
     897             : 
     898             :     rdc->comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
     899             :     rdc->comp_pred_diff[COMPOUND_REFERENCE] += ctx->comp_pred_diff;
     900             :     rdc->comp_pred_diff[REFERENCE_MODE_SELECT] += ctx->hybrid_pred_diff;
     901             :   }
     902             : 
     903             :   for (h = 0; h < y_mis; ++h) {
     904             :     MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
     905             :     for (w = 0; w < x_mis; ++w) {
     906             :       MV_REF *const mv = frame_mv + w;
     907             :       mv->ref_frame[0] = mi->mbmi.ref_frame[0];
     908             :       mv->ref_frame[1] = mi->mbmi.ref_frame[1];
     909             :       mv->mv[0].as_int = mi->mbmi.mv[0].as_int;
     910             :       mv->mv[1].as_int = mi->mbmi.mv[1].as_int;
     911             :     }
     912             :   }
     913             : }
     914             : 
     915             : static void update_state_sb_supertx(const AV1_COMP *const cpi, ThreadData *td,
     916             :                                     const TileInfo *const tile, int mi_row,
     917             :                                     int mi_col, BLOCK_SIZE bsize,
     918             :                                     RUN_TYPE dry_run, PC_TREE *pc_tree) {
     919             :   const AV1_COMMON *const cm = &cpi->common;
     920             :   MACROBLOCK *const x = &td->mb;
     921             :   MACROBLOCKD *const xd = &x->e_mbd;
     922             :   struct macroblock_plane *const p = x->plane;
     923             :   struct macroblockd_plane *const pd = xd->plane;
     924             :   int hbs = mi_size_wide[bsize] / 2;
     925             : #if CONFIG_CB4X4
     926             :   const int unify_bsize = 1;
     927             : #else
     928             :   const int unify_bsize = 0;
     929             : #endif
     930             :   PARTITION_TYPE partition = pc_tree->partitioning;
     931             :   BLOCK_SIZE subsize = get_subsize(bsize, partition);
     932             :   int i;
     933             : #if CONFIG_EXT_PARTITION_TYPES
     934             :   BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
     935             : #endif
     936             :   PICK_MODE_CONTEXT *pmc = NULL;
     937             : 
     938             :   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
     939             : 
     940             :   if (bsize == BLOCK_16X16 && cpi->vaq_refresh)
     941             :     x->mb_energy = av1_block_energy(cpi, x, bsize);
     942             : 
     943             :   switch (partition) {
     944             :     case PARTITION_NONE:
     945             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col, subsize);
     946             :       update_state_supertx(cpi, td, &pc_tree->none, mi_row, mi_col, subsize,
     947             :                            dry_run);
     948             :       break;
     949             :     case PARTITION_VERT:
     950             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col, subsize);
     951             :       update_state_supertx(cpi, td, &pc_tree->vertical[0], mi_row, mi_col,
     952             :                            subsize, dry_run);
     953             :       if (mi_col + hbs < cm->mi_cols && (bsize > BLOCK_8X8 || unify_bsize)) {
     954             :         set_offsets_supertx(cpi, td, tile, mi_row, mi_col + hbs, subsize);
     955             :         update_state_supertx(cpi, td, &pc_tree->vertical[1], mi_row,
     956             :                              mi_col + hbs, subsize, dry_run);
     957             :       }
     958             :       pmc = &pc_tree->vertical_supertx;
     959             :       break;
     960             :     case PARTITION_HORZ:
     961             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col, subsize);
     962             :       update_state_supertx(cpi, td, &pc_tree->horizontal[0], mi_row, mi_col,
     963             :                            subsize, dry_run);
     964             :       if (mi_row + hbs < cm->mi_rows && (bsize > BLOCK_8X8 || unify_bsize)) {
     965             :         set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col, subsize);
     966             :         update_state_supertx(cpi, td, &pc_tree->horizontal[1], mi_row + hbs,
     967             :                              mi_col, subsize, dry_run);
     968             :       }
     969             :       pmc = &pc_tree->horizontal_supertx;
     970             :       break;
     971             :     case PARTITION_SPLIT:
     972             :       if (bsize == BLOCK_8X8 && !unify_bsize) {
     973             :         set_offsets_supertx(cpi, td, tile, mi_row, mi_col, subsize);
     974             :         update_state_supertx(cpi, td, pc_tree->leaf_split[0], mi_row, mi_col,
     975             :                              subsize, dry_run);
     976             :       } else {
     977             :         set_offsets_supertx(cpi, td, tile, mi_row, mi_col, subsize);
     978             :         update_state_sb_supertx(cpi, td, tile, mi_row, mi_col, subsize, dry_run,
     979             :                                 pc_tree->split[0]);
     980             :         set_offsets_supertx(cpi, td, tile, mi_row, mi_col + hbs, subsize);
     981             :         update_state_sb_supertx(cpi, td, tile, mi_row, mi_col + hbs, subsize,
     982             :                                 dry_run, pc_tree->split[1]);
     983             :         set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col, subsize);
     984             :         update_state_sb_supertx(cpi, td, tile, mi_row + hbs, mi_col, subsize,
     985             :                                 dry_run, pc_tree->split[2]);
     986             :         set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col + hbs, subsize);
     987             :         update_state_sb_supertx(cpi, td, tile, mi_row + hbs, mi_col + hbs,
     988             :                                 subsize, dry_run, pc_tree->split[3]);
     989             :       }
     990             :       pmc = &pc_tree->split_supertx;
     991             :       break;
     992             : #if CONFIG_EXT_PARTITION_TYPES
     993             :     case PARTITION_HORZ_A:
     994             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col, bsize2);
     995             :       update_state_supertx(cpi, td, &pc_tree->horizontala[0], mi_row, mi_col,
     996             :                            bsize2, dry_run);
     997             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col + hbs, bsize2);
     998             :       update_state_supertx(cpi, td, &pc_tree->horizontala[1], mi_row,
     999             :                            mi_col + hbs, bsize2, dry_run);
    1000             :       set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col, subsize);
    1001             :       update_state_supertx(cpi, td, &pc_tree->horizontala[2], mi_row + hbs,
    1002             :                            mi_col, subsize, dry_run);
    1003             :       pmc = &pc_tree->horizontala_supertx;
    1004             :       break;
    1005             :     case PARTITION_HORZ_B:
    1006             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col, subsize);
    1007             :       update_state_supertx(cpi, td, &pc_tree->horizontalb[0], mi_row, mi_col,
    1008             :                            subsize, dry_run);
    1009             :       set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col, bsize2);
    1010             :       update_state_supertx(cpi, td, &pc_tree->horizontalb[1], mi_row + hbs,
    1011             :                            mi_col, bsize2, dry_run);
    1012             :       set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col + hbs, bsize2);
    1013             :       update_state_supertx(cpi, td, &pc_tree->horizontalb[2], mi_row + hbs,
    1014             :                            mi_col + hbs, bsize2, dry_run);
    1015             :       pmc = &pc_tree->horizontalb_supertx;
    1016             :       break;
    1017             :     case PARTITION_VERT_A:
    1018             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col, bsize2);
    1019             :       update_state_supertx(cpi, td, &pc_tree->verticala[0], mi_row, mi_col,
    1020             :                            bsize2, dry_run);
    1021             :       set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col, bsize2);
    1022             :       update_state_supertx(cpi, td, &pc_tree->verticala[1], mi_row + hbs,
    1023             :                            mi_col, bsize2, dry_run);
    1024             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col + hbs, subsize);
    1025             :       update_state_supertx(cpi, td, &pc_tree->verticala[2], mi_row,
    1026             :                            mi_col + hbs, subsize, dry_run);
    1027             :       pmc = &pc_tree->verticala_supertx;
    1028             :       break;
    1029             :     case PARTITION_VERT_B:
    1030             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col, subsize);
    1031             :       update_state_supertx(cpi, td, &pc_tree->verticalb[0], mi_row, mi_col,
    1032             :                            subsize, dry_run);
    1033             :       set_offsets_supertx(cpi, td, tile, mi_row, mi_col + hbs, bsize2);
    1034             :       update_state_supertx(cpi, td, &pc_tree->verticalb[1], mi_row,
    1035             :                            mi_col + hbs, bsize2, dry_run);
    1036             :       set_offsets_supertx(cpi, td, tile, mi_row + hbs, mi_col + hbs, bsize2);
    1037             :       update_state_supertx(cpi, td, &pc_tree->verticalb[2], mi_row + hbs,
    1038             :                            mi_col + hbs, bsize2, dry_run);
    1039             :       pmc = &pc_tree->verticalb_supertx;
    1040             :       break;
    1041             : #endif  // CONFIG_EXT_PARTITION_TYPES
    1042             :     default: assert(0);
    1043             :   }
    1044             : 
    1045             :   for (i = 0; i < MAX_MB_PLANE; ++i) {
    1046             :     if (pmc != NULL) {
    1047             :       p[i].coeff = pmc->coeff[i];
    1048             :       p[i].qcoeff = pmc->qcoeff[i];
    1049             :       pd[i].dqcoeff = pmc->dqcoeff[i];
    1050             :       p[i].eobs = pmc->eobs[i];
    1051             :     } else {
    1052             :       // These should never be used
    1053             :       p[i].coeff = NULL;
    1054             :       p[i].qcoeff = NULL;
    1055             :       pd[i].dqcoeff = NULL;
    1056             :       p[i].eobs = NULL;
    1057             :     }
    1058             :   }
    1059             : }
    1060             : 
    1061             : static void update_supertx_param(ThreadData *td, PICK_MODE_CONTEXT *ctx,
    1062             :                                  int best_tx, TX_SIZE supertx_size) {
    1063             :   MACROBLOCK *const x = &td->mb;
    1064             : #if CONFIG_VAR_TX
    1065             :   int i;
    1066             : 
    1067             :   for (i = 0; i < 1; ++i)
    1068             :     memcpy(ctx->blk_skip[i], x->blk_skip[i],
    1069             :            sizeof(uint8_t) * ctx->num_4x4_blk);
    1070             :   ctx->mic.mbmi.min_tx_size = get_min_tx_size(supertx_size);
    1071             : #endif  // CONFIG_VAR_TX
    1072             :   ctx->mic.mbmi.tx_size = supertx_size;
    1073             :   ctx->skip = x->skip;
    1074             :   ctx->mic.mbmi.tx_type = best_tx;
    1075             : }
    1076             : 
    1077             : static void update_supertx_param_sb(const AV1_COMP *const cpi, ThreadData *td,
    1078             :                                     int mi_row, int mi_col, BLOCK_SIZE bsize,
    1079             :                                     int best_tx, TX_SIZE supertx_size,
    1080             :                                     PC_TREE *pc_tree) {
    1081             :   const AV1_COMMON *const cm = &cpi->common;
    1082             :   const int hbs = mi_size_wide[bsize] / 2;
    1083             :   PARTITION_TYPE partition = pc_tree->partitioning;
    1084             :   BLOCK_SIZE subsize = get_subsize(bsize, partition);
    1085             : #if CONFIG_CB4X4
    1086             :   const int unify_bsize = 1;
    1087             : #else
    1088             :   const int unify_bsize = 0;
    1089             : #endif
    1090             : #if CONFIG_EXT_PARTITION_TYPES
    1091             :   int i;
    1092             : #endif
    1093             : 
    1094             :   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
    1095             : 
    1096             :   switch (partition) {
    1097             :     case PARTITION_NONE:
    1098             :       update_supertx_param(td, &pc_tree->none, best_tx, supertx_size);
    1099             :       break;
    1100             :     case PARTITION_VERT:
    1101             :       update_supertx_param(td, &pc_tree->vertical[0], best_tx, supertx_size);
    1102             :       if (mi_col + hbs < cm->mi_cols && (bsize > BLOCK_8X8 || unify_bsize))
    1103             :         update_supertx_param(td, &pc_tree->vertical[1], best_tx, supertx_size);
    1104             :       break;
    1105             :     case PARTITION_HORZ:
    1106             :       update_supertx_param(td, &pc_tree->horizontal[0], best_tx, supertx_size);
    1107             :       if (mi_row + hbs < cm->mi_rows && (bsize > BLOCK_8X8 || unify_bsize))
    1108             :         update_supertx_param(td, &pc_tree->horizontal[1], best_tx,
    1109             :                              supertx_size);
    1110             :       break;
    1111             :     case PARTITION_SPLIT:
    1112             :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    1113             :         update_supertx_param(td, pc_tree->leaf_split[0], best_tx, supertx_size);
    1114             :       } else {
    1115             :         update_supertx_param_sb(cpi, td, mi_row, mi_col, subsize, best_tx,
    1116             :                                 supertx_size, pc_tree->split[0]);
    1117             :         update_supertx_param_sb(cpi, td, mi_row, mi_col + hbs, subsize, best_tx,
    1118             :                                 supertx_size, pc_tree->split[1]);
    1119             :         update_supertx_param_sb(cpi, td, mi_row + hbs, mi_col, subsize, best_tx,
    1120             :                                 supertx_size, pc_tree->split[2]);
    1121             :         update_supertx_param_sb(cpi, td, mi_row + hbs, mi_col + hbs, subsize,
    1122             :                                 best_tx, supertx_size, pc_tree->split[3]);
    1123             :       }
    1124             :       break;
    1125             : #if CONFIG_EXT_PARTITION_TYPES
    1126             :     case PARTITION_HORZ_A:
    1127             :       for (i = 0; i < 3; i++)
    1128             :         update_supertx_param(td, &pc_tree->horizontala[i], best_tx,
    1129             :                              supertx_size);
    1130             :       break;
    1131             :     case PARTITION_HORZ_B:
    1132             :       for (i = 0; i < 3; i++)
    1133             :         update_supertx_param(td, &pc_tree->horizontalb[i], best_tx,
    1134             :                              supertx_size);
    1135             :       break;
    1136             :     case PARTITION_VERT_A:
    1137             :       for (i = 0; i < 3; i++)
    1138             :         update_supertx_param(td, &pc_tree->verticala[i], best_tx, supertx_size);
    1139             :       break;
    1140             :     case PARTITION_VERT_B:
    1141             :       for (i = 0; i < 3; i++)
    1142             :         update_supertx_param(td, &pc_tree->verticalb[i], best_tx, supertx_size);
    1143             :       break;
    1144             : #endif  // CONFIG_EXT_PARTITION_TYPES
    1145             :     default: assert(0);
    1146             :   }
    1147             : }
    1148             : #endif  // CONFIG_SUPERTX
    1149             : 
    1150             : #if CONFIG_MOTION_VAR && CONFIG_NCOBMC
    1151             : static void set_mode_info_b(const AV1_COMP *const cpi,
    1152             :                             const TileInfo *const tile, ThreadData *td,
    1153             :                             int mi_row, int mi_col, BLOCK_SIZE bsize,
    1154             :                             PICK_MODE_CONTEXT *ctx) {
    1155             :   MACROBLOCK *const x = &td->mb;
    1156             :   set_offsets(cpi, tile, x, mi_row, mi_col, bsize);
    1157             :   update_state(cpi, td, ctx, mi_row, mi_col, bsize, 1);
    1158             : }
    1159             : 
    1160             : static void set_mode_info_sb(const AV1_COMP *const cpi, ThreadData *td,
    1161             :                              const TileInfo *const tile, TOKENEXTRA **tp,
    1162             :                              int mi_row, int mi_col, BLOCK_SIZE bsize,
    1163             :                              PC_TREE *pc_tree) {
    1164             :   const AV1_COMMON *const cm = &cpi->common;
    1165             :   const int hbs = mi_size_wide[bsize] / 2;
    1166             :   const PARTITION_TYPE partition = pc_tree->partitioning;
    1167             :   BLOCK_SIZE subsize = get_subsize(bsize, partition);
    1168             : #if CONFIG_EXT_PARTITION_TYPES
    1169             :   const BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
    1170             : #endif
    1171             : #if CONFIG_CB4X4
    1172             :   const int unify_bsize = 1;
    1173             : #else
    1174             :   const int unify_bsize = 0;
    1175             :   assert(bsize >= BLOCK_8X8);
    1176             : #endif
    1177             : 
    1178             :   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
    1179             : 
    1180             :   switch (partition) {
    1181             :     case PARTITION_NONE:
    1182             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize, &pc_tree->none);
    1183             :       break;
    1184             :     case PARTITION_VERT:
    1185             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
    1186             :                       &pc_tree->vertical[0]);
    1187             :       if (mi_col + hbs < cm->mi_cols && (bsize > BLOCK_8X8 || unify_bsize)) {
    1188             :         set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, subsize,
    1189             :                         &pc_tree->vertical[1]);
    1190             :       }
    1191             :       break;
    1192             :     case PARTITION_HORZ:
    1193             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
    1194             :                       &pc_tree->horizontal[0]);
    1195             :       if (mi_row + hbs < cm->mi_rows && (bsize > BLOCK_8X8 || unify_bsize)) {
    1196             :         set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, subsize,
    1197             :                         &pc_tree->horizontal[1]);
    1198             :       }
    1199             :       break;
    1200             :     case PARTITION_SPLIT:
    1201             :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    1202             :         set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
    1203             :                         pc_tree->leaf_split[0]);
    1204             :       } else {
    1205             :         set_mode_info_sb(cpi, td, tile, tp, mi_row, mi_col, subsize,
    1206             :                          pc_tree->split[0]);
    1207             :         set_mode_info_sb(cpi, td, tile, tp, mi_row, mi_col + hbs, subsize,
    1208             :                          pc_tree->split[1]);
    1209             :         set_mode_info_sb(cpi, td, tile, tp, mi_row + hbs, mi_col, subsize,
    1210             :                          pc_tree->split[2]);
    1211             :         set_mode_info_sb(cpi, td, tile, tp, mi_row + hbs, mi_col + hbs, subsize,
    1212             :                          pc_tree->split[3]);
    1213             :       }
    1214             :       break;
    1215             : #if CONFIG_EXT_PARTITION_TYPES
    1216             :     case PARTITION_HORZ_A:
    1217             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col, bsize2,
    1218             :                       &pc_tree->horizontala[0]);
    1219             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, bsize2,
    1220             :                       &pc_tree->horizontala[1]);
    1221             :       set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, subsize,
    1222             :                       &pc_tree->horizontala[2]);
    1223             :       break;
    1224             :     case PARTITION_HORZ_B:
    1225             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
    1226             :                       &pc_tree->horizontalb[0]);
    1227             :       set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, bsize2,
    1228             :                       &pc_tree->horizontalb[1]);
    1229             :       set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col + hbs, bsize2,
    1230             :                       &pc_tree->horizontalb[2]);
    1231             :       break;
    1232             :     case PARTITION_VERT_A:
    1233             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col, bsize2,
    1234             :                       &pc_tree->verticala[0]);
    1235             :       set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, bsize2,
    1236             :                       &pc_tree->verticala[1]);
    1237             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, subsize,
    1238             :                       &pc_tree->verticala[2]);
    1239             :       break;
    1240             :     case PARTITION_VERT_B:
    1241             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
    1242             :                       &pc_tree->verticalb[0]);
    1243             :       set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, bsize2,
    1244             :                       &pc_tree->verticalb[1]);
    1245             :       set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col + hbs, bsize2,
    1246             :                       &pc_tree->verticalb[2]);
    1247             :       break;
    1248             : #endif  // CONFIG_EXT_PARTITION_TYPES
    1249             :     default: assert(0 && "Invalid partition type."); break;
    1250             :   }
    1251             : }
    1252             : #endif
    1253             : 
    1254           0 : void av1_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
    1255             :                           int mi_row, int mi_col) {
    1256           0 :   uint8_t *const buffers[3] = { src->y_buffer, src->u_buffer, src->v_buffer };
    1257           0 :   const int widths[3] = { src->y_crop_width, src->uv_crop_width,
    1258           0 :                           src->uv_crop_width };
    1259           0 :   const int heights[3] = { src->y_crop_height, src->uv_crop_height,
    1260           0 :                            src->uv_crop_height };
    1261           0 :   const int strides[3] = { src->y_stride, src->uv_stride, src->uv_stride };
    1262             :   int i;
    1263             : 
    1264             :   // Set current frame pointer.
    1265           0 :   x->e_mbd.cur_buf = src;
    1266             : 
    1267           0 :   for (i = 0; i < MAX_MB_PLANE; i++)
    1268           0 :     setup_pred_plane(&x->plane[i].src, x->e_mbd.mi[0]->mbmi.sb_type, buffers[i],
    1269             :                      widths[i], heights[i], strides[i], mi_row, mi_col, NULL,
    1270             :                      x->e_mbd.plane[i].subsampling_x,
    1271             :                      x->e_mbd.plane[i].subsampling_y);
    1272           0 : }
    1273             : 
    1274           0 : static int set_segment_rdmult(const AV1_COMP *const cpi, MACROBLOCK *const x,
    1275             :                               int8_t segment_id) {
    1276             :   int segment_qindex;
    1277           0 :   const AV1_COMMON *const cm = &cpi->common;
    1278           0 :   av1_init_plane_quantizers(cpi, x, segment_id);
    1279           0 :   aom_clear_system_state();
    1280           0 :   segment_qindex = av1_get_qindex(&cm->seg, segment_id, cm->base_qindex);
    1281           0 :   return av1_compute_rd_mult(cpi, segment_qindex + cm->y_dc_delta_q);
    1282             : }
    1283             : 
    1284             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    1285             : static void daala_dist_set_sub8x8_dst(MACROBLOCK *const x, uint8_t *dst8x8,
    1286             :                                       BLOCK_SIZE bsize, int bw, int bh,
    1287             :                                       int mi_row, int mi_col) {
    1288             :   MACROBLOCKD *const xd = &x->e_mbd;
    1289             :   struct macroblockd_plane *const pd = &xd->plane[0];
    1290             :   const int dst_stride = pd->dst.stride;
    1291             :   uint8_t *dst = pd->dst.buf;
    1292             : 
    1293             :   assert(bsize < BLOCK_8X8);
    1294             : 
    1295             :   if (bsize < BLOCK_8X8) {
    1296             :     int i, j;
    1297             :     uint8_t *dst_sub8x8 = &dst8x8[((mi_row & 1) * 8 + (mi_col & 1)) << 2];
    1298             : 
    1299             :     for (j = 0; j < bh; ++j)
    1300             :       for (i = 0; i < bw; ++i) {
    1301             :         dst_sub8x8[j * 8 + i] = dst[j * dst_stride + i];
    1302             :       }
    1303             :   }
    1304             : }
    1305             : #endif
    1306             : 
    1307           0 : static void rd_pick_sb_modes(const AV1_COMP *const cpi, TileDataEnc *tile_data,
    1308             :                              MACROBLOCK *const x, int mi_row, int mi_col,
    1309             :                              RD_STATS *rd_cost,
    1310             : #if CONFIG_SUPERTX
    1311             :                              int *totalrate_nocoef,
    1312             : #endif
    1313             : #if CONFIG_EXT_PARTITION_TYPES
    1314             :                              PARTITION_TYPE partition,
    1315             : #endif
    1316             :                              BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
    1317             :                              int64_t best_rd) {
    1318           0 :   const AV1_COMMON *const cm = &cpi->common;
    1319           0 :   TileInfo *const tile_info = &tile_data->tile_info;
    1320           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    1321             :   MB_MODE_INFO *mbmi;
    1322           0 :   struct macroblock_plane *const p = x->plane;
    1323           0 :   struct macroblockd_plane *const pd = xd->plane;
    1324           0 :   const AQ_MODE aq_mode = cpi->oxcf.aq_mode;
    1325             :   int i, orig_rdmult;
    1326             : 
    1327           0 :   aom_clear_system_state();
    1328             : 
    1329             : #if CONFIG_PVQ
    1330             :   x->pvq_speed = 1;
    1331             :   x->pvq_coded = 0;
    1332             : #endif
    1333             : #if CONFIG_CFL
    1334             :   // Don't store luma during RDO (we will store the best mode later).
    1335             :   x->cfl_store_y = 0;
    1336             : #endif
    1337             : 
    1338           0 :   set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
    1339           0 :   mbmi = &xd->mi[0]->mbmi;
    1340           0 :   mbmi->sb_type = bsize;
    1341             : #if CONFIG_RD_DEBUG
    1342             :   mbmi->mi_row = mi_row;
    1343             :   mbmi->mi_col = mi_col;
    1344             : #endif
    1345             : #if CONFIG_SUPERTX
    1346             :   // We set tx_size here as skip blocks would otherwise not set it.
    1347             :   // tx_size needs to be set at this point as supertx_enable in
    1348             :   // write_modes_sb is computed based on this, and if the garbage in memory
    1349             :   // just happens to be the supertx_size, then the packer will code this
    1350             :   // block as a supertx block, even if rdopt did not pick it as such.
    1351             :   mbmi->tx_size = max_txsize_lookup[bsize];
    1352             : #endif
    1353             : #if CONFIG_EXT_PARTITION_TYPES
    1354             :   mbmi->partition = partition;
    1355             : #endif
    1356             : 
    1357           0 :   for (i = 0; i < MAX_MB_PLANE; ++i) {
    1358           0 :     p[i].coeff = ctx->coeff[i];
    1359           0 :     p[i].qcoeff = ctx->qcoeff[i];
    1360           0 :     pd[i].dqcoeff = ctx->dqcoeff[i];
    1361             : #if CONFIG_PVQ
    1362             :     pd[i].pvq_ref_coeff = ctx->pvq_ref_coeff[i];
    1363             : #endif
    1364           0 :     p[i].eobs = ctx->eobs[i];
    1365             : #if CONFIG_LV_MAP
    1366             :     p[i].txb_entropy_ctx = ctx->txb_entropy_ctx[i];
    1367             : #endif
    1368             :   }
    1369             : 
    1370             : #if CONFIG_PALETTE
    1371           0 :   for (i = 0; i < 2; ++i) pd[i].color_index_map = ctx->color_index_map[i];
    1372             : #endif  // CONFIG_PALETTE
    1373             : 
    1374           0 :   ctx->skippable = 0;
    1375             : 
    1376             :   // Set to zero to make sure we do not use the previous encoded frame stats
    1377           0 :   mbmi->skip = 0;
    1378             : 
    1379             : #if CONFIG_CB4X4
    1380           0 :   x->skip_chroma_rd =
    1381           0 :       !is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
    1382             :                            xd->plane[1].subsampling_y);
    1383             : #endif
    1384             : 
    1385             : #if CONFIG_HIGHBITDEPTH
    1386           0 :   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    1387           0 :     x->source_variance = av1_high_get_sby_perpixel_variance(
    1388           0 :         cpi, &x->plane[0].src, bsize, xd->bd);
    1389             :   } else {
    1390           0 :     x->source_variance =
    1391           0 :         av1_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
    1392             :   }
    1393             : #else
    1394             :   x->source_variance =
    1395             :       av1_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
    1396             : #endif  // CONFIG_HIGHBITDEPTH
    1397             : 
    1398             :   // Save rdmult before it might be changed, so it can be restored later.
    1399           0 :   orig_rdmult = x->rdmult;
    1400             : 
    1401           0 :   if (aq_mode == VARIANCE_AQ) {
    1402           0 :     if (cpi->vaq_refresh) {
    1403           0 :       const int energy =
    1404           0 :           bsize <= BLOCK_16X16 ? x->mb_energy : av1_block_energy(cpi, x, bsize);
    1405           0 :       mbmi->segment_id = av1_vaq_segment_id(energy);
    1406             :       // Re-initialise quantiser
    1407           0 :       av1_init_plane_quantizers(cpi, x, mbmi->segment_id);
    1408             :     }
    1409           0 :     x->rdmult = set_segment_rdmult(cpi, x, mbmi->segment_id);
    1410           0 :   } else if (aq_mode == COMPLEXITY_AQ) {
    1411           0 :     x->rdmult = set_segment_rdmult(cpi, x, mbmi->segment_id);
    1412           0 :   } else if (aq_mode == CYCLIC_REFRESH_AQ) {
    1413             :     // If segment is boosted, use rdmult for that segment.
    1414           0 :     if (cyclic_refresh_segment_id_boosted(mbmi->segment_id))
    1415           0 :       x->rdmult = av1_cyclic_refresh_get_rdmult(cpi->cyclic_refresh);
    1416             :   }
    1417             : 
    1418             :   // Find best coding mode & reconstruct the MB so it is available
    1419             :   // as a predictor for MBs that follow in the SB
    1420           0 :   if (frame_is_intra_only(cm)) {
    1421           0 :     av1_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd);
    1422             : #if CONFIG_SUPERTX
    1423             :     *totalrate_nocoef = 0;
    1424             : #endif  // CONFIG_SUPERTX
    1425             :   } else {
    1426           0 :     if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    1427           0 :       av1_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, mi_row, mi_col,
    1428             :                                          rd_cost, bsize, ctx, best_rd);
    1429             : #if CONFIG_SUPERTX
    1430             :       *totalrate_nocoef = rd_cost->rate;
    1431             : #endif  // CONFIG_SUPERTX
    1432             :     } else {
    1433           0 :       av1_rd_pick_inter_mode_sb(cpi, tile_data, x, mi_row, mi_col, rd_cost,
    1434             : #if CONFIG_SUPERTX
    1435             :                                 totalrate_nocoef,
    1436             : #endif  // CONFIG_SUPERTX
    1437             :                                 bsize, ctx, best_rd);
    1438             : #if CONFIG_SUPERTX
    1439             :       assert(*totalrate_nocoef >= 0);
    1440             : #endif  // CONFIG_SUPERTX
    1441             :     }
    1442             :   }
    1443             : 
    1444             :   // Examine the resulting rate and for AQ mode 2 make a segment choice.
    1445           0 :   if ((rd_cost->rate != INT_MAX) && (aq_mode == COMPLEXITY_AQ) &&
    1446           0 :       (bsize >= BLOCK_16X16) &&
    1447           0 :       (cm->frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame ||
    1448           0 :        (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref))) {
    1449           0 :     av1_caq_select_segment(cpi, x, bsize, mi_row, mi_col, rd_cost->rate);
    1450             :   }
    1451             : 
    1452           0 :   x->rdmult = orig_rdmult;
    1453             : 
    1454             :   // TODO(jingning) The rate-distortion optimization flow needs to be
    1455             :   // refactored to provide proper exit/return handle.
    1456           0 :   if (rd_cost->rate == INT_MAX) rd_cost->rdcost = INT64_MAX;
    1457             : 
    1458           0 :   ctx->rate = rd_cost->rate;
    1459           0 :   ctx->dist = rd_cost->dist;
    1460           0 : }
    1461             : 
    1462           0 : static void update_inter_mode_stats(FRAME_COUNTS *counts, PREDICTION_MODE mode,
    1463             :                                     int16_t mode_context) {
    1464           0 :   int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
    1465           0 :   if (mode == NEWMV) {
    1466           0 :     ++counts->newmv_mode[mode_ctx][0];
    1467           0 :     return;
    1468             :   } else {
    1469           0 :     ++counts->newmv_mode[mode_ctx][1];
    1470             : 
    1471           0 :     if (mode_context & (1 << ALL_ZERO_FLAG_OFFSET)) {
    1472           0 :       return;
    1473             :     }
    1474             : 
    1475           0 :     mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
    1476           0 :     if (mode == ZEROMV) {
    1477           0 :       ++counts->zeromv_mode[mode_ctx][0];
    1478           0 :       return;
    1479             :     } else {
    1480           0 :       ++counts->zeromv_mode[mode_ctx][1];
    1481           0 :       mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
    1482             : 
    1483           0 :       if (mode_context & (1 << SKIP_NEARESTMV_OFFSET)) mode_ctx = 6;
    1484           0 :       if (mode_context & (1 << SKIP_NEARMV_OFFSET)) mode_ctx = 7;
    1485           0 :       if (mode_context & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) mode_ctx = 8;
    1486             : 
    1487           0 :       ++counts->refmv_mode[mode_ctx][mode != NEARESTMV];
    1488             :     }
    1489             :   }
    1490             : }
    1491             : 
    1492           0 : static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
    1493             :                          int mi_col
    1494             : #if CONFIG_SUPERTX
    1495             :                          ,
    1496             :                          int supertx_enabled
    1497             : #endif
    1498             :                          ) {
    1499             : #if CONFIG_DELTA_Q
    1500           0 :   MACROBLOCK *x = &td->mb;
    1501           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    1502             : #else
    1503             :   const MACROBLOCK *x = &td->mb;
    1504             :   const MACROBLOCKD *const xd = &x->e_mbd;
    1505             : #endif
    1506           0 :   const MODE_INFO *const mi = xd->mi[0];
    1507           0 :   const MB_MODE_INFO *const mbmi = &mi->mbmi;
    1508           0 :   const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
    1509           0 :   const BLOCK_SIZE bsize = mbmi->sb_type;
    1510             : 
    1511             : #if CONFIG_DELTA_Q
    1512             :   // delta quant applies to both intra and inter
    1513           0 :   const int super_block_upper_left = ((mi_row & 7) == 0) && ((mi_col & 7) == 0);
    1514             : 
    1515           0 :   if (cm->delta_q_present_flag && (bsize != BLOCK_64X64 || !mbmi->skip) &&
    1516             :       super_block_upper_left) {
    1517           0 :     const int dq = (mbmi->current_q_index - xd->prev_qindex) / cm->delta_q_res;
    1518           0 :     const int absdq = abs(dq);
    1519             :     int i;
    1520           0 :     for (i = 0; i < AOMMIN(absdq, DELTA_Q_SMALL); ++i) {
    1521           0 :       td->counts->delta_q[i][1]++;
    1522             :     }
    1523           0 :     if (absdq < DELTA_Q_SMALL) td->counts->delta_q[absdq][0]++;
    1524           0 :     xd->prev_qindex = mbmi->current_q_index;
    1525             : #if CONFIG_EXT_DELTA_Q
    1526           0 :     if (cm->delta_lf_present_flag) {
    1527           0 :       const int dlf =
    1528           0 :           (mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) /
    1529           0 :           cm->delta_lf_res;
    1530           0 :       const int absdlf = abs(dlf);
    1531           0 :       for (i = 0; i < AOMMIN(absdlf, DELTA_LF_SMALL); ++i) {
    1532           0 :         td->counts->delta_lf[i][1]++;
    1533             :       }
    1534           0 :       if (absdlf < DELTA_LF_SMALL) td->counts->delta_lf[absdlf][0]++;
    1535           0 :       xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base;
    1536             :     }
    1537             : #endif
    1538             :   }
    1539             : #else
    1540             :   (void)mi_row;
    1541             :   (void)mi_col;
    1542             : #endif
    1543           0 :   if (!frame_is_intra_only(cm)) {
    1544           0 :     FRAME_COUNTS *const counts = td->counts;
    1545           0 :     const int inter_block = is_inter_block(mbmi);
    1546           0 :     const int seg_ref_active =
    1547           0 :         segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_REF_FRAME);
    1548           0 :     if (!seg_ref_active) {
    1549             : #if CONFIG_SUPERTX
    1550             :       if (!supertx_enabled)
    1551             : #endif
    1552           0 :         counts->intra_inter[av1_get_intra_inter_context(xd)][inter_block]++;
    1553             :       // If the segment reference feature is enabled we have only a single
    1554             :       // reference frame allowed for the segment so exclude it from
    1555             :       // the reference frame counts used to work out probabilities.
    1556           0 :       if (inter_block) {
    1557           0 :         const MV_REFERENCE_FRAME ref0 = mbmi->ref_frame[0];
    1558             : #if CONFIG_EXT_REFS
    1559           0 :         const MV_REFERENCE_FRAME ref1 = mbmi->ref_frame[1];
    1560             : #endif  // CONFIG_EXT_REFS
    1561             : 
    1562           0 :         if (cm->reference_mode == REFERENCE_MODE_SELECT) {
    1563             : #if !SUB8X8_COMP_REF
    1564           0 :           if (mbmi->sb_type != BLOCK_4X4)
    1565           0 :             counts->comp_inter[av1_get_reference_mode_context(cm, xd)]
    1566           0 :                               [has_second_ref(mbmi)]++;
    1567             : #else
    1568             :           counts->comp_inter[av1_get_reference_mode_context(cm, xd)]
    1569             :                             [has_second_ref(mbmi)]++;
    1570             : #endif
    1571             :         }
    1572             : 
    1573           0 :         if (has_second_ref(mbmi)) {
    1574             : #if CONFIG_EXT_REFS
    1575           0 :           const int bit = (ref0 == GOLDEN_FRAME || ref0 == LAST3_FRAME);
    1576             : 
    1577           0 :           counts->comp_ref[av1_get_pred_context_comp_ref_p(cm, xd)][0][bit]++;
    1578           0 :           if (!bit) {
    1579           0 :             counts->comp_ref[av1_get_pred_context_comp_ref_p1(cm, xd)][1]
    1580           0 :                             [ref0 == LAST_FRAME]++;
    1581             :           } else {
    1582           0 :             counts->comp_ref[av1_get_pred_context_comp_ref_p2(cm, xd)][2]
    1583           0 :                             [ref0 == GOLDEN_FRAME]++;
    1584             :           }
    1585             : 
    1586           0 :           counts->comp_bwdref[av1_get_pred_context_comp_bwdref_p(cm, xd)][0]
    1587           0 :                              [ref1 == ALTREF_FRAME]++;
    1588             : #else
    1589             :           counts->comp_ref[av1_get_pred_context_comp_ref_p(cm, xd)][0]
    1590             :                           [ref0 == GOLDEN_FRAME]++;
    1591             : #endif  // CONFIG_EXT_REFS
    1592             :         } else {
    1593             : #if CONFIG_EXT_REFS
    1594           0 :           const int bit = (ref0 == ALTREF_FRAME || ref0 == BWDREF_FRAME);
    1595             : 
    1596           0 :           counts->single_ref[av1_get_pred_context_single_ref_p1(xd)][0][bit]++;
    1597           0 :           if (bit) {
    1598           0 :             counts->single_ref[av1_get_pred_context_single_ref_p2(xd)][1]
    1599           0 :                               [ref0 != BWDREF_FRAME]++;
    1600             :           } else {
    1601           0 :             const int bit1 = !(ref0 == LAST2_FRAME || ref0 == LAST_FRAME);
    1602             :             counts
    1603           0 :                 ->single_ref[av1_get_pred_context_single_ref_p3(xd)][2][bit1]++;
    1604           0 :             if (!bit1) {
    1605           0 :               counts->single_ref[av1_get_pred_context_single_ref_p4(xd)][3]
    1606           0 :                                 [ref0 != LAST_FRAME]++;
    1607             :             } else {
    1608           0 :               counts->single_ref[av1_get_pred_context_single_ref_p5(xd)][4]
    1609           0 :                                 [ref0 != LAST3_FRAME]++;
    1610             :             }
    1611             :           }
    1612             : #else
    1613             :           counts->single_ref[av1_get_pred_context_single_ref_p1(xd)][0]
    1614             :                             [ref0 != LAST_FRAME]++;
    1615             :           if (ref0 != LAST_FRAME) {
    1616             :             counts->single_ref[av1_get_pred_context_single_ref_p2(xd)][1]
    1617             :                               [ref0 != GOLDEN_FRAME]++;
    1618             :           }
    1619             : #endif  // CONFIG_EXT_REFS
    1620             :         }
    1621             : 
    1622             : #if CONFIG_EXT_INTER && CONFIG_INTERINTRA
    1623           0 :         if (cm->reference_mode != COMPOUND_REFERENCE &&
    1624             : #if CONFIG_SUPERTX
    1625             :             !supertx_enabled &&
    1626             : #endif
    1627           0 :             cm->allow_interintra_compound && is_interintra_allowed(mbmi)) {
    1628           0 :           const int bsize_group = size_group_lookup[bsize];
    1629           0 :           if (mbmi->ref_frame[1] == INTRA_FRAME) {
    1630           0 :             counts->interintra[bsize_group][1]++;
    1631           0 :             counts->interintra_mode[bsize_group][mbmi->interintra_mode]++;
    1632           0 :             if (is_interintra_wedge_used(bsize))
    1633           0 :               counts->wedge_interintra[bsize][mbmi->use_wedge_interintra]++;
    1634             :           } else {
    1635           0 :             counts->interintra[bsize_group][0]++;
    1636             :           }
    1637             :         }
    1638             : #endif  // CONFIG_EXT_INTER && CONFIG_INTERINTRA
    1639             : 
    1640             : #if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
    1641           0 :         const MOTION_MODE motion_allowed = motion_mode_allowed(
    1642             : #if CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
    1643           0 :             0, xd->global_motion,
    1644             : #endif  // CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
    1645             :             mi);
    1646             : #if CONFIG_SUPERTX
    1647             :         if (!supertx_enabled)
    1648             : #endif  // CONFIG_SUPERTX
    1649             : #if CONFIG_EXT_INTER
    1650           0 :           if (mbmi->ref_frame[1] != INTRA_FRAME)
    1651             : #endif  // CONFIG_EXT_INTER
    1652             : #if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
    1653             :           {
    1654           0 :             if (motion_allowed == WARPED_CAUSAL)
    1655           0 :               counts->motion_mode[mbmi->sb_type][mbmi->motion_mode]++;
    1656           0 :             else if (motion_allowed == OBMC_CAUSAL)
    1657           0 :               counts->obmc[mbmi->sb_type][mbmi->motion_mode == OBMC_CAUSAL]++;
    1658             :           }
    1659             : #else
    1660             :         if (motion_allowed > SIMPLE_TRANSLATION)
    1661             :           counts->motion_mode[mbmi->sb_type][mbmi->motion_mode]++;
    1662             : #endif  // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
    1663             : #endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
    1664             : 
    1665             : #if CONFIG_EXT_INTER
    1666           0 :         if (cm->reference_mode != SINGLE_REFERENCE &&
    1667           0 :             is_inter_compound_mode(mbmi->mode)
    1668             : #if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
    1669           0 :             && mbmi->motion_mode == SIMPLE_TRANSLATION
    1670             : #endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
    1671             :             ) {
    1672           0 :           counts->compound_interinter[bsize][mbmi->interinter_compound_type]++;
    1673             :         }
    1674             : #endif  // CONFIG_EXT_INTER
    1675             :       }
    1676             :     }
    1677             : 
    1678           0 :     if (inter_block &&
    1679           0 :         !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    1680             :       int16_t mode_ctx;
    1681           0 :       const PREDICTION_MODE mode = mbmi->mode;
    1682             : #if CONFIG_EXT_INTER
    1683           0 :       if (has_second_ref(mbmi)) {
    1684           0 :         mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]];
    1685           0 :         ++counts->inter_compound_mode[mode_ctx][INTER_COMPOUND_OFFSET(mode)];
    1686             :       } else {
    1687             : #endif  // CONFIG_EXT_INTER
    1688           0 :         mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context,
    1689           0 :                                              mbmi->ref_frame, bsize, -1);
    1690           0 :         update_inter_mode_stats(counts, mode, mode_ctx);
    1691             : #if CONFIG_EXT_INTER
    1692             :       }
    1693             : #endif  // CONFIG_EXT_INTER
    1694             : 
    1695             : #if CONFIG_EXT_INTER
    1696           0 :       if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
    1697             : #else
    1698             :       if (mbmi->mode == NEWMV) {
    1699             : #endif
    1700           0 :         uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
    1701             :         int idx;
    1702             : 
    1703           0 :         for (idx = 0; idx < 2; ++idx) {
    1704           0 :           if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
    1705           0 :             uint8_t drl_ctx =
    1706           0 :                 av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
    1707           0 :             ++counts->drl_mode[drl_ctx][mbmi->ref_mv_idx != idx];
    1708             : 
    1709           0 :             if (mbmi->ref_mv_idx == idx) break;
    1710             :           }
    1711             :         }
    1712             :       }
    1713             : 
    1714             : #if CONFIG_EXT_INTER
    1715           0 :       if (have_nearmv_in_inter_mode(mbmi->mode)) {
    1716             : #else
    1717             :       if (mbmi->mode == NEARMV) {
    1718             : #endif
    1719           0 :         uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
    1720             :         int idx;
    1721             : 
    1722           0 :         for (idx = 1; idx < 3; ++idx) {
    1723           0 :           if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
    1724           0 :             uint8_t drl_ctx =
    1725           0 :                 av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
    1726           0 :             ++counts->drl_mode[drl_ctx][mbmi->ref_mv_idx != idx - 1];
    1727             : 
    1728           0 :             if (mbmi->ref_mv_idx == idx - 1) break;
    1729             :           }
    1730             :         }
    1731             :       }
    1732             :     }
    1733             : #if CONFIG_INTRABC
    1734             :   } else {
    1735             :     if (cm->allow_screen_content_tools && bsize >= BLOCK_8X8) {
    1736             :       FRAME_COUNTS *const counts = td->counts;
    1737             :       ++counts->intrabc[mbmi->use_intrabc];
    1738             :     } else {
    1739             :       assert(!mbmi->use_intrabc);
    1740             :     }
    1741             : #endif
    1742             :   }
    1743           0 : }
    1744             : 
    1745             : typedef struct {
    1746             :   ENTROPY_CONTEXT a[2 * MAX_MIB_SIZE * MAX_MB_PLANE];
    1747             :   ENTROPY_CONTEXT l[2 * MAX_MIB_SIZE * MAX_MB_PLANE];
    1748             :   PARTITION_CONTEXT sa[MAX_MIB_SIZE];
    1749             :   PARTITION_CONTEXT sl[MAX_MIB_SIZE];
    1750             : #if CONFIG_VAR_TX
    1751             :   TXFM_CONTEXT *p_ta;
    1752             :   TXFM_CONTEXT *p_tl;
    1753             :   TXFM_CONTEXT ta[2 * MAX_MIB_SIZE];
    1754             :   TXFM_CONTEXT tl[2 * MAX_MIB_SIZE];
    1755             : #endif
    1756             : } RD_SEARCH_MACROBLOCK_CONTEXT;
    1757             : 
    1758           0 : static void restore_context(MACROBLOCK *x,
    1759             :                             const RD_SEARCH_MACROBLOCK_CONTEXT *ctx, int mi_row,
    1760             :                             int mi_col,
    1761             : #if CONFIG_PVQ
    1762             :                             od_rollback_buffer *rdo_buf,
    1763             : #endif
    1764             :                             BLOCK_SIZE bsize) {
    1765           0 :   MACROBLOCKD *xd = &x->e_mbd;
    1766             :   int p;
    1767           0 :   const int num_4x4_blocks_wide =
    1768           0 :       block_size_wide[bsize] >> tx_size_wide_log2[0];
    1769           0 :   const int num_4x4_blocks_high =
    1770           0 :       block_size_high[bsize] >> tx_size_high_log2[0];
    1771           0 :   int mi_width = mi_size_wide[bsize];
    1772           0 :   int mi_height = mi_size_high[bsize];
    1773           0 :   for (p = 0; p < MAX_MB_PLANE; p++) {
    1774             :     int tx_col;
    1775             :     int tx_row;
    1776           0 :     tx_col = mi_col << (MI_SIZE_LOG2 - tx_size_wide_log2[0]);
    1777           0 :     tx_row = (mi_row & MAX_MIB_MASK) << (MI_SIZE_LOG2 - tx_size_high_log2[0]);
    1778           0 :     memcpy(xd->above_context[p] + (tx_col >> xd->plane[p].subsampling_x),
    1779           0 :            ctx->a + num_4x4_blocks_wide * p,
    1780           0 :            (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
    1781           0 :                xd->plane[p].subsampling_x);
    1782           0 :     memcpy(xd->left_context[p] + (tx_row >> xd->plane[p].subsampling_y),
    1783           0 :            ctx->l + num_4x4_blocks_high * p,
    1784           0 :            (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
    1785           0 :                xd->plane[p].subsampling_y);
    1786             :   }
    1787           0 :   memcpy(xd->above_seg_context + mi_col, ctx->sa,
    1788             :          sizeof(*xd->above_seg_context) * mi_width);
    1789           0 :   memcpy(xd->left_seg_context + (mi_row & MAX_MIB_MASK), ctx->sl,
    1790             :          sizeof(xd->left_seg_context[0]) * mi_height);
    1791             : #if CONFIG_VAR_TX
    1792           0 :   xd->above_txfm_context = ctx->p_ta;
    1793           0 :   xd->left_txfm_context = ctx->p_tl;
    1794           0 :   memcpy(xd->above_txfm_context, ctx->ta,
    1795           0 :          sizeof(*xd->above_txfm_context) * (mi_width << TX_UNIT_WIDE_LOG2));
    1796           0 :   memcpy(xd->left_txfm_context, ctx->tl,
    1797           0 :          sizeof(*xd->left_txfm_context) * (mi_height << TX_UNIT_HIGH_LOG2));
    1798             : #endif
    1799             : #if CONFIG_PVQ
    1800             :   od_encode_rollback(&x->daala_enc, rdo_buf);
    1801             : #endif
    1802           0 : }
    1803             : 
    1804           0 : static void save_context(const MACROBLOCK *x, RD_SEARCH_MACROBLOCK_CONTEXT *ctx,
    1805             :                          int mi_row, int mi_col,
    1806             : #if CONFIG_PVQ
    1807             :                          od_rollback_buffer *rdo_buf,
    1808             : #endif
    1809             :                          BLOCK_SIZE bsize) {
    1810           0 :   const MACROBLOCKD *xd = &x->e_mbd;
    1811             :   int p;
    1812           0 :   const int num_4x4_blocks_wide =
    1813           0 :       block_size_wide[bsize] >> tx_size_wide_log2[0];
    1814           0 :   const int num_4x4_blocks_high =
    1815           0 :       block_size_high[bsize] >> tx_size_high_log2[0];
    1816           0 :   int mi_width = mi_size_wide[bsize];
    1817           0 :   int mi_height = mi_size_high[bsize];
    1818             : 
    1819             :   // buffer the above/left context information of the block in search.
    1820           0 :   for (p = 0; p < MAX_MB_PLANE; ++p) {
    1821             :     int tx_col;
    1822             :     int tx_row;
    1823           0 :     tx_col = mi_col << (MI_SIZE_LOG2 - tx_size_wide_log2[0]);
    1824           0 :     tx_row = (mi_row & MAX_MIB_MASK) << (MI_SIZE_LOG2 - tx_size_high_log2[0]);
    1825           0 :     memcpy(ctx->a + num_4x4_blocks_wide * p,
    1826           0 :            xd->above_context[p] + (tx_col >> xd->plane[p].subsampling_x),
    1827           0 :            (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
    1828           0 :                xd->plane[p].subsampling_x);
    1829           0 :     memcpy(ctx->l + num_4x4_blocks_high * p,
    1830           0 :            xd->left_context[p] + (tx_row >> xd->plane[p].subsampling_y),
    1831           0 :            (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
    1832           0 :                xd->plane[p].subsampling_y);
    1833             :   }
    1834           0 :   memcpy(ctx->sa, xd->above_seg_context + mi_col,
    1835             :          sizeof(*xd->above_seg_context) * mi_width);
    1836           0 :   memcpy(ctx->sl, xd->left_seg_context + (mi_row & MAX_MIB_MASK),
    1837             :          sizeof(xd->left_seg_context[0]) * mi_height);
    1838             : #if CONFIG_VAR_TX
    1839           0 :   memcpy(ctx->ta, xd->above_txfm_context,
    1840           0 :          sizeof(*xd->above_txfm_context) * (mi_width << TX_UNIT_WIDE_LOG2));
    1841           0 :   memcpy(ctx->tl, xd->left_txfm_context,
    1842           0 :          sizeof(*xd->left_txfm_context) * (mi_height << TX_UNIT_HIGH_LOG2));
    1843           0 :   ctx->p_ta = xd->above_txfm_context;
    1844           0 :   ctx->p_tl = xd->left_txfm_context;
    1845             : #endif
    1846             : #if CONFIG_PVQ
    1847             :   od_encode_checkpoint(&x->daala_enc, rdo_buf);
    1848             : #endif
    1849           0 : }
    1850             : 
    1851           0 : static void encode_b(const AV1_COMP *const cpi, const TileInfo *const tile,
    1852             :                      ThreadData *td, TOKENEXTRA **tp, int mi_row, int mi_col,
    1853             :                      RUN_TYPE dry_run, BLOCK_SIZE bsize,
    1854             : #if CONFIG_EXT_PARTITION_TYPES
    1855             :                      PARTITION_TYPE partition,
    1856             : #endif
    1857             :                      PICK_MODE_CONTEXT *ctx, int *rate) {
    1858           0 :   MACROBLOCK *const x = &td->mb;
    1859             : #if (CONFIG_MOTION_VAR && CONFIG_NCOBMC) | CONFIG_EXT_DELTA_Q
    1860           0 :   MACROBLOCKD *xd = &x->e_mbd;
    1861             :   MB_MODE_INFO *mbmi;
    1862             : #if CONFIG_MOTION_VAR && CONFIG_NCOBMC
    1863             :   int check_ncobmc;
    1864             : #endif
    1865             : #endif
    1866             : 
    1867           0 :   set_offsets(cpi, tile, x, mi_row, mi_col, bsize);
    1868             : #if CONFIG_EXT_PARTITION_TYPES
    1869             :   x->e_mbd.mi[0]->mbmi.partition = partition;
    1870             : #endif
    1871           0 :   update_state(cpi, td, ctx, mi_row, mi_col, bsize, dry_run);
    1872             : #if CONFIG_MOTION_VAR && CONFIG_NCOBMC
    1873             :   mbmi = &xd->mi[0]->mbmi;
    1874             :   const MOTION_MODE motion_allowed = motion_mode_allowed(
    1875             : #if CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
    1876             :       0, xd->global_motion,
    1877             : #endif  // CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
    1878             :       xd->mi[0]);
    1879             :   check_ncobmc = is_inter_block(mbmi) && motion_allowed >= OBMC_CAUSAL;
    1880             :   if (!dry_run && check_ncobmc) {
    1881             :     av1_check_ncobmc_rd(cpi, x, mi_row, mi_col);
    1882             :     av1_setup_dst_planes(x->e_mbd.plane, bsize,
    1883             :                          get_frame_new_buffer(&cpi->common), mi_row, mi_col);
    1884             :   }
    1885             : #endif
    1886           0 :   encode_superblock(cpi, td, tp, dry_run, mi_row, mi_col, bsize, rate);
    1887             : 
    1888           0 :   if (!dry_run) {
    1889             : #if CONFIG_EXT_DELTA_Q
    1890           0 :     mbmi = &xd->mi[0]->mbmi;
    1891           0 :     if (bsize == BLOCK_64X64 && mbmi->skip == 1 && is_inter_block(mbmi) &&
    1892           0 :         cpi->common.delta_lf_present_flag) {
    1893           0 :       mbmi->current_delta_lf_from_base = xd->prev_delta_lf_from_base;
    1894             :     }
    1895             : #endif
    1896             : #if CONFIG_SUPERTX
    1897             :     update_stats(&cpi->common, td, mi_row, mi_col, 0);
    1898             : #else
    1899           0 :     update_stats(&cpi->common, td, mi_row, mi_col);
    1900             : #endif
    1901             :   }
    1902           0 : }
    1903             : 
    1904           0 : static void encode_sb(const AV1_COMP *const cpi, ThreadData *td,
    1905             :                       const TileInfo *const tile, TOKENEXTRA **tp, int mi_row,
    1906             :                       int mi_col, RUN_TYPE dry_run, BLOCK_SIZE bsize,
    1907             :                       PC_TREE *pc_tree, int *rate) {
    1908           0 :   const AV1_COMMON *const cm = &cpi->common;
    1909           0 :   MACROBLOCK *const x = &td->mb;
    1910           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    1911           0 :   const int hbs = mi_size_wide[bsize] / 2;
    1912           0 :   const int is_partition_root = bsize >= BLOCK_8X8;
    1913           0 :   const int ctx = is_partition_root
    1914           0 :                       ? partition_plane_context(xd, mi_row, mi_col,
    1915             : #if CONFIG_UNPOISON_PARTITION_CTX
    1916             :                                                 mi_row + hbs < cm->mi_rows,
    1917             :                                                 mi_col + hbs < cm->mi_cols,
    1918             : #endif
    1919             :                                                 bsize)
    1920           0 :                       : -1;
    1921           0 :   const PARTITION_TYPE partition = pc_tree->partitioning;
    1922           0 :   const BLOCK_SIZE subsize = get_subsize(bsize, partition);
    1923             : #if CONFIG_EXT_PARTITION_TYPES
    1924             :   const BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
    1925             : #endif
    1926             : 
    1927             : #if CONFIG_CB4X4
    1928           0 :   const int unify_bsize = 1;
    1929             : #else
    1930             :   const int unify_bsize = 0;
    1931             :   assert(bsize >= BLOCK_8X8);
    1932             : #endif
    1933             : 
    1934           0 :   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
    1935             : 
    1936           0 :   if (!dry_run && ctx >= 0) td->counts->partition[ctx][partition]++;
    1937             : 
    1938             : #if CONFIG_SUPERTX
    1939             :   if (!frame_is_intra_only(cm) && bsize <= MAX_SUPERTX_BLOCK_SIZE &&
    1940             :       partition != PARTITION_NONE && !xd->lossless[0]) {
    1941             :     int supertx_enabled;
    1942             :     TX_SIZE supertx_size = max_txsize_lookup[bsize];
    1943             :     supertx_enabled = check_supertx_sb(bsize, supertx_size, pc_tree);
    1944             :     if (supertx_enabled) {
    1945             :       const int mi_width = mi_size_wide[bsize];
    1946             :       const int mi_height = mi_size_high[bsize];
    1947             :       int x_idx, y_idx, i;
    1948             :       uint8_t *dst_buf[3];
    1949             :       int dst_stride[3];
    1950             :       set_skip_context(xd, mi_row, mi_col);
    1951             :       set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
    1952             :       update_state_sb_supertx(cpi, td, tile, mi_row, mi_col, bsize, dry_run,
    1953             :                               pc_tree);
    1954             : 
    1955             :       av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
    1956             :                            mi_col);
    1957             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    1958             :         dst_buf[i] = xd->plane[i].dst.buf;
    1959             :         dst_stride[i] = xd->plane[i].dst.stride;
    1960             :       }
    1961             :       predict_sb_complex(cpi, td, tile, mi_row, mi_col, mi_row, mi_col, dry_run,
    1962             :                          bsize, bsize, dst_buf, dst_stride, pc_tree);
    1963             : 
    1964             :       set_offsets_without_segment_id(cpi, tile, x, mi_row, mi_col, bsize);
    1965             :       set_segment_id_supertx(cpi, x, mi_row, mi_col, bsize);
    1966             : 
    1967             :       if (!x->skip) {
    1968             :         int this_rate = 0;
    1969             :         av1_encode_sb_supertx((AV1_COMMON *)cm, x, bsize);
    1970             :         av1_tokenize_sb_supertx(cpi, td, tp, dry_run, mi_row, mi_col, bsize,
    1971             :                                 rate);
    1972             :         if (rate) *rate += this_rate;
    1973             :       } else {
    1974             :         xd->mi[0]->mbmi.skip = 1;
    1975             :         if (!dry_run) td->counts->skip[av1_get_skip_context(xd)][1]++;
    1976             :         av1_reset_skip_context(xd, mi_row, mi_col, bsize);
    1977             :       }
    1978             :       if (!dry_run) {
    1979             :         for (y_idx = 0; y_idx < mi_height; y_idx++)
    1980             :           for (x_idx = 0; x_idx < mi_width; x_idx++) {
    1981             :             if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width >
    1982             :                     x_idx &&
    1983             :                 (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height >
    1984             :                     y_idx) {
    1985             :               xd->mi[x_idx + y_idx * cm->mi_stride]->mbmi.skip =
    1986             :                   xd->mi[0]->mbmi.skip;
    1987             :             }
    1988             :           }
    1989             :         td->counts->supertx[partition_supertx_context_lookup[partition]]
    1990             :                            [supertx_size][1]++;
    1991             :         td->counts->supertx_size[supertx_size]++;
    1992             : #if CONFIG_EXT_TX
    1993             :         if (get_ext_tx_types(supertx_size, bsize, 1, cm->reduced_tx_set_used) >
    1994             :                 1 &&
    1995             :             !xd->mi[0]->mbmi.skip) {
    1996             :           const int eset =
    1997             :               get_ext_tx_set(supertx_size, bsize, 1, cm->reduced_tx_set_used);
    1998             :           if (eset > 0) {
    1999             :             ++td->counts
    2000             :                   ->inter_ext_tx[eset][supertx_size][xd->mi[0]->mbmi.tx_type];
    2001             :           }
    2002             :         }
    2003             : #else
    2004             :         if (supertx_size < TX_32X32 && !xd->mi[0]->mbmi.skip) {
    2005             :           ++td->counts->inter_ext_tx[supertx_size][xd->mi[0]->mbmi.tx_type];
    2006             :         }
    2007             : #endif  // CONFIG_EXT_TX
    2008             :       }
    2009             : #if CONFIG_EXT_PARTITION_TYPES
    2010             :       update_ext_partition_context(xd, mi_row, mi_col, subsize, bsize,
    2011             :                                    partition);
    2012             : #else
    2013             :       if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
    2014             :         update_partition_context(xd, mi_row, mi_col, subsize, bsize);
    2015             : #endif
    2016             : #if CONFIG_VAR_TX
    2017             :       set_txfm_ctxs(supertx_size, mi_width, mi_height, xd->mi[0]->mbmi.skip,
    2018             :                     xd);
    2019             : #endif  // CONFIG_VAR_TX
    2020             :       return;
    2021             :     } else {
    2022             :       if (!dry_run) {
    2023             :         td->counts->supertx[partition_supertx_context_lookup[partition]]
    2024             :                            [supertx_size][0]++;
    2025             :       }
    2026             :     }
    2027             :   }
    2028             : #endif  // CONFIG_SUPERTX
    2029             : 
    2030           0 :   switch (partition) {
    2031             :     case PARTITION_NONE:
    2032           0 :       encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, subsize,
    2033             : #if CONFIG_EXT_PARTITION_TYPES
    2034             :                partition,
    2035             : #endif
    2036             :                &pc_tree->none, rate);
    2037           0 :       break;
    2038             :     case PARTITION_VERT:
    2039           0 :       encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, subsize,
    2040             : #if CONFIG_EXT_PARTITION_TYPES
    2041             :                partition,
    2042             : #endif
    2043             :                &pc_tree->vertical[0], rate);
    2044           0 :       if (mi_col + hbs < cm->mi_cols && (bsize > BLOCK_8X8 || unify_bsize)) {
    2045           0 :         encode_b(cpi, tile, td, tp, mi_row, mi_col + hbs, dry_run, subsize,
    2046             : #if CONFIG_EXT_PARTITION_TYPES
    2047             :                  partition,
    2048             : #endif
    2049             :                  &pc_tree->vertical[1], rate);
    2050             :       }
    2051           0 :       break;
    2052             :     case PARTITION_HORZ:
    2053           0 :       encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, subsize,
    2054             : #if CONFIG_EXT_PARTITION_TYPES
    2055             :                partition,
    2056             : #endif
    2057             :                &pc_tree->horizontal[0], rate);
    2058           0 :       if (mi_row + hbs < cm->mi_rows && (bsize > BLOCK_8X8 || unify_bsize)) {
    2059           0 :         encode_b(cpi, tile, td, tp, mi_row + hbs, mi_col, dry_run, subsize,
    2060             : #if CONFIG_EXT_PARTITION_TYPES
    2061             :                  partition,
    2062             : #endif
    2063             :                  &pc_tree->horizontal[1], rate);
    2064             :       }
    2065           0 :       break;
    2066             :     case PARTITION_SPLIT:
    2067           0 :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    2068           0 :         encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, subsize,
    2069             : #if CONFIG_EXT_PARTITION_TYPES
    2070             :                  partition,
    2071             : #endif
    2072             :                  pc_tree->leaf_split[0], rate);
    2073             :       } else {
    2074           0 :         encode_sb(cpi, td, tile, tp, mi_row, mi_col, dry_run, subsize,
    2075           0 :                   pc_tree->split[0], rate);
    2076           0 :         encode_sb(cpi, td, tile, tp, mi_row, mi_col + hbs, dry_run, subsize,
    2077           0 :                   pc_tree->split[1], rate);
    2078           0 :         encode_sb(cpi, td, tile, tp, mi_row + hbs, mi_col, dry_run, subsize,
    2079           0 :                   pc_tree->split[2], rate);
    2080           0 :         encode_sb(cpi, td, tile, tp, mi_row + hbs, mi_col + hbs, dry_run,
    2081           0 :                   subsize, pc_tree->split[3], rate);
    2082             :       }
    2083           0 :       break;
    2084             : #if CONFIG_EXT_PARTITION_TYPES
    2085             :     case PARTITION_HORZ_A:
    2086             :       encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, bsize2, partition,
    2087             :                &pc_tree->horizontala[0], rate);
    2088             :       encode_b(cpi, tile, td, tp, mi_row, mi_col + hbs, dry_run, bsize2,
    2089             :                partition, &pc_tree->horizontala[1], rate);
    2090             :       encode_b(cpi, tile, td, tp, mi_row + hbs, mi_col, dry_run, subsize,
    2091             :                partition, &pc_tree->horizontala[2], rate);
    2092             :       break;
    2093             :     case PARTITION_HORZ_B:
    2094             :       encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, subsize, partition,
    2095             :                &pc_tree->horizontalb[0], rate);
    2096             :       encode_b(cpi, tile, td, tp, mi_row + hbs, mi_col, dry_run, bsize2,
    2097             :                partition, &pc_tree->horizontalb[1], rate);
    2098             :       encode_b(cpi, tile, td, tp, mi_row + hbs, mi_col + hbs, dry_run, bsize2,
    2099             :                partition, &pc_tree->horizontalb[2], rate);
    2100             :       break;
    2101             :     case PARTITION_VERT_A:
    2102             :       encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, bsize2, partition,
    2103             :                &pc_tree->verticala[0], rate);
    2104             :       encode_b(cpi, tile, td, tp, mi_row + hbs, mi_col, dry_run, bsize2,
    2105             :                partition, &pc_tree->verticala[1], rate);
    2106             :       encode_b(cpi, tile, td, tp, mi_row, mi_col + hbs, dry_run, subsize,
    2107             :                partition, &pc_tree->verticala[2], rate);
    2108             : 
    2109             :       break;
    2110             :     case PARTITION_VERT_B:
    2111             :       encode_b(cpi, tile, td, tp, mi_row, mi_col, dry_run, subsize, partition,
    2112             :                &pc_tree->verticalb[0], rate);
    2113             :       encode_b(cpi, tile, td, tp, mi_row, mi_col + hbs, dry_run, bsize2,
    2114             :                partition, &pc_tree->verticalb[1], rate);
    2115             :       encode_b(cpi, tile, td, tp, mi_row + hbs, mi_col + hbs, dry_run, bsize2,
    2116             :                partition, &pc_tree->verticalb[2], rate);
    2117             :       break;
    2118             : #endif  // CONFIG_EXT_PARTITION_TYPES
    2119           0 :     default: assert(0 && "Invalid partition type."); break;
    2120             :   }
    2121             : 
    2122             : #if CONFIG_EXT_PARTITION_TYPES
    2123             :   update_ext_partition_context(xd, mi_row, mi_col, subsize, bsize, partition);
    2124             : #else
    2125           0 :   if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
    2126           0 :     update_partition_context(xd, mi_row, mi_col, subsize, bsize);
    2127             : #endif  // CONFIG_EXT_PARTITION_TYPES
    2128             : }
    2129             : 
    2130             : // Check to see if the given partition size is allowed for a specified number
    2131             : // of mi block rows and columns remaining in the image.
    2132             : // If not then return the largest allowed partition size
    2133           0 : static BLOCK_SIZE find_partition_size(BLOCK_SIZE bsize, int rows_left,
    2134             :                                       int cols_left, int *bh, int *bw) {
    2135           0 :   if (rows_left <= 0 || cols_left <= 0) {
    2136           0 :     return AOMMIN(bsize, BLOCK_8X8);
    2137             :   } else {
    2138           0 :     for (; bsize > 0; bsize -= 3) {
    2139           0 :       *bh = mi_size_high[bsize];
    2140           0 :       *bw = mi_size_wide[bsize];
    2141           0 :       if ((*bh <= rows_left) && (*bw <= cols_left)) {
    2142           0 :         break;
    2143             :       }
    2144             :     }
    2145             :   }
    2146           0 :   return bsize;
    2147             : }
    2148             : 
    2149           0 : static void set_partial_sb_partition(const AV1_COMMON *const cm, MODE_INFO *mi,
    2150             :                                      int bh_in, int bw_in,
    2151             :                                      int mi_rows_remaining,
    2152             :                                      int mi_cols_remaining, BLOCK_SIZE bsize,
    2153             :                                      MODE_INFO **mib) {
    2154           0 :   int bh = bh_in;
    2155             :   int r, c;
    2156           0 :   for (r = 0; r < cm->mib_size; r += bh) {
    2157           0 :     int bw = bw_in;
    2158           0 :     for (c = 0; c < cm->mib_size; c += bw) {
    2159           0 :       const int index = r * cm->mi_stride + c;
    2160           0 :       mib[index] = mi + index;
    2161           0 :       mib[index]->mbmi.sb_type = find_partition_size(
    2162             :           bsize, mi_rows_remaining - r, mi_cols_remaining - c, &bh, &bw);
    2163             :     }
    2164             :   }
    2165           0 : }
    2166             : 
    2167             : // This function attempts to set all mode info entries in a given superblock
    2168             : // to the same block partition size.
    2169             : // However, at the bottom and right borders of the image the requested size
    2170             : // may not be allowed in which case this code attempts to choose the largest
    2171             : // allowable partition.
    2172           0 : static void set_fixed_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
    2173             :                                    MODE_INFO **mib, int mi_row, int mi_col,
    2174             :                                    BLOCK_SIZE bsize) {
    2175           0 :   AV1_COMMON *const cm = &cpi->common;
    2176           0 :   const int mi_rows_remaining = tile->mi_row_end - mi_row;
    2177           0 :   const int mi_cols_remaining = tile->mi_col_end - mi_col;
    2178             :   int block_row, block_col;
    2179           0 :   MODE_INFO *const mi_upper_left = cm->mi + mi_row * cm->mi_stride + mi_col;
    2180           0 :   int bh = mi_size_high[bsize];
    2181           0 :   int bw = mi_size_wide[bsize];
    2182             : 
    2183           0 :   assert((mi_rows_remaining > 0) && (mi_cols_remaining > 0));
    2184             : 
    2185             :   // Apply the requested partition size to the SB if it is all "in image"
    2186           0 :   if ((mi_cols_remaining >= cm->mib_size) &&
    2187           0 :       (mi_rows_remaining >= cm->mib_size)) {
    2188           0 :     for (block_row = 0; block_row < cm->mib_size; block_row += bh) {
    2189           0 :       for (block_col = 0; block_col < cm->mib_size; block_col += bw) {
    2190           0 :         int index = block_row * cm->mi_stride + block_col;
    2191           0 :         mib[index] = mi_upper_left + index;
    2192           0 :         mib[index]->mbmi.sb_type = bsize;
    2193             :       }
    2194             :     }
    2195             :   } else {
    2196             :     // Else this is a partial SB.
    2197           0 :     set_partial_sb_partition(cm, mi_upper_left, bh, bw, mi_rows_remaining,
    2198             :                              mi_cols_remaining, bsize, mib);
    2199             :   }
    2200           0 : }
    2201             : 
    2202           0 : static void rd_use_partition(AV1_COMP *cpi, ThreadData *td,
    2203             :                              TileDataEnc *tile_data, MODE_INFO **mib,
    2204             :                              TOKENEXTRA **tp, int mi_row, int mi_col,
    2205             :                              BLOCK_SIZE bsize, int *rate, int64_t *dist,
    2206             : #if CONFIG_SUPERTX
    2207             :                              int *rate_nocoef,
    2208             : #endif
    2209             :                              int do_recon, PC_TREE *pc_tree) {
    2210           0 :   AV1_COMMON *const cm = &cpi->common;
    2211           0 :   TileInfo *const tile_info = &tile_data->tile_info;
    2212           0 :   MACROBLOCK *const x = &td->mb;
    2213           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    2214           0 :   const int bs = mi_size_wide[bsize];
    2215           0 :   const int hbs = bs / 2;
    2216             :   int i;
    2217           0 :   const int pl = (bsize >= BLOCK_8X8)
    2218           0 :                      ? partition_plane_context(xd, mi_row, mi_col,
    2219             : #if CONFIG_UNPOISON_PARTITION_CTX
    2220             :                                                mi_row + hbs < cm->mi_rows,
    2221             :                                                mi_col + hbs < cm->mi_cols,
    2222             : #endif
    2223             :                                                bsize)
    2224           0 :                      : 0;
    2225           0 :   const PARTITION_TYPE partition =
    2226           0 :       (bsize >= BLOCK_8X8) ? get_partition(cm, mi_row, mi_col, bsize)
    2227           0 :                            : PARTITION_NONE;
    2228           0 :   const BLOCK_SIZE subsize = get_subsize(bsize, partition);
    2229             :   RD_SEARCH_MACROBLOCK_CONTEXT x_ctx;
    2230             :   RD_STATS last_part_rdc, none_rdc, chosen_rdc;
    2231           0 :   BLOCK_SIZE sub_subsize = BLOCK_4X4;
    2232           0 :   int splits_below = 0;
    2233           0 :   BLOCK_SIZE bs_type = mib[0]->mbmi.sb_type;
    2234           0 :   int do_partition_search = 1;
    2235           0 :   PICK_MODE_CONTEXT *ctx_none = &pc_tree->none;
    2236           0 :   const int unify_bsize = CONFIG_CB4X4;
    2237             : #if CONFIG_SUPERTX
    2238             :   int last_part_rate_nocoef = INT_MAX;
    2239             :   int none_rate_nocoef = INT_MAX;
    2240             :   int chosen_rate_nocoef = INT_MAX;
    2241             : #endif
    2242             : #if CONFIG_PVQ
    2243             :   od_rollback_buffer pre_rdo_buf;
    2244             : #endif
    2245           0 :   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
    2246             : 
    2247           0 :   assert(num_4x4_blocks_wide_lookup[bsize] ==
    2248             :          num_4x4_blocks_high_lookup[bsize]);
    2249             : 
    2250           0 :   av1_invalid_rd_stats(&last_part_rdc);
    2251           0 :   av1_invalid_rd_stats(&none_rdc);
    2252           0 :   av1_invalid_rd_stats(&chosen_rdc);
    2253             : 
    2254           0 :   pc_tree->partitioning = partition;
    2255             : 
    2256             : #if CONFIG_VAR_TX
    2257           0 :   xd->above_txfm_context =
    2258           0 :       cm->above_txfm_context + (mi_col << TX_UNIT_WIDE_LOG2);
    2259           0 :   xd->left_txfm_context = xd->left_txfm_context_buffer +
    2260           0 :                           ((mi_row & MAX_MIB_MASK) << TX_UNIT_HIGH_LOG2);
    2261             : #endif
    2262             : #if !CONFIG_PVQ
    2263           0 :   save_context(x, &x_ctx, mi_row, mi_col, bsize);
    2264             : #else
    2265             :   save_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    2266             : #endif
    2267             : 
    2268           0 :   if (bsize == BLOCK_16X16 && cpi->vaq_refresh) {
    2269           0 :     set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
    2270           0 :     x->mb_energy = av1_block_energy(cpi, x, bsize);
    2271             :   }
    2272             : 
    2273           0 :   if (do_partition_search &&
    2274           0 :       cpi->sf.partition_search_type == SEARCH_PARTITION &&
    2275           0 :       cpi->sf.adjust_partitioning_from_last_frame) {
    2276             :     // Check if any of the sub blocks are further split.
    2277           0 :     if (partition == PARTITION_SPLIT && subsize > BLOCK_8X8) {
    2278           0 :       sub_subsize = get_subsize(subsize, PARTITION_SPLIT);
    2279           0 :       splits_below = 1;
    2280           0 :       for (i = 0; i < 4; i++) {
    2281           0 :         int jj = i >> 1, ii = i & 0x01;
    2282           0 :         MODE_INFO *this_mi = mib[jj * hbs * cm->mi_stride + ii * hbs];
    2283           0 :         if (this_mi && this_mi->mbmi.sb_type >= sub_subsize) {
    2284           0 :           splits_below = 0;
    2285             :         }
    2286             :       }
    2287             :     }
    2288             : 
    2289             :     // If partition is not none try none unless each of the 4 splits are split
    2290             :     // even further..
    2291           0 :     if (partition != PARTITION_NONE && !splits_below &&
    2292           0 :         mi_row + hbs < cm->mi_rows && mi_col + hbs < cm->mi_cols) {
    2293           0 :       pc_tree->partitioning = PARTITION_NONE;
    2294           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &none_rdc,
    2295             : #if CONFIG_SUPERTX
    2296             :                        &none_rate_nocoef,
    2297             : #endif
    2298             : #if CONFIG_EXT_PARTITION_TYPES
    2299             :                        PARTITION_NONE,
    2300             : #endif
    2301             :                        bsize, ctx_none, INT64_MAX);
    2302             : 
    2303           0 :       if (none_rdc.rate < INT_MAX) {
    2304           0 :         none_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE];
    2305           0 :         none_rdc.rdcost =
    2306           0 :             RDCOST(x->rdmult, x->rddiv, none_rdc.rate, none_rdc.dist);
    2307             : #if CONFIG_SUPERTX
    2308             :         none_rate_nocoef += cpi->partition_cost[pl][PARTITION_NONE];
    2309             : #endif
    2310             :       }
    2311             : 
    2312             : #if !CONFIG_PVQ
    2313           0 :       restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    2314             : #else
    2315             :       restore_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    2316             : #endif
    2317           0 :       mib[0]->mbmi.sb_type = bs_type;
    2318           0 :       pc_tree->partitioning = partition;
    2319             :     }
    2320             :   }
    2321             : 
    2322           0 :   switch (partition) {
    2323             :     case PARTITION_NONE:
    2324           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
    2325             : #if CONFIG_SUPERTX
    2326             :                        &last_part_rate_nocoef,
    2327             : #endif
    2328             : #if CONFIG_EXT_PARTITION_TYPES
    2329             :                        PARTITION_NONE,
    2330             : #endif
    2331             :                        bsize, ctx_none, INT64_MAX);
    2332           0 :       break;
    2333             :     case PARTITION_HORZ:
    2334           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
    2335             : #if CONFIG_SUPERTX
    2336             :                        &last_part_rate_nocoef,
    2337             : #endif
    2338             : #if CONFIG_EXT_PARTITION_TYPES
    2339             :                        PARTITION_HORZ,
    2340             : #endif
    2341             :                        subsize, &pc_tree->horizontal[0], INT64_MAX);
    2342           0 :       if (last_part_rdc.rate != INT_MAX && bsize >= BLOCK_8X8 &&
    2343           0 :           mi_row + hbs < cm->mi_rows) {
    2344             :         RD_STATS tmp_rdc;
    2345             : #if CONFIG_SUPERTX
    2346             :         int rt_nocoef = 0;
    2347             : #endif
    2348           0 :         PICK_MODE_CONTEXT *ctx_h = &pc_tree->horizontal[0];
    2349           0 :         av1_init_rd_stats(&tmp_rdc);
    2350           0 :         update_state(cpi, td, ctx_h, mi_row, mi_col, subsize, 1);
    2351           0 :         encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row, mi_col, subsize,
    2352             :                           NULL);
    2353           0 :         rd_pick_sb_modes(cpi, tile_data, x, mi_row + hbs, mi_col, &tmp_rdc,
    2354             : #if CONFIG_SUPERTX
    2355             :                          &rt_nocoef,
    2356             : #endif
    2357             : #if CONFIG_EXT_PARTITION_TYPES
    2358             :                          PARTITION_HORZ,
    2359             : #endif
    2360             :                          subsize, &pc_tree->horizontal[1], INT64_MAX);
    2361           0 :         if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
    2362           0 :           av1_invalid_rd_stats(&last_part_rdc);
    2363             : #if CONFIG_SUPERTX
    2364             :           last_part_rate_nocoef = INT_MAX;
    2365             : #endif
    2366           0 :           break;
    2367             :         }
    2368           0 :         last_part_rdc.rate += tmp_rdc.rate;
    2369           0 :         last_part_rdc.dist += tmp_rdc.dist;
    2370           0 :         last_part_rdc.rdcost += tmp_rdc.rdcost;
    2371             : #if CONFIG_SUPERTX
    2372             :         last_part_rate_nocoef += rt_nocoef;
    2373             : #endif
    2374             :       }
    2375           0 :       break;
    2376             :     case PARTITION_VERT:
    2377           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
    2378             : #if CONFIG_SUPERTX
    2379             :                        &last_part_rate_nocoef,
    2380             : #endif
    2381             : #if CONFIG_EXT_PARTITION_TYPES
    2382             :                        PARTITION_VERT,
    2383             : #endif
    2384             :                        subsize, &pc_tree->vertical[0], INT64_MAX);
    2385           0 :       if (last_part_rdc.rate != INT_MAX && bsize >= BLOCK_8X8 &&
    2386           0 :           mi_col + hbs < cm->mi_cols) {
    2387             :         RD_STATS tmp_rdc;
    2388             : #if CONFIG_SUPERTX
    2389             :         int rt_nocoef = 0;
    2390             : #endif
    2391           0 :         PICK_MODE_CONTEXT *ctx_v = &pc_tree->vertical[0];
    2392           0 :         av1_init_rd_stats(&tmp_rdc);
    2393           0 :         update_state(cpi, td, ctx_v, mi_row, mi_col, subsize, 1);
    2394           0 :         encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row, mi_col, subsize,
    2395             :                           NULL);
    2396           0 :         rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + hbs, &tmp_rdc,
    2397             : #if CONFIG_SUPERTX
    2398             :                          &rt_nocoef,
    2399             : #endif
    2400             : #if CONFIG_EXT_PARTITION_TYPES
    2401             :                          PARTITION_VERT,
    2402             : #endif
    2403           0 :                          subsize, &pc_tree->vertical[bsize > BLOCK_8X8],
    2404             :                          INT64_MAX);
    2405           0 :         if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
    2406           0 :           av1_invalid_rd_stats(&last_part_rdc);
    2407             : #if CONFIG_SUPERTX
    2408             :           last_part_rate_nocoef = INT_MAX;
    2409             : #endif
    2410           0 :           break;
    2411             :         }
    2412           0 :         last_part_rdc.rate += tmp_rdc.rate;
    2413           0 :         last_part_rdc.dist += tmp_rdc.dist;
    2414           0 :         last_part_rdc.rdcost += tmp_rdc.rdcost;
    2415             : #if CONFIG_SUPERTX
    2416             :         last_part_rate_nocoef += rt_nocoef;
    2417             : #endif
    2418             :       }
    2419           0 :       break;
    2420             :     case PARTITION_SPLIT:
    2421           0 :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    2422           0 :         rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
    2423             : #if CONFIG_SUPERTX
    2424             :                          &last_part_rate_nocoef,
    2425             : #endif
    2426             : #if CONFIG_EXT_PARTITION_TYPES
    2427             :                          PARTITION_SPLIT,
    2428             : #endif
    2429             :                          subsize, pc_tree->leaf_split[0], INT64_MAX);
    2430           0 :         break;
    2431             :       }
    2432           0 :       last_part_rdc.rate = 0;
    2433           0 :       last_part_rdc.dist = 0;
    2434           0 :       last_part_rdc.rdcost = 0;
    2435             : #if CONFIG_SUPERTX
    2436             :       last_part_rate_nocoef = 0;
    2437             : #endif
    2438           0 :       for (i = 0; i < 4; i++) {
    2439           0 :         int x_idx = (i & 1) * hbs;
    2440           0 :         int y_idx = (i >> 1) * hbs;
    2441           0 :         int jj = i >> 1, ii = i & 0x01;
    2442             :         RD_STATS tmp_rdc;
    2443             : #if CONFIG_SUPERTX
    2444             :         int rt_nocoef;
    2445             : #endif
    2446           0 :         if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
    2447           0 :           continue;
    2448             : 
    2449           0 :         av1_init_rd_stats(&tmp_rdc);
    2450           0 :         rd_use_partition(cpi, td, tile_data,
    2451           0 :                          mib + jj * hbs * cm->mi_stride + ii * hbs, tp,
    2452             :                          mi_row + y_idx, mi_col + x_idx, subsize, &tmp_rdc.rate,
    2453             :                          &tmp_rdc.dist,
    2454             : #if CONFIG_SUPERTX
    2455             :                          &rt_nocoef,
    2456             : #endif
    2457           0 :                          i != 3, pc_tree->split[i]);
    2458           0 :         if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
    2459           0 :           av1_invalid_rd_stats(&last_part_rdc);
    2460             : #if CONFIG_SUPERTX
    2461             :           last_part_rate_nocoef = INT_MAX;
    2462             : #endif
    2463           0 :           break;
    2464             :         }
    2465           0 :         last_part_rdc.rate += tmp_rdc.rate;
    2466           0 :         last_part_rdc.dist += tmp_rdc.dist;
    2467             : #if CONFIG_SUPERTX
    2468             :         last_part_rate_nocoef += rt_nocoef;
    2469             : #endif
    2470             :       }
    2471           0 :       break;
    2472             : #if CONFIG_EXT_PARTITION_TYPES
    2473             :     case PARTITION_VERT_A:
    2474             :     case PARTITION_VERT_B:
    2475             :     case PARTITION_HORZ_A:
    2476             :     case PARTITION_HORZ_B: assert(0 && "Cannot handle extended partiton types");
    2477             : #endif  //  CONFIG_EXT_PARTITION_TYPES
    2478           0 :     default: assert(0); break;
    2479             :   }
    2480             : 
    2481           0 :   if (last_part_rdc.rate < INT_MAX) {
    2482           0 :     last_part_rdc.rate += cpi->partition_cost[pl][partition];
    2483           0 :     last_part_rdc.rdcost =
    2484           0 :         RDCOST(x->rdmult, x->rddiv, last_part_rdc.rate, last_part_rdc.dist);
    2485             : #if CONFIG_SUPERTX
    2486             :     last_part_rate_nocoef += cpi->partition_cost[pl][partition];
    2487             : #endif
    2488             :   }
    2489             : 
    2490           0 :   if (do_partition_search && cpi->sf.adjust_partitioning_from_last_frame &&
    2491           0 :       cpi->sf.partition_search_type == SEARCH_PARTITION &&
    2492           0 :       partition != PARTITION_SPLIT && bsize > BLOCK_8X8 &&
    2493           0 :       (mi_row + bs < cm->mi_rows || mi_row + hbs == cm->mi_rows) &&
    2494           0 :       (mi_col + bs < cm->mi_cols || mi_col + hbs == cm->mi_cols)) {
    2495           0 :     BLOCK_SIZE split_subsize = get_subsize(bsize, PARTITION_SPLIT);
    2496           0 :     chosen_rdc.rate = 0;
    2497           0 :     chosen_rdc.dist = 0;
    2498             : #if CONFIG_SUPERTX
    2499             :     chosen_rate_nocoef = 0;
    2500             : #endif
    2501             : #if !CONFIG_PVQ
    2502           0 :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    2503             : #else
    2504             :     restore_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    2505             : #endif
    2506           0 :     pc_tree->partitioning = PARTITION_SPLIT;
    2507             : 
    2508             :     // Split partition.
    2509           0 :     for (i = 0; i < 4; i++) {
    2510           0 :       int x_idx = (i & 1) * hbs;
    2511           0 :       int y_idx = (i >> 1) * hbs;
    2512             :       RD_STATS tmp_rdc;
    2513             : #if CONFIG_SUPERTX
    2514             :       int rt_nocoef = 0;
    2515             : #endif
    2516             : #if CONFIG_PVQ
    2517             :       od_rollback_buffer buf;
    2518             : #endif
    2519           0 :       if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
    2520           0 :         continue;
    2521             : 
    2522             : #if !CONFIG_PVQ
    2523           0 :       save_context(x, &x_ctx, mi_row, mi_col, bsize);
    2524             : #else
    2525             :       save_context(x, &x_ctx, mi_row, mi_col, &buf, bsize);
    2526             : #endif
    2527           0 :       pc_tree->split[i]->partitioning = PARTITION_NONE;
    2528           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row + y_idx, mi_col + x_idx,
    2529             :                        &tmp_rdc,
    2530             : #if CONFIG_SUPERTX
    2531             :                        &rt_nocoef,
    2532             : #endif
    2533             : #if CONFIG_EXT_PARTITION_TYPES
    2534             :                        PARTITION_SPLIT,
    2535             : #endif
    2536           0 :                        split_subsize, &pc_tree->split[i]->none, INT64_MAX);
    2537             : 
    2538             : #if !CONFIG_PVQ
    2539           0 :       restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    2540             : #else
    2541             :       restore_context(x, &x_ctx, mi_row, mi_col, &buf, bsize);
    2542             : #endif
    2543           0 :       if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
    2544           0 :         av1_invalid_rd_stats(&chosen_rdc);
    2545             : #if CONFIG_SUPERTX
    2546             :         chosen_rate_nocoef = INT_MAX;
    2547             : #endif
    2548           0 :         break;
    2549             :       }
    2550             : 
    2551           0 :       chosen_rdc.rate += tmp_rdc.rate;
    2552           0 :       chosen_rdc.dist += tmp_rdc.dist;
    2553             : #if CONFIG_SUPERTX
    2554             :       chosen_rate_nocoef += rt_nocoef;
    2555             : #endif
    2556             : 
    2557           0 :       if (i != 3)
    2558           0 :         encode_sb(cpi, td, tile_info, tp, mi_row + y_idx, mi_col + x_idx,
    2559           0 :                   OUTPUT_ENABLED, split_subsize, pc_tree->split[i], NULL);
    2560             : 
    2561           0 :       chosen_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE];
    2562             : #if CONFIG_SUPERTX
    2563             :       chosen_rate_nocoef += cpi->partition_cost[pl][PARTITION_SPLIT];
    2564             : #endif
    2565             :     }
    2566           0 :     if (chosen_rdc.rate < INT_MAX) {
    2567           0 :       chosen_rdc.rate += cpi->partition_cost[pl][PARTITION_SPLIT];
    2568           0 :       chosen_rdc.rdcost =
    2569           0 :           RDCOST(x->rdmult, x->rddiv, chosen_rdc.rate, chosen_rdc.dist);
    2570             : #if CONFIG_SUPERTX
    2571             :       chosen_rate_nocoef += cpi->partition_cost[pl][PARTITION_NONE];
    2572             : #endif
    2573             :     }
    2574             :   }
    2575             : 
    2576             :   // If last_part is better set the partitioning to that.
    2577           0 :   if (last_part_rdc.rdcost < chosen_rdc.rdcost) {
    2578           0 :     mib[0]->mbmi.sb_type = bsize;
    2579           0 :     if (bsize >= BLOCK_8X8) pc_tree->partitioning = partition;
    2580           0 :     chosen_rdc = last_part_rdc;
    2581             : #if CONFIG_SUPERTX
    2582             :     chosen_rate_nocoef = last_part_rate_nocoef;
    2583             : #endif
    2584             :   }
    2585             :   // If none was better set the partitioning to that.
    2586           0 :   if (none_rdc.rdcost < chosen_rdc.rdcost) {
    2587           0 :     if (bsize >= BLOCK_8X8) pc_tree->partitioning = PARTITION_NONE;
    2588           0 :     chosen_rdc = none_rdc;
    2589             : #if CONFIG_SUPERTX
    2590             :     chosen_rate_nocoef = none_rate_nocoef;
    2591             : #endif
    2592             :   }
    2593             : 
    2594             : #if !CONFIG_PVQ
    2595           0 :   restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    2596             : #else
    2597             :   restore_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    2598             : #endif
    2599             : 
    2600             :   // We must have chosen a partitioning and encoding or we'll fail later on.
    2601             :   // No other opportunities for success.
    2602           0 :   if (bsize == cm->sb_size)
    2603           0 :     assert(chosen_rdc.rate < INT_MAX && chosen_rdc.dist < INT64_MAX);
    2604             : 
    2605           0 :   if (do_recon) {
    2606           0 :     if (bsize == cm->sb_size) {
    2607             :       // NOTE: To get estimate for rate due to the tokens, use:
    2608             :       // int rate_coeffs = 0;
    2609             :       // encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, DRY_RUN_COSTCOEFFS,
    2610             :       //           bsize, pc_tree, &rate_coeffs);
    2611           0 :       encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, OUTPUT_ENABLED, bsize,
    2612             :                 pc_tree, NULL);
    2613             :     } else {
    2614           0 :       encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, DRY_RUN_NORMAL, bsize,
    2615             :                 pc_tree, NULL);
    2616             :     }
    2617             :   }
    2618             : 
    2619           0 :   *rate = chosen_rdc.rate;
    2620           0 :   *dist = chosen_rdc.dist;
    2621             : #if CONFIG_SUPERTX
    2622             :   *rate_nocoef = chosen_rate_nocoef;
    2623             : #endif
    2624             : }
    2625             : 
    2626             : /* clang-format off */
    2627             : static const BLOCK_SIZE min_partition_size[BLOCK_SIZES] = {
    2628             : #if CONFIG_CB4X4
    2629             :   BLOCK_2X2,   BLOCK_2X2,   BLOCK_2X2,    //    2x2,    2x4,     4x2
    2630             : #endif
    2631             :                             BLOCK_4X4,    //                     4x4
    2632             :   BLOCK_4X4,   BLOCK_4X4,   BLOCK_4X4,    //    4x8,    8x4,     8x8
    2633             :   BLOCK_4X4,   BLOCK_4X4,   BLOCK_8X8,    //   8x16,   16x8,   16x16
    2634             :   BLOCK_8X8,   BLOCK_8X8,   BLOCK_16X16,  //  16x32,  32x16,   32x32
    2635             :   BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,  //  32x64,  64x32,   64x64
    2636             : #if CONFIG_EXT_PARTITION
    2637             :   BLOCK_16X16, BLOCK_16X16, BLOCK_16X16   // 64x128, 128x64, 128x128
    2638             : #endif  // CONFIG_EXT_PARTITION
    2639             : };
    2640             : 
    2641             : static const BLOCK_SIZE max_partition_size[BLOCK_SIZES] = {
    2642             : #if CONFIG_CB4X4
    2643             :   BLOCK_4X4,     BLOCK_4X4,       BLOCK_4X4,    //    2x2,    2x4,     4x2
    2644             : #endif
    2645             :                                   BLOCK_8X8,    //                     4x4
    2646             :   BLOCK_16X16,   BLOCK_16X16,   BLOCK_16X16,    //    4x8,    8x4,     8x8
    2647             :   BLOCK_32X32,   BLOCK_32X32,   BLOCK_32X32,    //   8x16,   16x8,   16x16
    2648             :   BLOCK_64X64,   BLOCK_64X64,   BLOCK_64X64,    //  16x32,  32x16,   32x32
    2649             :   BLOCK_LARGEST, BLOCK_LARGEST, BLOCK_LARGEST,  //  32x64,  64x32,   64x64
    2650             : #if CONFIG_EXT_PARTITION
    2651             :   BLOCK_LARGEST, BLOCK_LARGEST, BLOCK_LARGEST   // 64x128, 128x64, 128x128
    2652             : #endif  // CONFIG_EXT_PARTITION
    2653             : };
    2654             : 
    2655             : // Next square block size less or equal than current block size.
    2656             : static const BLOCK_SIZE next_square_size[BLOCK_SIZES] = {
    2657             : #if CONFIG_CB4X4
    2658             :   BLOCK_2X2,   BLOCK_2X2,     BLOCK_2X2,    //    2x2,    2x4,     4x2
    2659             : #endif
    2660             :                               BLOCK_4X4,    //                     4x4
    2661             :   BLOCK_4X4,   BLOCK_4X4,     BLOCK_8X8,    //    4x8,    8x4,     8x8
    2662             :   BLOCK_8X8,   BLOCK_8X8,     BLOCK_16X16,  //   8x16,   16x8,   16x16
    2663             :   BLOCK_16X16, BLOCK_16X16,   BLOCK_32X32,  //  16x32,  32x16,   32x32
    2664             :   BLOCK_32X32, BLOCK_32X32,   BLOCK_64X64,  //  32x64,  64x32,   64x64
    2665             : #if CONFIG_EXT_PARTITION
    2666             :   BLOCK_64X64, BLOCK_64X64, BLOCK_128X128   // 64x128, 128x64, 128x128
    2667             : #endif  // CONFIG_EXT_PARTITION
    2668             : };
    2669             : /* clang-format on */
    2670             : 
    2671             : // Look at all the mode_info entries for blocks that are part of this
    2672             : // partition and find the min and max values for sb_type.
    2673             : // At the moment this is designed to work on a superblock but could be
    2674             : // adjusted to use a size parameter.
    2675             : //
    2676             : // The min and max are assumed to have been initialized prior to calling this
    2677             : // function so repeat calls can accumulate a min and max of more than one
    2678             : // superblock.
    2679           0 : static void get_sb_partition_size_range(const AV1_COMMON *const cm,
    2680             :                                         MACROBLOCKD *xd, MODE_INFO **mib,
    2681             :                                         BLOCK_SIZE *min_block_size,
    2682             :                                         BLOCK_SIZE *max_block_size) {
    2683             :   int i, j;
    2684           0 :   int index = 0;
    2685             : 
    2686             :   // Check the sb_type for each block that belongs to this region.
    2687           0 :   for (i = 0; i < cm->mib_size; ++i) {
    2688           0 :     for (j = 0; j < cm->mib_size; ++j) {
    2689           0 :       MODE_INFO *mi = mib[index + j];
    2690           0 :       BLOCK_SIZE sb_type = mi ? mi->mbmi.sb_type : BLOCK_4X4;
    2691           0 :       *min_block_size = AOMMIN(*min_block_size, sb_type);
    2692           0 :       *max_block_size = AOMMAX(*max_block_size, sb_type);
    2693             :     }
    2694           0 :     index += xd->mi_stride;
    2695             :   }
    2696           0 : }
    2697             : 
    2698             : // Look at neighboring blocks and set a min and max partition size based on
    2699             : // what they chose.
    2700           0 : static void rd_auto_partition_range(AV1_COMP *cpi, const TileInfo *const tile,
    2701             :                                     MACROBLOCKD *const xd, int mi_row,
    2702             :                                     int mi_col, BLOCK_SIZE *min_block_size,
    2703             :                                     BLOCK_SIZE *max_block_size) {
    2704           0 :   AV1_COMMON *const cm = &cpi->common;
    2705           0 :   MODE_INFO **mi = xd->mi;
    2706           0 :   const int left_in_image = xd->left_available && mi[-1];
    2707           0 :   const int above_in_image = xd->up_available && mi[-xd->mi_stride];
    2708           0 :   const int mi_rows_remaining = tile->mi_row_end - mi_row;
    2709           0 :   const int mi_cols_remaining = tile->mi_col_end - mi_col;
    2710             :   int bh, bw;
    2711           0 :   BLOCK_SIZE min_size = BLOCK_4X4;
    2712           0 :   BLOCK_SIZE max_size = BLOCK_LARGEST;
    2713             : 
    2714             :   // Trap case where we do not have a prediction.
    2715           0 :   if (left_in_image || above_in_image || cm->frame_type != KEY_FRAME) {
    2716             :     // Default "min to max" and "max to min"
    2717           0 :     min_size = BLOCK_LARGEST;
    2718           0 :     max_size = BLOCK_4X4;
    2719             : 
    2720             :     // NOTE: each call to get_sb_partition_size_range() uses the previous
    2721             :     // passed in values for min and max as a starting point.
    2722             :     // Find the min and max partition used in previous frame at this location
    2723           0 :     if (cm->frame_type != KEY_FRAME) {
    2724           0 :       MODE_INFO **prev_mi =
    2725           0 :           &cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col];
    2726           0 :       get_sb_partition_size_range(cm, xd, prev_mi, &min_size, &max_size);
    2727             :     }
    2728             :     // Find the min and max partition sizes used in the left superblock
    2729           0 :     if (left_in_image) {
    2730           0 :       MODE_INFO **left_sb_mi = &mi[-cm->mib_size];
    2731           0 :       get_sb_partition_size_range(cm, xd, left_sb_mi, &min_size, &max_size);
    2732             :     }
    2733             :     // Find the min and max partition sizes used in the above suprblock.
    2734           0 :     if (above_in_image) {
    2735           0 :       MODE_INFO **above_sb_mi = &mi[-xd->mi_stride * cm->mib_size];
    2736           0 :       get_sb_partition_size_range(cm, xd, above_sb_mi, &min_size, &max_size);
    2737             :     }
    2738             : 
    2739             :     // Adjust observed min and max for "relaxed" auto partition case.
    2740           0 :     if (cpi->sf.auto_min_max_partition_size == RELAXED_NEIGHBORING_MIN_MAX) {
    2741           0 :       min_size = min_partition_size[min_size];
    2742           0 :       max_size = max_partition_size[max_size];
    2743             :     }
    2744             :   }
    2745             : 
    2746             :   // Check border cases where max and min from neighbors may not be legal.
    2747           0 :   max_size = find_partition_size(max_size, mi_rows_remaining, mi_cols_remaining,
    2748             :                                  &bh, &bw);
    2749           0 :   min_size = AOMMIN(min_size, max_size);
    2750             : 
    2751             :   // Test for blocks at the edge of the active image.
    2752             :   // This may be the actual edge of the image or where there are formatting
    2753             :   // bars.
    2754           0 :   if (av1_active_edge_sb(cpi, mi_row, mi_col)) {
    2755           0 :     min_size = BLOCK_4X4;
    2756             :   } else {
    2757           0 :     min_size = AOMMIN(cpi->sf.rd_auto_partition_min_limit, min_size);
    2758             :   }
    2759             : 
    2760             :   // When use_square_partition_only is true, make sure at least one square
    2761             :   // partition is allowed by selecting the next smaller square size as
    2762             :   // *min_block_size.
    2763           0 :   if (cpi->sf.use_square_partition_only) {
    2764           0 :     min_size = AOMMIN(min_size, next_square_size[max_size]);
    2765             :   }
    2766             : 
    2767           0 :   *min_block_size = AOMMIN(min_size, cm->sb_size);
    2768           0 :   *max_block_size = AOMMIN(max_size, cm->sb_size);
    2769           0 : }
    2770             : 
    2771             : // TODO(jingning) refactor functions setting partition search range
    2772           0 : static void set_partition_range(const AV1_COMMON *const cm,
    2773             :                                 const MACROBLOCKD *const xd, int mi_row,
    2774             :                                 int mi_col, BLOCK_SIZE bsize,
    2775             :                                 BLOCK_SIZE *const min_bs,
    2776             :                                 BLOCK_SIZE *const max_bs) {
    2777           0 :   const int mi_width = mi_size_wide[bsize];
    2778           0 :   const int mi_height = mi_size_high[bsize];
    2779             :   int idx, idy;
    2780             : 
    2781           0 :   const int idx_str = cm->mi_stride * mi_row + mi_col;
    2782           0 :   MODE_INFO **const prev_mi = &cm->prev_mi_grid_visible[idx_str];
    2783           0 :   BLOCK_SIZE min_size = BLOCK_64X64;  // default values
    2784           0 :   BLOCK_SIZE max_size = BLOCK_4X4;
    2785             : 
    2786           0 :   if (prev_mi) {
    2787           0 :     for (idy = 0; idy < mi_height; ++idy) {
    2788           0 :       for (idx = 0; idx < mi_width; ++idx) {
    2789           0 :         const MODE_INFO *const mi = prev_mi[idy * cm->mi_stride + idx];
    2790           0 :         const BLOCK_SIZE bs = mi ? mi->mbmi.sb_type : bsize;
    2791           0 :         min_size = AOMMIN(min_size, bs);
    2792           0 :         max_size = AOMMAX(max_size, bs);
    2793             :       }
    2794             :     }
    2795             :   }
    2796             : 
    2797           0 :   if (xd->left_available) {
    2798           0 :     for (idy = 0; idy < mi_height; ++idy) {
    2799           0 :       const MODE_INFO *const mi = xd->mi[idy * cm->mi_stride - 1];
    2800           0 :       const BLOCK_SIZE bs = mi ? mi->mbmi.sb_type : bsize;
    2801           0 :       min_size = AOMMIN(min_size, bs);
    2802           0 :       max_size = AOMMAX(max_size, bs);
    2803             :     }
    2804             :   }
    2805             : 
    2806           0 :   if (xd->up_available) {
    2807           0 :     for (idx = 0; idx < mi_width; ++idx) {
    2808           0 :       const MODE_INFO *const mi = xd->mi[idx - cm->mi_stride];
    2809           0 :       const BLOCK_SIZE bs = mi ? mi->mbmi.sb_type : bsize;
    2810           0 :       min_size = AOMMIN(min_size, bs);
    2811           0 :       max_size = AOMMAX(max_size, bs);
    2812             :     }
    2813             :   }
    2814             : 
    2815           0 :   if (min_size == max_size) {
    2816           0 :     min_size = min_partition_size[min_size];
    2817           0 :     max_size = max_partition_size[max_size];
    2818             :   }
    2819             : 
    2820           0 :   *min_bs = AOMMIN(min_size, cm->sb_size);
    2821           0 :   *max_bs = AOMMIN(max_size, cm->sb_size);
    2822           0 : }
    2823             : 
    2824           0 : static INLINE void store_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
    2825           0 :   memcpy(ctx->pred_mv, x->pred_mv, sizeof(x->pred_mv));
    2826           0 : }
    2827             : 
    2828           0 : static INLINE void load_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
    2829           0 :   memcpy(x->pred_mv, ctx->pred_mv, sizeof(x->pred_mv));
    2830           0 : }
    2831             : 
    2832             : #if CONFIG_FP_MB_STATS
    2833             : const int qindex_skip_threshold_lookup[BLOCK_SIZES] = {
    2834             :   0,
    2835             :   10,
    2836             :   10,
    2837             :   30,
    2838             :   40,
    2839             :   40,
    2840             :   60,
    2841             :   80,
    2842             :   80,
    2843             :   90,
    2844             :   100,
    2845             :   100,
    2846             :   120,
    2847             : #if CONFIG_EXT_PARTITION
    2848             :   // TODO(debargha): What are the correct numbers here?
    2849             :   130,
    2850             :   130,
    2851             :   150
    2852             : #endif  // CONFIG_EXT_PARTITION
    2853             : };
    2854             : const int qindex_split_threshold_lookup[BLOCK_SIZES] = {
    2855             :   0,
    2856             :   3,
    2857             :   3,
    2858             :   7,
    2859             :   15,
    2860             :   15,
    2861             :   30,
    2862             :   40,
    2863             :   40,
    2864             :   60,
    2865             :   80,
    2866             :   80,
    2867             :   120,
    2868             : #if CONFIG_EXT_PARTITION
    2869             :   // TODO(debargha): What are the correct numbers here?
    2870             :   160,
    2871             :   160,
    2872             :   240
    2873             : #endif  // CONFIG_EXT_PARTITION
    2874             : };
    2875             : const int complexity_16x16_blocks_threshold[BLOCK_SIZES] = {
    2876             :   1,
    2877             :   1,
    2878             :   1,
    2879             :   1,
    2880             :   1,
    2881             :   1,
    2882             :   1,
    2883             :   1,
    2884             :   1,
    2885             :   1,
    2886             :   4,
    2887             :   4,
    2888             :   6,
    2889             : #if CONFIG_EXT_PARTITION
    2890             :   // TODO(debargha): What are the correct numbers here?
    2891             :   8,
    2892             :   8,
    2893             :   10
    2894             : #endif  // CONFIG_EXT_PARTITION
    2895             : };
    2896             : 
    2897             : typedef enum {
    2898             :   MV_ZERO = 0,
    2899             :   MV_LEFT = 1,
    2900             :   MV_UP = 2,
    2901             :   MV_RIGHT = 3,
    2902             :   MV_DOWN = 4,
    2903             :   MV_INVALID
    2904             : } MOTION_DIRECTION;
    2905             : 
    2906             : static INLINE MOTION_DIRECTION get_motion_direction_fp(uint8_t fp_byte) {
    2907             :   if (fp_byte & FPMB_MOTION_ZERO_MASK) {
    2908             :     return MV_ZERO;
    2909             :   } else if (fp_byte & FPMB_MOTION_LEFT_MASK) {
    2910             :     return MV_LEFT;
    2911             :   } else if (fp_byte & FPMB_MOTION_RIGHT_MASK) {
    2912             :     return MV_RIGHT;
    2913             :   } else if (fp_byte & FPMB_MOTION_UP_MASK) {
    2914             :     return MV_UP;
    2915             :   } else {
    2916             :     return MV_DOWN;
    2917             :   }
    2918             : }
    2919             : 
    2920             : static INLINE int get_motion_inconsistency(MOTION_DIRECTION this_mv,
    2921             :                                            MOTION_DIRECTION that_mv) {
    2922             :   if (this_mv == that_mv) {
    2923             :     return 0;
    2924             :   } else {
    2925             :     return abs(this_mv - that_mv) == 2 ? 2 : 1;
    2926             :   }
    2927             : }
    2928             : #endif
    2929             : 
    2930             : #if CONFIG_EXT_PARTITION_TYPES
    2931             : static void rd_test_partition3(
    2932             :     const AV1_COMP *const cpi, ThreadData *td, TileDataEnc *tile_data,
    2933             :     TOKENEXTRA **tp, PC_TREE *pc_tree, RD_STATS *best_rdc,
    2934             :     PICK_MODE_CONTEXT ctxs[3], PICK_MODE_CONTEXT *ctx, int mi_row, int mi_col,
    2935             :     BLOCK_SIZE bsize, PARTITION_TYPE partition,
    2936             : #if CONFIG_SUPERTX
    2937             :     int64_t best_rd, int *best_rate_nocoef, RD_SEARCH_MACROBLOCK_CONTEXT *x_ctx,
    2938             : #endif
    2939             :     int mi_row0, int mi_col0, BLOCK_SIZE subsize0, int mi_row1, int mi_col1,
    2940             :     BLOCK_SIZE subsize1, int mi_row2, int mi_col2, BLOCK_SIZE subsize2) {
    2941             :   MACROBLOCK *const x = &td->mb;
    2942             :   MACROBLOCKD *const xd = &x->e_mbd;
    2943             :   RD_STATS this_rdc, sum_rdc;
    2944             : #if CONFIG_SUPERTX
    2945             :   const AV1_COMMON *const cm = &cpi->common;
    2946             :   TileInfo *const tile_info = &tile_data->tile_info;
    2947             :   int this_rate_nocoef, sum_rate_nocoef;
    2948             :   int abort_flag;
    2949             :   const int supertx_allowed = !frame_is_intra_only(cm) &&
    2950             :                               bsize <= MAX_SUPERTX_BLOCK_SIZE &&
    2951             :                               !xd->lossless[0];
    2952             : #endif
    2953             :   if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx);
    2954             : 
    2955             :   rd_pick_sb_modes(cpi, tile_data, x, mi_row0, mi_col0, &sum_rdc,
    2956             : #if CONFIG_SUPERTX
    2957             :                    &sum_rate_nocoef,
    2958             : #endif
    2959             : #if CONFIG_EXT_PARTITION_TYPES
    2960             :                    partition,
    2961             : #endif
    2962             :                    subsize0, &ctxs[0], best_rdc->rdcost);
    2963             : #if CONFIG_SUPERTX
    2964             :   abort_flag = sum_rdc.rdcost >= best_rd;
    2965             : #endif
    2966             : 
    2967             : #if CONFIG_SUPERTX
    2968             :   if (sum_rdc.rdcost < INT64_MAX) {
    2969             : #else
    2970             :   if (sum_rdc.rdcost < best_rdc->rdcost) {
    2971             : #endif
    2972             :     PICK_MODE_CONTEXT *ctx_0 = &ctxs[0];
    2973             :     update_state(cpi, td, ctx_0, mi_row0, mi_col0, subsize0, 1);
    2974             :     encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row0, mi_col0, subsize0,
    2975             :                       NULL);
    2976             : 
    2977             :     if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx_0);
    2978             : 
    2979             : #if CONFIG_SUPERTX
    2980             :     rd_pick_sb_modes(cpi, tile_data, x, mi_row1, mi_col1, &this_rdc,
    2981             :                      &this_rate_nocoef,
    2982             : #if CONFIG_EXT_PARTITION_TYPES
    2983             :                      partition,
    2984             : #endif
    2985             :                      subsize1, &ctxs[1], INT64_MAX - sum_rdc.rdcost);
    2986             : #else
    2987             :     rd_pick_sb_modes(cpi, tile_data, x, mi_row1, mi_col1, &this_rdc,
    2988             : #if CONFIG_EXT_PARTITION_TYPES
    2989             :                      partition,
    2990             : #endif
    2991             :                      subsize1, &ctxs[1], best_rdc->rdcost - sum_rdc.rdcost);
    2992             : #endif  // CONFIG_SUPERTX
    2993             : 
    2994             :     if (this_rdc.rate == INT_MAX) {
    2995             :       sum_rdc.rdcost = INT64_MAX;
    2996             : #if CONFIG_SUPERTX
    2997             :       sum_rate_nocoef = INT_MAX;
    2998             : #endif
    2999             :     } else {
    3000             :       sum_rdc.rate += this_rdc.rate;
    3001             :       sum_rdc.dist += this_rdc.dist;
    3002             :       sum_rdc.rdcost += this_rdc.rdcost;
    3003             : #if CONFIG_SUPERTX
    3004             :       sum_rate_nocoef += this_rate_nocoef;
    3005             : #endif
    3006             :     }
    3007             : 
    3008             : #if CONFIG_SUPERTX
    3009             :     if (sum_rdc.rdcost < INT64_MAX) {
    3010             : #else
    3011             :     if (sum_rdc.rdcost < best_rdc->rdcost) {
    3012             : #endif
    3013             :       PICK_MODE_CONTEXT *ctx_1 = &ctxs[1];
    3014             :       update_state(cpi, td, ctx_1, mi_row1, mi_col1, subsize1, 1);
    3015             :       encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row1, mi_col1, subsize1,
    3016             :                         NULL);
    3017             : 
    3018             :       if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx_1);
    3019             : 
    3020             : #if CONFIG_SUPERTX
    3021             :       rd_pick_sb_modes(cpi, tile_data, x, mi_row2, mi_col2, &this_rdc,
    3022             :                        &this_rate_nocoef,
    3023             : #if CONFIG_EXT_PARTITION_TYPES
    3024             :                        partition,
    3025             : #endif
    3026             :                        subsize2, &ctxs[2], INT64_MAX - sum_rdc.rdcost);
    3027             : #else
    3028             :       rd_pick_sb_modes(cpi, tile_data, x, mi_row2, mi_col2, &this_rdc,
    3029             : #if CONFIG_EXT_PARTITION_TYPES
    3030             :                        partition,
    3031             : #endif
    3032             :                        subsize2, &ctxs[2], best_rdc->rdcost - sum_rdc.rdcost);
    3033             : #endif  // CONFIG_SUPERTX
    3034             : 
    3035             :       if (this_rdc.rate == INT_MAX) {
    3036             :         sum_rdc.rdcost = INT64_MAX;
    3037             : #if CONFIG_SUPERTX
    3038             :         sum_rate_nocoef = INT_MAX;
    3039             : #endif
    3040             :       } else {
    3041             :         sum_rdc.rate += this_rdc.rate;
    3042             :         sum_rdc.dist += this_rdc.dist;
    3043             :         sum_rdc.rdcost += this_rdc.rdcost;
    3044             : #if CONFIG_SUPERTX
    3045             :         sum_rate_nocoef += this_rate_nocoef;
    3046             : #endif
    3047             :       }
    3048             : 
    3049             : #if CONFIG_SUPERTX
    3050             :       if (supertx_allowed && !abort_flag && sum_rdc.rdcost < INT64_MAX) {
    3051             :         TX_SIZE supertx_size = max_txsize_lookup[bsize];
    3052             :         const PARTITION_TYPE best_partition = pc_tree->partitioning;
    3053             :         pc_tree->partitioning = partition;
    3054             :         sum_rdc.rate += av1_cost_bit(
    3055             :             cm->fc->supertx_prob[partition_supertx_context_lookup[partition]]
    3056             :                                 [supertx_size],
    3057             :             0);
    3058             :         sum_rdc.rdcost =
    3059             :             RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3060             : 
    3061             :         if (!check_intra_sb(cpi, tile_info, mi_row, mi_col, bsize, pc_tree)) {
    3062             :           TX_TYPE best_tx = DCT_DCT;
    3063             :           RD_STATS tmp_rdc = { sum_rate_nocoef, 0, 0 };
    3064             : 
    3065             :           restore_context(x, x_ctx, mi_row, mi_col, bsize);
    3066             : 
    3067             :           rd_supertx_sb(cpi, td, tile_info, mi_row, mi_col, bsize,
    3068             :                         &tmp_rdc.rate, &tmp_rdc.dist, &best_tx, pc_tree);
    3069             : 
    3070             :           tmp_rdc.rate += av1_cost_bit(
    3071             :               cm->fc->supertx_prob[partition_supertx_context_lookup[partition]]
    3072             :                                   [supertx_size],
    3073             :               1);
    3074             :           tmp_rdc.rdcost =
    3075             :               RDCOST(x->rdmult, x->rddiv, tmp_rdc.rate, tmp_rdc.dist);
    3076             :           if (tmp_rdc.rdcost < sum_rdc.rdcost) {
    3077             :             sum_rdc = tmp_rdc;
    3078             :             update_supertx_param_sb(cpi, td, mi_row, mi_col, bsize, best_tx,
    3079             :                                     supertx_size, pc_tree);
    3080             :           }
    3081             :         }
    3082             : 
    3083             :         pc_tree->partitioning = best_partition;
    3084             :       }
    3085             : #endif  // CONFIG_SUPERTX
    3086             : 
    3087             :       if (sum_rdc.rdcost < best_rdc->rdcost) {
    3088             :         int pl = partition_plane_context(xd, mi_row, mi_col,
    3089             : #if CONFIG_UNPOISON_PARTITION_CTX
    3090             :                                          has_rows, has_cols,
    3091             : #endif
    3092             :                                          bsize);
    3093             :         sum_rdc.rate += cpi->partition_cost[pl][partition];
    3094             :         sum_rdc.rdcost =
    3095             :             RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3096             : #if CONFIG_SUPERTX
    3097             :         sum_rate_nocoef += cpi->partition_cost[pl][partition];
    3098             : #endif
    3099             :         if (sum_rdc.rdcost < best_rdc->rdcost) {
    3100             : #if CONFIG_SUPERTX
    3101             :           *best_rate_nocoef = sum_rate_nocoef;
    3102             :           assert(*best_rate_nocoef >= 0);
    3103             : #endif
    3104             :           *best_rdc = sum_rdc;
    3105             :           pc_tree->partitioning = partition;
    3106             :         }
    3107             :       }
    3108             :     }
    3109             :   }
    3110             : }
    3111             : #endif  // CONFIG_EXT_PARTITION_TYPES
    3112             : 
    3113             : // TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
    3114             : // unlikely to be selected depending on previous rate-distortion optimization
    3115             : // results, for encoding speed-up.
    3116           0 : static void rd_pick_partition(const AV1_COMP *const cpi, ThreadData *td,
    3117             :                               TileDataEnc *tile_data, TOKENEXTRA **tp,
    3118             :                               int mi_row, int mi_col, BLOCK_SIZE bsize,
    3119             :                               RD_STATS *rd_cost,
    3120             : #if CONFIG_SUPERTX
    3121             :                               int *rate_nocoef,
    3122             : #endif
    3123             :                               int64_t best_rd, PC_TREE *pc_tree) {
    3124           0 :   const AV1_COMMON *const cm = &cpi->common;
    3125           0 :   TileInfo *const tile_info = &tile_data->tile_info;
    3126           0 :   MACROBLOCK *const x = &td->mb;
    3127           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    3128           0 :   const int mi_step = mi_size_wide[bsize] / 2;
    3129             :   RD_SEARCH_MACROBLOCK_CONTEXT x_ctx;
    3130           0 :   const TOKENEXTRA *const tp_orig = *tp;
    3131           0 :   PICK_MODE_CONTEXT *ctx_none = &pc_tree->none;
    3132             : #if CONFIG_UNPOISON_PARTITION_CTX
    3133             :   const int hbs = mi_size_wide[bsize] / 2;
    3134             :   const int has_rows = mi_row + hbs < cm->mi_rows;
    3135             :   const int has_cols = mi_col + hbs < cm->mi_cols;
    3136             : #else
    3137             :   int tmp_partition_cost[PARTITION_TYPES];
    3138             : #endif
    3139             :   BLOCK_SIZE subsize;
    3140             :   RD_STATS this_rdc, sum_rdc, best_rdc;
    3141           0 :   const int bsize_at_least_8x8 = (bsize >= BLOCK_8X8);
    3142           0 :   int do_square_split = bsize_at_least_8x8;
    3143             : #if CONFIG_CB4X4
    3144           0 :   const int unify_bsize = 1;
    3145           0 :   const int pl = bsize_at_least_8x8
    3146           0 :                      ? partition_plane_context(xd, mi_row, mi_col,
    3147             : #if CONFIG_UNPOISON_PARTITION_CTX
    3148             :                                                has_rows, has_cols,
    3149             : #endif
    3150             :                                                bsize)
    3151           0 :                      : 0;
    3152             : #else
    3153             :   const int unify_bsize = 0;
    3154             :   const int pl = partition_plane_context(xd, mi_row, mi_col,
    3155             : #if CONFIG_UNPOISON_PARTITION_CTX
    3156             :                                          has_rows, has_cols,
    3157             : #endif
    3158             :                                          bsize);
    3159             : #endif  // CONFIG_CB4X4
    3160           0 :   const int *partition_cost = cpi->partition_cost[pl];
    3161             : #if CONFIG_SUPERTX
    3162             :   int this_rate_nocoef, sum_rate_nocoef = 0, best_rate_nocoef = INT_MAX;
    3163             :   int abort_flag;
    3164             :   const int supertx_allowed = !frame_is_intra_only(cm) &&
    3165             :                               bsize <= MAX_SUPERTX_BLOCK_SIZE &&
    3166             :                               !xd->lossless[0];
    3167             : #endif  // CONFIG_SUPERTX
    3168             : 
    3169           0 :   int do_rectangular_split = 1;
    3170             : #if CONFIG_EXT_PARTITION_TYPES
    3171             :   BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
    3172             : #endif
    3173             : 
    3174             :   // Override skipping rectangular partition operations for edge blocks
    3175           0 :   const int force_horz_split = (mi_row + mi_step >= cm->mi_rows);
    3176           0 :   const int force_vert_split = (mi_col + mi_step >= cm->mi_cols);
    3177           0 :   const int xss = x->e_mbd.plane[1].subsampling_x;
    3178           0 :   const int yss = x->e_mbd.plane[1].subsampling_y;
    3179             : 
    3180           0 :   BLOCK_SIZE min_size = x->min_partition_size;
    3181           0 :   BLOCK_SIZE max_size = x->max_partition_size;
    3182             : 
    3183             : #if CONFIG_FP_MB_STATS
    3184             :   unsigned int src_diff_var = UINT_MAX;
    3185             :   int none_complexity = 0;
    3186             : #endif
    3187             : 
    3188           0 :   int partition_none_allowed = !force_horz_split && !force_vert_split;
    3189           0 :   int partition_horz_allowed =
    3190           0 :       !force_vert_split && yss <= xss && bsize_at_least_8x8;
    3191           0 :   int partition_vert_allowed =
    3192           0 :       !force_horz_split && xss <= yss && bsize_at_least_8x8;
    3193             : 
    3194             : #if CONFIG_PVQ
    3195             :   od_rollback_buffer pre_rdo_buf;
    3196             : #endif
    3197             : 
    3198             :   (void)*tp_orig;
    3199             : 
    3200             : #if !CONFIG_UNPOISON_PARTITION_CTX
    3201           0 :   if (force_horz_split || force_vert_split) {
    3202           0 :     tmp_partition_cost[PARTITION_NONE] = INT_MAX;
    3203             : 
    3204           0 :     if (!force_vert_split) {  // force_horz_split only
    3205           0 :       tmp_partition_cost[PARTITION_VERT] = INT_MAX;
    3206           0 :       tmp_partition_cost[PARTITION_HORZ] =
    3207           0 :           av1_cost_bit(cm->fc->partition_prob[pl][PARTITION_HORZ], 0);
    3208           0 :       tmp_partition_cost[PARTITION_SPLIT] =
    3209           0 :           av1_cost_bit(cm->fc->partition_prob[pl][PARTITION_HORZ], 1);
    3210           0 :     } else if (!force_horz_split) {  // force_vert_split only
    3211           0 :       tmp_partition_cost[PARTITION_HORZ] = INT_MAX;
    3212           0 :       tmp_partition_cost[PARTITION_VERT] =
    3213           0 :           av1_cost_bit(cm->fc->partition_prob[pl][PARTITION_VERT], 0);
    3214           0 :       tmp_partition_cost[PARTITION_SPLIT] =
    3215           0 :           av1_cost_bit(cm->fc->partition_prob[pl][PARTITION_VERT], 1);
    3216             :     } else {  // force_ horz_split && force_vert_split horz_split
    3217           0 :       tmp_partition_cost[PARTITION_HORZ] = INT_MAX;
    3218           0 :       tmp_partition_cost[PARTITION_VERT] = INT_MAX;
    3219           0 :       tmp_partition_cost[PARTITION_SPLIT] = 0;
    3220             :     }
    3221             : 
    3222           0 :     partition_cost = tmp_partition_cost;
    3223             :   }
    3224             : #endif
    3225             : 
    3226             : #if CONFIG_VAR_TX
    3227             : #ifndef NDEBUG
    3228             :   // Nothing should rely on the default value of this array (which is just
    3229             :   // leftover from encoding the previous block. Setting it to magic number
    3230             :   // when debugging.
    3231           0 :   memset(x->blk_skip[0], 234, sizeof(x->blk_skip[0]));
    3232             : #endif  // NDEBUG
    3233             : #endif  // CONFIG_VAR_TX
    3234             : 
    3235           0 :   assert(mi_size_wide[bsize] == mi_size_high[bsize]);
    3236             : 
    3237           0 :   av1_init_rd_stats(&this_rdc);
    3238           0 :   av1_init_rd_stats(&sum_rdc);
    3239           0 :   av1_invalid_rd_stats(&best_rdc);
    3240           0 :   best_rdc.rdcost = best_rd;
    3241             : 
    3242           0 :   set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
    3243             : 
    3244           0 :   if (bsize == BLOCK_16X16 && cpi->vaq_refresh)
    3245           0 :     x->mb_energy = av1_block_energy(cpi, x, bsize);
    3246             : 
    3247           0 :   if (cpi->sf.cb_partition_search && bsize == BLOCK_16X16) {
    3248           0 :     const int cb_partition_search_ctrl =
    3249           0 :         ((pc_tree->index == 0 || pc_tree->index == 3) +
    3250           0 :          get_chessboard_index(cm->current_video_frame)) &
    3251             :         0x1;
    3252             : 
    3253           0 :     if (cb_partition_search_ctrl && bsize > min_size && bsize < max_size)
    3254           0 :       set_partition_range(cm, xd, mi_row, mi_col, bsize, &min_size, &max_size);
    3255             :   }
    3256             : 
    3257             :   // Determine partition types in search according to the speed features.
    3258             :   // The threshold set here has to be of square block size.
    3259           0 :   if (cpi->sf.auto_min_max_partition_size) {
    3260           0 :     const int no_partition_allowed = (bsize <= max_size && bsize >= min_size);
    3261             :     // Note: Further partitioning is NOT allowed when bsize == min_size already.
    3262           0 :     const int partition_allowed = (bsize <= max_size && bsize > min_size);
    3263           0 :     partition_none_allowed &= no_partition_allowed;
    3264           0 :     partition_horz_allowed &= partition_allowed || force_horz_split;
    3265           0 :     partition_vert_allowed &= partition_allowed || force_vert_split;
    3266           0 :     do_square_split &= bsize > min_size;
    3267             :   }
    3268           0 :   if (cpi->sf.use_square_partition_only) {
    3269           0 :     partition_horz_allowed &= force_horz_split;
    3270           0 :     partition_vert_allowed &= force_vert_split;
    3271             :   }
    3272             : 
    3273             : #if CONFIG_VAR_TX
    3274           0 :   xd->above_txfm_context =
    3275           0 :       cm->above_txfm_context + (mi_col << TX_UNIT_WIDE_LOG2);
    3276           0 :   xd->left_txfm_context = xd->left_txfm_context_buffer +
    3277           0 :                           ((mi_row & MAX_MIB_MASK) << TX_UNIT_HIGH_LOG2);
    3278             : #endif
    3279             : #if !CONFIG_PVQ
    3280           0 :   save_context(x, &x_ctx, mi_row, mi_col, bsize);
    3281             : #else
    3282             :   save_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    3283             : #endif
    3284             : 
    3285             : #if CONFIG_FP_MB_STATS
    3286             :   if (cpi->use_fp_mb_stats) {
    3287             :     set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
    3288             :     src_diff_var = get_sby_perpixel_diff_variance(cpi, &x->plane[0].src, mi_row,
    3289             :                                                   mi_col, bsize);
    3290             :   }
    3291             : #endif
    3292             : 
    3293             : #if CONFIG_FP_MB_STATS
    3294             :   // Decide whether we shall split directly and skip searching NONE by using
    3295             :   // the first pass block statistics
    3296             :   if (cpi->use_fp_mb_stats && bsize >= BLOCK_32X32 && do_square_split &&
    3297             :       partition_none_allowed && src_diff_var > 4 &&
    3298             :       cm->base_qindex < qindex_split_threshold_lookup[bsize]) {
    3299             :     int mb_row = mi_row >> 1;
    3300             :     int mb_col = mi_col >> 1;
    3301             :     int mb_row_end =
    3302             :         AOMMIN(mb_row + num_16x16_blocks_high_lookup[bsize], cm->mb_rows);
    3303             :     int mb_col_end =
    3304             :         AOMMIN(mb_col + num_16x16_blocks_wide_lookup[bsize], cm->mb_cols);
    3305             :     int r, c;
    3306             : 
    3307             :     // compute a complexity measure, basically measure inconsistency of motion
    3308             :     // vectors obtained from the first pass in the current block
    3309             :     for (r = mb_row; r < mb_row_end; r++) {
    3310             :       for (c = mb_col; c < mb_col_end; c++) {
    3311             :         const int mb_index = r * cm->mb_cols + c;
    3312             : 
    3313             :         MOTION_DIRECTION this_mv;
    3314             :         MOTION_DIRECTION right_mv;
    3315             :         MOTION_DIRECTION bottom_mv;
    3316             : 
    3317             :         this_mv =
    3318             :             get_motion_direction_fp(cpi->twopass.this_frame_mb_stats[mb_index]);
    3319             : 
    3320             :         // to its right
    3321             :         if (c != mb_col_end - 1) {
    3322             :           right_mv = get_motion_direction_fp(
    3323             :               cpi->twopass.this_frame_mb_stats[mb_index + 1]);
    3324             :           none_complexity += get_motion_inconsistency(this_mv, right_mv);
    3325             :         }
    3326             : 
    3327             :         // to its bottom
    3328             :         if (r != mb_row_end - 1) {
    3329             :           bottom_mv = get_motion_direction_fp(
    3330             :               cpi->twopass.this_frame_mb_stats[mb_index + cm->mb_cols]);
    3331             :           none_complexity += get_motion_inconsistency(this_mv, bottom_mv);
    3332             :         }
    3333             : 
    3334             :         // do not count its left and top neighbors to avoid double counting
    3335             :       }
    3336             :     }
    3337             : 
    3338             :     if (none_complexity > complexity_16x16_blocks_threshold[bsize]) {
    3339             :       partition_none_allowed = 0;
    3340             :     }
    3341             :   }
    3342             : #endif
    3343             : 
    3344             :   // PARTITION_NONE
    3345           0 :   if (partition_none_allowed) {
    3346           0 :     rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &this_rdc,
    3347             : #if CONFIG_SUPERTX
    3348             :                      &this_rate_nocoef,
    3349             : #endif
    3350             : #if CONFIG_EXT_PARTITION_TYPES
    3351             :                      PARTITION_NONE,
    3352             : #endif
    3353             :                      bsize, ctx_none, best_rdc.rdcost);
    3354           0 :     if (this_rdc.rate != INT_MAX) {
    3355           0 :       if (bsize_at_least_8x8) {
    3356           0 :         this_rdc.rate += partition_cost[PARTITION_NONE];
    3357           0 :         this_rdc.rdcost =
    3358           0 :             RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist);
    3359             : #if CONFIG_SUPERTX
    3360             :         this_rate_nocoef += partition_cost[PARTITION_NONE];
    3361             : #endif
    3362             :       }
    3363             : 
    3364           0 :       if (this_rdc.rdcost < best_rdc.rdcost) {
    3365             :         // Adjust dist breakout threshold according to the partition size.
    3366           0 :         const int64_t dist_breakout_thr =
    3367           0 :             cpi->sf.partition_search_breakout_dist_thr >>
    3368           0 :             ((2 * (MAX_SB_SIZE_LOG2 - 2)) -
    3369           0 :              (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]));
    3370           0 :         const int rate_breakout_thr =
    3371           0 :             cpi->sf.partition_search_breakout_rate_thr *
    3372           0 :             num_pels_log2_lookup[bsize];
    3373             : 
    3374           0 :         best_rdc = this_rdc;
    3375             : #if CONFIG_SUPERTX
    3376             :         best_rate_nocoef = this_rate_nocoef;
    3377             :         assert(best_rate_nocoef >= 0);
    3378             : #endif
    3379           0 :         if (bsize_at_least_8x8) pc_tree->partitioning = PARTITION_NONE;
    3380             : 
    3381             :         // If all y, u, v transform blocks in this partition are skippable, and
    3382             :         // the dist & rate are within the thresholds, the partition search is
    3383             :         // terminated for current branch of the partition search tree.
    3384             :         // The dist & rate thresholds are set to 0 at speed 0 to disable the
    3385             :         // early termination at that speed.
    3386           0 :         if (!x->e_mbd.lossless[xd->mi[0]->mbmi.segment_id] &&
    3387           0 :             (ctx_none->skippable && best_rdc.dist < dist_breakout_thr &&
    3388           0 :              best_rdc.rate < rate_breakout_thr)) {
    3389           0 :           do_square_split = 0;
    3390           0 :           do_rectangular_split = 0;
    3391             :         }
    3392             : 
    3393             : #if CONFIG_FP_MB_STATS
    3394             :         // Check if every 16x16 first pass block statistics has zero
    3395             :         // motion and the corresponding first pass residue is small enough.
    3396             :         // If that is the case, check the difference variance between the
    3397             :         // current frame and the last frame. If the variance is small enough,
    3398             :         // stop further splitting in RD optimization
    3399             :         if (cpi->use_fp_mb_stats && do_square_split &&
    3400             :             cm->base_qindex > qindex_skip_threshold_lookup[bsize]) {
    3401             :           int mb_row = mi_row >> 1;
    3402             :           int mb_col = mi_col >> 1;
    3403             :           int mb_row_end =
    3404             :               AOMMIN(mb_row + num_16x16_blocks_high_lookup[bsize], cm->mb_rows);
    3405             :           int mb_col_end =
    3406             :               AOMMIN(mb_col + num_16x16_blocks_wide_lookup[bsize], cm->mb_cols);
    3407             :           int r, c;
    3408             : 
    3409             :           int skip = 1;
    3410             :           for (r = mb_row; r < mb_row_end; r++) {
    3411             :             for (c = mb_col; c < mb_col_end; c++) {
    3412             :               const int mb_index = r * cm->mb_cols + c;
    3413             :               if (!(cpi->twopass.this_frame_mb_stats[mb_index] &
    3414             :                     FPMB_MOTION_ZERO_MASK) ||
    3415             :                   !(cpi->twopass.this_frame_mb_stats[mb_index] &
    3416             :                     FPMB_ERROR_SMALL_MASK)) {
    3417             :                 skip = 0;
    3418             :                 break;
    3419             :               }
    3420             :             }
    3421             :             if (skip == 0) {
    3422             :               break;
    3423             :             }
    3424             :           }
    3425             :           if (skip) {
    3426             :             if (src_diff_var == UINT_MAX) {
    3427             :               set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
    3428             :               src_diff_var = get_sby_perpixel_diff_variance(
    3429             :                   cpi, &x->plane[0].src, mi_row, mi_col, bsize);
    3430             :             }
    3431             :             if (src_diff_var < 8) {
    3432             :               do_square_split = 0;
    3433             :               do_rectangular_split = 0;
    3434             :             }
    3435             :           }
    3436             :         }
    3437             : #endif
    3438             :       }
    3439             :     }
    3440             : #if !CONFIG_PVQ
    3441           0 :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    3442             : #else
    3443             :     restore_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    3444             : #endif
    3445             :   }
    3446             : 
    3447             :   // store estimated motion vector
    3448           0 :   if (cpi->sf.adaptive_motion_search) store_pred_mv(x, ctx_none);
    3449             : 
    3450             :   // PARTITION_SPLIT
    3451             :   // TODO(jingning): use the motion vectors given by the above search as
    3452             :   // the starting point of motion search in the following partition type check.
    3453           0 :   if (do_square_split) {
    3454           0 :     int reached_last_index = 0;
    3455           0 :     subsize = get_subsize(bsize, PARTITION_SPLIT);
    3456           0 :     if (bsize == BLOCK_8X8 && !unify_bsize) {
    3457             : #if CONFIG_DUAL_FILTER
    3458           0 :       if (cpi->sf.adaptive_pred_interp_filter && partition_none_allowed)
    3459           0 :         pc_tree->leaf_split[0]->pred_interp_filter =
    3460           0 :             ctx_none->mic.mbmi.interp_filter[0];
    3461             : #else
    3462             :       if (cpi->sf.adaptive_pred_interp_filter && partition_none_allowed)
    3463             :         pc_tree->leaf_split[0]->pred_interp_filter =
    3464             :             ctx_none->mic.mbmi.interp_filter;
    3465             : #endif
    3466             : #if CONFIG_SUPERTX
    3467             :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc,
    3468             :                        &sum_rate_nocoef,
    3469             : #if CONFIG_EXT_PARTITION_TYPES
    3470             :                        PARTITION_SPLIT,
    3471             : #endif
    3472             :                        subsize, pc_tree->leaf_split[0], INT64_MAX);
    3473             : #else
    3474           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc,
    3475             : #if CONFIG_EXT_PARTITION_TYPES
    3476             :                        PARTITION_SPLIT,
    3477             : #endif
    3478             :                        subsize, pc_tree->leaf_split[0], best_rdc.rdcost);
    3479             : #endif  // CONFIG_SUPERTX
    3480           0 :       if (sum_rdc.rate == INT_MAX) {
    3481           0 :         sum_rdc.rdcost = INT64_MAX;
    3482             : #if CONFIG_SUPERTX
    3483             :         sum_rate_nocoef = INT_MAX;
    3484             : #endif
    3485             :       }
    3486             : #if CONFIG_SUPERTX
    3487             :       if (supertx_allowed && sum_rdc.rdcost < INT64_MAX) {
    3488             :         TX_SIZE supertx_size = max_txsize_lookup[bsize];
    3489             :         const PARTITION_TYPE best_partition = pc_tree->partitioning;
    3490             : 
    3491             :         pc_tree->partitioning = PARTITION_SPLIT;
    3492             : 
    3493             :         sum_rdc.rate += av1_cost_bit(
    3494             :             cm->fc->supertx_prob[partition_supertx_context_lookup
    3495             :                                      [PARTITION_SPLIT]][supertx_size],
    3496             :             0);
    3497             :         sum_rdc.rdcost =
    3498             :             RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3499             : 
    3500             :         if (is_inter_mode(pc_tree->leaf_split[0]->mic.mbmi.mode)) {
    3501             :           TX_TYPE best_tx = DCT_DCT;
    3502             :           RD_STATS tmp_rdc;
    3503             :           av1_init_rd_stats(&tmp_rdc);
    3504             :           tmp_rdc.rate = sum_rate_nocoef;
    3505             : 
    3506             :           restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    3507             : 
    3508             :           rd_supertx_sb(cpi, td, tile_info, mi_row, mi_col, bsize,
    3509             :                         &tmp_rdc.rate, &tmp_rdc.dist, &best_tx, pc_tree);
    3510             : 
    3511             :           tmp_rdc.rate += av1_cost_bit(
    3512             :               cm->fc->supertx_prob[partition_supertx_context_lookup
    3513             :                                        [PARTITION_SPLIT]][supertx_size],
    3514             :               1);
    3515             :           tmp_rdc.rdcost =
    3516             :               RDCOST(x->rdmult, x->rddiv, tmp_rdc.rate, tmp_rdc.dist);
    3517             :           if (tmp_rdc.rdcost < sum_rdc.rdcost) {
    3518             :             sum_rdc = tmp_rdc;
    3519             :             update_supertx_param_sb(cpi, td, mi_row, mi_col, bsize, best_tx,
    3520             :                                     supertx_size, pc_tree);
    3521             :           }
    3522             :         }
    3523             : 
    3524             :         pc_tree->partitioning = best_partition;
    3525             :       }
    3526             : #endif  // CONFIG_SUPERTX
    3527           0 :       reached_last_index = 1;
    3528             :     } else {
    3529             :       int idx;
    3530             : #if CONFIG_SUPERTX
    3531             :       for (idx = 0; idx < 4 && sum_rdc.rdcost < INT64_MAX; ++idx) {
    3532             : #else
    3533           0 :       for (idx = 0; idx < 4 && sum_rdc.rdcost < best_rdc.rdcost; ++idx) {
    3534             : #endif  // CONFIG_SUPERTX
    3535           0 :         const int x_idx = (idx & 1) * mi_step;
    3536           0 :         const int y_idx = (idx >> 1) * mi_step;
    3537             : 
    3538           0 :         if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols)
    3539           0 :           continue;
    3540             : 
    3541           0 :         if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx_none);
    3542             : 
    3543           0 :         pc_tree->split[idx]->index = idx;
    3544             : #if CONFIG_SUPERTX
    3545             :         rd_pick_partition(cpi, td, tile_data, tp, mi_row + y_idx,
    3546             :                           mi_col + x_idx, subsize, &this_rdc, &this_rate_nocoef,
    3547             :                           INT64_MAX - sum_rdc.rdcost, pc_tree->split[idx]);
    3548             : #else
    3549           0 :         rd_pick_partition(
    3550             :             cpi, td, tile_data, tp, mi_row + y_idx, mi_col + x_idx, subsize,
    3551           0 :             &this_rdc, best_rdc.rdcost - sum_rdc.rdcost, pc_tree->split[idx]);
    3552             : #endif  // CONFIG_SUPERTX
    3553             : 
    3554           0 :         if (this_rdc.rate == INT_MAX) {
    3555           0 :           sum_rdc.rdcost = INT64_MAX;
    3556             : #if CONFIG_SUPERTX
    3557             :           sum_rate_nocoef = INT_MAX;
    3558             : #endif  // CONFIG_SUPERTX
    3559           0 :           break;
    3560             :         } else {
    3561           0 :           sum_rdc.rate += this_rdc.rate;
    3562           0 :           sum_rdc.dist += this_rdc.dist;
    3563           0 :           sum_rdc.rdcost += this_rdc.rdcost;
    3564             : #if CONFIG_SUPERTX
    3565             :           sum_rate_nocoef += this_rate_nocoef;
    3566             : #endif  // CONFIG_SUPERTX
    3567             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3568             :           sum_rdc.dist_y += this_rdc.dist_y;
    3569             : #endif
    3570             :         }
    3571             :       }
    3572           0 :       reached_last_index = (idx == 4);
    3573             : 
    3574             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3575             :       if (reached_last_index && sum_rdc.rdcost != INT64_MAX &&
    3576             :           bsize == BLOCK_8X8) {
    3577             :         int use_activity_masking = 0;
    3578             :         int64_t daala_dist;
    3579             :         const int src_stride = x->plane[0].src.stride;
    3580             :         daala_dist = av1_daala_dist(x->plane[0].src.buf - 4 * src_stride - 4,
    3581             :                                     src_stride, x->decoded_8x8, 8, 8, 8, 1,
    3582             :                                     use_activity_masking, x->qindex)
    3583             :                      << 4;
    3584             :         sum_rdc.dist = sum_rdc.dist - sum_rdc.dist_y + daala_dist;
    3585             :         sum_rdc.rdcost =
    3586             :             RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3587             :       }
    3588             : #endif  // CONFIG_DAALA_DIST && CONFIG_CB4X4
    3589             : 
    3590             : #if CONFIG_SUPERTX
    3591             :       if (supertx_allowed && sum_rdc.rdcost < INT64_MAX && reached_last_index) {
    3592             :         TX_SIZE supertx_size = max_txsize_lookup[bsize];
    3593             :         const PARTITION_TYPE best_partition = pc_tree->partitioning;
    3594             : 
    3595             :         pc_tree->partitioning = PARTITION_SPLIT;
    3596             : 
    3597             :         sum_rdc.rate += av1_cost_bit(
    3598             :             cm->fc->supertx_prob[partition_supertx_context_lookup
    3599             :                                      [PARTITION_SPLIT]][supertx_size],
    3600             :             0);
    3601             :         sum_rdc.rdcost =
    3602             :             RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3603             : 
    3604             :         if (!check_intra_sb(cpi, tile_info, mi_row, mi_col, bsize, pc_tree)) {
    3605             :           TX_TYPE best_tx = DCT_DCT;
    3606             :           RD_STATS tmp_rdc;
    3607             :           av1_init_rd_stats(&tmp_rdc);
    3608             :           tmp_rdc.rate = sum_rate_nocoef;
    3609             : 
    3610             :           restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    3611             : 
    3612             :           rd_supertx_sb(cpi, td, tile_info, mi_row, mi_col, bsize,
    3613             :                         &tmp_rdc.rate, &tmp_rdc.dist, &best_tx, pc_tree);
    3614             : 
    3615             :           tmp_rdc.rate += av1_cost_bit(
    3616             :               cm->fc->supertx_prob[partition_supertx_context_lookup
    3617             :                                        [PARTITION_SPLIT]][supertx_size],
    3618             :               1);
    3619             :           tmp_rdc.rdcost =
    3620             :               RDCOST(x->rdmult, x->rddiv, tmp_rdc.rate, tmp_rdc.dist);
    3621             :           if (tmp_rdc.rdcost < sum_rdc.rdcost) {
    3622             :             sum_rdc = tmp_rdc;
    3623             :             update_supertx_param_sb(cpi, td, mi_row, mi_col, bsize, best_tx,
    3624             :                                     supertx_size, pc_tree);
    3625             :           }
    3626             :         }
    3627             : 
    3628             :         pc_tree->partitioning = best_partition;
    3629             :       }
    3630             : #endif  // CONFIG_SUPERTX
    3631             :     }
    3632             : 
    3633           0 :     if (reached_last_index && sum_rdc.rdcost < best_rdc.rdcost) {
    3634           0 :       sum_rdc.rate += partition_cost[PARTITION_SPLIT];
    3635           0 :       sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3636             : #if CONFIG_SUPERTX
    3637             :       sum_rate_nocoef += partition_cost[PARTITION_SPLIT];
    3638             : #endif  // CONFIG_SUPERTX
    3639             : 
    3640           0 :       if (sum_rdc.rdcost < best_rdc.rdcost) {
    3641           0 :         best_rdc = sum_rdc;
    3642             : #if CONFIG_SUPERTX
    3643             :         best_rate_nocoef = sum_rate_nocoef;
    3644             :         assert(best_rate_nocoef >= 0);
    3645             : #endif  // CONFIG_SUPERTX
    3646           0 :         pc_tree->partitioning = PARTITION_SPLIT;
    3647             :       }
    3648           0 :     } else if (cpi->sf.less_rectangular_check) {
    3649             :       // skip rectangular partition test when larger block size
    3650             :       // gives better rd cost
    3651           0 :       do_rectangular_split &= !partition_none_allowed;
    3652             :     }
    3653             : #if !CONFIG_PVQ
    3654           0 :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    3655             : #else
    3656             :     restore_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    3657             : #endif
    3658             :   }  // if (do_split)
    3659             : 
    3660             :   // PARTITION_HORZ
    3661           0 :   if (partition_horz_allowed &&
    3662           0 :       (do_rectangular_split || av1_active_h_edge(cpi, mi_row, mi_step))) {
    3663           0 :     subsize = get_subsize(bsize, PARTITION_HORZ);
    3664           0 :     if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx_none);
    3665             : #if CONFIG_DUAL_FILTER
    3666           0 :     if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3667             :         partition_none_allowed)
    3668           0 :       pc_tree->horizontal[0].pred_interp_filter =
    3669           0 :           ctx_none->mic.mbmi.interp_filter[0];
    3670             : #else
    3671             :     if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3672             :         partition_none_allowed)
    3673             :       pc_tree->horizontal[0].pred_interp_filter =
    3674             :           ctx_none->mic.mbmi.interp_filter;
    3675             : #endif
    3676           0 :     rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc,
    3677             : #if CONFIG_SUPERTX
    3678             :                      &sum_rate_nocoef,
    3679             : #endif  // CONFIG_SUPERTX
    3680             : #if CONFIG_EXT_PARTITION_TYPES
    3681             :                      PARTITION_HORZ,
    3682             : #endif
    3683             :                      subsize, &pc_tree->horizontal[0], best_rdc.rdcost);
    3684             : 
    3685             : #if CONFIG_SUPERTX
    3686             :     abort_flag =
    3687             :         (sum_rdc.rdcost >= best_rd && (bsize > BLOCK_8X8 || unify_bsize)) ||
    3688             :         (sum_rdc.rate == INT_MAX && bsize == BLOCK_8X8);
    3689             :     if (sum_rdc.rdcost < INT64_MAX &&
    3690             : #else
    3691           0 :     if (sum_rdc.rdcost < best_rdc.rdcost &&
    3692             : #endif  // CONFIG_SUPERTX
    3693           0 :         !force_horz_split && (bsize > BLOCK_8X8 || unify_bsize)) {
    3694           0 :       PICK_MODE_CONTEXT *ctx_h = &pc_tree->horizontal[0];
    3695           0 :       update_state(cpi, td, ctx_h, mi_row, mi_col, subsize, 1);
    3696           0 :       encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row, mi_col, subsize,
    3697             :                         NULL);
    3698             : 
    3699           0 :       if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx_h);
    3700             : 
    3701             : #if CONFIG_DUAL_FILTER
    3702           0 :       if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3703             :           partition_none_allowed)
    3704           0 :         pc_tree->horizontal[1].pred_interp_filter =
    3705           0 :             ctx_h->mic.mbmi.interp_filter[0];
    3706             : #else
    3707             :       if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3708             :           partition_none_allowed)
    3709             :         pc_tree->horizontal[1].pred_interp_filter =
    3710             :             ctx_none->mic.mbmi.interp_filter;
    3711             : #endif
    3712             : #if CONFIG_SUPERTX
    3713             :       rd_pick_sb_modes(cpi, tile_data, x, mi_row + mi_step, mi_col, &this_rdc,
    3714             :                        &this_rate_nocoef,
    3715             : #if CONFIG_EXT_PARTITION_TYPES
    3716             :                        PARTITION_HORZ,
    3717             : #endif
    3718             :                        subsize, &pc_tree->horizontal[1], INT64_MAX);
    3719             : #else
    3720           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row + mi_step, mi_col, &this_rdc,
    3721             : #if CONFIG_EXT_PARTITION_TYPES
    3722             :                        PARTITION_HORZ,
    3723             : #endif
    3724             :                        subsize, &pc_tree->horizontal[1],
    3725           0 :                        best_rdc.rdcost - sum_rdc.rdcost);
    3726             : #endif  // CONFIG_SUPERTX
    3727             : 
    3728             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3729             :       if (this_rdc.rate != INT_MAX && bsize == BLOCK_8X8) {
    3730             :         update_state(cpi, td, &pc_tree->horizontal[1], mi_row + mi_step, mi_col,
    3731             :                      subsize, DRY_RUN_NORMAL);
    3732             :         encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row + mi_step, mi_col,
    3733             :                           subsize, NULL);
    3734             :       }
    3735             : #endif  // CONFIG_DAALA_DIST && CONFIG_CB4X4
    3736             : 
    3737           0 :       if (this_rdc.rate == INT_MAX) {
    3738           0 :         sum_rdc.rdcost = INT64_MAX;
    3739             : #if CONFIG_SUPERTX
    3740             :         sum_rate_nocoef = INT_MAX;
    3741             : #endif  // CONFIG_SUPERTX
    3742             :       } else {
    3743           0 :         sum_rdc.rate += this_rdc.rate;
    3744           0 :         sum_rdc.dist += this_rdc.dist;
    3745           0 :         sum_rdc.rdcost += this_rdc.rdcost;
    3746             : #if CONFIG_SUPERTX
    3747             :         sum_rate_nocoef += this_rate_nocoef;
    3748             : #endif  // CONFIG_SUPERTX
    3749             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3750             :         sum_rdc.dist_y += this_rdc.dist_y;
    3751             : #endif
    3752             :       }
    3753             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3754             :       if (sum_rdc.rdcost != INT64_MAX && bsize == BLOCK_8X8) {
    3755             :         int use_activity_masking = 0;
    3756             :         int64_t daala_dist;
    3757             :         const int src_stride = x->plane[0].src.stride;
    3758             :         daala_dist = av1_daala_dist(x->plane[0].src.buf - 4 * src_stride,
    3759             :                                     src_stride, x->decoded_8x8, 8, 8, 8, 1,
    3760             :                                     use_activity_masking, x->qindex)
    3761             :                      << 4;
    3762             :         sum_rdc.dist = sum_rdc.dist - sum_rdc.dist_y + daala_dist;
    3763             :         sum_rdc.rdcost =
    3764             :             RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3765             :       }
    3766             : #endif  // CONFIG_DAALA_DIST && CONFIG_CB4X4
    3767             :     }
    3768             : 
    3769             : #if CONFIG_SUPERTX
    3770             :     if (supertx_allowed && sum_rdc.rdcost < INT64_MAX && !abort_flag) {
    3771             :       TX_SIZE supertx_size = max_txsize_lookup[bsize];
    3772             :       const PARTITION_TYPE best_partition = pc_tree->partitioning;
    3773             : 
    3774             :       pc_tree->partitioning = PARTITION_HORZ;
    3775             : 
    3776             :       sum_rdc.rate += av1_cost_bit(
    3777             :           cm->fc->supertx_prob[partition_supertx_context_lookup[PARTITION_HORZ]]
    3778             :                               [supertx_size],
    3779             :           0);
    3780             :       sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3781             : 
    3782             :       if (!check_intra_sb(cpi, tile_info, mi_row, mi_col, bsize, pc_tree)) {
    3783             :         TX_TYPE best_tx = DCT_DCT;
    3784             :         RD_STATS tmp_rdc;
    3785             :         av1_init_rd_stats(&tmp_rdc);
    3786             :         tmp_rdc.rate = sum_rate_nocoef;
    3787             : 
    3788             :         restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    3789             : 
    3790             :         rd_supertx_sb(cpi, td, tile_info, mi_row, mi_col, bsize, &tmp_rdc.rate,
    3791             :                       &tmp_rdc.dist, &best_tx, pc_tree);
    3792             : 
    3793             :         tmp_rdc.rate += av1_cost_bit(
    3794             :             cm->fc
    3795             :                 ->supertx_prob[partition_supertx_context_lookup[PARTITION_HORZ]]
    3796             :                               [supertx_size],
    3797             :             1);
    3798             :         tmp_rdc.rdcost =
    3799             :             RDCOST(x->rdmult, x->rddiv, tmp_rdc.rate, tmp_rdc.dist);
    3800             :         if (tmp_rdc.rdcost < sum_rdc.rdcost) {
    3801             :           sum_rdc = tmp_rdc;
    3802             :           update_supertx_param_sb(cpi, td, mi_row, mi_col, bsize, best_tx,
    3803             :                                   supertx_size, pc_tree);
    3804             :         }
    3805             :       }
    3806             : 
    3807             :       pc_tree->partitioning = best_partition;
    3808             :     }
    3809             : #endif  // CONFIG_SUPERTX
    3810             : 
    3811           0 :     if (sum_rdc.rdcost < best_rdc.rdcost) {
    3812           0 :       sum_rdc.rate += partition_cost[PARTITION_HORZ];
    3813           0 :       sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3814             : #if CONFIG_SUPERTX
    3815             :       sum_rate_nocoef += partition_cost[PARTITION_HORZ];
    3816             : #endif  // CONFIG_SUPERTX
    3817           0 :       if (sum_rdc.rdcost < best_rdc.rdcost) {
    3818           0 :         best_rdc = sum_rdc;
    3819             : #if CONFIG_SUPERTX
    3820             :         best_rate_nocoef = sum_rate_nocoef;
    3821             :         assert(best_rate_nocoef >= 0);
    3822             : #endif  // CONFIG_SUPERTX
    3823           0 :         pc_tree->partitioning = PARTITION_HORZ;
    3824             :       }
    3825             :     }
    3826             : #if !CONFIG_PVQ
    3827           0 :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    3828             : #else
    3829             :     restore_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    3830             : #endif
    3831             :   }
    3832             : 
    3833             :   // PARTITION_VERT
    3834           0 :   if (partition_vert_allowed &&
    3835           0 :       (do_rectangular_split || av1_active_v_edge(cpi, mi_col, mi_step))) {
    3836           0 :     subsize = get_subsize(bsize, PARTITION_VERT);
    3837             : 
    3838           0 :     if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx_none);
    3839             : 
    3840             : #if CONFIG_DUAL_FILTER
    3841           0 :     if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3842             :         partition_none_allowed)
    3843           0 :       pc_tree->vertical[0].pred_interp_filter =
    3844           0 :           ctx_none->mic.mbmi.interp_filter[0];
    3845             : #else
    3846             :     if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3847             :         partition_none_allowed)
    3848             :       pc_tree->vertical[0].pred_interp_filter =
    3849             :           ctx_none->mic.mbmi.interp_filter;
    3850             : #endif
    3851           0 :     rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc,
    3852             : #if CONFIG_SUPERTX
    3853             :                      &sum_rate_nocoef,
    3854             : #endif  // CONFIG_SUPERTX
    3855             : #if CONFIG_EXT_PARTITION_TYPES
    3856             :                      PARTITION_VERT,
    3857             : #endif
    3858             :                      subsize, &pc_tree->vertical[0], best_rdc.rdcost);
    3859             : #if CONFIG_SUPERTX
    3860             :     abort_flag =
    3861             :         (sum_rdc.rdcost >= best_rd && (bsize > BLOCK_8X8 || unify_bsize)) ||
    3862             :         (sum_rdc.rate == INT_MAX && bsize == BLOCK_8X8);
    3863             :     if (sum_rdc.rdcost < INT64_MAX &&
    3864             : #else
    3865           0 :     if (sum_rdc.rdcost < best_rdc.rdcost &&
    3866             : #endif  // CONFIG_SUPERTX
    3867           0 :         !force_vert_split && (bsize > BLOCK_8X8 || unify_bsize)) {
    3868           0 :       update_state(cpi, td, &pc_tree->vertical[0], mi_row, mi_col, subsize, 1);
    3869           0 :       encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row, mi_col, subsize,
    3870             :                         NULL);
    3871             : 
    3872           0 :       if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx_none);
    3873             : 
    3874             : #if CONFIG_DUAL_FILTER
    3875           0 :       if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3876             :           partition_none_allowed)
    3877           0 :         pc_tree->vertical[1].pred_interp_filter =
    3878           0 :             ctx_none->mic.mbmi.interp_filter[0];
    3879             : #else
    3880             :       if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
    3881             :           partition_none_allowed)
    3882             :         pc_tree->vertical[1].pred_interp_filter =
    3883             :             ctx_none->mic.mbmi.interp_filter;
    3884             : #endif
    3885             : #if CONFIG_SUPERTX
    3886             :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + mi_step, &this_rdc,
    3887             :                        &this_rate_nocoef,
    3888             : #if CONFIG_EXT_PARTITION_TYPES
    3889             :                        PARTITION_VERT,
    3890             : #endif
    3891             :                        subsize, &pc_tree->vertical[1],
    3892             :                        INT64_MAX - sum_rdc.rdcost);
    3893             : #else
    3894           0 :       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + mi_step, &this_rdc,
    3895             : #if CONFIG_EXT_PARTITION_TYPES
    3896             :                        PARTITION_VERT,
    3897             : #endif
    3898             :                        subsize, &pc_tree->vertical[1],
    3899           0 :                        best_rdc.rdcost - sum_rdc.rdcost);
    3900             : #endif  // CONFIG_SUPERTX
    3901             : 
    3902             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3903             :       if (this_rdc.rate != INT_MAX && bsize == BLOCK_8X8) {
    3904             :         update_state(cpi, td, &pc_tree->vertical[1], mi_row, mi_col + mi_step,
    3905             :                      subsize, DRY_RUN_NORMAL);
    3906             :         encode_superblock(cpi, td, tp, DRY_RUN_NORMAL, mi_row, mi_col + mi_step,
    3907             :                           subsize, NULL);
    3908             :       }
    3909             : #endif  // CONFIG_DAALA_DIST && CONFIG_CB4X4
    3910             : 
    3911           0 :       if (this_rdc.rate == INT_MAX) {
    3912           0 :         sum_rdc.rdcost = INT64_MAX;
    3913             : #if CONFIG_SUPERTX
    3914             :         sum_rate_nocoef = INT_MAX;
    3915             : #endif  // CONFIG_SUPERTX
    3916             :       } else {
    3917           0 :         sum_rdc.rate += this_rdc.rate;
    3918           0 :         sum_rdc.dist += this_rdc.dist;
    3919           0 :         sum_rdc.rdcost += this_rdc.rdcost;
    3920             : #if CONFIG_SUPERTX
    3921             :         sum_rate_nocoef += this_rate_nocoef;
    3922             : #endif  // CONFIG_SUPERTX
    3923             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3924             :         sum_rdc.dist_y += this_rdc.dist_y;
    3925             : #endif
    3926             :       }
    3927             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    3928             :       if (sum_rdc.rdcost != INT64_MAX && bsize == BLOCK_8X8) {
    3929             :         int use_activity_masking = 0;
    3930             :         int64_t daala_dist;
    3931             :         const int src_stride = x->plane[0].src.stride;
    3932             :         daala_dist =
    3933             :             av1_daala_dist(x->plane[0].src.buf - 4, src_stride, x->decoded_8x8,
    3934             :                            8, 8, 8, 1, use_activity_masking, x->qindex)
    3935             :             << 4;
    3936             :         sum_rdc.dist = sum_rdc.dist - sum_rdc.dist_y + daala_dist;
    3937             :         sum_rdc.rdcost =
    3938             :             RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3939             :       }
    3940             : #endif  // CONFIG_DAALA_DIST && CONFIG_CB4X4
    3941             :     }
    3942             : #if CONFIG_SUPERTX
    3943             :     if (supertx_allowed && sum_rdc.rdcost < INT64_MAX && !abort_flag) {
    3944             :       TX_SIZE supertx_size = max_txsize_lookup[bsize];
    3945             :       const PARTITION_TYPE best_partition = pc_tree->partitioning;
    3946             : 
    3947             :       pc_tree->partitioning = PARTITION_VERT;
    3948             : 
    3949             :       sum_rdc.rate += av1_cost_bit(
    3950             :           cm->fc->supertx_prob[partition_supertx_context_lookup[PARTITION_VERT]]
    3951             :                               [supertx_size],
    3952             :           0);
    3953             :       sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3954             : 
    3955             :       if (!check_intra_sb(cpi, tile_info, mi_row, mi_col, bsize, pc_tree)) {
    3956             :         TX_TYPE best_tx = DCT_DCT;
    3957             :         RD_STATS tmp_rdc;
    3958             :         av1_init_rd_stats(&tmp_rdc);
    3959             :         tmp_rdc.rate = sum_rate_nocoef;
    3960             : 
    3961             :         restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    3962             : 
    3963             :         rd_supertx_sb(cpi, td, tile_info, mi_row, mi_col, bsize, &tmp_rdc.rate,
    3964             :                       &tmp_rdc.dist, &best_tx, pc_tree);
    3965             : 
    3966             :         tmp_rdc.rate += av1_cost_bit(
    3967             :             cm->fc
    3968             :                 ->supertx_prob[partition_supertx_context_lookup[PARTITION_VERT]]
    3969             :                               [supertx_size],
    3970             :             1);
    3971             :         tmp_rdc.rdcost =
    3972             :             RDCOST(x->rdmult, x->rddiv, tmp_rdc.rate, tmp_rdc.dist);
    3973             :         if (tmp_rdc.rdcost < sum_rdc.rdcost) {
    3974             :           sum_rdc = tmp_rdc;
    3975             :           update_supertx_param_sb(cpi, td, mi_row, mi_col, bsize, best_tx,
    3976             :                                   supertx_size, pc_tree);
    3977             :         }
    3978             :       }
    3979             : 
    3980             :       pc_tree->partitioning = best_partition;
    3981             :     }
    3982             : #endif  // CONFIG_SUPERTX
    3983             : 
    3984           0 :     if (sum_rdc.rdcost < best_rdc.rdcost) {
    3985           0 :       sum_rdc.rate += partition_cost[PARTITION_VERT];
    3986           0 :       sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
    3987             : #if CONFIG_SUPERTX
    3988             :       sum_rate_nocoef += partition_cost[PARTITION_VERT];
    3989             : #endif  // CONFIG_SUPERTX
    3990           0 :       if (sum_rdc.rdcost < best_rdc.rdcost) {
    3991           0 :         best_rdc = sum_rdc;
    3992             : #if CONFIG_SUPERTX
    3993             :         best_rate_nocoef = sum_rate_nocoef;
    3994             :         assert(best_rate_nocoef >= 0);
    3995             : #endif  // CONFIG_SUPERTX
    3996           0 :         pc_tree->partitioning = PARTITION_VERT;
    3997             :       }
    3998             :     }
    3999             : #if !CONFIG_PVQ
    4000           0 :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    4001             : #else
    4002             :     restore_context(x, &x_ctx, mi_row, mi_col, &pre_rdo_buf, bsize);
    4003             : #endif
    4004             :   }
    4005             : 
    4006             : #if CONFIG_EXT_PARTITION_TYPES
    4007             :   // PARTITION_HORZ_A
    4008             :   if (partition_horz_allowed && do_rectangular_split && bsize > BLOCK_8X8 &&
    4009             :       partition_none_allowed) {
    4010             :     subsize = get_subsize(bsize, PARTITION_HORZ_A);
    4011             :     rd_test_partition3(cpi, td, tile_data, tp, pc_tree, &best_rdc,
    4012             :                        pc_tree->horizontala, ctx_none, mi_row, mi_col, bsize,
    4013             :                        PARTITION_HORZ_A,
    4014             : #if CONFIG_SUPERTX
    4015             :                        best_rd, &best_rate_nocoef, &x_ctx,
    4016             : #endif
    4017             :                        mi_row, mi_col, bsize2, mi_row, mi_col + mi_step, bsize2,
    4018             :                        mi_row + mi_step, mi_col, subsize);
    4019             :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    4020             :   }
    4021             :   // PARTITION_HORZ_B
    4022             :   if (partition_horz_allowed && do_rectangular_split && bsize > BLOCK_8X8 &&
    4023             :       partition_none_allowed) {
    4024             :     subsize = get_subsize(bsize, PARTITION_HORZ_B);
    4025             :     rd_test_partition3(cpi, td, tile_data, tp, pc_tree, &best_rdc,
    4026             :                        pc_tree->horizontalb, ctx_none, mi_row, mi_col, bsize,
    4027             :                        PARTITION_HORZ_B,
    4028             : #if CONFIG_SUPERTX
    4029             :                        best_rd, &best_rate_nocoef, &x_ctx,
    4030             : #endif
    4031             :                        mi_row, mi_col, subsize, mi_row + mi_step, mi_col,
    4032             :                        bsize2, mi_row + mi_step, mi_col + mi_step, bsize2);
    4033             :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    4034             :   }
    4035             :   // PARTITION_VERT_A
    4036             :   if (partition_vert_allowed && do_rectangular_split && bsize > BLOCK_8X8 &&
    4037             :       partition_none_allowed) {
    4038             :     subsize = get_subsize(bsize, PARTITION_VERT_A);
    4039             :     rd_test_partition3(cpi, td, tile_data, tp, pc_tree, &best_rdc,
    4040             :                        pc_tree->verticala, ctx_none, mi_row, mi_col, bsize,
    4041             :                        PARTITION_VERT_A,
    4042             : #if CONFIG_SUPERTX
    4043             :                        best_rd, &best_rate_nocoef, &x_ctx,
    4044             : #endif
    4045             :                        mi_row, mi_col, bsize2, mi_row + mi_step, mi_col, bsize2,
    4046             :                        mi_row, mi_col + mi_step, subsize);
    4047             :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    4048             :   }
    4049             :   // PARTITION_VERT_B
    4050             :   if (partition_vert_allowed && do_rectangular_split && bsize > BLOCK_8X8 &&
    4051             :       partition_none_allowed) {
    4052             :     subsize = get_subsize(bsize, PARTITION_VERT_B);
    4053             :     rd_test_partition3(cpi, td, tile_data, tp, pc_tree, &best_rdc,
    4054             :                        pc_tree->verticalb, ctx_none, mi_row, mi_col, bsize,
    4055             :                        PARTITION_VERT_B,
    4056             : #if CONFIG_SUPERTX
    4057             :                        best_rd, &best_rate_nocoef, &x_ctx,
    4058             : #endif
    4059             :                        mi_row, mi_col, subsize, mi_row, mi_col + mi_step,
    4060             :                        bsize2, mi_row + mi_step, mi_col + mi_step, bsize2);
    4061             :     restore_context(x, &x_ctx, mi_row, mi_col, bsize);
    4062             :   }
    4063             : #endif  // CONFIG_EXT_PARTITION_TYPES
    4064             : 
    4065             :   // TODO(jbb): This code added so that we avoid static analysis
    4066             :   // warning related to the fact that best_rd isn't used after this
    4067             :   // point.  This code should be refactored so that the duplicate
    4068             :   // checks occur in some sub function and thus are used...
    4069             :   (void)best_rd;
    4070           0 :   *rd_cost = best_rdc;
    4071             : #if CONFIG_SUPERTX
    4072             :   *rate_nocoef = best_rate_nocoef;
    4073             : #endif  // CONFIG_SUPERTX
    4074             : 
    4075             : #if CONFIG_CFL
    4076             :   // Store the luma for the best mode
    4077             :   x->cfl_store_y = 1;
    4078             : #endif
    4079           0 :   if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX &&
    4080           0 :       pc_tree->index != 3) {
    4081           0 :     if (bsize == cm->sb_size) {
    4082             : #if CONFIG_MOTION_VAR && CONFIG_NCOBMC
    4083             :       set_mode_info_sb(cpi, td, tile_info, tp, mi_row, mi_col, bsize, pc_tree);
    4084             : #endif
    4085           0 :       encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, OUTPUT_ENABLED, bsize,
    4086             :                 pc_tree, NULL);
    4087             :     } else {
    4088           0 :       encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, DRY_RUN_NORMAL, bsize,
    4089             :                 pc_tree, NULL);
    4090             :     }
    4091             :   }
    4092             : #if CONFIG_CFL
    4093             :   x->cfl_store_y = 0;
    4094             : #endif
    4095             : 
    4096             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    4097             :   if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX &&
    4098             :       bsize == BLOCK_4X4 && pc_tree->index == 3) {
    4099             :     encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, DRY_RUN_NORMAL, bsize,
    4100             :               pc_tree, NULL);
    4101             :   }
    4102             : #endif  // CONFIG_DAALA_DIST && CONFIG_CB4X4
    4103             : 
    4104           0 :   if (bsize == cm->sb_size) {
    4105             : #if !CONFIG_PVQ && !CONFIG_LV_MAP
    4106           0 :     assert(tp_orig < *tp || (tp_orig == *tp && xd->mi[0]->mbmi.skip));
    4107             : #endif
    4108           0 :     assert(best_rdc.rate < INT_MAX);
    4109           0 :     assert(best_rdc.dist < INT64_MAX);
    4110             :   } else {
    4111           0 :     assert(tp_orig == *tp);
    4112             :   }
    4113           0 : }
    4114             : 
    4115           0 : static void encode_rd_sb_row(AV1_COMP *cpi, ThreadData *td,
    4116             :                              TileDataEnc *tile_data, int mi_row,
    4117             :                              TOKENEXTRA **tp) {
    4118           0 :   AV1_COMMON *const cm = &cpi->common;
    4119           0 :   const TileInfo *const tile_info = &tile_data->tile_info;
    4120           0 :   MACROBLOCK *const x = &td->mb;
    4121           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    4122           0 :   SPEED_FEATURES *const sf = &cpi->sf;
    4123             :   int mi_col;
    4124             : #if CONFIG_EXT_PARTITION
    4125             :   const int leaf_nodes = 256;
    4126             : #else
    4127           0 :   const int leaf_nodes = 64;
    4128             : #endif  // CONFIG_EXT_PARTITION
    4129             : 
    4130             :   // Initialize the left context for the new SB row
    4131           0 :   av1_zero_left_context(xd);
    4132             : 
    4133             : #if CONFIG_DELTA_Q
    4134             :   // Reset delta for every tile
    4135           0 :   if (cm->delta_q_present_flag)
    4136           0 :     if (mi_row == tile_info->mi_row_start) xd->prev_qindex = cm->base_qindex;
    4137             : #if CONFIG_EXT_DELTA_Q
    4138           0 :   if (cm->delta_lf_present_flag)
    4139           0 :     if (mi_row == tile_info->mi_row_start) xd->prev_delta_lf_from_base = 0;
    4140             : #endif
    4141             : #endif
    4142             : 
    4143             :   // Code each SB in the row
    4144           0 :   for (mi_col = tile_info->mi_col_start; mi_col < tile_info->mi_col_end;
    4145           0 :        mi_col += cm->mib_size) {
    4146           0 :     const struct segmentation *const seg = &cm->seg;
    4147             :     int dummy_rate;
    4148             :     int64_t dummy_dist;
    4149             :     RD_STATS dummy_rdc;
    4150             : #if CONFIG_SUPERTX
    4151             :     int dummy_rate_nocoef;
    4152             : #endif  // CONFIG_SUPERTX
    4153             :     int i;
    4154           0 :     int seg_skip = 0;
    4155             : 
    4156           0 :     const int idx_str = cm->mi_stride * mi_row + mi_col;
    4157           0 :     MODE_INFO **mi = cm->mi_grid_visible + idx_str;
    4158           0 :     PC_TREE *const pc_root = td->pc_root[cm->mib_size_log2 - MIN_MIB_SIZE_LOG2];
    4159             : 
    4160           0 :     av1_update_boundary_info(cm, tile_info, mi_row, mi_col);
    4161             : 
    4162           0 :     if (sf->adaptive_pred_interp_filter) {
    4163           0 :       for (i = 0; i < leaf_nodes; ++i)
    4164           0 :         td->leaf_tree[i].pred_interp_filter = SWITCHABLE;
    4165             : 
    4166           0 :       for (i = 0; i < leaf_nodes; ++i) {
    4167           0 :         td->pc_tree[i].vertical[0].pred_interp_filter = SWITCHABLE;
    4168           0 :         td->pc_tree[i].vertical[1].pred_interp_filter = SWITCHABLE;
    4169           0 :         td->pc_tree[i].horizontal[0].pred_interp_filter = SWITCHABLE;
    4170           0 :         td->pc_tree[i].horizontal[1].pred_interp_filter = SWITCHABLE;
    4171             :       }
    4172             :     }
    4173             : 
    4174           0 :     av1_zero(x->pred_mv);
    4175           0 :     pc_root->index = 0;
    4176             : 
    4177           0 :     if (seg->enabled) {
    4178           0 :       const uint8_t *const map =
    4179           0 :           seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
    4180           0 :       int segment_id = get_segment_id(cm, map, cm->sb_size, mi_row, mi_col);
    4181           0 :       seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
    4182             :     }
    4183             : 
    4184             : #if CONFIG_DELTA_Q
    4185           0 :     if (cm->delta_q_present_flag) {
    4186             :       // Test mode for delta quantization
    4187           0 :       int sb_row = mi_row >> 3;
    4188           0 :       int sb_col = mi_col >> 3;
    4189           0 :       int sb_stride = (cm->width + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2;
    4190           0 :       int index = ((sb_row * sb_stride + sb_col + 8) & 31) - 16;
    4191             : 
    4192             :       // Ensure divisibility of delta_qindex by delta_q_res
    4193           0 :       int offset_qindex = (index < 0 ? -index - 8 : index - 8);
    4194           0 :       int qmask = ~(cm->delta_q_res - 1);
    4195           0 :       int current_qindex = clamp(cm->base_qindex + offset_qindex,
    4196           0 :                                  cm->delta_q_res, 256 - cm->delta_q_res);
    4197             : 
    4198           0 :       current_qindex =
    4199           0 :           ((current_qindex - cm->base_qindex + cm->delta_q_res / 2) & qmask) +
    4200           0 :           cm->base_qindex;
    4201           0 :       assert(current_qindex > 0);
    4202             : 
    4203           0 :       xd->delta_qindex = current_qindex - cm->base_qindex;
    4204           0 :       set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64);
    4205           0 :       xd->mi[0]->mbmi.current_q_index = current_qindex;
    4206             : #if !CONFIG_EXT_DELTA_Q
    4207             :       xd->mi[0]->mbmi.segment_id = 0;
    4208             : #endif  // CONFIG_EXT_DELTA_Q
    4209           0 :       av1_init_plane_quantizers(cpi, x, xd->mi[0]->mbmi.segment_id);
    4210             : #if CONFIG_EXT_DELTA_Q
    4211           0 :       if (cpi->oxcf.deltaq_mode == DELTA_Q_LF) {
    4212             :         int j, k;
    4213           0 :         int lfmask = ~(cm->delta_lf_res - 1);
    4214           0 :         int current_delta_lf_from_base = offset_qindex / 2;
    4215           0 :         current_delta_lf_from_base =
    4216           0 :             ((current_delta_lf_from_base + cm->delta_lf_res / 2) & lfmask);
    4217             : 
    4218             :         // pre-set the delta lf for loop filter. Note that this value is set
    4219             :         // before mi is assigned for each block in current superblock
    4220           0 :         for (j = 0; j < AOMMIN(cm->mib_size, cm->mi_rows - mi_row); j++) {
    4221           0 :           for (k = 0; k < AOMMIN(cm->mib_size, cm->mi_cols - mi_col); k++) {
    4222           0 :             cm->mi[(mi_row + j) * cm->mi_stride + (mi_col + k)]
    4223           0 :                 .mbmi.current_delta_lf_from_base = current_delta_lf_from_base;
    4224             :           }
    4225             :         }
    4226             :       }
    4227             : #endif  // CONFIG_EXT_DELTA_Q
    4228             :     }
    4229             : #endif  // CONFIG_DELTA_Q
    4230             : 
    4231           0 :     x->source_variance = UINT_MAX;
    4232           0 :     if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {
    4233             :       BLOCK_SIZE bsize;
    4234           0 :       set_offsets(cpi, tile_info, x, mi_row, mi_col, cm->sb_size);
    4235           0 :       bsize = seg_skip ? cm->sb_size : sf->always_this_block_size;
    4236           0 :       set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
    4237           0 :       rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, cm->sb_size,
    4238             :                        &dummy_rate, &dummy_dist,
    4239             : #if CONFIG_SUPERTX
    4240             :                        &dummy_rate_nocoef,
    4241             : #endif  // CONFIG_SUPERTX
    4242             :                        1, pc_root);
    4243           0 :     } else if (cpi->partition_search_skippable_frame) {
    4244             :       BLOCK_SIZE bsize;
    4245           0 :       set_offsets(cpi, tile_info, x, mi_row, mi_col, cm->sb_size);
    4246           0 :       bsize = get_rd_var_based_fixed_partition(cpi, x, mi_row, mi_col);
    4247           0 :       set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
    4248           0 :       rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, cm->sb_size,
    4249             :                        &dummy_rate, &dummy_dist,
    4250             : #if CONFIG_SUPERTX
    4251             :                        &dummy_rate_nocoef,
    4252             : #endif  // CONFIG_SUPERTX
    4253             :                        1, pc_root);
    4254             :     } else {
    4255             :       // If required set upper and lower partition size limits
    4256           0 :       if (sf->auto_min_max_partition_size) {
    4257           0 :         set_offsets(cpi, tile_info, x, mi_row, mi_col, cm->sb_size);
    4258           0 :         rd_auto_partition_range(cpi, tile_info, xd, mi_row, mi_col,
    4259             :                                 &x->min_partition_size, &x->max_partition_size);
    4260             :       }
    4261           0 :       rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, cm->sb_size,
    4262             :                         &dummy_rdc,
    4263             : #if CONFIG_SUPERTX
    4264             :                         &dummy_rate_nocoef,
    4265             : #endif  // CONFIG_SUPERTX
    4266             :                         INT64_MAX, pc_root);
    4267             :     }
    4268             :   }
    4269           0 : }
    4270             : 
    4271           0 : static void init_encode_frame_mb_context(AV1_COMP *cpi) {
    4272           0 :   MACROBLOCK *const x = &cpi->td.mb;
    4273           0 :   AV1_COMMON *const cm = &cpi->common;
    4274           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    4275             : 
    4276             :   // Copy data over into macro block data structures.
    4277           0 :   av1_setup_src_planes(x, cpi->source, 0, 0);
    4278             : 
    4279           0 :   av1_setup_block_planes(xd, cm->subsampling_x, cm->subsampling_y);
    4280           0 : }
    4281             : 
    4282             : #if !CONFIG_REF_ADAPT
    4283           0 : static int check_dual_ref_flags(AV1_COMP *cpi) {
    4284           0 :   const int ref_flags = cpi->ref_frame_flags;
    4285             : 
    4286           0 :   if (segfeature_active(&cpi->common.seg, 1, SEG_LVL_REF_FRAME)) {
    4287           0 :     return 0;
    4288             :   } else {
    4289           0 :     return (!!(ref_flags & AOM_GOLD_FLAG) + !!(ref_flags & AOM_LAST_FLAG) +
    4290             : #if CONFIG_EXT_REFS
    4291           0 :             !!(ref_flags & AOM_LAST2_FLAG) + !!(ref_flags & AOM_LAST3_FLAG) +
    4292           0 :             !!(ref_flags & AOM_BWD_FLAG) +
    4293             : #endif  // CONFIG_EXT_REFS
    4294           0 :             !!(ref_flags & AOM_ALT_FLAG)) >= 2;
    4295             :   }
    4296             : }
    4297             : #endif  // !CONFIG_REF_ADAPT
    4298             : 
    4299             : #if !CONFIG_VAR_TX
    4300             : static void reset_skip_tx_size(AV1_COMMON *cm, TX_SIZE max_tx_size) {
    4301             :   int mi_row, mi_col;
    4302             :   const int mis = cm->mi_stride;
    4303             :   MODE_INFO **mi_ptr = cm->mi_grid_visible;
    4304             : 
    4305             :   for (mi_row = 0; mi_row < cm->mi_rows; ++mi_row, mi_ptr += mis) {
    4306             :     for (mi_col = 0; mi_col < cm->mi_cols; ++mi_col) {
    4307             :       if (txsize_sqr_up_map[mi_ptr[mi_col]->mbmi.tx_size] > max_tx_size)
    4308             :         mi_ptr[mi_col]->mbmi.tx_size = max_tx_size;
    4309             :     }
    4310             :   }
    4311             : }
    4312             : #endif
    4313             : 
    4314           0 : static MV_REFERENCE_FRAME get_frame_type(const AV1_COMP *cpi) {
    4315           0 :   if (frame_is_intra_only(&cpi->common)) return INTRA_FRAME;
    4316             : #if CONFIG_EXT_REFS
    4317             :   // We will not update the golden frame with an internal overlay frame
    4318           0 :   else if ((cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame) ||
    4319           0 :            cpi->rc.is_src_frame_ext_arf)
    4320             : #else
    4321             :   else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
    4322             : #endif
    4323           0 :     return ALTREF_FRAME;
    4324           0 :   else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
    4325           0 :     return GOLDEN_FRAME;
    4326             :   else
    4327             :     // TODO(zoeliu): To investigate whether a frame_type other than
    4328             :     // INTRA/ALTREF/GOLDEN/LAST needs to be specified seperately.
    4329           0 :     return LAST_FRAME;
    4330             : }
    4331             : 
    4332           0 : static TX_MODE select_tx_mode(const AV1_COMP *cpi, MACROBLOCKD *const xd) {
    4333           0 :   int i, all_lossless = 1;
    4334             : 
    4335           0 :   if (cpi->common.seg.enabled) {
    4336           0 :     for (i = 0; i < MAX_SEGMENTS; ++i) {
    4337           0 :       if (!xd->lossless[i]) {
    4338           0 :         all_lossless = 0;
    4339           0 :         break;
    4340             :       }
    4341             :     }
    4342             :   } else {
    4343           0 :     all_lossless = xd->lossless[0];
    4344             :   }
    4345           0 :   if (all_lossless) return ONLY_4X4;
    4346           0 :   if (cpi->sf.tx_size_search_method == USE_LARGESTALL)
    4347           0 :     return ALLOW_32X32 + CONFIG_TX64X64;
    4348           0 :   else if (cpi->sf.tx_size_search_method == USE_FULL_RD ||
    4349           0 :            cpi->sf.tx_size_search_method == USE_TX_8X8)
    4350           0 :     return TX_MODE_SELECT;
    4351             :   else
    4352           0 :     return cpi->common.tx_mode;
    4353             : }
    4354             : 
    4355           0 : void av1_init_tile_data(AV1_COMP *cpi) {
    4356           0 :   AV1_COMMON *const cm = &cpi->common;
    4357           0 :   const int tile_cols = cm->tile_cols;
    4358           0 :   const int tile_rows = cm->tile_rows;
    4359             :   int tile_col, tile_row;
    4360           0 :   TOKENEXTRA *pre_tok = cpi->tile_tok[0][0];
    4361           0 :   unsigned int tile_tok = 0;
    4362             : 
    4363           0 :   if (cpi->tile_data == NULL || cpi->allocated_tiles < tile_cols * tile_rows) {
    4364           0 :     if (cpi->tile_data != NULL) aom_free(cpi->tile_data);
    4365           0 :     CHECK_MEM_ERROR(
    4366             :         cm, cpi->tile_data,
    4367             :         aom_memalign(32, tile_cols * tile_rows * sizeof(*cpi->tile_data)));
    4368           0 :     cpi->allocated_tiles = tile_cols * tile_rows;
    4369             : 
    4370           0 :     for (tile_row = 0; tile_row < tile_rows; ++tile_row)
    4371           0 :       for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
    4372           0 :         TileDataEnc *const tile_data =
    4373           0 :             &cpi->tile_data[tile_row * tile_cols + tile_col];
    4374             :         int i, j;
    4375           0 :         for (i = 0; i < BLOCK_SIZES; ++i) {
    4376           0 :           for (j = 0; j < MAX_MODES; ++j) {
    4377           0 :             tile_data->thresh_freq_fact[i][j] = 32;
    4378           0 :             tile_data->mode_map[i][j] = j;
    4379             :           }
    4380             :         }
    4381             : #if CONFIG_PVQ
    4382             :         // This will be dynamically increased as more pvq block is encoded.
    4383             :         tile_data->pvq_q.buf_len = 1000;
    4384             :         CHECK_MEM_ERROR(
    4385             :             cm, tile_data->pvq_q.buf,
    4386             :             aom_malloc(tile_data->pvq_q.buf_len * sizeof(PVQ_INFO)));
    4387             :         tile_data->pvq_q.curr_pos = 0;
    4388             : #endif
    4389             :       }
    4390             :   }
    4391             : 
    4392           0 :   for (tile_row = 0; tile_row < tile_rows; ++tile_row) {
    4393           0 :     for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
    4394           0 :       TileInfo *const tile_info =
    4395           0 :           &cpi->tile_data[tile_row * tile_cols + tile_col].tile_info;
    4396           0 :       av1_tile_init(tile_info, cm, tile_row, tile_col);
    4397             : 
    4398           0 :       cpi->tile_tok[tile_row][tile_col] = pre_tok + tile_tok;
    4399           0 :       pre_tok = cpi->tile_tok[tile_row][tile_col];
    4400           0 :       tile_tok = allocated_tokens(*tile_info);
    4401             : #if CONFIG_PVQ
    4402             :       cpi->tile_data[tile_row * tile_cols + tile_col].pvq_q.curr_pos = 0;
    4403             : #endif
    4404             :     }
    4405             :   }
    4406           0 : }
    4407             : 
    4408           0 : void av1_encode_tile(AV1_COMP *cpi, ThreadData *td, int tile_row,
    4409             :                      int tile_col) {
    4410           0 :   AV1_COMMON *const cm = &cpi->common;
    4411           0 :   TileDataEnc *const this_tile =
    4412           0 :       &cpi->tile_data[tile_row * cm->tile_cols + tile_col];
    4413           0 :   const TileInfo *const tile_info = &this_tile->tile_info;
    4414           0 :   TOKENEXTRA *tok = cpi->tile_tok[tile_row][tile_col];
    4415             :   int mi_row;
    4416             : 
    4417             : #if CONFIG_DEPENDENT_HORZTILES
    4418             : #if CONFIG_TILE_GROUPS
    4419             :   if ((!cm->dependent_horz_tiles) || (tile_row == 0) ||
    4420             :       tile_info->tg_horz_boundary) {
    4421             : #else
    4422             :   if ((!cm->dependent_horz_tiles) || (tile_row == 0)) {
    4423             : #endif
    4424             :     av1_zero_above_context(cm, tile_info->mi_col_start, tile_info->mi_col_end);
    4425             :   }
    4426             : #else
    4427           0 :   av1_zero_above_context(cm, tile_info->mi_col_start, tile_info->mi_col_end);
    4428             : #endif
    4429             : 
    4430             :   // Set up pointers to per thread motion search counters.
    4431           0 :   this_tile->m_search_count = 0;   // Count of motion search hits.
    4432           0 :   this_tile->ex_search_count = 0;  // Exhaustive mesh search hits.
    4433           0 :   td->mb.m_search_count_ptr = &this_tile->m_search_count;
    4434           0 :   td->mb.ex_search_count_ptr = &this_tile->ex_search_count;
    4435             : 
    4436             : #if CONFIG_PVQ
    4437             :   td->mb.pvq_q = &this_tile->pvq_q;
    4438             : 
    4439             :   // TODO(yushin) : activity masking info needs be signaled by a bitstream
    4440             :   td->mb.daala_enc.use_activity_masking = AV1_PVQ_ENABLE_ACTIVITY_MASKING;
    4441             : 
    4442             :   if (td->mb.daala_enc.use_activity_masking)
    4443             :     td->mb.daala_enc.qm = OD_HVS_QM;  // Hard coded. Enc/dec required to sync.
    4444             :   else
    4445             :     td->mb.daala_enc.qm = OD_FLAT_QM;  // Hard coded. Enc/dec required to sync.
    4446             : 
    4447             :   {
    4448             :     // FIXME: Multiple segments support
    4449             :     int segment_id = 0;
    4450             :     int rdmult = set_segment_rdmult(cpi, &td->mb, segment_id);
    4451             :     int qindex = av1_get_qindex(&cm->seg, segment_id, cm->base_qindex);
    4452             : #if CONFIG_HIGHBITDEPTH
    4453             :     const int quantizer_shift = td->mb.e_mbd.bd - 8;
    4454             : #else
    4455             :     const int quantizer_shift = 0;
    4456             : #endif  // CONFIG_HIGHBITDEPTH
    4457             :     int64_t q_ac = OD_MAXI(
    4458             :         1, av1_ac_quant(qindex, 0, cpi->common.bit_depth) >> quantizer_shift);
    4459             :     int64_t q_dc = OD_MAXI(
    4460             :         1, av1_dc_quant(qindex, 0, cpi->common.bit_depth) >> quantizer_shift);
    4461             :     /* td->mb.daala_enc.pvq_norm_lambda = OD_PVQ_LAMBDA; */
    4462             :     td->mb.daala_enc.pvq_norm_lambda =
    4463             :         (double)rdmult * (64 / 16) / (q_ac * q_ac * (1 << RDDIV_BITS));
    4464             :     td->mb.daala_enc.pvq_norm_lambda_dc =
    4465             :         (double)rdmult * (64 / 16) / (q_dc * q_dc * (1 << RDDIV_BITS));
    4466             :     // printf("%f\n", td->mb.daala_enc.pvq_norm_lambda);
    4467             :   }
    4468             :   od_init_qm(td->mb.daala_enc.state.qm, td->mb.daala_enc.state.qm_inv,
    4469             :              td->mb.daala_enc.qm == OD_HVS_QM ? OD_QM8_Q4_HVS : OD_QM8_Q4_FLAT);
    4470             : 
    4471             :   if (td->mb.daala_enc.use_activity_masking) {
    4472             :     int pli;
    4473             :     int use_masking = td->mb.daala_enc.use_activity_masking;
    4474             :     int segment_id = 0;
    4475             :     int qindex = av1_get_qindex(&cm->seg, segment_id, cm->base_qindex);
    4476             : 
    4477             :     for (pli = 0; pli < MAX_MB_PLANE; pli++) {
    4478             :       int i;
    4479             :       int q;
    4480             : 
    4481             :       q = qindex;
    4482             :       if (q <= OD_DEFAULT_QMS[use_masking][0][pli].interp_q << OD_COEFF_SHIFT) {
    4483             :         od_interp_qm(&td->mb.daala_enc.state.pvq_qm_q4[pli][0], q,
    4484             :                      &OD_DEFAULT_QMS[use_masking][0][pli], NULL);
    4485             :       } else {
    4486             :         i = 0;
    4487             :         while (OD_DEFAULT_QMS[use_masking][i + 1][pli].qm_q4 != NULL &&
    4488             :                q > OD_DEFAULT_QMS[use_masking][i + 1][pli].interp_q
    4489             :                        << OD_COEFF_SHIFT) {
    4490             :           i++;
    4491             :         }
    4492             :         od_interp_qm(&td->mb.daala_enc.state.pvq_qm_q4[pli][0], q,
    4493             :                      &OD_DEFAULT_QMS[use_masking][i][pli],
    4494             :                      &OD_DEFAULT_QMS[use_masking][i + 1][pli]);
    4495             :       }
    4496             :     }
    4497             :   }
    4498             : 
    4499             : #if !CONFIG_ANS
    4500             :   od_ec_enc_init(&td->mb.daala_enc.w.ec, 65025);
    4501             :   od_ec_enc_reset(&td->mb.daala_enc.w.ec);
    4502             : #else
    4503             : #error "CONFIG_PVQ currently requires !CONFIG_ANS."
    4504             : #endif
    4505             : #endif  // #if CONFIG_PVQ
    4506             : 
    4507             : #if CONFIG_EC_ADAPT
    4508           0 :   this_tile->tctx = *cm->fc;
    4509           0 :   td->mb.e_mbd.tile_ctx = &this_tile->tctx;
    4510             : #endif  // #if CONFIG_EC_ADAPT
    4511             : 
    4512             : #if CONFIG_CFL
    4513             :   MACROBLOCKD *const xd = &td->mb.e_mbd;
    4514             :   xd->cfl = &this_tile->cfl;
    4515             :   cfl_init(xd->cfl, cm, xd->plane[AOM_PLANE_U].subsampling_x,
    4516             :            xd->plane[AOM_PLANE_U].subsampling_y);
    4517             : #endif
    4518             : 
    4519             : #if CONFIG_PVQ
    4520             :   td->mb.daala_enc.state.adapt = &this_tile->tctx.pvq_context;
    4521             : #endif  // CONFIG_PVQ
    4522             : 
    4523           0 :   for (mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
    4524           0 :        mi_row += cm->mib_size) {
    4525           0 :     encode_rd_sb_row(cpi, td, this_tile, mi_row, &tok);
    4526             :   }
    4527             : 
    4528           0 :   cpi->tok_count[tile_row][tile_col] =
    4529           0 :       (unsigned int)(tok - cpi->tile_tok[tile_row][tile_col]);
    4530           0 :   assert(cpi->tok_count[tile_row][tile_col] <= allocated_tokens(*tile_info));
    4531             : #if CONFIG_PVQ
    4532             : #if !CONFIG_ANS
    4533             :   od_ec_enc_clear(&td->mb.daala_enc.w.ec);
    4534             : #else
    4535             : #error "CONFIG_PVQ currently requires !CONFIG_ANS."
    4536             : #endif
    4537             : 
    4538             :   td->mb.pvq_q->last_pos = td->mb.pvq_q->curr_pos;
    4539             :   // rewind current position so that bitstream can be written
    4540             :   // from the 1st pvq block
    4541             :   td->mb.pvq_q->curr_pos = 0;
    4542             : 
    4543             :   td->mb.pvq_q = NULL;
    4544             : #endif
    4545           0 : }
    4546             : 
    4547           0 : static void encode_tiles(AV1_COMP *cpi) {
    4548           0 :   AV1_COMMON *const cm = &cpi->common;
    4549             :   int tile_col, tile_row;
    4550             : 
    4551           0 :   av1_init_tile_data(cpi);
    4552             : 
    4553           0 :   for (tile_row = 0; tile_row < cm->tile_rows; ++tile_row)
    4554           0 :     for (tile_col = 0; tile_col < cm->tile_cols; ++tile_col)
    4555           0 :       av1_encode_tile(cpi, &cpi->td, tile_row, tile_col);
    4556           0 : }
    4557             : 
    4558             : #if CONFIG_FP_MB_STATS
    4559             : static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats,
    4560             :                             AV1_COMMON *cm, uint8_t **this_frame_mb_stats) {
    4561             :   uint8_t *mb_stats_in = firstpass_mb_stats->mb_stats_start +
    4562             :                          cm->current_video_frame * cm->MBs * sizeof(uint8_t);
    4563             : 
    4564             :   if (mb_stats_in > firstpass_mb_stats->mb_stats_end) return EOF;
    4565             : 
    4566             :   *this_frame_mb_stats = mb_stats_in;
    4567             : 
    4568             :   return 1;
    4569             : }
    4570             : #endif
    4571             : 
    4572             : #if CONFIG_GLOBAL_MOTION
    4573             : #define GLOBAL_TRANS_TYPES_ENC 3  // highest motion model to search
    4574           0 : static int gm_get_params_cost(WarpedMotionParams *gm,
    4575             :                               WarpedMotionParams *ref_gm, int allow_hp) {
    4576           0 :   assert(gm->wmtype < GLOBAL_TRANS_TYPES);
    4577           0 :   int params_cost = 0;
    4578             :   int trans_bits, trans_prec_diff;
    4579           0 :   switch (gm->wmtype) {
    4580             :     case HOMOGRAPHY:
    4581             :     case HORTRAPEZOID:
    4582             :     case VERTRAPEZOID:
    4583           0 :       if (gm->wmtype != HORTRAPEZOID)
    4584           0 :         params_cost += aom_count_signed_primitive_refsubexpfin(
    4585             :             GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
    4586           0 :             (ref_gm->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF),
    4587           0 :             (gm->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF));
    4588           0 :       if (gm->wmtype != VERTRAPEZOID)
    4589           0 :         params_cost += aom_count_signed_primitive_refsubexpfin(
    4590             :             GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
    4591           0 :             (ref_gm->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF),
    4592           0 :             (gm->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF));
    4593             :     // Fallthrough intended
    4594             :     case AFFINE:
    4595             :     case ROTZOOM:
    4596           0 :       params_cost += aom_count_signed_primitive_refsubexpfin(
    4597             :           GM_ALPHA_MAX + 1, SUBEXPFIN_K,
    4598           0 :           (ref_gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS),
    4599           0 :           (gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
    4600           0 :       if (gm->wmtype != VERTRAPEZOID)
    4601           0 :         params_cost += aom_count_signed_primitive_refsubexpfin(
    4602             :             GM_ALPHA_MAX + 1, SUBEXPFIN_K,
    4603           0 :             (ref_gm->wmmat[3] >> GM_ALPHA_PREC_DIFF),
    4604           0 :             (gm->wmmat[3] >> GM_ALPHA_PREC_DIFF));
    4605           0 :       if (gm->wmtype >= AFFINE) {
    4606           0 :         if (gm->wmtype != HORTRAPEZOID)
    4607           0 :           params_cost += aom_count_signed_primitive_refsubexpfin(
    4608             :               GM_ALPHA_MAX + 1, SUBEXPFIN_K,
    4609           0 :               (ref_gm->wmmat[4] >> GM_ALPHA_PREC_DIFF),
    4610           0 :               (gm->wmmat[4] >> GM_ALPHA_PREC_DIFF));
    4611           0 :         params_cost += aom_count_signed_primitive_refsubexpfin(
    4612             :             GM_ALPHA_MAX + 1, SUBEXPFIN_K,
    4613           0 :             (ref_gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
    4614             :                 (1 << GM_ALPHA_PREC_BITS),
    4615           0 :             (gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
    4616             :       }
    4617             :     // Fallthrough intended
    4618             :     case TRANSLATION:
    4619           0 :       trans_bits = (gm->wmtype == TRANSLATION)
    4620           0 :                        ? GM_ABS_TRANS_ONLY_BITS - !allow_hp
    4621           0 :                        : GM_ABS_TRANS_BITS;
    4622           0 :       trans_prec_diff = (gm->wmtype == TRANSLATION)
    4623           0 :                             ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
    4624           0 :                             : GM_TRANS_PREC_DIFF;
    4625           0 :       params_cost += aom_count_signed_primitive_refsubexpfin(
    4626           0 :           (1 << trans_bits) + 1, SUBEXPFIN_K,
    4627           0 :           (ref_gm->wmmat[0] >> trans_prec_diff),
    4628           0 :           (gm->wmmat[0] >> trans_prec_diff));
    4629           0 :       params_cost += aom_count_signed_primitive_refsubexpfin(
    4630           0 :           (1 << trans_bits) + 1, SUBEXPFIN_K,
    4631           0 :           (ref_gm->wmmat[1] >> trans_prec_diff),
    4632           0 :           (gm->wmmat[1] >> trans_prec_diff));
    4633             :     // Fallthrough intended
    4634           0 :     case IDENTITY: break;
    4635           0 :     default: assert(0);
    4636             :   }
    4637           0 :   return (params_cost << AV1_PROB_COST_SHIFT);
    4638             : }
    4639             : 
    4640           0 : static int do_gm_search_logic(SPEED_FEATURES *const sf, int num_refs_using_gm,
    4641             :                               int frame) {
    4642             :   (void)num_refs_using_gm;
    4643             :   (void)frame;
    4644           0 :   switch (sf->gm_search_type) {
    4645           0 :     case GM_FULL_SEARCH: return 1;
    4646             :     case GM_REDUCED_REF_SEARCH:
    4647             : #if CONFIG_EXT_REFS
    4648           0 :       return !(frame == LAST2_FRAME || frame == LAST3_FRAME);
    4649             : #else
    4650             :       return (num_refs_using_gm < 2);
    4651             : #endif  // CONFIG_EXT_REFS
    4652           0 :     case GM_DISABLE_SEARCH: return 0;
    4653           0 :     default: assert(0);
    4654             :   }
    4655             :   return 1;
    4656             : }
    4657             : #endif  // CONFIG_GLOBAL_MOTION
    4658             : 
    4659           0 : static void encode_frame_internal(AV1_COMP *cpi) {
    4660           0 :   ThreadData *const td = &cpi->td;
    4661           0 :   MACROBLOCK *const x = &td->mb;
    4662           0 :   AV1_COMMON *const cm = &cpi->common;
    4663           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    4664           0 :   RD_COUNTS *const rdc = &cpi->td.rd_counts;
    4665             :   int i;
    4666             : #if CONFIG_TEMPMV_SIGNALING || CONFIG_EXT_REFS
    4667           0 :   const int last_fb_buf_idx = get_ref_frame_buf_idx(cpi, LAST_FRAME);
    4668             : #endif  // CONFIG_TEMPMV_SIGNALING || CONFIG_EXT_REFS
    4669             : 
    4670             : #if CONFIG_ADAPT_SCAN
    4671             :   av1_deliver_eob_threshold(cm, xd);
    4672             : #endif
    4673             : 
    4674           0 :   x->min_partition_size = AOMMIN(x->min_partition_size, cm->sb_size);
    4675           0 :   x->max_partition_size = AOMMIN(x->max_partition_size, cm->sb_size);
    4676           0 :   cm->setup_mi(cm);
    4677             : 
    4678           0 :   xd->mi = cm->mi_grid_visible;
    4679           0 :   xd->mi[0] = cm->mi;
    4680             : 
    4681           0 :   av1_zero(*td->counts);
    4682           0 :   av1_zero(rdc->coef_counts);
    4683           0 :   av1_zero(rdc->comp_pred_diff);
    4684             : 
    4685             : #if CONFIG_GLOBAL_MOTION
    4686           0 :   av1_zero(rdc->global_motion_used);
    4687           0 :   av1_zero(cpi->gmparams_cost);
    4688           0 :   if (cpi->common.frame_type == INTER_FRAME && cpi->source &&
    4689           0 :       !cpi->global_motion_search_done) {
    4690             :     YV12_BUFFER_CONFIG *ref_buf[TOTAL_REFS_PER_FRAME];
    4691             :     int frame;
    4692             :     double params_by_motion[RANSAC_NUM_MOTIONS * (MAX_PARAMDIM - 1)];
    4693             :     const double *params_this_motion;
    4694             :     int inliers_by_motion[RANSAC_NUM_MOTIONS];
    4695             :     WarpedMotionParams tmp_wm_params;
    4696             :     static const double kIdentityParams[MAX_PARAMDIM - 1] = {
    4697             :       0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0
    4698             :     };
    4699           0 :     int num_refs_using_gm = 0;
    4700             : 
    4701           0 :     for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
    4702           0 :       ref_buf[frame] = get_ref_frame_buffer(cpi, frame);
    4703             :       int pframe;
    4704             :       // check for duplicate buffer
    4705           0 :       for (pframe = LAST_FRAME; pframe < frame; ++pframe) {
    4706           0 :         if (ref_buf[frame] == ref_buf[pframe]) break;
    4707             :       }
    4708           0 :       if (pframe < frame) {
    4709           0 :         memcpy(&cm->global_motion[frame], &cm->global_motion[pframe],
    4710             :                sizeof(WarpedMotionParams));
    4711           0 :       } else if (ref_buf[frame] &&
    4712           0 :                  do_gm_search_logic(&cpi->sf, num_refs_using_gm, frame)) {
    4713             :         TransformationType model;
    4714           0 :         const int64_t ref_frame_error = av1_frame_error(
    4715             : #if CONFIG_HIGHBITDEPTH
    4716           0 :             xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
    4717             : #endif  // CONFIG_HIGHBITDEPTH
    4718           0 :             ref_buf[frame]->y_buffer, ref_buf[frame]->y_stride,
    4719           0 :             cpi->source->y_buffer, 0, 0, cpi->source->y_width,
    4720           0 :             cpi->source->y_height, cpi->source->y_stride);
    4721             : 
    4722           0 :         if (ref_frame_error == 0) continue;
    4723             : 
    4724           0 :         aom_clear_system_state();
    4725           0 :         for (model = ROTZOOM; model < GLOBAL_TRANS_TYPES_ENC; ++model) {
    4726           0 :           int64_t best_warp_error = INT64_MAX;
    4727             :           // Initially set all params to identity.
    4728           0 :           for (i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
    4729           0 :             memcpy(params_by_motion + (MAX_PARAMDIM - 1) * i, kIdentityParams,
    4730             :                    (MAX_PARAMDIM - 1) * sizeof(*params_by_motion));
    4731             :           }
    4732             : 
    4733           0 :           compute_global_motion_feature_based(
    4734             :               model, cpi->source, ref_buf[frame],
    4735             : #if CONFIG_HIGHBITDEPTH
    4736           0 :               cpi->common.bit_depth,
    4737             : #endif  // CONFIG_HIGHBITDEPTH
    4738             :               inliers_by_motion, params_by_motion, RANSAC_NUM_MOTIONS);
    4739             : 
    4740           0 :           for (i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
    4741           0 :             if (inliers_by_motion[i] == 0) continue;
    4742             : 
    4743           0 :             params_this_motion = params_by_motion + (MAX_PARAMDIM - 1) * i;
    4744           0 :             convert_model_to_params(params_this_motion, &tmp_wm_params);
    4745             : 
    4746           0 :             if (tmp_wm_params.wmtype != IDENTITY) {
    4747           0 :               const int64_t warp_error = refine_integerized_param(
    4748             :                   &tmp_wm_params, tmp_wm_params.wmtype,
    4749             : #if CONFIG_HIGHBITDEPTH
    4750           0 :                   xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
    4751             : #endif  // CONFIG_HIGHBITDEPTH
    4752           0 :                   ref_buf[frame]->y_buffer, ref_buf[frame]->y_width,
    4753           0 :                   ref_buf[frame]->y_height, ref_buf[frame]->y_stride,
    4754           0 :                   cpi->source->y_buffer, cpi->source->y_width,
    4755           0 :                   cpi->source->y_height, cpi->source->y_stride, 3);
    4756           0 :               if (warp_error < best_warp_error) {
    4757           0 :                 best_warp_error = warp_error;
    4758             :                 // Save the wm_params modified by refine_integerized_param()
    4759             :                 // rather than motion index to avoid rerunning refine() below.
    4760           0 :                 memcpy(&(cm->global_motion[frame]), &tmp_wm_params,
    4761             :                        sizeof(WarpedMotionParams));
    4762             :               }
    4763             :             }
    4764             :           }
    4765           0 :           if (cm->global_motion[frame].wmtype <= AFFINE)
    4766           0 :             if (!get_shear_params(&cm->global_motion[frame]))
    4767           0 :               set_default_warp_params(&cm->global_motion[frame]);
    4768             : 
    4769           0 :           if (cm->global_motion[frame].wmtype == TRANSLATION) {
    4770           0 :             cm->global_motion[frame].wmmat[0] =
    4771           0 :                 convert_to_trans_prec(cm->allow_high_precision_mv,
    4772           0 :                                       cm->global_motion[frame].wmmat[0]) *
    4773             :                 GM_TRANS_ONLY_DECODE_FACTOR;
    4774           0 :             cm->global_motion[frame].wmmat[1] =
    4775           0 :                 convert_to_trans_prec(cm->allow_high_precision_mv,
    4776           0 :                                       cm->global_motion[frame].wmmat[1]) *
    4777             :                 GM_TRANS_ONLY_DECODE_FACTOR;
    4778             :           }
    4779             : 
    4780             :           // If the best error advantage found doesn't meet the threshold for
    4781             :           // this motion type, revert to IDENTITY.
    4782           0 :           if (!is_enough_erroradvantage(
    4783           0 :                   (double)best_warp_error / ref_frame_error,
    4784             :                   gm_get_params_cost(&cm->global_motion[frame],
    4785           0 :                                      &cm->prev_frame->global_motion[frame],
    4786             :                                      cm->allow_high_precision_mv))) {
    4787           0 :             set_default_warp_params(&cm->global_motion[frame]);
    4788             :           }
    4789           0 :           if (cm->global_motion[frame].wmtype != IDENTITY) break;
    4790             :         }
    4791           0 :         aom_clear_system_state();
    4792             :       }
    4793           0 :       if (cm->global_motion[frame].wmtype != IDENTITY) num_refs_using_gm++;
    4794           0 :       cpi->gmparams_cost[frame] =
    4795           0 :           gm_get_params_cost(&cm->global_motion[frame],
    4796           0 :                              &cm->prev_frame->global_motion[frame],
    4797           0 :                              cm->allow_high_precision_mv) +
    4798           0 :           cpi->gmtype_cost[cm->global_motion[frame].wmtype] -
    4799           0 :           cpi->gmtype_cost[IDENTITY];
    4800             :     }
    4801           0 :     cpi->global_motion_search_done = 1;
    4802             :   }
    4803           0 :   memcpy(cm->cur_frame->global_motion, cm->global_motion,
    4804             :          TOTAL_REFS_PER_FRAME * sizeof(WarpedMotionParams));
    4805             : #endif  // CONFIG_GLOBAL_MOTION
    4806             : 
    4807           0 :   for (i = 0; i < MAX_SEGMENTS; ++i) {
    4808           0 :     const int qindex = cm->seg.enabled
    4809           0 :                            ? av1_get_qindex(&cm->seg, i, cm->base_qindex)
    4810           0 :                            : cm->base_qindex;
    4811           0 :     xd->lossless[i] = qindex == 0 && cm->y_dc_delta_q == 0 &&
    4812           0 :                       cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
    4813           0 :     xd->qindex[i] = qindex;
    4814             :   }
    4815             : 
    4816           0 :   if (!cm->seg.enabled && xd->lossless[0]) x->optimize = 0;
    4817             : 
    4818           0 :   cm->tx_mode = select_tx_mode(cpi, xd);
    4819             : 
    4820             : #if CONFIG_DELTA_Q
    4821             :   // Fix delta q resolution for the moment
    4822           0 :   cm->delta_q_res = DEFAULT_DELTA_Q_RES;
    4823             : // Set delta_q_present_flag before it is used for the first time
    4824             : #if CONFIG_EXT_DELTA_Q
    4825           0 :   cm->delta_lf_res = DEFAULT_DELTA_LF_RES;
    4826             :   // update delta_q_present_flag and delta_lf_present_flag based on base_qindex
    4827           0 :   cm->delta_q_present_flag &= cm->base_qindex > 0;
    4828           0 :   cm->delta_lf_present_flag &= cm->base_qindex > 0;
    4829             : #else
    4830             :   cm->delta_q_present_flag =
    4831             :       cpi->oxcf.aq_mode == DELTA_AQ && cm->base_qindex > 0;
    4832             : #endif  // CONFIG_EXT_DELTA_Q
    4833             : #endif
    4834             : 
    4835           0 :   av1_frame_init_quantizer(cpi);
    4836             : 
    4837           0 :   av1_initialize_rd_consts(cpi);
    4838           0 :   av1_initialize_me_consts(cpi, x, cm->base_qindex);
    4839           0 :   init_encode_frame_mb_context(cpi);
    4840             : 
    4841             : #if CONFIG_EXT_REFS || CONFIG_TEMPMV_SIGNALING
    4842             :   // NOTE(zoeliu): As cm->prev_frame can take neither a frame of
    4843             :   //               show_exisiting_frame=1, nor can it take a frame not used as
    4844             :   //               a reference, it is probable that by the time it is being
    4845             :   //               referred to, the frame buffer it originally points to may
    4846             :   //               already get expired and have been reassigned to the current
    4847             :   //               newly coded frame. Hence, we need to check whether this is
    4848             :   //               the case, and if yes, we have 2 choices:
    4849             :   //               (1) Simply disable the use of previous frame mvs; or
    4850             :   //               (2) Have cm->prev_frame point to one reference frame buffer,
    4851             :   //                   e.g. LAST_FRAME.
    4852           0 :   if (!enc_is_ref_frame_buf(cpi, cm->prev_frame)) {
    4853             :     // Reassign the LAST_FRAME buffer to cm->prev_frame.
    4854           0 :     cm->prev_frame = last_fb_buf_idx != INVALID_IDX
    4855           0 :                          ? &cm->buffer_pool->frame_bufs[last_fb_buf_idx]
    4856           0 :                          : NULL;
    4857             :   }
    4858             : #endif  // CONFIG_EXT_REFS || CONFIG_TEMPMV_SIGNALING
    4859             : 
    4860             : #if CONFIG_TEMPMV_SIGNALING
    4861           0 :   if (cm->prev_frame) {
    4862           0 :     cm->use_prev_frame_mvs &= !cm->error_resilient_mode &&
    4863           0 :                               cm->width == cm->prev_frame->buf.y_width &&
    4864           0 :                               cm->height == cm->prev_frame->buf.y_height &&
    4865           0 :                               !cm->intra_only && !cm->prev_frame->intra_only;
    4866             :   } else {
    4867           0 :     cm->use_prev_frame_mvs = 0;
    4868             :   }
    4869             : #else
    4870             :   cm->use_prev_frame_mvs = !cm->error_resilient_mode && cm->prev_frame &&
    4871             :                            cm->width == cm->prev_frame->buf.y_crop_width &&
    4872             :                            cm->height == cm->prev_frame->buf.y_crop_height &&
    4873             :                            !cm->intra_only && cm->last_show_frame;
    4874             : #endif  // CONFIG_TEMPMV_SIGNALING
    4875             : 
    4876             :   // Special case: set prev_mi to NULL when the previous mode info
    4877             :   // context cannot be used.
    4878           0 :   cm->prev_mi =
    4879           0 :       cm->use_prev_frame_mvs ? cm->prev_mip + cm->mi_stride + 1 : NULL;
    4880             : 
    4881             : #if CONFIG_VAR_TX
    4882           0 :   x->txb_split_count = 0;
    4883           0 :   av1_zero(x->blk_skip_drl);
    4884             : #endif
    4885             : 
    4886             :   {
    4887             :     struct aom_usec_timer emr_timer;
    4888           0 :     aom_usec_timer_start(&emr_timer);
    4889             : 
    4890             : #if CONFIG_FP_MB_STATS
    4891             :     if (cpi->use_fp_mb_stats) {
    4892             :       input_fpmb_stats(&cpi->twopass.firstpass_mb_stats, cm,
    4893             :                        &cpi->twopass.this_frame_mb_stats);
    4894             :     }
    4895             : #endif
    4896             : 
    4897             :     // If allowed, encoding tiles in parallel with one thread handling one tile.
    4898             :     // TODO(geza.lore): The multi-threaded encoder is not safe with more than
    4899             :     // 1 tile rows, as it uses the single above_context et al arrays from
    4900             :     // cpi->common
    4901           0 :     if (AOMMIN(cpi->oxcf.max_threads, cm->tile_cols) > 1 && cm->tile_rows == 1)
    4902           0 :       av1_encode_tiles_mt(cpi);
    4903             :     else
    4904           0 :       encode_tiles(cpi);
    4905             : 
    4906           0 :     aom_usec_timer_mark(&emr_timer);
    4907           0 :     cpi->time_encode_sb_row += aom_usec_timer_elapsed(&emr_timer);
    4908             :   }
    4909             : 
    4910             : #if 0
    4911             :   // Keep record of the total distortion this time around for future use
    4912             :   cpi->last_frame_distortion = cpi->frame_distortion;
    4913             : #endif
    4914           0 : }
    4915             : 
    4916             : #if CONFIG_EXT_INTER
    4917           0 : static void make_consistent_compound_tools(AV1_COMMON *cm) {
    4918             :   (void)cm;
    4919             : #if CONFIG_INTERINTRA
    4920           0 :   if (frame_is_intra_only(cm) || cm->reference_mode == COMPOUND_REFERENCE)
    4921           0 :     cm->allow_interintra_compound = 0;
    4922             : #endif  // CONFIG_INTERINTRA
    4923             : #if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
    4924           0 :   if (frame_is_intra_only(cm) || cm->reference_mode == SINGLE_REFERENCE)
    4925           0 :     cm->allow_masked_compound = 0;
    4926             : #endif  // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
    4927           0 : }
    4928             : #endif  // CONFIG_EXT_INTER
    4929             : 
    4930           0 : void av1_encode_frame(AV1_COMP *cpi) {
    4931           0 :   AV1_COMMON *const cm = &cpi->common;
    4932             : #if CONFIG_EXT_TX
    4933             :   // Indicates whether or not to use a default reduced set for ext-tx
    4934             :   // rather than the potential full set of 16 transforms
    4935           0 :   cm->reduced_tx_set_used = 0;
    4936             : #endif  // CONFIG_EXT_TX
    4937             : 
    4938             :   // In the longer term the encoder should be generalized to match the
    4939             :   // decoder such that we allow compound where one of the 3 buffers has a
    4940             :   // different sign bias and that buffer is then the fixed ref. However, this
    4941             :   // requires further work in the rd loop. For now the only supported encoder
    4942             :   // side behavior is where the ALT ref buffer has opposite sign bias to
    4943             :   // the other two.
    4944           0 :   if (!frame_is_intra_only(cm)) {
    4945             : #if !CONFIG_ONE_SIDED_COMPOUND
    4946             :     if ((cm->ref_frame_sign_bias[ALTREF_FRAME] ==
    4947             :          cm->ref_frame_sign_bias[GOLDEN_FRAME]) ||
    4948             :         (cm->ref_frame_sign_bias[ALTREF_FRAME] ==
    4949             :          cm->ref_frame_sign_bias[LAST_FRAME])) {
    4950             :       cpi->allow_comp_inter_inter = 0;
    4951             :     } else {
    4952             : #endif
    4953           0 :       cpi->allow_comp_inter_inter = 1;
    4954             : #if CONFIG_EXT_REFS
    4955           0 :       cm->comp_fwd_ref[0] = LAST_FRAME;
    4956           0 :       cm->comp_fwd_ref[1] = LAST2_FRAME;
    4957           0 :       cm->comp_fwd_ref[2] = LAST3_FRAME;
    4958           0 :       cm->comp_fwd_ref[3] = GOLDEN_FRAME;
    4959           0 :       cm->comp_bwd_ref[0] = BWDREF_FRAME;
    4960           0 :       cm->comp_bwd_ref[1] = ALTREF_FRAME;
    4961             : #else
    4962             :     cm->comp_fixed_ref = ALTREF_FRAME;
    4963             :     cm->comp_var_ref[0] = LAST_FRAME;
    4964             :     cm->comp_var_ref[1] = GOLDEN_FRAME;
    4965             : #endif                          // CONFIG_EXT_REFS
    4966             : #if !CONFIG_ONE_SIDED_COMPOUND  // Normative in encoder
    4967             :     }
    4968             : #endif
    4969             :   } else {
    4970           0 :     cpi->allow_comp_inter_inter = 0;
    4971             :   }
    4972             : 
    4973           0 :   if (cpi->sf.frame_parameter_update) {
    4974             :     int i;
    4975           0 :     RD_OPT *const rd_opt = &cpi->rd;
    4976           0 :     FRAME_COUNTS *counts = cpi->td.counts;
    4977           0 :     RD_COUNTS *const rdc = &cpi->td.rd_counts;
    4978             : 
    4979             :     // This code does a single RD pass over the whole frame assuming
    4980             :     // either compound, single or hybrid prediction as per whatever has
    4981             :     // worked best for that type of frame in the past.
    4982             :     // It also predicts whether another coding mode would have worked
    4983             :     // better than this coding mode. If that is the case, it remembers
    4984             :     // that for subsequent frames.
    4985             :     // It does the same analysis for transform size selection also.
    4986             :     //
    4987             :     // TODO(zoeliu): To investigate whether a frame_type other than
    4988             :     // INTRA/ALTREF/GOLDEN/LAST needs to be specified seperately.
    4989           0 :     const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
    4990           0 :     int64_t *const mode_thrs = rd_opt->prediction_type_threshes[frame_type];
    4991           0 :     const int is_alt_ref = frame_type == ALTREF_FRAME;
    4992             : 
    4993             : /* prediction (compound, single or hybrid) mode selection */
    4994             : #if CONFIG_REF_ADAPT
    4995             :     // NOTE(zoeliu): "is_alt_ref" is true only for OVERLAY/INTNL_OVERLAY frames
    4996             :     if (is_alt_ref || !cpi->allow_comp_inter_inter)
    4997             :       cm->reference_mode = SINGLE_REFERENCE;
    4998             :     else
    4999             :       cm->reference_mode = REFERENCE_MODE_SELECT;
    5000             : #else
    5001           0 :     if (is_alt_ref || !cpi->allow_comp_inter_inter)
    5002           0 :       cm->reference_mode = SINGLE_REFERENCE;
    5003           0 :     else if (mode_thrs[COMPOUND_REFERENCE] > mode_thrs[SINGLE_REFERENCE] &&
    5004           0 :              mode_thrs[COMPOUND_REFERENCE] > mode_thrs[REFERENCE_MODE_SELECT] &&
    5005           0 :              check_dual_ref_flags(cpi) && cpi->static_mb_pct == 100)
    5006           0 :       cm->reference_mode = COMPOUND_REFERENCE;
    5007           0 :     else if (mode_thrs[SINGLE_REFERENCE] > mode_thrs[REFERENCE_MODE_SELECT])
    5008           0 :       cm->reference_mode = SINGLE_REFERENCE;
    5009             :     else
    5010           0 :       cm->reference_mode = REFERENCE_MODE_SELECT;
    5011             : #endif  // CONFIG_REF_ADAPT
    5012             : 
    5013             : #if CONFIG_DUAL_FILTER
    5014           0 :     cm->interp_filter = SWITCHABLE;
    5015             : #endif
    5016             : 
    5017             : #if CONFIG_EXT_INTER
    5018           0 :     make_consistent_compound_tools(cm);
    5019             : #endif  // CONFIG_EXT_INTER
    5020           0 :     encode_frame_internal(cpi);
    5021             : 
    5022           0 :     for (i = 0; i < REFERENCE_MODES; ++i)
    5023           0 :       mode_thrs[i] = (mode_thrs[i] + rdc->comp_pred_diff[i] / cm->MBs) / 2;
    5024             : 
    5025           0 :     if (cm->reference_mode == REFERENCE_MODE_SELECT) {
    5026           0 :       int single_count_zero = 0;
    5027           0 :       int comp_count_zero = 0;
    5028             : 
    5029           0 :       for (i = 0; i < COMP_INTER_CONTEXTS; i++) {
    5030           0 :         single_count_zero += counts->comp_inter[i][0];
    5031           0 :         comp_count_zero += counts->comp_inter[i][1];
    5032             :       }
    5033             : 
    5034           0 :       if (comp_count_zero == 0) {
    5035           0 :         cm->reference_mode = SINGLE_REFERENCE;
    5036           0 :         av1_zero(counts->comp_inter);
    5037             : #if !CONFIG_REF_ADAPT
    5038           0 :       } else if (single_count_zero == 0) {
    5039           0 :         cm->reference_mode = COMPOUND_REFERENCE;
    5040           0 :         av1_zero(counts->comp_inter);
    5041             : #endif  // !CONFIG_REF_ADAPT
    5042             :       }
    5043             :     }
    5044             : #if CONFIG_EXT_INTER
    5045           0 :     make_consistent_compound_tools(cm);
    5046             : #endif  // CONFIG_EXT_INTER
    5047             : 
    5048             : #if CONFIG_VAR_TX
    5049           0 :     if (cm->tx_mode == TX_MODE_SELECT && cpi->td.mb.txb_split_count == 0)
    5050           0 :       cm->tx_mode = ALLOW_32X32 + CONFIG_TX64X64;
    5051             : #else
    5052             : #if CONFIG_EXT_TX && CONFIG_RECT_TX && CONFIG_RECT_TX_EXT
    5053             :     if (cm->tx_mode == TX_MODE_SELECT && counts->quarter_tx_size[1] == 0) {
    5054             : #else
    5055             :     if (cm->tx_mode == TX_MODE_SELECT) {
    5056             : #endif
    5057             : #if CONFIG_TX64X64
    5058             :       int count4x4 = 0;
    5059             :       int count8x8_8x8p = 0, count8x8_lp = 0;
    5060             :       int count16x16_16x16p = 0, count16x16_lp = 0;
    5061             :       int count32x32_32x32p = 0, count32x32_lp = 0;
    5062             :       int count64x64_64x64p = 0;
    5063             :       for (i = 0; i < TX_SIZE_CONTEXTS; ++i) {
    5064             :         int depth;
    5065             :         // counts->tx_size[max_depth][context_idx][this_depth_level]
    5066             :         depth = tx_size_to_depth(TX_4X4);
    5067             :         count4x4 += counts->tx_size[TX_8X8 - TX_SIZE_CTX_MIN][i][depth];
    5068             :         count4x4 += counts->tx_size[TX_16X16 - TX_SIZE_CTX_MIN][i][depth];
    5069             :         count4x4 += counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5070             :         count4x4 += counts->tx_size[TX_64X64 - TX_SIZE_CTX_MIN][i][depth];
    5071             : 
    5072             :         depth = tx_size_to_depth(TX_8X8);
    5073             :         count8x8_8x8p += counts->tx_size[TX_8X8 - TX_SIZE_CTX_MIN][i][depth];
    5074             :         count8x8_lp += counts->tx_size[TX_16X16 - TX_SIZE_CTX_MIN][i][depth];
    5075             :         count8x8_lp += counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5076             :         count8x8_lp += counts->tx_size[TX_64X64 - TX_SIZE_CTX_MIN][i][depth];
    5077             : 
    5078             :         depth = tx_size_to_depth(TX_16X16);
    5079             :         count16x16_16x16p +=
    5080             :             counts->tx_size[TX_16X16 - TX_SIZE_CTX_MIN][i][depth];
    5081             :         count16x16_lp += counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5082             :         count16x16_lp += counts->tx_size[TX_64X64 - TX_SIZE_CTX_MIN][i][depth];
    5083             : 
    5084             :         depth = tx_size_to_depth(TX_32X32);
    5085             :         count32x32_32x32p +=
    5086             :             counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5087             :         count32x32_lp += counts->tx_size[TX_64X64 - TX_SIZE_CTX_MIN][i][depth];
    5088             : 
    5089             :         depth = tx_size_to_depth(TX_64X64);
    5090             :         count64x64_64x64p +=
    5091             :             counts->tx_size[TX_64X64 - TX_SIZE_CTX_MIN][i][depth];
    5092             :       }
    5093             : #if CONFIG_EXT_TX && CONFIG_RECT_TX
    5094             :       count4x4 += counts->tx_size_implied[TX_4X4][TX_4X4];
    5095             :       count4x4 += counts->tx_size_implied[TX_8X8][TX_4X4];
    5096             :       count4x4 += counts->tx_size_implied[TX_16X16][TX_4X4];
    5097             :       count4x4 += counts->tx_size_implied[TX_32X32][TX_4X4];
    5098             :       count8x8_8x8p += counts->tx_size_implied[TX_8X8][TX_8X8];
    5099             :       count8x8_lp += counts->tx_size_implied[TX_16X16][TX_8X8];
    5100             :       count8x8_lp += counts->tx_size_implied[TX_32X32][TX_8X8];
    5101             :       count8x8_lp += counts->tx_size_implied[TX_64X64][TX_8X8];
    5102             :       count16x16_16x16p += counts->tx_size_implied[TX_16X16][TX_16X16];
    5103             :       count16x16_lp += counts->tx_size_implied[TX_32X32][TX_16X16];
    5104             :       count16x16_lp += counts->tx_size_implied[TX_64X64][TX_16X16];
    5105             :       count32x32_32x32p += counts->tx_size_implied[TX_32X32][TX_32X32];
    5106             :       count32x32_lp += counts->tx_size_implied[TX_64X64][TX_32X32];
    5107             :       count64x64_64x64p += counts->tx_size_implied[TX_64X64][TX_64X64];
    5108             : #endif  // CONFIG_EXT_TX && CONFIG_RECT_TX
    5109             :       if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 &&
    5110             :           count32x32_lp == 0 && count32x32_32x32p == 0 &&
    5111             : #if CONFIG_SUPERTX
    5112             :           cm->counts.supertx_size[TX_16X16] == 0 &&
    5113             :           cm->counts.supertx_size[TX_32X32] == 0 &&
    5114             :           cm->counts.supertx_size[TX_64X64] == 0 &&
    5115             : #endif
    5116             :           count64x64_64x64p == 0) {
    5117             :         cm->tx_mode = ALLOW_8X8;
    5118             :         reset_skip_tx_size(cm, TX_8X8);
    5119             :       } else if (count8x8_8x8p == 0 && count8x8_lp == 0 &&
    5120             :                  count16x16_16x16p == 0 && count16x16_lp == 0 &&
    5121             :                  count32x32_32x32p == 0 && count32x32_lp == 0 &&
    5122             : #if CONFIG_SUPERTX
    5123             :                  cm->counts.supertx_size[TX_8X8] == 0 &&
    5124             :                  cm->counts.supertx_size[TX_16X16] == 0 &&
    5125             :                  cm->counts.supertx_size[TX_32X32] == 0 &&
    5126             :                  cm->counts.supertx_size[TX_64X64] == 0 &&
    5127             : #endif
    5128             :                  count64x64_64x64p == 0) {
    5129             :         cm->tx_mode = ONLY_4X4;
    5130             :         reset_skip_tx_size(cm, TX_4X4);
    5131             :       } else if (count4x4 == 0 && count8x8_lp == 0 && count16x16_lp == 0 &&
    5132             :                  count32x32_lp == 0) {
    5133             :         cm->tx_mode = ALLOW_64X64;
    5134             :       } else if (count4x4 == 0 && count8x8_lp == 0 && count16x16_lp == 0 &&
    5135             : #if CONFIG_SUPERTX
    5136             :                  cm->counts.supertx_size[TX_64X64] == 0 &&
    5137             : #endif
    5138             :                  count64x64_64x64p == 0) {
    5139             :         cm->tx_mode = ALLOW_32X32;
    5140             :         reset_skip_tx_size(cm, TX_32X32);
    5141             :       } else if (count4x4 == 0 && count8x8_lp == 0 && count32x32_lp == 0 &&
    5142             :                  count32x32_32x32p == 0 &&
    5143             : #if CONFIG_SUPERTX
    5144             :                  cm->counts.supertx_size[TX_32X32] == 0 &&
    5145             :                  cm->counts.supertx_size[TX_64X64] == 0 &&
    5146             : #endif
    5147             :                  count64x64_64x64p == 0) {
    5148             :         cm->tx_mode = ALLOW_16X16;
    5149             :         reset_skip_tx_size(cm, TX_16X16);
    5150             :       }
    5151             : 
    5152             : #else  // CONFIG_TX64X64
    5153             : 
    5154             :       int count4x4 = 0;
    5155             :       int count8x8_lp = 0, count8x8_8x8p = 0;
    5156             :       int count16x16_16x16p = 0, count16x16_lp = 0;
    5157             :       int count32x32 = 0;
    5158             :       for (i = 0; i < TX_SIZE_CONTEXTS; ++i) {
    5159             :         int depth;
    5160             :         // counts->tx_size[max_depth][context_idx][this_depth_level]
    5161             :         depth = tx_size_to_depth(TX_4X4);
    5162             :         count4x4 += counts->tx_size[TX_8X8 - TX_SIZE_CTX_MIN][i][depth];
    5163             :         count4x4 += counts->tx_size[TX_16X16 - TX_SIZE_CTX_MIN][i][depth];
    5164             :         count4x4 += counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5165             : 
    5166             :         depth = tx_size_to_depth(TX_8X8);
    5167             :         count8x8_8x8p += counts->tx_size[TX_8X8 - TX_SIZE_CTX_MIN][i][depth];
    5168             :         count8x8_lp += counts->tx_size[TX_16X16 - TX_SIZE_CTX_MIN][i][depth];
    5169             :         count8x8_lp += counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5170             : 
    5171             :         depth = tx_size_to_depth(TX_16X16);
    5172             :         count16x16_16x16p +=
    5173             :             counts->tx_size[TX_16X16 - TX_SIZE_CTX_MIN][i][depth];
    5174             :         count16x16_lp += counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5175             : 
    5176             :         depth = tx_size_to_depth(TX_32X32);
    5177             :         count32x32 += counts->tx_size[TX_32X32 - TX_SIZE_CTX_MIN][i][depth];
    5178             :       }
    5179             : #if CONFIG_EXT_TX && CONFIG_RECT_TX
    5180             :       count4x4 += counts->tx_size_implied[TX_4X4][TX_4X4];
    5181             :       count4x4 += counts->tx_size_implied[TX_8X8][TX_4X4];
    5182             :       count4x4 += counts->tx_size_implied[TX_16X16][TX_4X4];
    5183             :       count4x4 += counts->tx_size_implied[TX_32X32][TX_4X4];
    5184             :       count8x8_8x8p += counts->tx_size_implied[TX_8X8][TX_8X8];
    5185             :       count8x8_lp += counts->tx_size_implied[TX_16X16][TX_8X8];
    5186             :       count8x8_lp += counts->tx_size_implied[TX_32X32][TX_8X8];
    5187             :       count16x16_16x16p += counts->tx_size_implied[TX_16X16][TX_16X16];
    5188             :       count16x16_lp += counts->tx_size_implied[TX_32X32][TX_16X16];
    5189             :       count32x32 += counts->tx_size_implied[TX_32X32][TX_32X32];
    5190             : #endif  // CONFIG_EXT_TX && CONFIG_RECT_TX
    5191             :       if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 &&
    5192             : #if CONFIG_SUPERTX
    5193             :           cm->counts.supertx_size[TX_16X16] == 0 &&
    5194             :           cm->counts.supertx_size[TX_32X32] == 0 &&
    5195             : #endif  // CONFIG_SUPERTX
    5196             :           count32x32 == 0) {
    5197             :         cm->tx_mode = ALLOW_8X8;
    5198             :         reset_skip_tx_size(cm, TX_8X8);
    5199             :       } else if (count8x8_8x8p == 0 && count16x16_16x16p == 0 &&
    5200             :                  count8x8_lp == 0 && count16x16_lp == 0 &&
    5201             : #if CONFIG_SUPERTX
    5202             :                  cm->counts.supertx_size[TX_8X8] == 0 &&
    5203             :                  cm->counts.supertx_size[TX_16X16] == 0 &&
    5204             :                  cm->counts.supertx_size[TX_32X32] == 0 &&
    5205             : #endif  // CONFIG_SUPERTX
    5206             :                  count32x32 == 0) {
    5207             :         cm->tx_mode = ONLY_4X4;
    5208             :         reset_skip_tx_size(cm, TX_4X4);
    5209             :       } else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) {
    5210             :         cm->tx_mode = ALLOW_32X32;
    5211             :       } else if (count32x32 == 0 && count8x8_lp == 0 &&
    5212             : #if CONFIG_SUPERTX
    5213             :                  cm->counts.supertx_size[TX_32X32] == 0 &&
    5214             : #endif  // CONFIG_SUPERTX
    5215             :                  count4x4 == 0) {
    5216             :         cm->tx_mode = ALLOW_16X16;
    5217             :         reset_skip_tx_size(cm, TX_16X16);
    5218             :       }
    5219             : #endif  // CONFIG_TX64X64
    5220             :     }
    5221             : #endif
    5222             :   } else {
    5223             : #if CONFIG_EXT_INTER
    5224           0 :     make_consistent_compound_tools(cm);
    5225             : #endif  // CONFIG_EXT_INTER
    5226           0 :     encode_frame_internal(cpi);
    5227             :   }
    5228           0 : }
    5229             : 
    5230           0 : static void sum_intra_stats(FRAME_COUNTS *counts, MACROBLOCKD *xd,
    5231             :                             const MODE_INFO *mi, const MODE_INFO *above_mi,
    5232             :                             const MODE_INFO *left_mi, const int intraonly,
    5233             :                             const int mi_row, const int mi_col) {
    5234           0 :   const MB_MODE_INFO *const mbmi = &mi->mbmi;
    5235           0 :   const PREDICTION_MODE y_mode = mbmi->mode;
    5236           0 :   const PREDICTION_MODE uv_mode = mbmi->uv_mode;
    5237           0 :   const BLOCK_SIZE bsize = mbmi->sb_type;
    5238           0 :   const int unify_bsize = CONFIG_CB4X4;
    5239             : 
    5240           0 :   if (bsize < BLOCK_8X8 && !unify_bsize) {
    5241             :     int idx, idy;
    5242           0 :     const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
    5243           0 :     const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
    5244           0 :     for (idy = 0; idy < 2; idy += num_4x4_h)
    5245           0 :       for (idx = 0; idx < 2; idx += num_4x4_w) {
    5246           0 :         const int bidx = idy * 2 + idx;
    5247           0 :         const PREDICTION_MODE bmode = mi->bmi[bidx].as_mode;
    5248           0 :         if (intraonly) {
    5249           0 :           const PREDICTION_MODE a = av1_above_block_mode(mi, above_mi, bidx);
    5250           0 :           const PREDICTION_MODE l = av1_left_block_mode(mi, left_mi, bidx);
    5251           0 :           ++counts->kf_y_mode[a][l][bmode];
    5252             :         } else {
    5253           0 :           ++counts->y_mode[0][bmode];
    5254             :         }
    5255             :       }
    5256             :   } else {
    5257           0 :     if (intraonly) {
    5258           0 :       const PREDICTION_MODE above = av1_above_block_mode(mi, above_mi, 0);
    5259           0 :       const PREDICTION_MODE left = av1_left_block_mode(mi, left_mi, 0);
    5260           0 :       ++counts->kf_y_mode[above][left][y_mode];
    5261             :     } else {
    5262           0 :       ++counts->y_mode[size_group_lookup[bsize]][y_mode];
    5263             :     }
    5264             : #if CONFIG_FILTER_INTRA
    5265             :     if (mbmi->mode == DC_PRED
    5266             : #if CONFIG_PALETTE
    5267             :         && mbmi->palette_mode_info.palette_size[0] == 0
    5268             : #endif  // CONFIG_PALETTE
    5269             :         ) {
    5270             :       const int use_filter_intra_mode =
    5271             :           mbmi->filter_intra_mode_info.use_filter_intra_mode[0];
    5272             :       ++counts->filter_intra[0][use_filter_intra_mode];
    5273             :     }
    5274             :     if (mbmi->uv_mode == DC_PRED
    5275             : #if CONFIG_CB4X4
    5276             :         &&
    5277             :         is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
    5278             :                             xd->plane[1].subsampling_y)
    5279             : #endif
    5280             : #if CONFIG_PALETTE
    5281             :         && mbmi->palette_mode_info.palette_size[1] == 0
    5282             : #endif  // CONFIG_PALETTE
    5283             :         ) {
    5284             :       const int use_filter_intra_mode =
    5285             :           mbmi->filter_intra_mode_info.use_filter_intra_mode[1];
    5286             :       ++counts->filter_intra[1][use_filter_intra_mode];
    5287             :     }
    5288             : #endif  // CONFIG_FILTER_INTRA
    5289             : #if CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP
    5290             :     if (av1_is_directional_mode(mbmi->mode, bsize)) {
    5291             :       const int intra_filter_ctx = av1_get_pred_context_intra_interp(xd);
    5292             :       const int p_angle =
    5293             :           mode_to_angle_map[mbmi->mode] + mbmi->angle_delta[0] * ANGLE_STEP;
    5294             :       if (av1_is_intra_filter_switchable(p_angle))
    5295             :         ++counts->intra_filter[intra_filter_ctx][mbmi->intra_filter];
    5296             :     }
    5297             : #endif  // CONFIG_INTRA_INTERP && CONFIG_INTRA_INTERP
    5298             :   }
    5299             : 
    5300             : #if CONFIG_CB4X4
    5301           0 :   if (!is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
    5302             :                            xd->plane[1].subsampling_y))
    5303           0 :     return;
    5304             : #else
    5305             :   (void)mi_row;
    5306             :   (void)mi_col;
    5307             :   (void)xd;
    5308             : #endif
    5309           0 :   ++counts->uv_mode[y_mode][uv_mode];
    5310             : }
    5311             : 
    5312             : #if CONFIG_VAR_TX
    5313           0 : static void update_txfm_count(MACROBLOCK *x, MACROBLOCKD *xd,
    5314             :                               FRAME_COUNTS *counts, TX_SIZE tx_size, int depth,
    5315             :                               int blk_row, int blk_col) {
    5316           0 :   MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
    5317           0 :   const int tx_row = blk_row >> 1;
    5318           0 :   const int tx_col = blk_col >> 1;
    5319           0 :   const int max_blocks_high = max_block_high(xd, mbmi->sb_type, 0);
    5320           0 :   const int max_blocks_wide = max_block_wide(xd, mbmi->sb_type, 0);
    5321           0 :   int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
    5322           0 :                                    xd->left_txfm_context + blk_row,
    5323           0 :                                    mbmi->sb_type, tx_size);
    5324           0 :   const TX_SIZE plane_tx_size = mbmi->inter_tx_size[tx_row][tx_col];
    5325             : 
    5326           0 :   if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
    5327             : 
    5328           0 :   if (tx_size == plane_tx_size) {
    5329           0 :     ++counts->txfm_partition[ctx][0];
    5330           0 :     mbmi->tx_size = tx_size;
    5331           0 :     txfm_partition_update(xd->above_txfm_context + blk_col,
    5332           0 :                           xd->left_txfm_context + blk_row, tx_size, tx_size);
    5333             :   } else {
    5334           0 :     const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    5335           0 :     const int bs = tx_size_wide_unit[sub_txs];
    5336             :     int i;
    5337             : 
    5338           0 :     ++counts->txfm_partition[ctx][1];
    5339           0 :     ++x->txb_split_count;
    5340             : 
    5341           0 :     if (tx_size == TX_8X8) {
    5342           0 :       mbmi->inter_tx_size[tx_row][tx_col] = TX_4X4;
    5343           0 :       mbmi->tx_size = TX_4X4;
    5344           0 :       txfm_partition_update(xd->above_txfm_context + blk_col,
    5345           0 :                             xd->left_txfm_context + blk_row, TX_4X4, tx_size);
    5346           0 :       return;
    5347             :     }
    5348             : 
    5349           0 :     for (i = 0; i < 4; ++i) {
    5350           0 :       int offsetr = (i >> 1) * bs;
    5351           0 :       int offsetc = (i & 0x01) * bs;
    5352           0 :       update_txfm_count(x, xd, counts, sub_txs, depth + 1, blk_row + offsetr,
    5353             :                         blk_col + offsetc);
    5354             :     }
    5355             :   }
    5356             : }
    5357             : 
    5358           0 : static void tx_partition_count_update(const AV1_COMMON *const cm, MACROBLOCK *x,
    5359             :                                       BLOCK_SIZE plane_bsize, int mi_row,
    5360             :                                       int mi_col, FRAME_COUNTS *td_counts) {
    5361           0 :   MACROBLOCKD *xd = &x->e_mbd;
    5362           0 :   const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
    5363           0 :   const int mi_height = block_size_high[plane_bsize] >> tx_size_wide_log2[0];
    5364           0 :   TX_SIZE max_tx_size = get_vartx_max_txsize(&xd->mi[0]->mbmi, plane_bsize);
    5365           0 :   const int bh = tx_size_high_unit[max_tx_size];
    5366           0 :   const int bw = tx_size_wide_unit[max_tx_size];
    5367             :   int idx, idy;
    5368             : 
    5369           0 :   xd->above_txfm_context =
    5370           0 :       cm->above_txfm_context + (mi_col << TX_UNIT_WIDE_LOG2);
    5371           0 :   xd->left_txfm_context = xd->left_txfm_context_buffer +
    5372           0 :                           ((mi_row & MAX_MIB_MASK) << TX_UNIT_HIGH_LOG2);
    5373             : 
    5374           0 :   for (idy = 0; idy < mi_height; idy += bh)
    5375           0 :     for (idx = 0; idx < mi_width; idx += bw)
    5376           0 :       update_txfm_count(x, xd, td_counts, max_tx_size, mi_width != mi_height,
    5377             :                         idy, idx);
    5378           0 : }
    5379             : 
    5380           0 : static void set_txfm_context(MACROBLOCKD *xd, TX_SIZE tx_size, int blk_row,
    5381             :                              int blk_col) {
    5382           0 :   MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
    5383           0 :   const int tx_row = blk_row >> 1;
    5384           0 :   const int tx_col = blk_col >> 1;
    5385           0 :   const int max_blocks_high = max_block_high(xd, mbmi->sb_type, 0);
    5386           0 :   const int max_blocks_wide = max_block_wide(xd, mbmi->sb_type, 0);
    5387           0 :   const TX_SIZE plane_tx_size = mbmi->inter_tx_size[tx_row][tx_col];
    5388             : 
    5389           0 :   if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
    5390             : 
    5391           0 :   if (tx_size == plane_tx_size) {
    5392           0 :     mbmi->tx_size = tx_size;
    5393           0 :     txfm_partition_update(xd->above_txfm_context + blk_col,
    5394           0 :                           xd->left_txfm_context + blk_row, tx_size, tx_size);
    5395             : 
    5396             :   } else {
    5397           0 :     const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    5398           0 :     const int bsl = tx_size_wide_unit[sub_txs];
    5399             :     int i;
    5400             : 
    5401           0 :     if (tx_size == TX_8X8) {
    5402           0 :       mbmi->inter_tx_size[tx_row][tx_col] = TX_4X4;
    5403           0 :       mbmi->tx_size = TX_4X4;
    5404           0 :       txfm_partition_update(xd->above_txfm_context + blk_col,
    5405           0 :                             xd->left_txfm_context + blk_row, TX_4X4, tx_size);
    5406           0 :       return;
    5407             :     }
    5408             : 
    5409           0 :     assert(bsl > 0);
    5410           0 :     for (i = 0; i < 4; ++i) {
    5411           0 :       int offsetr = (i >> 1) * bsl;
    5412           0 :       int offsetc = (i & 0x01) * bsl;
    5413           0 :       set_txfm_context(xd, sub_txs, blk_row + offsetr, blk_col + offsetc);
    5414             :     }
    5415             :   }
    5416             : }
    5417             : 
    5418           0 : static void tx_partition_set_contexts(const AV1_COMMON *const cm,
    5419             :                                       MACROBLOCKD *xd, BLOCK_SIZE plane_bsize,
    5420             :                                       int mi_row, int mi_col) {
    5421           0 :   const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
    5422           0 :   const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
    5423           0 :   TX_SIZE max_tx_size = get_vartx_max_txsize(&xd->mi[0]->mbmi, plane_bsize);
    5424           0 :   const int bh = tx_size_high_unit[max_tx_size];
    5425           0 :   const int bw = tx_size_wide_unit[max_tx_size];
    5426             :   int idx, idy;
    5427             : 
    5428           0 :   xd->above_txfm_context =
    5429           0 :       cm->above_txfm_context + (mi_col << TX_UNIT_WIDE_LOG2);
    5430           0 :   xd->left_txfm_context = xd->left_txfm_context_buffer +
    5431           0 :                           ((mi_row & MAX_MIB_MASK) << TX_UNIT_HIGH_LOG2);
    5432             : 
    5433           0 :   for (idy = 0; idy < mi_height; idy += bh)
    5434           0 :     for (idx = 0; idx < mi_width; idx += bw)
    5435           0 :       set_txfm_context(xd, max_tx_size, idy, idx);
    5436           0 : }
    5437             : #endif
    5438             : 
    5439           0 : void av1_update_tx_type_count(const AV1_COMMON *cm, MACROBLOCKD *xd,
    5440             : #if CONFIG_TXK_SEL
    5441             :                               int block, int plane,
    5442             : #endif
    5443             :                               BLOCK_SIZE bsize, TX_SIZE tx_size,
    5444             :                               FRAME_COUNTS *counts) {
    5445           0 :   MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
    5446           0 :   int is_inter = is_inter_block(mbmi);
    5447             : #if !CONFIG_TXK_SEL
    5448           0 :   TX_TYPE tx_type = mbmi->tx_type;
    5449             : #else
    5450             :   // Only y plane's tx_type is updated
    5451             :   if (plane > 0) return;
    5452             :   TX_TYPE tx_type = get_tx_type(PLANE_TYPE_Y, xd, block, tx_size);
    5453             : #endif
    5454             : #if CONFIG_EXT_TX
    5455           0 :   if (get_ext_tx_types(tx_size, bsize, is_inter, cm->reduced_tx_set_used) > 1 &&
    5456           0 :       cm->base_qindex > 0 && !mbmi->skip &&
    5457           0 :       !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    5458           0 :     const int eset =
    5459           0 :         get_ext_tx_set(tx_size, bsize, is_inter, cm->reduced_tx_set_used);
    5460           0 :     if (eset > 0) {
    5461           0 :       if (is_inter) {
    5462           0 :         ++counts->inter_ext_tx[eset][txsize_sqr_map[tx_size]][tx_type];
    5463             :       } else {
    5464           0 :         ++counts->intra_ext_tx[eset][txsize_sqr_map[tx_size]][mbmi->mode]
    5465           0 :                               [tx_type];
    5466             :       }
    5467             :     }
    5468             :   }
    5469             : #else
    5470             :   (void)bsize;
    5471             :   if (tx_size < TX_32X32 &&
    5472             :       ((!cm->seg.enabled && cm->base_qindex > 0) ||
    5473             :        (cm->seg.enabled && xd->qindex[mbmi->segment_id] > 0)) &&
    5474             :       !mbmi->skip &&
    5475             :       !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    5476             :     if (is_inter) {
    5477             :       ++counts->inter_ext_tx[tx_size][tx_type];
    5478             :     } else {
    5479             :       ++counts->intra_ext_tx[tx_size][intra_mode_to_tx_type_context[mbmi->mode]]
    5480             :                             [tx_type];
    5481             :     }
    5482             :   }
    5483             : #endif  // CONFIG_EXT_TX
    5484           0 : }
    5485             : 
    5486           0 : static void encode_superblock(const AV1_COMP *const cpi, ThreadData *td,
    5487             :                               TOKENEXTRA **t, RUN_TYPE dry_run, int mi_row,
    5488             :                               int mi_col, BLOCK_SIZE bsize, int *rate) {
    5489           0 :   const AV1_COMMON *const cm = &cpi->common;
    5490           0 :   MACROBLOCK *const x = &td->mb;
    5491           0 :   MACROBLOCKD *const xd = &x->e_mbd;
    5492           0 :   MODE_INFO **mi_8x8 = xd->mi;
    5493           0 :   MODE_INFO *mi = mi_8x8[0];
    5494           0 :   MB_MODE_INFO *mbmi = &mi->mbmi;
    5495           0 :   const int seg_skip =
    5496           0 :       segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP);
    5497           0 :   const int mis = cm->mi_stride;
    5498           0 :   const int mi_width = mi_size_wide[bsize];
    5499           0 :   const int mi_height = mi_size_high[bsize];
    5500           0 :   const int is_inter = is_inter_block(mbmi);
    5501             : #if CONFIG_CB4X4
    5502           0 :   const BLOCK_SIZE block_size = bsize;
    5503             : #else
    5504             :   const BLOCK_SIZE block_size = AOMMAX(bsize, BLOCK_8X8);
    5505             : #endif
    5506             : 
    5507             : #if CONFIG_PVQ
    5508             :   x->pvq_speed = 0;
    5509             :   x->pvq_coded = (dry_run == OUTPUT_ENABLED) ? 1 : 0;
    5510             : #endif
    5511             : #if CONFIG_CFL
    5512             :   x->cfl_store_y = (dry_run == OUTPUT_ENABLED) ? 1 : 0;
    5513             : #endif
    5514             : 
    5515           0 :   if (!is_inter) {
    5516             :     int plane;
    5517           0 :     mbmi->skip = 1;
    5518           0 :     for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
    5519           0 :       av1_encode_intra_block_plane((AV1_COMMON *)cm, x, block_size, plane, 1,
    5520             :                                    mi_row, mi_col);
    5521             :     }
    5522           0 :     if (!dry_run) {
    5523           0 :       sum_intra_stats(td->counts, xd, mi, xd->above_mi, xd->left_mi,
    5524             :                       frame_is_intra_only(cm), mi_row, mi_col);
    5525             :     }
    5526             : #if CONFIG_PALETTE
    5527           0 :     if (bsize >= BLOCK_8X8 && !dry_run) {
    5528           0 :       for (plane = 0; plane <= 1; ++plane) {
    5529           0 :         if (mbmi->palette_mode_info.palette_size[plane] > 0) {
    5530           0 :           mbmi->palette_mode_info.palette_first_color_idx[plane] =
    5531           0 :               xd->plane[plane].color_index_map[0];
    5532             :           // TODO(huisu): this increases the use of token buffer. Needs stretch
    5533             :           // test to verify.
    5534           0 :           av1_tokenize_palette_sb(cpi, td, plane, t, dry_run, bsize, rate);
    5535             :         }
    5536             :       }
    5537             :     }
    5538             : #endif  // CONFIG_PALETTE
    5539             : #if CONFIG_VAR_TX
    5540           0 :     mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
    5541             : #endif
    5542             : #if CONFIG_LV_MAP
    5543             :     av1_update_txb_context(cpi, td, dry_run, block_size, rate, mi_row, mi_col);
    5544             : #else   // CONFIG_LV_MAP
    5545           0 :     av1_tokenize_sb(cpi, td, t, dry_run, block_size, rate, mi_row, mi_col);
    5546             : #endif  // CONFIG_LV_MAP
    5547             :   } else {
    5548             :     int ref;
    5549           0 :     const int is_compound = has_second_ref(mbmi);
    5550             : 
    5551           0 :     set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
    5552           0 :     for (ref = 0; ref < 1 + is_compound; ++ref) {
    5553           0 :       YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[ref]);
    5554             : #if CONFIG_INTRABC
    5555             :       assert(IMPLIES(!is_intrabc_block(mbmi), cfg));
    5556             : #else
    5557           0 :       assert(cfg != NULL);
    5558             : #endif  // !CONFIG_INTRABC
    5559           0 :       av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
    5560           0 :                            &xd->block_refs[ref]->sf);
    5561             :     }
    5562           0 :     av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, NULL, block_size);
    5563             : 
    5564           0 :     av1_build_inter_predictors_sbuv(cm, xd, mi_row, mi_col, NULL, block_size);
    5565             : #if CONFIG_MOTION_VAR
    5566           0 :     if (mbmi->motion_mode == OBMC_CAUSAL) {
    5567             : #if CONFIG_NCOBMC
    5568             :       if (dry_run == OUTPUT_ENABLED)
    5569             :         av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
    5570             :       else
    5571             : #endif
    5572           0 :         av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
    5573             :     }
    5574             : #endif  // CONFIG_MOTION_VAR
    5575             : 
    5576           0 :     av1_encode_sb((AV1_COMMON *)cm, x, block_size, mi_row, mi_col);
    5577             : #if CONFIG_VAR_TX
    5578           0 :     if (mbmi->skip) mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
    5579           0 :     av1_tokenize_sb_vartx(cpi, td, t, dry_run, mi_row, mi_col, block_size,
    5580             :                           rate);
    5581             : #else
    5582             : #if CONFIG_LV_MAP
    5583             :     av1_update_txb_context(cpi, td, dry_run, block_size, rate, mi_row, mi_col);
    5584             : #else   // CONFIG_LV_MAP
    5585             :     av1_tokenize_sb(cpi, td, t, dry_run, block_size, rate, mi_row, mi_col);
    5586             : #endif  // CONFIG_LV_MAP
    5587             : #endif
    5588             :   }
    5589             : 
    5590             : #if CONFIG_DAALA_DIST && CONFIG_CB4X4
    5591             :   if (bsize < BLOCK_8X8) {
    5592             :     daala_dist_set_sub8x8_dst(x, x->decoded_8x8, bsize, block_size_wide[bsize],
    5593             :                               block_size_high[bsize], mi_row, mi_col);
    5594             :   }
    5595             : #endif
    5596             : 
    5597           0 :   if (!dry_run) {
    5598             : #if CONFIG_VAR_TX
    5599           0 :     TX_SIZE tx_size =
    5600           0 :         is_inter && !mbmi->skip ? mbmi->min_tx_size : mbmi->tx_size;
    5601             : #else
    5602             :     TX_SIZE tx_size = mbmi->tx_size;
    5603             : #endif
    5604           0 :     if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id] &&
    5605             : #if CONFIG_CB4X4 && (CONFIG_VAR_TX || CONFIG_EXT_TX) && CONFIG_RECT_TX
    5606           0 :         mbmi->sb_type > BLOCK_4X4 &&
    5607             : #else
    5608             :         mbmi->sb_type >= BLOCK_8X8 &&
    5609             : #endif
    5610           0 :         !(is_inter && (mbmi->skip || seg_skip))) {
    5611             : #if CONFIG_VAR_TX
    5612           0 :       if (is_inter) {
    5613           0 :         tx_partition_count_update(cm, x, bsize, mi_row, mi_col, td->counts);
    5614             :       } else {
    5615           0 :         const int tx_size_ctx = get_tx_size_context(xd);
    5616           0 :         const int tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize]
    5617           0 :                                          : intra_tx_size_cat_lookup[bsize];
    5618           0 :         const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
    5619           0 :         const int depth = tx_size_to_depth(coded_tx_size);
    5620           0 :         ++td->counts->tx_size[tx_size_cat][tx_size_ctx][depth];
    5621           0 :         if (tx_size != max_txsize_rect_lookup[bsize]) ++x->txb_split_count;
    5622             :       }
    5623             : #else
    5624             :       const int tx_size_ctx = get_tx_size_context(xd);
    5625             :       const int tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize]
    5626             :                                        : intra_tx_size_cat_lookup[bsize];
    5627             :       const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
    5628             :       const int depth = tx_size_to_depth(coded_tx_size);
    5629             : 
    5630             :       ++td->counts->tx_size[tx_size_cat][tx_size_ctx][depth];
    5631             : #endif
    5632             : #if CONFIG_EXT_TX && CONFIG_RECT_TX && CONFIG_RECT_TX_EXT
    5633             :       if (is_quarter_tx_allowed(xd, mbmi, is_inter) &&
    5634             :           mbmi->tx_size != txsize_sqr_up_map[mbmi->tx_size]) {
    5635             :         ++td->counts->quarter_tx_size[mbmi->tx_size ==
    5636             :                                       quarter_txsize_lookup[mbmi->sb_type]];
    5637             :       }
    5638             : #endif  // CONFIG_EXT_TX && CONFIG_RECT_TX && CONFIG_RECT_TX_EXT
    5639             : #if CONFIG_EXT_TX && CONFIG_RECT_TX
    5640           0 :       assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
    5641             : #endif  // CONFIG_EXT_TX && CONFIG_RECT_TX
    5642             :     } else {
    5643             :       int i, j;
    5644             :       TX_SIZE intra_tx_size;
    5645             :       // The new intra coding scheme requires no change of transform size
    5646           0 :       if (is_inter) {
    5647           0 :         if (xd->lossless[mbmi->segment_id]) {
    5648           0 :           intra_tx_size = TX_4X4;
    5649             :         } else {
    5650           0 :           intra_tx_size = tx_size_from_tx_mode(bsize, cm->tx_mode, 1);
    5651             :         }
    5652             :       } else {
    5653             : #if CONFIG_EXT_TX && CONFIG_RECT_TX
    5654           0 :         intra_tx_size = tx_size;
    5655             : #else
    5656             :         intra_tx_size = (bsize >= BLOCK_8X8) ? tx_size : TX_4X4;
    5657             : #endif  // CONFIG_EXT_TX && CONFIG_RECT_TX
    5658             :       }
    5659             : #if CONFIG_EXT_TX && CONFIG_RECT_TX
    5660           0 :       ++td->counts->tx_size_implied[max_txsize_lookup[bsize]]
    5661           0 :                                    [txsize_sqr_up_map[tx_size]];
    5662             : #endif  // CONFIG_EXT_TX && CONFIG_RECT_TX
    5663             : 
    5664           0 :       for (j = 0; j < mi_height; j++)
    5665           0 :         for (i = 0; i < mi_width; i++)
    5666           0 :           if (mi_col + i < cm->mi_cols && mi_row + j < cm->mi_rows)
    5667           0 :             mi_8x8[mis * j + i]->mbmi.tx_size = intra_tx_size;
    5668             : 
    5669             : #if CONFIG_VAR_TX
    5670           0 :       mbmi->min_tx_size = get_min_tx_size(intra_tx_size);
    5671           0 :       if (intra_tx_size != max_txsize_rect_lookup[bsize]) ++x->txb_split_count;
    5672             : #endif
    5673             :     }
    5674             : 
    5675           0 :     ++td->counts->tx_size_totals[txsize_sqr_map[tx_size]];
    5676           0 :     ++td->counts
    5677           0 :           ->tx_size_totals[txsize_sqr_map[get_uv_tx_size(mbmi, &xd->plane[1])]];
    5678             : #if !CONFIG_TXK_SEL
    5679           0 :     av1_update_tx_type_count(cm, xd, bsize, tx_size, td->counts);
    5680             : #endif
    5681             :   }
    5682             : 
    5683             : #if CONFIG_VAR_TX
    5684           0 :   if (cm->tx_mode == TX_MODE_SELECT &&
    5685             : #if CONFIG_CB4X4
    5686           0 :       mbmi->sb_type > BLOCK_4X4 &&
    5687             : #else
    5688             :       mbmi->sb_type >= BLOCK_8X8 &&
    5689             : #endif
    5690           0 :       is_inter && !(mbmi->skip || seg_skip)) {
    5691           0 :     if (dry_run) tx_partition_set_contexts(cm, xd, bsize, mi_row, mi_col);
    5692             :   } else {
    5693           0 :     TX_SIZE tx_size = mbmi->tx_size;
    5694             :     // The new intra coding scheme requires no change of transform size
    5695           0 :     if (is_inter)
    5696           0 :       tx_size = tx_size_from_tx_mode(bsize, cm->tx_mode, is_inter);
    5697             :     else
    5698           0 :       tx_size = (bsize > BLOCK_4X4) ? tx_size : TX_4X4;
    5699           0 :     mbmi->tx_size = tx_size;
    5700           0 :     set_txfm_ctxs(tx_size, xd->n8_w, xd->n8_h, (mbmi->skip || seg_skip), xd);
    5701             :   }
    5702             : #endif  // CONFIG_VAR_TX
    5703           0 : }
    5704             : 
    5705             : #if CONFIG_SUPERTX
    5706             : static int check_intra_b(PICK_MODE_CONTEXT *ctx) {
    5707             :   if (!is_inter_mode((&ctx->mic)->mbmi.mode)) return 1;
    5708             : #if CONFIG_EXT_INTER
    5709             :   if (ctx->mic.mbmi.ref_frame[1] == INTRA_FRAME) return 1;
    5710             : #endif  // CONFIG_EXT_INTER
    5711             :   return 0;
    5712             : }
    5713             : 
    5714             : static int check_intra_sb(const AV1_COMP *const cpi, const TileInfo *const tile,
    5715             :                           int mi_row, int mi_col, BLOCK_SIZE bsize,
    5716             :                           PC_TREE *pc_tree) {
    5717             :   const AV1_COMMON *const cm = &cpi->common;
    5718             :   const int hbs = mi_size_wide[bsize] / 2;
    5719             :   const PARTITION_TYPE partition = pc_tree->partitioning;
    5720             :   const BLOCK_SIZE subsize = get_subsize(bsize, partition);
    5721             : #if CONFIG_EXT_PARTITION_TYPES
    5722             :   int i;
    5723             : #endif
    5724             : #if CONFIG_CB4X4
    5725             :   const int unify_bsize = 1;
    5726             : #else
    5727             :   const int unify_bsize = 0;
    5728             : #endif
    5729             : 
    5730             : #if !CONFIG_CB4X4
    5731             :   assert(bsize >= BLOCK_8X8);
    5732             : #endif
    5733             : 
    5734             :   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return 1;
    5735             : 
    5736             :   switch (partition) {
    5737             :     case PARTITION_NONE: return check_intra_b(&pc_tree->none); break;
    5738             :     case PARTITION_VERT:
    5739             :       if (check_intra_b(&pc_tree->vertical[0])) return 1;
    5740             :       if (mi_col + hbs < cm->mi_cols && (bsize > BLOCK_8X8 || unify_bsize)) {
    5741             :         if (check_intra_b(&pc_tree->vertical[1])) return 1;
    5742             :       }
    5743             :       break;
    5744             :     case PARTITION_HORZ:
    5745             :       if (check_intra_b(&pc_tree->horizontal[0])) return 1;
    5746             :       if (mi_row + hbs < cm->mi_rows && (bsize > BLOCK_8X8 || unify_bsize)) {
    5747             :         if (check_intra_b(&pc_tree->horizontal[1])) return 1;
    5748             :       }
    5749             :       break;
    5750             :     case PARTITION_SPLIT:
    5751             :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    5752             :         if (check_intra_b(pc_tree->leaf_split[0])) return 1;
    5753             :       } else {
    5754             :         if (check_intra_sb(cpi, tile, mi_row, mi_col, subsize,
    5755             :                            pc_tree->split[0]))
    5756             :           return 1;
    5757             :         if (check_intra_sb(cpi, tile, mi_row, mi_col + hbs, subsize,
    5758             :                            pc_tree->split[1]))
    5759             :           return 1;
    5760             :         if (check_intra_sb(cpi, tile, mi_row + hbs, mi_col, subsize,
    5761             :                            pc_tree->split[2]))
    5762             :           return 1;
    5763             :         if (check_intra_sb(cpi, tile, mi_row + hbs, mi_col + hbs, subsize,
    5764             :                            pc_tree->split[3]))
    5765             :           return 1;
    5766             :       }
    5767             :       break;
    5768             : #if CONFIG_EXT_PARTITION_TYPES
    5769             :     case PARTITION_HORZ_A:
    5770             :       for (i = 0; i < 3; i++) {
    5771             :         if (check_intra_b(&pc_tree->horizontala[i])) return 1;
    5772             :       }
    5773             :       break;
    5774             :     case PARTITION_HORZ_B:
    5775             :       for (i = 0; i < 3; i++) {
    5776             :         if (check_intra_b(&pc_tree->horizontalb[i])) return 1;
    5777             :       }
    5778             :       break;
    5779             :     case PARTITION_VERT_A:
    5780             :       for (i = 0; i < 3; i++) {
    5781             :         if (check_intra_b(&pc_tree->verticala[i])) return 1;
    5782             :       }
    5783             :       break;
    5784             :     case PARTITION_VERT_B:
    5785             :       for (i = 0; i < 3; i++) {
    5786             :         if (check_intra_b(&pc_tree->verticalb[i])) return 1;
    5787             :       }
    5788             :       break;
    5789             : #endif  // CONFIG_EXT_PARTITION_TYPES
    5790             :     default: assert(0);
    5791             :   }
    5792             :   return 0;
    5793             : }
    5794             : 
    5795             : static int check_supertx_b(TX_SIZE supertx_size, PICK_MODE_CONTEXT *ctx) {
    5796             :   return ctx->mic.mbmi.tx_size == supertx_size;
    5797             : }
    5798             : 
    5799             : static int check_supertx_sb(BLOCK_SIZE bsize, TX_SIZE supertx_size,
    5800             :                             PC_TREE *pc_tree) {
    5801             :   PARTITION_TYPE partition;
    5802             :   BLOCK_SIZE subsize;
    5803             : #if CONFIG_CB4X4
    5804             :   const int unify_bsize = 1;
    5805             : #else
    5806             :   const int unify_bsize = 0;
    5807             : #endif
    5808             : 
    5809             :   partition = pc_tree->partitioning;
    5810             :   subsize = get_subsize(bsize, partition);
    5811             :   switch (partition) {
    5812             :     case PARTITION_NONE: return check_supertx_b(supertx_size, &pc_tree->none);
    5813             :     case PARTITION_VERT:
    5814             :       return check_supertx_b(supertx_size, &pc_tree->vertical[0]);
    5815             :     case PARTITION_HORZ:
    5816             :       return check_supertx_b(supertx_size, &pc_tree->horizontal[0]);
    5817             :     case PARTITION_SPLIT:
    5818             :       if (bsize == BLOCK_8X8 && !unify_bsize)
    5819             :         return check_supertx_b(supertx_size, pc_tree->leaf_split[0]);
    5820             :       else
    5821             :         return check_supertx_sb(subsize, supertx_size, pc_tree->split[0]);
    5822             : #if CONFIG_EXT_PARTITION_TYPES
    5823             :     case PARTITION_HORZ_A:
    5824             :       return check_supertx_b(supertx_size, &pc_tree->horizontala[0]);
    5825             :     case PARTITION_HORZ_B:
    5826             :       return check_supertx_b(supertx_size, &pc_tree->horizontalb[0]);
    5827             :     case PARTITION_VERT_A:
    5828             :       return check_supertx_b(supertx_size, &pc_tree->verticala[0]);
    5829             :     case PARTITION_VERT_B:
    5830             :       return check_supertx_b(supertx_size, &pc_tree->verticalb[0]);
    5831             : #endif  // CONFIG_EXT_PARTITION_TYPES
    5832             :     default: assert(0); return 0;
    5833             :   }
    5834             : }
    5835             : 
    5836             : static void predict_superblock(const AV1_COMP *const cpi, ThreadData *td,
    5837             : #if CONFIG_EXT_INTER
    5838             :                                int mi_row_ori, int mi_col_ori,
    5839             : #endif  // CONFIG_EXT_INTER
    5840             :                                int mi_row_pred, int mi_col_pred,
    5841             :                                BLOCK_SIZE bsize_pred, int b_sub8x8, int block) {
    5842             :   // Used in supertx
    5843             :   // (mi_row_ori, mi_col_ori): location for mv
    5844             :   // (mi_row_pred, mi_col_pred, bsize_pred): region to predict
    5845             :   const AV1_COMMON *const cm = &cpi->common;
    5846             :   MACROBLOCK *const x = &td->mb;
    5847             :   MACROBLOCKD *const xd = &x->e_mbd;
    5848             :   MODE_INFO *mi_8x8 = xd->mi[0];
    5849             :   MODE_INFO *mi = mi_8x8;
    5850             :   MB_MODE_INFO *mbmi = &mi->mbmi;
    5851             :   int ref;
    5852             :   const int is_compound = has_second_ref(mbmi);
    5853             : 
    5854             :   set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
    5855             : 
    5856             :   for (ref = 0; ref < 1 + is_compound; ++ref) {
    5857             :     YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[ref]);
    5858             :     av1_setup_pre_planes(xd, ref, cfg, mi_row_pred, mi_col_pred,
    5859             :                          &xd->block_refs[ref]->sf);
    5860             :   }
    5861             : 
    5862             :   if (!b_sub8x8)
    5863             :     av1_build_inter_predictors_sb_extend(cm, xd,
    5864             : #if CONFIG_EXT_INTER
    5865             :                                          mi_row_ori, mi_col_ori,
    5866             : #endif  // CONFIG_EXT_INTER
    5867             :                                          mi_row_pred, mi_col_pred, bsize_pred);
    5868             :   else
    5869             :     av1_build_inter_predictors_sb_sub8x8_extend(cm, xd,
    5870             : #if CONFIG_EXT_INTER
    5871             :                                                 mi_row_ori, mi_col_ori,
    5872             : #endif  // CONFIG_EXT_INTER
    5873             :                                                 mi_row_pred, mi_col_pred,
    5874             :                                                 bsize_pred, block);
    5875             : }
    5876             : 
    5877             : static void predict_b_extend(const AV1_COMP *const cpi, ThreadData *td,
    5878             :                              const TileInfo *const tile, int block,
    5879             :                              int mi_row_ori, int mi_col_ori, int mi_row_pred,
    5880             :                              int mi_col_pred, int mi_row_top, int mi_col_top,
    5881             :                              uint8_t *dst_buf[3], int dst_stride[3],
    5882             :                              BLOCK_SIZE bsize_top, BLOCK_SIZE bsize_pred,
    5883             :                              RUN_TYPE dry_run, int b_sub8x8, int bextend) {
    5884             :   // Used in supertx
    5885             :   // (mi_row_ori, mi_col_ori): location for mv
    5886             :   // (mi_row_pred, mi_col_pred, bsize_pred): region to predict
    5887             :   // (mi_row_top, mi_col_top, bsize_top): region of the top partition size
    5888             :   // block: sub location of sub8x8 blocks
    5889             :   // b_sub8x8: 1: ori is sub8x8; 0: ori is not sub8x8
    5890             :   // bextend: 1: region to predict is an extension of ori; 0: not
    5891             : 
    5892             :   MACROBLOCK *const x = &td->mb;
    5893             :   const AV1_COMMON *const cm = &cpi->common;
    5894             :   MACROBLOCKD *const xd = &x->e_mbd;
    5895             :   int r = (mi_row_pred - mi_row_top) * MI_SIZE;
    5896             :   int c = (mi_col_pred - mi_col_top) * MI_SIZE;
    5897             :   const int mi_width_top = mi_size_wide[bsize_top];
    5898             :   const int mi_height_top = mi_size_high[bsize_top];
    5899             : 
    5900             :   if (mi_row_pred < mi_row_top || mi_col_pred < mi_col_top ||
    5901             :       mi_row_pred >= mi_row_top + mi_height_top ||
    5902             :       mi_col_pred >= mi_col_top + mi_width_top || mi_row_pred >= cm->mi_rows ||
    5903             :       mi_col_pred >= cm->mi_cols)
    5904             :     return;
    5905             : 
    5906             :   set_offsets_extend(cpi, td, tile, mi_row_pred, mi_col_pred, mi_row_ori,
    5907             :                      mi_col_ori, bsize_pred);
    5908             :   xd->plane[0].dst.stride = dst_stride[0];
    5909             :   xd->plane[1].dst.stride = dst_stride[1];
    5910             :   xd->plane[2].dst.stride = dst_stride[2];
    5911             :   xd->plane[0].dst.buf = dst_buf[0] +
    5912             :                          (r >> xd->plane[0].subsampling_y) * dst_stride[0] +
    5913             :                          (c >> xd->plane[0].subsampling_x);
    5914             :   xd->plane[1].dst.buf = dst_buf[1] +
    5915             :                          (r >> xd->plane[1].subsampling_y) * dst_stride[1] +
    5916             :                          (c >> xd->plane[1].subsampling_x);
    5917             :   xd->plane[2].dst.buf = dst_buf[2] +
    5918             :                          (r >> xd->plane[2].subsampling_y) * dst_stride[2] +
    5919             :                          (c >> xd->plane[2].subsampling_x);
    5920             : 
    5921             :   predict_superblock(cpi, td,
    5922             : #if CONFIG_EXT_INTER
    5923             :                      mi_row_ori, mi_col_ori,
    5924             : #endif  // CONFIG_EXT_INTER
    5925             :                      mi_row_pred, mi_col_pred, bsize_pred, b_sub8x8, block);
    5926             : 
    5927             :   if (!dry_run && !bextend)
    5928             :     update_stats(&cpi->common, td, mi_row_pred, mi_col_pred, 1);
    5929             : }
    5930             : 
    5931             : static void extend_dir(const AV1_COMP *const cpi, ThreadData *td,
    5932             :                        const TileInfo *const tile, int block, BLOCK_SIZE bsize,
    5933             :                        BLOCK_SIZE top_bsize, int mi_row, int mi_col,
    5934             :                        int mi_row_top, int mi_col_top, RUN_TYPE dry_run,
    5935             :                        uint8_t *dst_buf[3], int dst_stride[3], int dir) {
    5936             :   // dir: 0-lower, 1-upper, 2-left, 3-right
    5937             :   //      4-lowerleft, 5-upperleft, 6-lowerright, 7-upperright
    5938             :   MACROBLOCKD *xd = &td->mb.e_mbd;
    5939             :   const int mi_width = mi_size_wide[bsize];
    5940             :   const int mi_height = mi_size_high[bsize];
    5941             :   int xss = xd->plane[1].subsampling_x;
    5942             :   int yss = xd->plane[1].subsampling_y;
    5943             : #if CONFIG_CB4X4
    5944             :   const int unify_bsize = 1;
    5945             : #else
    5946             :   const int unify_bsize = 0;
    5947             : #endif
    5948             :   int b_sub8x8 = (bsize < BLOCK_8X8) && !unify_bsize ? 1 : 0;
    5949             :   int wide_unit, high_unit;
    5950             :   int i, j;
    5951             :   int ext_offset = 0;
    5952             : 
    5953             :   BLOCK_SIZE extend_bsize;
    5954             :   int mi_row_pred, mi_col_pred;
    5955             : 
    5956             :   if (dir == 0 || dir == 1) {  // lower and upper
    5957             :     extend_bsize =
    5958             :         (mi_width == mi_size_wide[BLOCK_8X8] || bsize < BLOCK_8X8 || xss < yss)
    5959             :             ? BLOCK_8X8
    5960             :             : BLOCK_16X8;
    5961             : 
    5962             : #if CONFIG_CB4X4
    5963             :     if (bsize < BLOCK_8X8) {
    5964             :       extend_bsize = BLOCK_4X4;
    5965             :       ext_offset = mi_size_wide[BLOCK_8X8];
    5966             :     }
    5967             : #endif
    5968             :     wide_unit = mi_size_wide[extend_bsize];
    5969             :     high_unit = mi_size_high[extend_bsize];
    5970             : 
    5971             :     mi_row_pred = mi_row + ((dir == 0) ? mi_height : -(mi_height + ext_offset));
    5972             :     mi_col_pred = mi_col;
    5973             : 
    5974             :     for (j = 0; j < mi_height + ext_offset; j += high_unit)
    5975             :       for (i = 0; i < mi_width + ext_offset; i += wide_unit)
    5976             :         predict_b_extend(cpi, td, tile, block, mi_row, mi_col, mi_row_pred + j,
    5977             :                          mi_col_pred + i, mi_row_top, mi_col_top, dst_buf,
    5978             :                          dst_stride, top_bsize, extend_bsize, dry_run, b_sub8x8,
    5979             :                          1);
    5980             :   } else if (dir == 2 || dir == 3) {  // left and right
    5981             :     extend_bsize =
    5982             :         (mi_height == mi_size_high[BLOCK_8X8] || bsize < BLOCK_8X8 || yss < xss)
    5983             :             ? BLOCK_8X8
    5984             :             : BLOCK_8X16;
    5985             : #if CONFIG_CB4X4
    5986             :     if (bsize < BLOCK_8X8) {
    5987             :       extend_bsize = BLOCK_4X4;
    5988             :       ext_offset = mi_size_wide[BLOCK_8X8];
    5989             :     }
    5990             : #endif
    5991             :     wide_unit = mi_size_wide[extend_bsize];
    5992             :     high_unit = mi_size_high[extend_bsize];
    5993             : 
    5994             :     mi_row_pred = mi_row;
    5995             :     mi_col_pred = mi_col + ((dir == 3) ? mi_width : -(mi_width + ext_offset));
    5996             : 
    5997             :     for (j = 0; j < mi_height + ext_offset; j += high_unit)
    5998             :       for (i = 0; i < mi_width + ext_offset; i += wide_unit)
    5999             :         predict_b_extend(cpi, td, tile, block, mi_row, mi_col, mi_row_pred + j,
    6000             :                          mi_col_pred + i, mi_row_top, mi_col_top, dst_buf,
    6001             :                          dst_stride, top_bsize, extend_bsize, dry_run, b_sub8x8,
    6002             :                          1);
    6003             :   } else {
    6004             :     extend_bsize = BLOCK_8X8;
    6005             : #if CONFIG_CB4X4
    6006             :     if (bsize < BLOCK_8X8) {
    6007             :       extend_bsize = BLOCK_4X4;
    6008             :       ext_offset = mi_size_wide[BLOCK_8X8];
    6009             :     }
    6010             : #endif
    6011             :     wide_unit = mi_size_wide[extend_bsize];
    6012             :     high_unit = mi_size_high[extend_bsize];
    6013             : 
    6014             :     mi_row_pred = mi_row + ((dir == 4 || dir == 6) ? mi_height
    6015             :                                                    : -(mi_height + ext_offset));
    6016             :     mi_col_pred =
    6017             :         mi_col + ((dir == 6 || dir == 7) ? mi_width : -(mi_width + ext_offset));
    6018             : 
    6019             :     for (j = 0; j < mi_height + ext_offset; j += high_unit)
    6020             :       for (i = 0; i < mi_width + ext_offset; i += wide_unit)
    6021             :         predict_b_extend(cpi, td, tile, block, mi_row, mi_col, mi_row_pred + j,
    6022             :                          mi_col_pred + i, mi_row_top, mi_col_top, dst_buf,
    6023             :                          dst_stride, top_bsize, extend_bsize, dry_run, b_sub8x8,
    6024             :                          1);
    6025             :   }
    6026             : }
    6027             : 
    6028             : static void extend_all(const AV1_COMP *const cpi, ThreadData *td,
    6029             :                        const TileInfo *const tile, int block, BLOCK_SIZE bsize,
    6030             :                        BLOCK_SIZE top_bsize, int mi_row, int mi_col,
    6031             :                        int mi_row_top, int mi_col_top, RUN_TYPE dry_run,
    6032             :                        uint8_t *dst_buf[3], int dst_stride[3]) {
    6033             :   assert(block >= 0 && block < 4);
    6034             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6035             :              mi_col_top, dry_run, dst_buf, dst_stride, 0);
    6036             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6037             :              mi_col_top, dry_run, dst_buf, dst_stride, 1);
    6038             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6039             :              mi_col_top, dry_run, dst_buf, dst_stride, 2);
    6040             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6041             :              mi_col_top, dry_run, dst_buf, dst_stride, 3);
    6042             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6043             :              mi_col_top, dry_run, dst_buf, dst_stride, 4);
    6044             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6045             :              mi_col_top, dry_run, dst_buf, dst_stride, 5);
    6046             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6047             :              mi_col_top, dry_run, dst_buf, dst_stride, 6);
    6048             :   extend_dir(cpi, td, tile, block, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6049             :              mi_col_top, dry_run, dst_buf, dst_stride, 7);
    6050             : }
    6051             : 
    6052             : // This function generates prediction for multiple blocks, between which
    6053             : // discontinuity around boundary is reduced by smoothing masks. The basic
    6054             : // smoothing mask is a soft step function along horz/vert direction. In more
    6055             : // complicated case when a block is split into 4 subblocks, the basic mask is
    6056             : // first applied to neighboring subblocks (2 pairs) in horizontal direction and
    6057             : // then applied to the 2 masked prediction mentioned above in vertical direction
    6058             : // If the block is split into more than one level, at every stage, masked
    6059             : // prediction is stored in dst_buf[] passed from higher level.
    6060             : static void predict_sb_complex(const AV1_COMP *const cpi, ThreadData *td,
    6061             :                                const TileInfo *const tile, int mi_row,
    6062             :                                int mi_col, int mi_row_top, int mi_col_top,
    6063             :                                RUN_TYPE dry_run, BLOCK_SIZE bsize,
    6064             :                                BLOCK_SIZE top_bsize, uint8_t *dst_buf[3],
    6065             :                                int dst_stride[3], PC_TREE *pc_tree) {
    6066             :   const AV1_COMMON *const cm = &cpi->common;
    6067             :   MACROBLOCK *const x = &td->mb;
    6068             :   MACROBLOCKD *const xd = &x->e_mbd;
    6069             :   const int hbs = mi_size_wide[bsize] / 2;
    6070             :   const int is_partition_root = bsize >= BLOCK_8X8;
    6071             :   const int ctx = is_partition_root
    6072             :                       ? partition_plane_context(xd, mi_row, mi_col,
    6073             : #if CONFIG_UNPOISON_PARTITION_CTX
    6074             :                                                 mi_row + hbs < cm->mi_rows,
    6075             :                                                 mi_col + hbs < cm->mi_cols,
    6076             : #endif
    6077             :                                                 bsize)
    6078             :                       : -1;
    6079             :   const PARTITION_TYPE partition = pc_tree->partitioning;
    6080             :   const BLOCK_SIZE subsize = get_subsize(bsize, partition);
    6081             : #if CONFIG_EXT_PARTITION_TYPES
    6082             :   const BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
    6083             : #endif
    6084             : 
    6085             :   int i;
    6086             :   uint8_t *dst_buf1[3], *dst_buf2[3], *dst_buf3[3];
    6087             :   DECLARE_ALIGNED(16, uint8_t, tmp_buf1[MAX_MB_PLANE * MAX_TX_SQUARE * 2]);
    6088             :   DECLARE_ALIGNED(16, uint8_t, tmp_buf2[MAX_MB_PLANE * MAX_TX_SQUARE * 2]);
    6089             :   DECLARE_ALIGNED(16, uint8_t, tmp_buf3[MAX_MB_PLANE * MAX_TX_SQUARE * 2]);
    6090             :   int dst_stride1[3] = { MAX_TX_SIZE, MAX_TX_SIZE, MAX_TX_SIZE };
    6091             :   int dst_stride2[3] = { MAX_TX_SIZE, MAX_TX_SIZE, MAX_TX_SIZE };
    6092             :   int dst_stride3[3] = { MAX_TX_SIZE, MAX_TX_SIZE, MAX_TX_SIZE };
    6093             : #if CONFIG_CB4X4
    6094             :   const int unify_bsize = 1;
    6095             : #else
    6096             :   const int unify_bsize = 0;
    6097             :   assert(bsize >= BLOCK_8X8);
    6098             : #endif
    6099             : 
    6100             :   if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
    6101             : 
    6102             : #if CONFIG_HIGHBITDEPTH
    6103             :   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    6104             :     int len = sizeof(uint16_t);
    6105             :     dst_buf1[0] = CONVERT_TO_BYTEPTR(tmp_buf1);
    6106             :     dst_buf1[1] = CONVERT_TO_BYTEPTR(tmp_buf1 + MAX_TX_SQUARE * len);
    6107             :     dst_buf1[2] = CONVERT_TO_BYTEPTR(tmp_buf1 + 2 * MAX_TX_SQUARE * len);
    6108             :     dst_buf2[0] = CONVERT_TO_BYTEPTR(tmp_buf2);
    6109             :     dst_buf2[1] = CONVERT_TO_BYTEPTR(tmp_buf2 + MAX_TX_SQUARE * len);
    6110             :     dst_buf2[2] = CONVERT_TO_BYTEPTR(tmp_buf2 + 2 * MAX_TX_SQUARE * len);
    6111             :     dst_buf3[0] = CONVERT_TO_BYTEPTR(tmp_buf3);
    6112             :     dst_buf3[1] = CONVERT_TO_BYTEPTR(tmp_buf3 + MAX_TX_SQUARE * len);
    6113             :     dst_buf3[2] = CONVERT_TO_BYTEPTR(tmp_buf3 + 2 * MAX_TX_SQUARE * len);
    6114             :   } else {
    6115             : #endif  // CONFIG_HIGHBITDEPTH
    6116             :     dst_buf1[0] = tmp_buf1;
    6117             :     dst_buf1[1] = tmp_buf1 + MAX_TX_SQUARE;
    6118             :     dst_buf1[2] = tmp_buf1 + 2 * MAX_TX_SQUARE;
    6119             :     dst_buf2[0] = tmp_buf2;
    6120             :     dst_buf2[1] = tmp_buf2 + MAX_TX_SQUARE;
    6121             :     dst_buf2[2] = tmp_buf2 + 2 * MAX_TX_SQUARE;
    6122             :     dst_buf3[0] = tmp_buf3;
    6123             :     dst_buf3[1] = tmp_buf3 + MAX_TX_SQUARE;
    6124             :     dst_buf3[2] = tmp_buf3 + 2 * MAX_TX_SQUARE;
    6125             : #if CONFIG_HIGHBITDEPTH
    6126             :   }
    6127             : #endif  // CONFIG_HIGHBITDEPTH
    6128             : 
    6129             :   if (!dry_run && ctx >= 0 && bsize < top_bsize) {
    6130             :     // Explicitly cast away const.
    6131             :     FRAME_COUNTS *const frame_counts = (FRAME_COUNTS *)&cm->counts;
    6132             :     frame_counts->partition[ctx][partition]++;
    6133             :   }
    6134             : 
    6135             :   for (i = 0; i < MAX_MB_PLANE; i++) {
    6136             :     xd->plane[i].dst.buf = dst_buf[i];
    6137             :     xd->plane[i].dst.stride = dst_stride[i];
    6138             :   }
    6139             : 
    6140             :   switch (partition) {
    6141             :     case PARTITION_NONE:
    6142             :       assert(bsize < top_bsize);
    6143             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6144             :                        mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6145             :                        bsize, dry_run, 0, 0);
    6146             :       extend_all(cpi, td, tile, 0, bsize, top_bsize, mi_row, mi_col, mi_row_top,
    6147             :                  mi_col_top, dry_run, dst_buf, dst_stride);
    6148             :       break;
    6149             :     case PARTITION_HORZ:
    6150             :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    6151             :         // Fisrt half
    6152             :         predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6153             :                          mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6154             :                          BLOCK_8X8, dry_run, 1, 0);
    6155             :         if (bsize < top_bsize)
    6156             :           extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6157             :                      mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6158             : 
    6159             :         // Second half
    6160             :         predict_b_extend(cpi, td, tile, 2, mi_row, mi_col, mi_row, mi_col,
    6161             :                          mi_row_top, mi_col_top, dst_buf1, dst_stride1,
    6162             :                          top_bsize, BLOCK_8X8, dry_run, 1, 1);
    6163             :         if (bsize < top_bsize)
    6164             :           extend_all(cpi, td, tile, 2, subsize, top_bsize, mi_row, mi_col,
    6165             :                      mi_row_top, mi_col_top, dry_run, dst_buf1, dst_stride1);
    6166             : 
    6167             :         // Smooth
    6168             :         xd->plane[0].dst.buf = dst_buf[0];
    6169             :         xd->plane[0].dst.stride = dst_stride[0];
    6170             :         av1_build_masked_inter_predictor_complex(
    6171             :             xd, dst_buf[0], dst_stride[0], dst_buf1[0], dst_stride1[0], mi_row,
    6172             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_HORZ,
    6173             :             0);
    6174             :       } else {
    6175             :         // First half
    6176             :         predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6177             :                          mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6178             :                          subsize, dry_run, 0, 0);
    6179             :         if (bsize < top_bsize)
    6180             :           extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6181             :                      mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6182             :         else
    6183             :           extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6184             :                      mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride, 0);
    6185             : 
    6186             :         if (mi_row + hbs < cm->mi_rows) {
    6187             :           // Second half
    6188             :           predict_b_extend(cpi, td, tile, 0, mi_row + hbs, mi_col, mi_row + hbs,
    6189             :                            mi_col, mi_row_top, mi_col_top, dst_buf1,
    6190             :                            dst_stride1, top_bsize, subsize, dry_run, 0, 0);
    6191             :           if (bsize < top_bsize)
    6192             :             extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row + hbs,
    6193             :                        mi_col, mi_row_top, mi_col_top, dry_run, dst_buf1,
    6194             :                        dst_stride1);
    6195             :           else
    6196             :             extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row + hbs,
    6197             :                        mi_col, mi_row_top, mi_col_top, dry_run, dst_buf1,
    6198             :                        dst_stride1, 1);
    6199             : 
    6200             :           // Smooth
    6201             :           for (i = 0; i < MAX_MB_PLANE; i++) {
    6202             :             xd->plane[i].dst.buf = dst_buf[i];
    6203             :             xd->plane[i].dst.stride = dst_stride[i];
    6204             :             av1_build_masked_inter_predictor_complex(
    6205             :                 xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i],
    6206             :                 mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6207             :                 PARTITION_HORZ, i);
    6208             :           }
    6209             :         }
    6210             :       }
    6211             :       break;
    6212             :     case PARTITION_VERT:
    6213             :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    6214             :         // First half
    6215             :         predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6216             :                          mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6217             :                          BLOCK_8X8, dry_run, 1, 0);
    6218             :         if (bsize < top_bsize)
    6219             :           extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6220             :                      mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6221             : 
    6222             :         // Second half
    6223             :         predict_b_extend(cpi, td, tile, 1, mi_row, mi_col, mi_row, mi_col,
    6224             :                          mi_row_top, mi_col_top, dst_buf1, dst_stride1,
    6225             :                          top_bsize, BLOCK_8X8, dry_run, 1, 1);
    6226             :         if (bsize < top_bsize)
    6227             :           extend_all(cpi, td, tile, 1, subsize, top_bsize, mi_row, mi_col,
    6228             :                      mi_row_top, mi_col_top, dry_run, dst_buf1, dst_stride1);
    6229             : 
    6230             :         // Smooth
    6231             :         xd->plane[0].dst.buf = dst_buf[0];
    6232             :         xd->plane[0].dst.stride = dst_stride[0];
    6233             :         av1_build_masked_inter_predictor_complex(
    6234             :             xd, dst_buf[0], dst_stride[0], dst_buf1[0], dst_stride1[0], mi_row,
    6235             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_VERT,
    6236             :             0);
    6237             :       } else {
    6238             :         // bsize: not important, not useful
    6239             :         predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6240             :                          mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6241             :                          subsize, dry_run, 0, 0);
    6242             :         if (bsize < top_bsize)
    6243             :           extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6244             :                      mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6245             :         else
    6246             :           extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6247             :                      mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride, 3);
    6248             : 
    6249             :         if (mi_col + hbs < cm->mi_cols) {
    6250             :           predict_b_extend(cpi, td, tile, 0, mi_row, mi_col + hbs, mi_row,
    6251             :                            mi_col + hbs, mi_row_top, mi_col_top, dst_buf1,
    6252             :                            dst_stride1, top_bsize, subsize, dry_run, 0, 0);
    6253             :           if (bsize < top_bsize)
    6254             :             extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row,
    6255             :                        mi_col + hbs, mi_row_top, mi_col_top, dry_run, dst_buf1,
    6256             :                        dst_stride1);
    6257             :           else
    6258             :             extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row,
    6259             :                        mi_col + hbs, mi_row_top, mi_col_top, dry_run, dst_buf1,
    6260             :                        dst_stride1, 2);
    6261             : 
    6262             :           for (i = 0; i < MAX_MB_PLANE; i++) {
    6263             :             xd->plane[i].dst.buf = dst_buf[i];
    6264             :             xd->plane[i].dst.stride = dst_stride[i];
    6265             :             av1_build_masked_inter_predictor_complex(
    6266             :                 xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i],
    6267             :                 mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6268             :                 PARTITION_VERT, i);
    6269             :           }
    6270             :         }
    6271             :       }
    6272             :       break;
    6273             :     case PARTITION_SPLIT:
    6274             :       if (bsize == BLOCK_8X8 && !unify_bsize) {
    6275             :         predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6276             :                          mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6277             :                          BLOCK_8X8, dry_run, 1, 0);
    6278             :         predict_b_extend(cpi, td, tile, 1, mi_row, mi_col, mi_row, mi_col,
    6279             :                          mi_row_top, mi_col_top, dst_buf1, dst_stride1,
    6280             :                          top_bsize, BLOCK_8X8, dry_run, 1, 1);
    6281             :         predict_b_extend(cpi, td, tile, 2, mi_row, mi_col, mi_row, mi_col,
    6282             :                          mi_row_top, mi_col_top, dst_buf2, dst_stride2,
    6283             :                          top_bsize, BLOCK_8X8, dry_run, 1, 1);
    6284             :         predict_b_extend(cpi, td, tile, 3, mi_row, mi_col, mi_row, mi_col,
    6285             :                          mi_row_top, mi_col_top, dst_buf3, dst_stride3,
    6286             :                          top_bsize, BLOCK_8X8, dry_run, 1, 1);
    6287             : 
    6288             :         if (bsize < top_bsize) {
    6289             :           extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6290             :                      mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6291             :           extend_all(cpi, td, tile, 1, subsize, top_bsize, mi_row, mi_col,
    6292             :                      mi_row_top, mi_col_top, dry_run, dst_buf1, dst_stride1);
    6293             :           extend_all(cpi, td, tile, 2, subsize, top_bsize, mi_row, mi_col,
    6294             :                      mi_row_top, mi_col_top, dry_run, dst_buf2, dst_stride2);
    6295             :           extend_all(cpi, td, tile, 3, subsize, top_bsize, mi_row, mi_col,
    6296             :                      mi_row_top, mi_col_top, dry_run, dst_buf3, dst_stride3);
    6297             :         }
    6298             :       } else {
    6299             :         predict_sb_complex(cpi, td, tile, mi_row, mi_col, mi_row_top,
    6300             :                            mi_col_top, dry_run, subsize, top_bsize, dst_buf,
    6301             :                            dst_stride, pc_tree->split[0]);
    6302             :         if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols)
    6303             :           predict_sb_complex(cpi, td, tile, mi_row, mi_col + hbs, mi_row_top,
    6304             :                              mi_col_top, dry_run, subsize, top_bsize, dst_buf1,
    6305             :                              dst_stride1, pc_tree->split[1]);
    6306             :         if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols)
    6307             :           predict_sb_complex(cpi, td, tile, mi_row + hbs, mi_col, mi_row_top,
    6308             :                              mi_col_top, dry_run, subsize, top_bsize, dst_buf2,
    6309             :                              dst_stride2, pc_tree->split[2]);
    6310             :         if (mi_row + hbs < cm->mi_rows && mi_col + hbs < cm->mi_cols)
    6311             :           predict_sb_complex(cpi, td, tile, mi_row + hbs, mi_col + hbs,
    6312             :                              mi_row_top, mi_col_top, dry_run, subsize,
    6313             :                              top_bsize, dst_buf3, dst_stride3,
    6314             :                              pc_tree->split[3]);
    6315             :       }
    6316             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6317             : #if !CONFIG_CB4X4
    6318             :         if (bsize == BLOCK_8X8 && i != 0)
    6319             :           continue;  // Skip <4x4 chroma smoothing
    6320             : #endif
    6321             :         if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols) {
    6322             :           av1_build_masked_inter_predictor_complex(
    6323             :               xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i],
    6324             :               mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6325             :               PARTITION_VERT, i);
    6326             :           if (mi_row + hbs < cm->mi_rows) {
    6327             :             av1_build_masked_inter_predictor_complex(
    6328             :                 xd, dst_buf2[i], dst_stride2[i], dst_buf3[i], dst_stride3[i],
    6329             :                 mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6330             :                 PARTITION_VERT, i);
    6331             :             av1_build_masked_inter_predictor_complex(
    6332             :                 xd, dst_buf[i], dst_stride[i], dst_buf2[i], dst_stride2[i],
    6333             :                 mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6334             :                 PARTITION_HORZ, i);
    6335             :           }
    6336             :         } else if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols) {
    6337             :           if (bsize == BLOCK_8X8 && i != 0)
    6338             :             continue;  // Skip <4x4 chroma smoothing
    6339             : 
    6340             :           av1_build_masked_inter_predictor_complex(
    6341             :               xd, dst_buf[i], dst_stride[i], dst_buf2[i], dst_stride2[i],
    6342             :               mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6343             :               PARTITION_HORZ, i);
    6344             :         }
    6345             :       }
    6346             :       break;
    6347             : #if CONFIG_EXT_PARTITION_TYPES
    6348             :     case PARTITION_HORZ_A:
    6349             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6350             :                        mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6351             :                        bsize2, dry_run, 0, 0);
    6352             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row, mi_col,
    6353             :                  mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6354             : 
    6355             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col + hbs, mi_row,
    6356             :                        mi_col + hbs, mi_row_top, mi_col_top, dst_buf1,
    6357             :                        dst_stride1, top_bsize, bsize2, dry_run, 0, 0);
    6358             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row, mi_col + hbs,
    6359             :                  mi_row_top, mi_col_top, dry_run, dst_buf1, dst_stride1);
    6360             : 
    6361             :       predict_b_extend(cpi, td, tile, 0, mi_row + hbs, mi_col, mi_row + hbs,
    6362             :                        mi_col, mi_row_top, mi_col_top, dst_buf2, dst_stride2,
    6363             :                        top_bsize, subsize, dry_run, 0, 0);
    6364             :       if (bsize < top_bsize)
    6365             :         extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row + hbs, mi_col,
    6366             :                    mi_row_top, mi_col_top, dry_run, dst_buf2, dst_stride2);
    6367             :       else
    6368             :         extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row + hbs, mi_col,
    6369             :                    mi_row_top, mi_col_top, dry_run, dst_buf2, dst_stride2, 1);
    6370             : 
    6371             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6372             :         xd->plane[i].dst.buf = dst_buf[i];
    6373             :         xd->plane[i].dst.stride = dst_stride[i];
    6374             :         av1_build_masked_inter_predictor_complex(
    6375             :             xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i], mi_row,
    6376             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_VERT,
    6377             :             i);
    6378             :       }
    6379             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6380             :         av1_build_masked_inter_predictor_complex(
    6381             :             xd, dst_buf[i], dst_stride[i], dst_buf2[i], dst_stride2[i], mi_row,
    6382             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_HORZ,
    6383             :             i);
    6384             :       }
    6385             : 
    6386             :       break;
    6387             :     case PARTITION_VERT_A:
    6388             : 
    6389             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6390             :                        mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6391             :                        bsize2, dry_run, 0, 0);
    6392             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row, mi_col,
    6393             :                  mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6394             : 
    6395             :       predict_b_extend(cpi, td, tile, 0, mi_row + hbs, mi_col, mi_row + hbs,
    6396             :                        mi_col, mi_row_top, mi_col_top, dst_buf1, dst_stride1,
    6397             :                        top_bsize, bsize2, dry_run, 0, 0);
    6398             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row + hbs, mi_col,
    6399             :                  mi_row_top, mi_col_top, dry_run, dst_buf1, dst_stride1);
    6400             : 
    6401             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col + hbs, mi_row,
    6402             :                        mi_col + hbs, mi_row_top, mi_col_top, dst_buf2,
    6403             :                        dst_stride2, top_bsize, subsize, dry_run, 0, 0);
    6404             :       if (bsize < top_bsize)
    6405             :         extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col + hbs,
    6406             :                    mi_row_top, mi_col_top, dry_run, dst_buf2, dst_stride2);
    6407             :       else
    6408             :         extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col + hbs,
    6409             :                    mi_row_top, mi_col_top, dry_run, dst_buf2, dst_stride2, 2);
    6410             : 
    6411             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6412             :         xd->plane[i].dst.buf = dst_buf[i];
    6413             :         xd->plane[i].dst.stride = dst_stride[i];
    6414             :         av1_build_masked_inter_predictor_complex(
    6415             :             xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i], mi_row,
    6416             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_HORZ,
    6417             :             i);
    6418             :       }
    6419             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6420             :         av1_build_masked_inter_predictor_complex(
    6421             :             xd, dst_buf[i], dst_stride[i], dst_buf2[i], dst_stride2[i], mi_row,
    6422             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_VERT,
    6423             :             i);
    6424             :       }
    6425             :       break;
    6426             :     case PARTITION_HORZ_B:
    6427             : 
    6428             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6429             :                        mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6430             :                        subsize, dry_run, 0, 0);
    6431             :       if (bsize < top_bsize)
    6432             :         extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6433             :                    mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6434             :       else
    6435             :         extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6436             :                    mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride, 0);
    6437             : 
    6438             :       predict_b_extend(cpi, td, tile, 0, mi_row + hbs, mi_col, mi_row + hbs,
    6439             :                        mi_col, mi_row_top, mi_col_top, dst_buf1, dst_stride1,
    6440             :                        top_bsize, bsize2, dry_run, 0, 0);
    6441             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row + hbs, mi_col,
    6442             :                  mi_row_top, mi_col_top, dry_run, dst_buf1, dst_stride1);
    6443             : 
    6444             :       predict_b_extend(cpi, td, tile, 0, mi_row + hbs, mi_col + hbs,
    6445             :                        mi_row + hbs, mi_col + hbs, mi_row_top, mi_col_top,
    6446             :                        dst_buf2, dst_stride2, top_bsize, bsize2, dry_run, 0, 0);
    6447             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row + hbs,
    6448             :                  mi_col + hbs, mi_row_top, mi_col_top, dry_run, dst_buf2,
    6449             :                  dst_stride2);
    6450             : 
    6451             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6452             :         xd->plane[i].dst.buf = dst_buf1[i];
    6453             :         xd->plane[i].dst.stride = dst_stride1[i];
    6454             :         av1_build_masked_inter_predictor_complex(
    6455             :             xd, dst_buf1[i], dst_stride1[i], dst_buf2[i], dst_stride2[i],
    6456             :             mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6457             :             PARTITION_VERT, i);
    6458             :       }
    6459             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6460             :         xd->plane[i].dst.buf = dst_buf[i];
    6461             :         xd->plane[i].dst.stride = dst_stride[i];
    6462             :         av1_build_masked_inter_predictor_complex(
    6463             :             xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i], mi_row,
    6464             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_HORZ,
    6465             :             i);
    6466             :       }
    6467             :       break;
    6468             :     case PARTITION_VERT_B:
    6469             : 
    6470             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col, mi_row, mi_col,
    6471             :                        mi_row_top, mi_col_top, dst_buf, dst_stride, top_bsize,
    6472             :                        subsize, dry_run, 0, 0);
    6473             :       if (bsize < top_bsize)
    6474             :         extend_all(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6475             :                    mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride);
    6476             :       else
    6477             :         extend_dir(cpi, td, tile, 0, subsize, top_bsize, mi_row, mi_col,
    6478             :                    mi_row_top, mi_col_top, dry_run, dst_buf, dst_stride, 3);
    6479             : 
    6480             :       predict_b_extend(cpi, td, tile, 0, mi_row, mi_col + hbs, mi_row,
    6481             :                        mi_col + hbs, mi_row_top, mi_col_top, dst_buf1,
    6482             :                        dst_stride1, top_bsize, bsize2, dry_run, 0, 0);
    6483             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row, mi_col + hbs,
    6484             :                  mi_row_top, mi_col_top, dry_run, dst_buf1, dst_stride1);
    6485             : 
    6486             :       predict_b_extend(cpi, td, tile, 0, mi_row + hbs, mi_col + hbs,
    6487             :                        mi_row + hbs, mi_col + hbs, mi_row_top, mi_col_top,
    6488             :                        dst_buf2, dst_stride2, top_bsize, bsize2, dry_run, 0, 0);
    6489             :       extend_all(cpi, td, tile, 0, bsize2, top_bsize, mi_row + hbs,
    6490             :                  mi_col + hbs, mi_row_top, mi_col_top, dry_run, dst_buf2,
    6491             :                  dst_stride2);
    6492             : 
    6493             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6494             :         xd->plane[i].dst.buf = dst_buf1[i];
    6495             :         xd->plane[i].dst.stride = dst_stride1[i];
    6496             :         av1_build_masked_inter_predictor_complex(
    6497             :             xd, dst_buf1[i], dst_stride1[i], dst_buf2[i], dst_stride2[i],
    6498             :             mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
    6499             :             PARTITION_HORZ, i);
    6500             :       }
    6501             :       for (i = 0; i < MAX_MB_PLANE; i++) {
    6502             :         xd->plane[i].dst.buf = dst_buf[i];
    6503             :         xd->plane[i].dst.stride = dst_stride[i];
    6504             :         av1_build_masked_inter_predictor_complex(
    6505             :             xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i], mi_row,
    6506             :             mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_VERT,
    6507             :             i);
    6508             :       }
    6509             :       break;
    6510             : #endif  // CONFIG_EXT_PARTITION_TYPES
    6511             :     default: assert(0);
    6512             :   }
    6513             : 
    6514             : #if CONFIG_EXT_PARTITION_TYPES
    6515             :   if (bsize < top_bsize)
    6516             :     update_ext_partition_context(xd, mi_row, mi_col, subsize, bsize, partition);
    6517             : #else
    6518             :   if (bsize < top_bsize && (partition != PARTITION_SPLIT || bsize == BLOCK_8X8))
    6519             :     update_partition_context(xd, mi_row, mi_col, subsize, bsize);
    6520             : #endif  // CONFIG_EXT_PARTITION_TYPES
    6521             : }
    6522             : 
    6523             : static void rd_supertx_sb(const AV1_COMP *const cpi, ThreadData *td,
    6524             :                           const TileInfo *const tile, int mi_row, int mi_col,
    6525             :                           BLOCK_SIZE bsize, int *tmp_rate, int64_t *tmp_dist,
    6526             :                           TX_TYPE *best_tx, PC_TREE *pc_tree) {
    6527             :   const AV1_COMMON *const cm = &cpi->common;
    6528             :   MACROBLOCK *const x = &td->mb;
    6529             :   MACROBLOCKD *const xd = &x->e_mbd;
    6530             :   int plane, pnskip, skippable, skippable_uv, rate_uv, this_rate,
    6531             :       base_rate = *tmp_rate;
    6532             :   int64_t sse, pnsse, sse_uv, this_dist, dist_uv;
    6533             :   uint8_t *dst_buf[3];
    6534             :   int dst_stride[3];
    6535             :   TX_SIZE tx_size;
    6536             :   MB_MODE_INFO *mbmi;
    6537             :   TX_TYPE tx_type, best_tx_nostx;
    6538             : #if CONFIG_EXT_TX
    6539             :   int ext_tx_set;
    6540             : #endif  // CONFIG_EXT_TX
    6541             :   int tmp_rate_tx = 0, skip_tx = 0;
    6542             :   int64_t tmp_dist_tx = 0, rd_tx, bestrd_tx = INT64_MAX;
    6543             : 
    6544             :   set_skip_context(xd, mi_row, mi_col);
    6545             :   set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
    6546             :   update_state_sb_supertx(cpi, td, tile, mi_row, mi_col, bsize, 1, pc_tree);
    6547             :   av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
    6548             :                        mi_col);
    6549             :   for (plane = 0; plane < MAX_MB_PLANE; plane++) {
    6550             :     dst_buf[plane] = xd->plane[plane].dst.buf;
    6551             :     dst_stride[plane] = xd->plane[plane].dst.stride;
    6552             :   }
    6553             :   predict_sb_complex(cpi, td, tile, mi_row, mi_col, mi_row, mi_col, 1, bsize,
    6554             :                      bsize, dst_buf, dst_stride, pc_tree);
    6555             : 
    6556             :   set_offsets_without_segment_id(cpi, tile, x, mi_row, mi_col, bsize);
    6557             :   set_segment_id_supertx(cpi, x, mi_row, mi_col, bsize);
    6558             : 
    6559             :   mbmi = &xd->mi[0]->mbmi;
    6560             :   best_tx_nostx = mbmi->tx_type;
    6561             : 
    6562             :   *best_tx = DCT_DCT;
    6563             : 
    6564             :   // chroma
    6565             :   skippable_uv = 1;
    6566             :   rate_uv = 0;
    6567             :   dist_uv = 0;
    6568             :   sse_uv = 0;
    6569             :   for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
    6570             : #if CONFIG_VAR_TX
    6571             :     ENTROPY_CONTEXT ctxa[2 * MAX_MIB_SIZE];
    6572             :     ENTROPY_CONTEXT ctxl[2 * MAX_MIB_SIZE];
    6573             :     const struct macroblockd_plane *const pd = &xd->plane[plane];
    6574             :     RD_STATS this_rd_stats;
    6575             :     av1_init_rd_stats(&this_rd_stats);
    6576             : 
    6577             :     tx_size = max_txsize_lookup[bsize];
    6578             :     tx_size =
    6579             :         uv_txsize_lookup[bsize][tx_size][cm->subsampling_x][cm->subsampling_y];
    6580             :     av1_get_entropy_contexts(bsize, tx_size, pd, ctxa, ctxl);
    6581             : 
    6582             :     av1_subtract_plane(x, bsize, plane);
    6583             :     av1_tx_block_rd_b(cpi, x, tx_size, 0, 0, plane, 0,
    6584             :                       get_plane_block_size(bsize, pd), &ctxa[0], &ctxl[0],
    6585             :                       &this_rd_stats);
    6586             : 
    6587             :     this_rate = this_rd_stats.rate;
    6588             :     this_dist = this_rd_stats.dist;
    6589             :     pnsse = this_rd_stats.sse;
    6590             :     pnskip = this_rd_stats.skip;
    6591             : #else
    6592             :     tx_size = max_txsize_lookup[bsize];
    6593             :     tx_size =
    6594             :         uv_txsize_lookup[bsize][tx_size][cm->subsampling_x][cm->subsampling_y];
    6595             :     av1_subtract_plane(x, bsize, plane);
    6596             :     av1_txfm_rd_in_plane_supertx(x, cpi, &this_rate, &this_dist, &pnskip,
    6597             :                                  &pnsse, INT64_MAX, plane, bsize, tx_size, 0);
    6598             : #endif  // CONFIG_VAR_TX
    6599             : 
    6600             :     rate_uv += this_rate;
    6601             :     dist_uv += this_dist;
    6602             :     sse_uv += pnsse;
    6603             :     skippable_uv &= pnskip;
    6604             :   }
    6605             : 
    6606             :   // luma
    6607             :   tx_size = max_txsize_lookup[bsize];
    6608             :   av1_subtract_plane(x, bsize, 0);
    6609             : #if CONFIG_EXT_TX
    6610             :   ext_tx_set = get_ext_tx_set(tx_size, bsize, 1, cm->reduced_tx_set_used);
    6611             : #endif  // CONFIG_EXT_TX
    6612             :   for (tx_type = DCT_DCT; tx_type < TX_TYPES; ++tx_type) {
    6613             : #if CONFIG_VAR_TX
    6614             :     ENTROPY_CONTEXT ctxa[2 * MAX_MIB_SIZE];
    6615             :     ENTROPY_CONTEXT ctxl[2 * MAX_MIB_SIZE];
    6616             :     const struct macroblockd_plane *const pd = &xd->plane[0];
    6617             :     RD_STATS this_rd_stats;
    6618             : #endif  // CONFIG_VAR_TX
    6619             : 
    6620             : #if CONFIG_EXT_TX
    6621             :     if (!ext_tx_used_inter[ext_tx_set][tx_type]) continue;
    6622             : #else
    6623             :     if (tx_size >= TX_32X32 && tx_type != DCT_DCT) continue;
    6624             : #endif  // CONFIG_EXT_TX
    6625             :     mbmi->tx_type = tx_type;
    6626             : 
    6627             : #if CONFIG_VAR_TX
    6628             :     av1_init_rd_stats(&this_rd_stats);
    6629             :     av1_get_entropy_contexts(bsize, tx_size, pd, ctxa, ctxl);
    6630             :     av1_tx_block_rd_b(cpi, x, tx_size, 0, 0, 0, 0, bsize, &ctxa[0], &ctxl[0],
    6631             :                       &this_rd_stats);
    6632             : 
    6633             :     this_rate = this_rd_stats.rate;
    6634             :     this_dist = this_rd_stats.dist;
    6635             :     pnsse = this_rd_stats.sse;
    6636             :     pnskip = this_rd_stats.skip;
    6637             : #else
    6638             :     av1_txfm_rd_in_plane_supertx(x, cpi, &this_rate, &this_dist, &pnskip,
    6639             :                                  &pnsse, INT64_MAX, 0, bsize, tx_size, 0);
    6640             : #endif  // CONFIG_VAR_TX
    6641             : 
    6642             : #if CONFIG_EXT_TX
    6643             :     if (get_ext_tx_types(tx_size, bsize, 1, cm->reduced_tx_set_used) > 1 &&
    6644             :         !xd->lossless[xd->mi[0]->mbmi.segment_id] && this_rate != INT_MAX) {
    6645             :       if (ext_tx_set > 0)
    6646             :         this_rate +=
    6647             :             cpi->inter_tx_type_costs[ext_tx_set][mbmi->tx_size][mbmi->tx_type];
    6648             :     }
    6649             : #else
    6650             :     if (tx_size < TX_32X32 && !xd->lossless[xd->mi[0]->mbmi.segment_id] &&
    6651             :         this_rate != INT_MAX) {
    6652             :       this_rate += cpi->inter_tx_type_costs[tx_size][mbmi->tx_type];
    6653             :     }
    6654             : #endif  // CONFIG_EXT_TX
    6655             :     *tmp_rate = rate_uv + this_rate;
    6656             :     *tmp_dist = dist_uv + this_dist;
    6657             :     sse = sse_uv + pnsse;
    6658             :     skippable = skippable_uv && pnskip;
    6659             :     if (skippable) {
    6660             :       *tmp_rate = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
    6661             :       x->skip = 1;
    6662             :     } else {
    6663             :       if (RDCOST(x->rdmult, x->rddiv, *tmp_rate, *tmp_dist) <
    6664             :           RDCOST(x->rdmult, x->rddiv, 0, sse)) {
    6665             :         *tmp_rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
    6666             :         x->skip = 0;
    6667             :       } else {
    6668             :         *tmp_dist = sse;
    6669             :         *tmp_rate = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
    6670             :         x->skip = 1;
    6671             :       }
    6672             :     }
    6673             :     *tmp_rate += base_rate;
    6674             :     rd_tx = RDCOST(x->rdmult, x->rddiv, *tmp_rate, *tmp_dist);
    6675             :     if (rd_tx < bestrd_tx * 0.99 || tx_type == DCT_DCT) {
    6676             :       *best_tx = tx_type;
    6677             :       bestrd_tx = rd_tx;
    6678             :       tmp_rate_tx = *tmp_rate;
    6679             :       tmp_dist_tx = *tmp_dist;
    6680             :       skip_tx = x->skip;
    6681             :     }
    6682             :   }
    6683             :   *tmp_rate = tmp_rate_tx;
    6684             :   *tmp_dist = tmp_dist_tx;
    6685             :   x->skip = skip_tx;
    6686             : #if CONFIG_VAR_TX
    6687             :   for (plane = 0; plane < 1; ++plane)
    6688             :     memset(x->blk_skip[plane], x->skip,
    6689             :            sizeof(uint8_t) * pc_tree->none.num_4x4_blk);
    6690             : #endif  // CONFIG_VAR_TX
    6691             :   xd->mi[0]->mbmi.tx_type = best_tx_nostx;
    6692             : }
    6693             : #endif  // CONFIG_SUPERTX

Generated by: LCOV version 1.13