1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <limits.h>
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <math.h>
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdio.h>
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vp9_rtcd.h"
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h"
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_ports/vpx_timer.h"
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_common.h"
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_entropy.h"
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_entropymode.h"
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_idct.h"
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_mvref_common.h"
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_pred_common.h"
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_quant_common.h"
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_reconintra.h"
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_reconinter.h"
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_seg_common.h"
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_systemdependent.h"
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_tile_common.h"
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_aq_complexity.h"
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_aq_cyclicrefresh.h"
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_aq_variance.h"
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_encodeframe.h"
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_encodemb.h"
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_encodemv.h"
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_extend.h"
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_pickmode.h"
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_rdopt.h"
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_segmentation.h"
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_tokenize.h"
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define GF_ZEROMV_ZBIN_BOOST 0
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LF_ZEROMV_ZBIN_BOOST 0
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define MV_ZBIN_BOOST        0
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define SPLIT_MV_ZBIN_BOOST  0
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define INTRA_ZBIN_BOOST     0
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan
51233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic INLINE uint8_t *get_sb_index(MACROBLOCK *x, BLOCK_SIZE subsize) {
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (subsize) {
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_64X64:
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_64X32:
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_32X64:
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_32X32:
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->sb_index;
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_32X16:
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_16X32:
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_16X16:
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->mb_index;
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_16X8:
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_8X16:
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_8X8:
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->b_index;
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_8X4:
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_4X8:
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_4X4:
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->ab_index;
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default:
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(0);
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return NULL;
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan
76233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              int mi_row, int mi_col, BLOCK_SIZE bsize);
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan
79233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void adjust_act_zbin(VP9_COMP *cpi, MACROBLOCK *x);
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan// activity_avg must be positive, or flat regions could get a zero weight
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan//  (infinite lambda), which confounds analysis.
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This also avoids the need for divide by zero checks in
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan//  vp9_activity_masking().
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ACTIVITY_AVG_MIN 64
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Motion vector component magnitude threshold for defining fast motion.
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define FAST_MOTION_MV_THRESH 24
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This is used as a reference when computing the source variance for the
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan//  purposes of activity masking.
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Eventually this should be replaced by custom no-reference routines,
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan//  which will be faster.
94233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const uint8_t VP9_VAR_OFFS[64] = {
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128,
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128,
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128,
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128,
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128,
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128,
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128,
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  128, 128, 128, 128, 128, 128, 128, 128
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan
105233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int get_sby_perpixel_variance(VP9_COMP *cpi,
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              MACROBLOCK *x,
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              BLOCK_SIZE bs) {
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int var, sse;
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           VP9_VAR_OFFS, 0, &sse);
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
114233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int get_sby_perpixel_diff_variance(VP9_COMP *cpi,
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   MACROBLOCK *x,
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   int mi_row,
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   int mi_col,
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   BLOCK_SIZE bs) {
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int offset = (mi_row * MI_SIZE) * yv12->y_stride + (mi_col * MI_SIZE);
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int var, sse;
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf,
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           x->plane[0].src.stride,
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           yv12->y_buffer + offset,
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           yv12->y_stride,
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           &sse);
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan
130233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic BLOCK_SIZE get_rd_var_based_fixed_partition(VP9_COMP *cpi,
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   int mi_row,
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   int mi_col) {
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb,
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    mi_row, mi_col,
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    BLOCK_64X64);
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (var < 8)
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return BLOCK_64X64;
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else if (var < 128)
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return BLOCK_32X32;
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else if (var < 2048)
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return BLOCK_16X16;
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return BLOCK_8X8;
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan
146233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic BLOCK_SIZE get_nonrd_var_based_fixed_partition(VP9_COMP *cpi,
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                      int mi_row,
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                      int mi_col) {
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb,
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    mi_row, mi_col,
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    BLOCK_64X64);
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (var < 4)
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return BLOCK_64X64;
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else if (var < 10)
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return BLOCK_32X32;
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return BLOCK_16X16;
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Lighter version of set_offsets that only sets the mode info
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan// pointers.
162233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic INLINE void set_modeinfo_offsets(VP9_COMMON *const cm,
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        MACROBLOCKD *const xd,
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        int mi_row,
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        int mi_col) {
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int idx_str = xd->mi_stride * mi_row + mi_col;
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  xd->mi = cm->mi_grid_visible + idx_str;
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  xd->mi[0] = cm->mi + idx_str;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
171233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int is_block_in_mb_map(const VP9_COMP *cpi, int mi_row, int mi_col,
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              BLOCK_SIZE bsize) {
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const VP9_COMMON *const cm = &cpi->common;
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_rows = cm->mb_rows;
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_cols = cm->mb_cols;
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_row = mi_row >> 1;
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_col = mi_col >> 1;
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_width = num_8x8_blocks_wide_lookup[bsize] >> 1;
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_height = num_8x8_blocks_high_lookup[bsize] >> 1;
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r, c;
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize <= BLOCK_16X16) {
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return cpi->active_map[mb_row * mb_cols + mb_col];
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (r = 0; r < mb_height; ++r) {
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (c = 0; c < mb_width; ++c) {
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int row = mb_row + r;
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int col = mb_col + c;
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (row >= mb_rows || col >= mb_cols)
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan        continue;
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->active_map[row * mb_cols + col])
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan
197233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int check_active_map(const VP9_COMP *cpi, const MACROBLOCK *x,
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            int mi_row, int mi_col,
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            BLOCK_SIZE bsize) {
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->active_map_enabled && !x->e_mbd.lossless) {
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return is_block_in_mb_map(cpi, mi_row, mi_col, bsize);
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan
207233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_offsets(VP9_COMP *cpi, const TileInfo *const tile,
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        int mi_row, int mi_col, BLOCK_SIZE bsize) {
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MB_MODE_INFO *mbmi;
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_width = num_8x8_blocks_wide_lookup[bsize];
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_height = num_8x8_blocks_high_lookup[bsize];
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_row = mi_row >> 1;
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mb_col = mi_col >> 1;
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int idx_map = mb_row * cm->mb_cols + mb_col;
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct segmentation *const seg = &cm->seg;
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_skip_context(xd, mi_row, mi_col);
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Activity map pointer
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->mb_activity_ptr = &cpi->mb_activity_map[idx_map];
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->in_active_map = check_active_map(cpi, x, mi_row, mi_col, bsize);
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_modeinfo_offsets(cm, xd, mi_row, mi_col);
227233d2500723e5594f3e7c70896ffeeef32b9c950ywan
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi = &xd->mi[0]->mbmi;
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Set up destination pointers.
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_setup_dst_planes(xd, get_frame_new_buffer(cm), mi_row, mi_col);
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Set up limit values for MV components.
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Mv beyond the range do not produce new/different prediction block.
235233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->mv_row_min = -(((mi_row + mi_height) * MI_SIZE) + VP9_INTERP_EXTEND);
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->mv_col_min = -(((mi_col + mi_width) * MI_SIZE) + VP9_INTERP_EXTEND);
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->mv_row_max = (cm->mi_rows - mi_row) * MI_SIZE + VP9_INTERP_EXTEND;
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->mv_col_max = (cm->mi_cols - mi_col) * MI_SIZE + VP9_INTERP_EXTEND;
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan
240233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Set up distance of MB to edge of frame in 1/8th pel units.
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width,
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 cm->mi_rows, cm->mi_cols);
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Set up source buffers.
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // R/D setup.
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->rddiv = cpi->RDDIV;
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->rdmult = cpi->RDMULT;
251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Setup segment ID.
253233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (seg->enabled) {
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.aq_mode != VARIANCE_AQ) {
255233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const uint8_t *const map = seg->update_map ? cpi->segmentation_map
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                 : cm->last_frame_seg_map;
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mbmi->segment_id = vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_init_plane_quantizers(cpi, x);
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seg->enabled && cpi->seg0_cnt > 0 &&
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan        !vp9_segfeature_active(seg, 0, SEG_LVL_REF_FRAME) &&
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp9_segfeature_active(seg, 1, SEG_LVL_REF_FRAME)) {
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt;
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int y = mb_row & ~3;
267233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int x = mb_col & ~3;
268233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int p16 = ((mb_row & 1) << 1) + (mb_col & 1);
269233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int p32 = ((mb_row & 2) << 2) + ((mb_col & 2) << 1);
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int tile_progress = tile->mi_col_start * cm->mb_rows >> 1;
271233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int mb_cols = (tile->mi_col_end - tile->mi_col_start) >> 1;
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan
273233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->seg0_progress = ((y * mb_cols + x * 4 + p32 + p16 + tile_progress)
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan          << 16) / cm->MBs;
275233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
276233d2500723e5594f3e7c70896ffeeef32b9c950ywan
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->encode_breakout = cpi->segment_encode_breakout[mbmi->segment_id];
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbmi->segment_id = 0;
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->encode_breakout = cpi->encode_breakout;
281233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
284233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void duplicate_mode_info_in_sb(VP9_COMMON * const cm,
285233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     MACROBLOCKD *const xd,
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     int mi_row,
287233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     int mi_col,
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     BLOCK_SIZE bsize) {
289233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int block_width = num_8x8_blocks_wide_lookup[bsize];
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int block_height = num_8x8_blocks_high_lookup[bsize];
291233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i, j;
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (j = 0; j < block_height; ++j)
293233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < block_width; ++i) {
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_row + j < cm->mi_rows && mi_col + i < cm->mi_cols)
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->mi[j * xd->mi_stride + i] = xd->mi[0];
296233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
298233d2500723e5594f3e7c70896ffeeef32b9c950ywan
299233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_block_size(VP9_COMP * const cpi,
300233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           const TileInfo *const tile,
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           int mi_row, int mi_col,
302233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           BLOCK_SIZE bsize) {
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->common.mi_cols > mi_col && cpi->common.mi_rows > mi_row) {
304233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MACROBLOCKD *const xd = &cpi->mb.e_mbd;
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_modeinfo_offsets(&cpi->common, xd, mi_row, mi_col);
306233d2500723e5594f3e7c70896ffeeef32b9c950ywan    xd->mi[0]->mbmi.sb_type = bsize;
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan    duplicate_mode_info_in_sb(&cpi->common, xd, mi_row, mi_col, bsize);
308233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
310233d2500723e5594f3e7c70896ffeeef32b9c950ywan
311233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef struct {
312233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t sum_square_error;
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t sum_error;
314233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int count;
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int variance;
316233d2500723e5594f3e7c70896ffeeef32b9c950ywan} var;
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan
318233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef struct {
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  var none;
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan  var horz[2];
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan  var vert[2];
322233d2500723e5594f3e7c70896ffeeef32b9c950ywan} partition_variance;
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
324233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef struct {
325233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition_variance part_variances;
326233d2500723e5594f3e7c70896ffeeef32b9c950ywan  var split[4];
327233d2500723e5594f3e7c70896ffeeef32b9c950ywan} v8x8;
328233d2500723e5594f3e7c70896ffeeef32b9c950ywan
329233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef struct {
330233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition_variance part_variances;
331233d2500723e5594f3e7c70896ffeeef32b9c950ywan  v8x8 split[4];
332233d2500723e5594f3e7c70896ffeeef32b9c950ywan} v16x16;
333233d2500723e5594f3e7c70896ffeeef32b9c950ywan
334233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef struct {
335233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition_variance part_variances;
336233d2500723e5594f3e7c70896ffeeef32b9c950ywan  v16x16 split[4];
337233d2500723e5594f3e7c70896ffeeef32b9c950ywan} v32x32;
338233d2500723e5594f3e7c70896ffeeef32b9c950ywan
339233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef struct {
340233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition_variance part_variances;
341233d2500723e5594f3e7c70896ffeeef32b9c950ywan  v32x32 split[4];
342233d2500723e5594f3e7c70896ffeeef32b9c950ywan} v64x64;
343233d2500723e5594f3e7c70896ffeeef32b9c950ywan
344233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef struct {
345233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition_variance *part_variances;
346233d2500723e5594f3e7c70896ffeeef32b9c950ywan  var *split[4];
347233d2500723e5594f3e7c70896ffeeef32b9c950ywan} variance_node;
348233d2500723e5594f3e7c70896ffeeef32b9c950ywan
349233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef enum {
350233d2500723e5594f3e7c70896ffeeef32b9c950ywan  V16X16,
351233d2500723e5594f3e7c70896ffeeef32b9c950ywan  V32X32,
352233d2500723e5594f3e7c70896ffeeef32b9c950ywan  V64X64,
353233d2500723e5594f3e7c70896ffeeef32b9c950ywan} TREE_LEVEL;
354233d2500723e5594f3e7c70896ffeeef32b9c950ywan
355233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void tree_to_node(void *data, BLOCK_SIZE bsize, variance_node *node) {
356233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i;
357233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (bsize) {
358233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_64X64: {
359233d2500723e5594f3e7c70896ffeeef32b9c950ywan      v64x64 *vt = (v64x64 *) data;
360233d2500723e5594f3e7c70896ffeeef32b9c950ywan      node->part_variances = &vt->part_variances;
361233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < 4; i++)
362233d2500723e5594f3e7c70896ffeeef32b9c950ywan        node->split[i] = &vt->split[i].part_variances.none;
363233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
364233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
365233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_32X32: {
366233d2500723e5594f3e7c70896ffeeef32b9c950ywan      v32x32 *vt = (v32x32 *) data;
367233d2500723e5594f3e7c70896ffeeef32b9c950ywan      node->part_variances = &vt->part_variances;
368233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < 4; i++)
369233d2500723e5594f3e7c70896ffeeef32b9c950ywan        node->split[i] = &vt->split[i].part_variances.none;
370233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
371233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
372233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_16X16: {
373233d2500723e5594f3e7c70896ffeeef32b9c950ywan      v16x16 *vt = (v16x16 *) data;
374233d2500723e5594f3e7c70896ffeeef32b9c950ywan      node->part_variances = &vt->part_variances;
375233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < 4; i++)
376233d2500723e5594f3e7c70896ffeeef32b9c950ywan        node->split[i] = &vt->split[i].part_variances.none;
377233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
378233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
379233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_8X8: {
380233d2500723e5594f3e7c70896ffeeef32b9c950ywan      v8x8 *vt = (v8x8 *) data;
381233d2500723e5594f3e7c70896ffeeef32b9c950ywan      node->part_variances = &vt->part_variances;
382233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < 4; i++)
383233d2500723e5594f3e7c70896ffeeef32b9c950ywan        node->split[i] = &vt->split[i];
384233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
385233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
386233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default: {
387233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(0);
388233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
389233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
390233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
391233d2500723e5594f3e7c70896ffeeef32b9c950ywan
392233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Set variance values given sum square error, sum error, count.
393233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void fill_variance(int64_t s2, int64_t s, int c, var *v) {
394233d2500723e5594f3e7c70896ffeeef32b9c950ywan  v->sum_square_error = s2;
395233d2500723e5594f3e7c70896ffeeef32b9c950ywan  v->sum_error = s;
396233d2500723e5594f3e7c70896ffeeef32b9c950ywan  v->count = c;
397233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (c > 0)
398233d2500723e5594f3e7c70896ffeeef32b9c950ywan    v->variance = (int)(256 *
399233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (v->sum_square_error - v->sum_error * v->sum_error /
400233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         v->count) / v->count);
401233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else
402233d2500723e5594f3e7c70896ffeeef32b9c950ywan    v->variance = 0;
403233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
405233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid sum_2_variances(const var *a, const var *b, var *r) {
406233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fill_variance(a->sum_square_error + b->sum_square_error,
407233d2500723e5594f3e7c70896ffeeef32b9c950ywan                a->sum_error + b->sum_error, a->count + b->count, r);
408233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
410233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void fill_variance_tree(void *data, BLOCK_SIZE bsize) {
411233d2500723e5594f3e7c70896ffeeef32b9c950ywan  variance_node node;
412233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tree_to_node(data, bsize, &node);
413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum_2_variances(node.split[0], node.split[1], &node.part_variances->horz[0]);
414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum_2_variances(node.split[2], node.split[3], &node.part_variances->horz[1]);
415233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum_2_variances(node.split[0], node.split[2], &node.part_variances->vert[0]);
416233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum_2_variances(node.split[1], node.split[3], &node.part_variances->vert[1]);
417233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum_2_variances(&node.part_variances->vert[0], &node.part_variances->vert[1],
418233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  &node.part_variances->none);
419233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
420233d2500723e5594f3e7c70896ffeeef32b9c950ywan
421233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int set_vt_partitioning(VP9_COMP *cpi,
422233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               void *data,
423233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               const TileInfo *const tile,
424233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               BLOCK_SIZE bsize,
425233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               int mi_row,
426233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               int mi_col,
427233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               int mi_size) {
428233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON * const cm = &cpi->common;
429233d2500723e5594f3e7c70896ffeeef32b9c950ywan  variance_node vt;
430233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int block_width = num_8x8_blocks_wide_lookup[bsize];
431233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int block_height = num_8x8_blocks_high_lookup[bsize];
432233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(debargha): Choose this more intelligently.
433233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64_t threshold_multiplier = 25;
434233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t threshold = threshold_multiplier * cpi->common.base_qindex;
435233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(block_height == block_width);
436233d2500723e5594f3e7c70896ffeeef32b9c950ywan
437233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tree_to_node(data, bsize, &vt);
438233d2500723e5594f3e7c70896ffeeef32b9c950ywan
439233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Split none is available only if we have more than half a block size
440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // in width and height inside the visible image.
441233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_col + block_width / 2 < cm->mi_cols &&
442233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mi_row + block_height / 2 < cm->mi_rows &&
443233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vt.part_variances->none.variance < threshold) {
444233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_block_size(cpi, tile, mi_row, mi_col, bsize);
445233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
446233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
447233d2500723e5594f3e7c70896ffeeef32b9c950ywan
448233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Vertical split is available on all but the bottom border.
449233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_row + block_height / 2 < cm->mi_rows &&
450233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vt.part_variances->vert[0].variance < threshold &&
451233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vt.part_variances->vert[1].variance < threshold) {
452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_VERT);
453233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_block_size(cpi, tile, mi_row, mi_col, subsize);
454233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_block_size(cpi, tile, mi_row, mi_col + block_width / 2, subsize);
455233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
456233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
457233d2500723e5594f3e7c70896ffeeef32b9c950ywan
458233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Horizontal split is available on all but the right border.
459233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_col + block_width / 2 < cm->mi_cols &&
460233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vt.part_variances->horz[0].variance < threshold &&
461233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vt.part_variances->horz[1].variance < threshold) {
462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_HORZ);
463233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_block_size(cpi, tile, mi_row, mi_col, subsize);
464233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_block_size(cpi, tile, mi_row + block_height / 2, mi_col, subsize);
465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
466233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
467233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
468233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
469233d2500723e5594f3e7c70896ffeeef32b9c950ywan
470233d2500723e5594f3e7c70896ffeeef32b9c950ywan// TODO(debargha): Fix this function and make it work as expected.
471233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void choose_partitioning(VP9_COMP *cpi,
472233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                const TileInfo *const tile,
473233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                int mi_row, int mi_col) {
474233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON * const cm = &cpi->common;
475233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *x = &cpi->mb;
476233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *xd = &cpi->mb.e_mbd;
477233d2500723e5594f3e7c70896ffeeef32b9c950ywan
478233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i, j, k;
479233d2500723e5594f3e7c70896ffeeef32b9c950ywan  v64x64 vt;
480233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint8_t *s;
481233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint8_t *d;
482233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int sp;
483233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int dp;
484233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int pixels_wide = 64, pixels_high = 64;
485233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int_mv nearest_mv, near_mv;
486233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
487233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct scale_factors *const sf = &cm->frame_refs[LAST_FRAME - 1].sf;
488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
489233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(vt);
490233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
492233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (xd->mb_to_right_edge < 0)
493233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pixels_wide += (xd->mb_to_right_edge >> 3);
494233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (xd->mb_to_bottom_edge < 0)
495233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pixels_high += (xd->mb_to_bottom_edge >> 3);
496233d2500723e5594f3e7c70896ffeeef32b9c950ywan
497233d2500723e5594f3e7c70896ffeeef32b9c950ywan  s = x->plane[0].src.buf;
498233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sp = x->plane[0].src.stride;
499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
500233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cm->frame_type != KEY_FRAME) {
501233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col, sf);
502233d2500723e5594f3e7c70896ffeeef32b9c950ywan
503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    xd->mi[0]->mbmi.ref_frame[0] = LAST_FRAME;
504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    xd->mi[0]->mbmi.sb_type = BLOCK_64X64;
505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv,
506233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          xd->mi[0]->mbmi.ref_mvs[LAST_FRAME],
507233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          &nearest_mv, &near_mv);
508233d2500723e5594f3e7c70896ffeeef32b9c950ywan
509233d2500723e5594f3e7c70896ffeeef32b9c950ywan    xd->mi[0]->mbmi.mv[0] = nearest_mv;
510233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_build_inter_predictors_sby(xd, mi_row, mi_col, BLOCK_64X64);
511233d2500723e5594f3e7c70896ffeeef32b9c950ywan
512233d2500723e5594f3e7c70896ffeeef32b9c950ywan    d = xd->plane[0].dst.buf;
513233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dp = xd->plane[0].dst.stride;
514233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
515233d2500723e5594f3e7c70896ffeeef32b9c950ywan    d = VP9_VAR_OFFS;
516233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dp = 0;
517233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
518233d2500723e5594f3e7c70896ffeeef32b9c950ywan
519233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Fill in the entire tree of 8x8 variances for splits.
520233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < 4; i++) {
521233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int x32_idx = ((i & 1) << 5);
522233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int y32_idx = ((i >> 1) << 5);
523233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (j = 0; j < 4; j++) {
524233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int x16_idx = x32_idx + ((j & 1) << 4);
525233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int y16_idx = y32_idx + ((j >> 1) << 4);
526233d2500723e5594f3e7c70896ffeeef32b9c950ywan      v16x16 *vst = &vt.split[i].split[j];
527233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (k = 0; k < 4; k++) {
528233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int x_idx = x16_idx + ((k & 1) << 3);
529233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int y_idx = y16_idx + ((k >> 1) << 3);
530233d2500723e5594f3e7c70896ffeeef32b9c950ywan        unsigned int sse = 0;
531233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int sum = 0;
532233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (x_idx < pixels_wide && y_idx < pixels_high)
533233d2500723e5594f3e7c70896ffeeef32b9c950ywan          vp9_get_sse_sum_8x8(s + y_idx * sp + x_idx, sp,
534233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              d + y_idx * dp + x_idx, dp, &sse, &sum);
535233d2500723e5594f3e7c70896ffeeef32b9c950ywan        fill_variance(sse, sum, 64, &vst->split[k].part_variances.none);
536233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
537233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
538233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
539233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Fill the rest of the variance tree by summing split partition values.
540233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < 4; i++) {
541233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (j = 0; j < 4; j++) {
542233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fill_variance_tree(&vt.split[i].split[j], BLOCK_16X16);
543233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
544233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fill_variance_tree(&vt.split[i], BLOCK_32X32);
545233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
546233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fill_variance_tree(&vt, BLOCK_64X64);
547233d2500723e5594f3e7c70896ffeeef32b9c950ywan
548233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Now go through the entire structure,  splitting every block size until
549233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // we get to one that's got a variance lower than our threshold,  or we
550233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // hit 8x8.
551233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!set_vt_partitioning(cpi, &vt, tile, BLOCK_64X64,
552233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           mi_row, mi_col, 8)) {
553233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < 4; ++i) {
554233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int x32_idx = ((i & 1) << 2);
555233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int y32_idx = ((i >> 1) << 2);
556233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!set_vt_partitioning(cpi, &vt.split[i], tile, BLOCK_32X32,
557233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               (mi_row + y32_idx), (mi_col + x32_idx), 4)) {
558233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (j = 0; j < 4; ++j) {
559233d2500723e5594f3e7c70896ffeeef32b9c950ywan          const int x16_idx = ((j & 1) << 1);
560233d2500723e5594f3e7c70896ffeeef32b9c950ywan          const int y16_idx = ((j >> 1) << 1);
561233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // NOTE: This is a temporary hack to disable 8x8 partitions,
562233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // since it works really bad - possibly due to a bug
563233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define DISABLE_8X8_VAR_BASED_PARTITION
564233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef DISABLE_8X8_VAR_BASED_PARTITION
565233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (mi_row + y32_idx + y16_idx + 1 < cm->mi_rows &&
566233d2500723e5594f3e7c70896ffeeef32b9c950ywan              mi_row + x32_idx + x16_idx + 1 < cm->mi_cols) {
567233d2500723e5594f3e7c70896ffeeef32b9c950ywan            set_block_size(cpi, tile,
568233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           (mi_row + y32_idx + y16_idx),
569233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           (mi_col + x32_idx + x16_idx),
570233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           BLOCK_16X16);
571233d2500723e5594f3e7c70896ffeeef32b9c950ywan          } else {
572233d2500723e5594f3e7c70896ffeeef32b9c950ywan            for (k = 0; k < 4; ++k) {
573233d2500723e5594f3e7c70896ffeeef32b9c950ywan              const int x8_idx = (k & 1);
574233d2500723e5594f3e7c70896ffeeef32b9c950ywan              const int y8_idx = (k >> 1);
575233d2500723e5594f3e7c70896ffeeef32b9c950ywan              set_block_size(cpi, tile,
576233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             (mi_row + y32_idx + y16_idx + y8_idx),
577233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             (mi_col + x32_idx + x16_idx + x8_idx),
578233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             BLOCK_8X8);
579233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
580233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
581233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
582233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (!set_vt_partitioning(cpi, &vt.split[i].split[j], tile,
583233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   BLOCK_16X16,
584233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   (mi_row + y32_idx + y16_idx),
585233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   (mi_col + x32_idx + x16_idx), 2)) {
586233d2500723e5594f3e7c70896ffeeef32b9c950ywan            for (k = 0; k < 4; ++k) {
587233d2500723e5594f3e7c70896ffeeef32b9c950ywan              const int x8_idx = (k & 1);
588233d2500723e5594f3e7c70896ffeeef32b9c950ywan              const int y8_idx = (k >> 1);
589233d2500723e5594f3e7c70896ffeeef32b9c950ywan              set_block_size(cpi, tile,
590233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             (mi_row + y32_idx + y16_idx + y8_idx),
591233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             (mi_col + x32_idx + x16_idx + x8_idx),
592233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             BLOCK_8X8);
593233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
594233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
595233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
596233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
597233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
598233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
599233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
600233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
602233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Original activity measure from Tim T's code.
603233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int tt_activity_measure(MACROBLOCK *x) {
604233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int sse;
605233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO: This could also be done over smaller areas (8x8), but that would
606233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // require extensive changes elsewhere, as lambda is assumed to be fixed
607233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // over an entire MB in most of the code.
608233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Another option is to compute four 8x8 variances, and pick a single
609233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // lambda using a non-linear combination (e.g., the smallest, or second
610233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // smallest, etc.).
611233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const unsigned int act = vp9_variance16x16(x->plane[0].src.buf,
612233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             x->plane[0].src.stride,
613233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             VP9_VAR_OFFS, 0, &sse) << 4;
614233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If the region is flat, lower the activity some more.
615233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return act < (8 << 12) ? MIN(act, 5 << 12) : act;
616233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
617233d2500723e5594f3e7c70896ffeeef32b9c950ywan
618233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Stub for alternative experimental activity measures.
619233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int alt_activity_measure(MACROBLOCK *x, int use_dc_pred) {
620233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return vp9_encode_intra(x, use_dc_pred);
621233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
622233d2500723e5594f3e7c70896ffeeef32b9c950ywan
623233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Measure the activity of the current macroblock
624233d2500723e5594f3e7c70896ffeeef32b9c950ywan// What we measure here is TBD so abstracted to this function
625233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ALT_ACT_MEASURE 1
626233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int mb_activity_measure(MACROBLOCK *x, int mb_row, int mb_col) {
627233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int mb_activity;
628233d2500723e5594f3e7c70896ffeeef32b9c950ywan
629233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ALT_ACT_MEASURE) {
630233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
631233d2500723e5594f3e7c70896ffeeef32b9c950ywan
632233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Or use and alternative.
633233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mb_activity = alt_activity_measure(x, use_dc_pred);
634233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
635233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Original activity measure from Tim T's code.
636233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mb_activity = tt_activity_measure(x);
637233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
638233d2500723e5594f3e7c70896ffeeef32b9c950ywan
639233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return MAX(mb_activity, ACTIVITY_AVG_MIN);
640233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
641233d2500723e5594f3e7c70896ffeeef32b9c950ywan
642233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Calculate an "average" mb activity value for the frame
643233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ACT_MEDIAN 0
644233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void calc_av_activity(VP9_COMP *cpi, int64_t activity_sum) {
645233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ACT_MEDIAN
646233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Find median: Simple n^2 algorithm for experimentation
647233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {
648233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int median;
649233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int i, j;
650233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int *sortlist;
651233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int tmp;
652233d2500723e5594f3e7c70896ffeeef32b9c950ywan
653233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Create a list to sort to
654233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CHECK_MEM_ERROR(&cpi->common, sortlist, vpx_calloc(sizeof(unsigned int),
655233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    cpi->common.MBs));
656233d2500723e5594f3e7c70896ffeeef32b9c950ywan
657233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Copy map to sort list
658233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memcpy(sortlist, cpi->mb_activity_map,
659233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sizeof(unsigned int) * cpi->common.MBs);
660233d2500723e5594f3e7c70896ffeeef32b9c950ywan
661233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Ripple each value down to its correct position
662233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 1; i < cpi->common.MBs; i ++) {
663233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (j = i; j > 0; j --) {
664233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (sortlist[j] < sortlist[j - 1]) {
665233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // Swap values
666233d2500723e5594f3e7c70896ffeeef32b9c950ywan          tmp = sortlist[j - 1];
667233d2500723e5594f3e7c70896ffeeef32b9c950ywan          sortlist[j - 1] = sortlist[j];
668233d2500723e5594f3e7c70896ffeeef32b9c950ywan          sortlist[j] = tmp;
669233d2500723e5594f3e7c70896ffeeef32b9c950ywan        } else {
670233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
671233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
672233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
673233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
675233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Even number MBs so estimate median as mean of two either side.
676233d2500723e5594f3e7c70896ffeeef32b9c950ywan    median = (1 + sortlist[cpi->common.MBs >> 1] +
677233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sortlist[(cpi->common.MBs >> 1) + 1]) >> 1;
678233d2500723e5594f3e7c70896ffeeef32b9c950ywan
679233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->activity_avg = median;
680233d2500723e5594f3e7c70896ffeeef32b9c950ywan
681233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_free(sortlist);
682233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
683233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
684233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Simple mean for now
685233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cpi->activity_avg = (unsigned int) (activity_sum / cpi->common.MBs);
686233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif  // ACT_MEDIAN
687233d2500723e5594f3e7c70896ffeeef32b9c950ywan
688233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->activity_avg < ACTIVITY_AVG_MIN)
689233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->activity_avg = ACTIVITY_AVG_MIN;
690233d2500723e5594f3e7c70896ffeeef32b9c950ywan
691233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Experimental code: return fixed value normalized for several clips
692233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ALT_ACT_MEASURE)
693233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->activity_avg = 100000;
694233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
695233d2500723e5594f3e7c70896ffeeef32b9c950ywan
696233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define USE_ACT_INDEX   0
697233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define OUTPUT_NORM_ACT_STATS   0
698233d2500723e5594f3e7c70896ffeeef32b9c950ywan
699233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if USE_ACT_INDEX
700233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Calculate an activity index for each mb
701233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void calc_activity_index(VP9_COMP *cpi, MACROBLOCK *x) {
702233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
703233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mb_row, mb_col;
704233d2500723e5594f3e7c70896ffeeef32b9c950ywan
705233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t act;
706233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t a;
707233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t b;
708233d2500723e5594f3e7c70896ffeeef32b9c950ywan
709233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if OUTPUT_NORM_ACT_STATS
710233d2500723e5594f3e7c70896ffeeef32b9c950ywan  FILE *f = fopen("norm_act.stt", "a");
711233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(f, "\n%12d\n", cpi->activity_avg);
712233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
714233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Reset pointers to start of activity map
715233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->mb_activity_ptr = cpi->mb_activity_map;
716233d2500723e5594f3e7c70896ffeeef32b9c950ywan
717233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Calculate normalized mb activity number.
718233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
719233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // for each macroblock col in image
720233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
721233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Read activity from the map
722233d2500723e5594f3e7c70896ffeeef32b9c950ywan      act = *(x->mb_activity_ptr);
723233d2500723e5594f3e7c70896ffeeef32b9c950ywan
724233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Calculate a normalized activity number
725233d2500723e5594f3e7c70896ffeeef32b9c950ywan      a = act + 4 * cpi->activity_avg;
726233d2500723e5594f3e7c70896ffeeef32b9c950ywan      b = 4 * act + cpi->activity_avg;
727233d2500723e5594f3e7c70896ffeeef32b9c950ywan
728233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (b >= a)
729233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(x->activity_ptr) = (int)((b + (a >> 1)) / a) - 1;
730233d2500723e5594f3e7c70896ffeeef32b9c950ywan      else
731233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(x->activity_ptr) = 1 - (int)((a + (b >> 1)) / b);
732233d2500723e5594f3e7c70896ffeeef32b9c950ywan
733233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if OUTPUT_NORM_ACT_STATS
734233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fprintf(f, " %6d", *(x->mb_activity_ptr));
735233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
736233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Increment activity map pointers
737233d2500723e5594f3e7c70896ffeeef32b9c950ywan      x->mb_activity_ptr++;
738233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
739233d2500723e5594f3e7c70896ffeeef32b9c950ywan
740233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if OUTPUT_NORM_ACT_STATS
741233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(f, "\n");
742233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
743233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
744233d2500723e5594f3e7c70896ffeeef32b9c950ywan
745233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if OUTPUT_NORM_ACT_STATS
746233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fclose(f);
747233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
748233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
749233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif  // USE_ACT_INDEX
750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
751233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Loop through all MBs. Note activity of each, average activity and
752233d2500723e5594f3e7c70896ffeeef32b9c950ywan// calculate a normalized activity for each
753233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void build_activity_map(VP9_COMP *cpi) {
754233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
755233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *xd = &x->e_mbd;
756233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
757233d2500723e5594f3e7c70896ffeeef32b9c950ywan
758233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ALT_ACT_MEASURE
759233d2500723e5594f3e7c70896ffeeef32b9c950ywan  YV12_BUFFER_CONFIG *new_yv12 = get_frame_new_buffer(cm);
760233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int recon_yoffset;
761233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int recon_y_stride = new_yv12->y_stride;
762233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
763233d2500723e5594f3e7c70896ffeeef32b9c950ywan
764233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mb_row, mb_col;
765233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int mb_activity;
766233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t activity_sum = 0;
767233d2500723e5594f3e7c70896ffeeef32b9c950ywan
768233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->mb_activity_ptr = cpi->mb_activity_map;
769233d2500723e5594f3e7c70896ffeeef32b9c950ywan
770233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // for each macroblock row in image
771233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
772233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ALT_ACT_MEASURE
773233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // reset above block coeffs
774233d2500723e5594f3e7c70896ffeeef32b9c950ywan    xd->up_available = (mb_row != 0);
775233d2500723e5594f3e7c70896ffeeef32b9c950ywan    recon_yoffset = (mb_row * recon_y_stride * 16);
776233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
777233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // for each macroblock col in image
778233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
779233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ALT_ACT_MEASURE
780233d2500723e5594f3e7c70896ffeeef32b9c950ywan      xd->plane[0].dst.buf = new_yv12->y_buffer + recon_yoffset;
781233d2500723e5594f3e7c70896ffeeef32b9c950ywan      xd->left_available = (mb_col != 0);
782233d2500723e5594f3e7c70896ffeeef32b9c950ywan      recon_yoffset += 16;
783233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
784233d2500723e5594f3e7c70896ffeeef32b9c950ywan
785233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // measure activity
786233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mb_activity = mb_activity_measure(x, mb_row, mb_col);
787233d2500723e5594f3e7c70896ffeeef32b9c950ywan
788233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Keep frame sum
789233d2500723e5594f3e7c70896ffeeef32b9c950ywan      activity_sum += mb_activity;
790233d2500723e5594f3e7c70896ffeeef32b9c950ywan
791233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Store MB level activity details.
792233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *x->mb_activity_ptr = mb_activity;
793233d2500723e5594f3e7c70896ffeeef32b9c950ywan
794233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Increment activity map pointer
795233d2500723e5594f3e7c70896ffeeef32b9c950ywan      x->mb_activity_ptr++;
796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
797233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // adjust to the next column of source macroblocks
798233d2500723e5594f3e7c70896ffeeef32b9c950ywan      x->plane[0].src.buf += 16;
799233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
800233d2500723e5594f3e7c70896ffeeef32b9c950ywan
801233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // adjust to the next row of mbs
802233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->plane[0].src.buf += 16 * x->plane[0].src.stride - 16 * cm->mb_cols;
803233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
804233d2500723e5594f3e7c70896ffeeef32b9c950ywan
805233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Calculate an "average" MB activity
806233d2500723e5594f3e7c70896ffeeef32b9c950ywan  calc_av_activity(cpi, activity_sum);
807233d2500723e5594f3e7c70896ffeeef32b9c950ywan
808233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if USE_ACT_INDEX
809233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Calculate an activity index number of each mb
810233d2500723e5594f3e7c70896ffeeef32b9c950ywan  calc_activity_index(cpi, x);
811233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
812233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
813233d2500723e5594f3e7c70896ffeeef32b9c950ywan
814233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Macroblock activity masking
815233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void activity_masking(VP9_COMP *cpi, MACROBLOCK *x) {
816233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if USE_ACT_INDEX
817233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2);
818233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);
819233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->errorperbit += (x->errorperbit == 0);
820233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
821233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64_t act = *(x->mb_activity_ptr);
822233d2500723e5594f3e7c70896ffeeef32b9c950ywan
823233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Apply the masking to the RD multiplier.
824233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64_t a = act + (2 * cpi->activity_avg);
825233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64_t b = (2 * act) + cpi->activity_avg;
826233d2500723e5594f3e7c70896ffeeef32b9c950ywan
827233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->rdmult = (unsigned int) (((int64_t) x->rdmult * b + (a >> 1)) / a);
828233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);
829233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->errorperbit += (x->errorperbit == 0);
830233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
831233d2500723e5594f3e7c70896ffeeef32b9c950ywan
832233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Activity based Zbin adjustment
833233d2500723e5594f3e7c70896ffeeef32b9c950ywan  adjust_act_zbin(cpi, x);
834233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
835233d2500723e5594f3e7c70896ffeeef32b9c950ywan
836233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
837233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         int mi_row, int mi_col, BLOCK_SIZE bsize,
838233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         int output_enabled) {
839233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i, x_idx, y;
840233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
841233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
842233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
843233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct macroblock_plane *const p = x->plane;
844233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct macroblockd_plane *const pd = xd->plane;
845233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO *mi = &ctx->mic;
846233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
847233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO *mi_addr = xd->mi[0];
848233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct segmentation *const seg = &cm->seg;
849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
850233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
851233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_width = num_8x8_blocks_wide_lookup[bsize];
852233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_height = num_8x8_blocks_high_lookup[bsize];
853233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int max_plane;
854233d2500723e5594f3e7c70896ffeeef32b9c950ywan
855233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(mi->mbmi.sb_type == bsize);
856233d2500723e5594f3e7c70896ffeeef32b9c950ywan
857233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *mi_addr = *mi;
858233d2500723e5594f3e7c70896ffeeef32b9c950ywan
859233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If segmentation in use
860233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (seg->enabled && output_enabled) {
861233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // For in frame complexity AQ copy the segment id from the segment map.
862233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
863233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const uint8_t *const map = seg->update_map ? cpi->segmentation_map
864233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                 : cm->last_frame_seg_map;
865233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mi_addr->mbmi.segment_id =
866233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
867233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
868233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Else for cyclic refresh mode update the segment map, set the segment id
869233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // and then update the quantizer.
870233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
871233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_cyclic_refresh_update_segment(cpi, &xd->mi[0]->mbmi,
872233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        mi_row, mi_col, bsize, 1);
873233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_init_plane_quantizers(cpi, x);
874233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
875233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
876233d2500723e5594f3e7c70896ffeeef32b9c950ywan
877233d2500723e5594f3e7c70896ffeeef32b9c950ywan  max_plane = is_inter_block(mbmi) ? MAX_MB_PLANE : 1;
878233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < max_plane; ++i) {
879233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].coeff = ctx->coeff_pbuf[i][1];
880233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].qcoeff = ctx->qcoeff_pbuf[i][1];
881233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][1];
882233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].eobs = ctx->eobs_pbuf[i][1];
883233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
884233d2500723e5594f3e7c70896ffeeef32b9c950ywan
885233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = max_plane; i < MAX_MB_PLANE; ++i) {
886233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].coeff = ctx->coeff_pbuf[i][2];
887233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].qcoeff = ctx->qcoeff_pbuf[i][2];
888233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][2];
889233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].eobs = ctx->eobs_pbuf[i][2];
890233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
891233d2500723e5594f3e7c70896ffeeef32b9c950ywan
892233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Restore the coding context of the MB to that that was in place
893233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // when the mode was picked for it
894233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (y = 0; y < mi_height; y++)
895233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (x_idx = 0; x_idx < mi_width; x_idx++)
896233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width > x_idx
897233d2500723e5594f3e7c70896ffeeef32b9c950ywan        && (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > y) {
898233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->mi[x_idx + y * mis] = mi_addr;
899233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
900233d2500723e5594f3e7c70896ffeeef32b9c950ywan
901233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->oxcf.aq_mode)
902233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_init_plane_quantizers(cpi, x);
903233d2500723e5594f3e7c70896ffeeef32b9c950ywan
904233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // FIXME(rbultje) I'm pretty sure this should go to the end of this block
905233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // (i.e. after the output_enabled)
906233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_32X32) {
907233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (bsize < BLOCK_16X16)
908233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ctx->tx_rd_diff[ALLOW_16X16] = ctx->tx_rd_diff[ALLOW_8X8];
909233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->tx_rd_diff[ALLOW_32X32] = ctx->tx_rd_diff[ALLOW_16X16];
910233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
911233d2500723e5594f3e7c70896ffeeef32b9c950ywan
912233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (is_inter_block(mbmi) && mbmi->sb_type < BLOCK_8X8) {
913233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
914233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
915233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
917233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->skip = ctx->skip;
918233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memcpy(x->zcoeff_blk[mbmi->tx_size], ctx->zcoeff_blk,
919233d2500723e5594f3e7c70896ffeeef32b9c950ywan             sizeof(uint8_t) * ctx->num_4x4_blk);
920233d2500723e5594f3e7c70896ffeeef32b9c950ywan
921233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!output_enabled)
922233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
923233d2500723e5594f3e7c70896ffeeef32b9c950ywan
924233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
925233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < TX_MODES; i++)
926233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->rd_tx_select_diff[i] += ctx->tx_rd_diff[i];
927233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
928233d2500723e5594f3e7c70896ffeeef32b9c950ywan
929233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_INTERNAL_STATS
930233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame_is_intra_only(cm)) {
931233d2500723e5594f3e7c70896ffeeef32b9c950ywan    static const int kf_mode_index[] = {
932233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_DC        /*DC_PRED*/,
933233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_V_PRED    /*V_PRED*/,
934233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_H_PRED    /*H_PRED*/,
935233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_D45_PRED  /*D45_PRED*/,
936233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_D135_PRED /*D135_PRED*/,
937233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_D117_PRED /*D117_PRED*/,
938233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_D153_PRED /*D153_PRED*/,
939233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_D207_PRED /*D207_PRED*/,
940233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_D63_PRED  /*D63_PRED*/,
941233d2500723e5594f3e7c70896ffeeef32b9c950ywan      THR_TM        /*TM_PRED*/,
942233d2500723e5594f3e7c70896ffeeef32b9c950ywan    };
943233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++cpi->mode_chosen_counts[kf_mode_index[mbmi->mode]];
944233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
945233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Note how often each mode chosen as best
946233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++cpi->mode_chosen_counts[ctx->best_mode_index];
947233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
948233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
949233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!frame_is_intra_only(cm)) {
950233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (is_inter_block(mbmi)) {
951233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_update_mv_count(cm, xd);
952233d2500723e5594f3e7c70896ffeeef32b9c950ywan
953233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cm->interp_filter == SWITCHABLE) {
954233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int ctx = vp9_get_pred_context_switchable_interp(xd);
955233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
956233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
957233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
958233d2500723e5594f3e7c70896ffeeef32b9c950ywan
959233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->rd_comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
960233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->rd_comp_pred_diff[COMPOUND_REFERENCE] += ctx->comp_pred_diff;
961233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->rd_comp_pred_diff[REFERENCE_MODE_SELECT] += ctx->hybrid_pred_diff;
962233d2500723e5594f3e7c70896ffeeef32b9c950ywan
963233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
964233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->rd_filter_diff[i] += ctx->best_filter_diff[i];
965233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
966233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
968233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
969233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          int mi_row, int mi_col) {
970233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint8_t *const buffers[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
971233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               src->alpha_buffer};
972233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
973233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          src->alpha_stride};
974233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i;
975233d2500723e5594f3e7c70896ffeeef32b9c950ywan
976233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Set current frame pointer.
977233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->e_mbd.cur_buf = src;
978233d2500723e5594f3e7c70896ffeeef32b9c950ywan
979233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < MAX_MB_PLANE; i++)
980233d2500723e5594f3e7c70896ffeeef32b9c950ywan    setup_pred_plane(&x->plane[i].src, buffers[i], strides[i], mi_row, mi_col,
981233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     NULL, x->e_mbd.plane[i].subsampling_x,
982233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     x->e_mbd.plane[i].subsampling_y);
983233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
984233d2500723e5594f3e7c70896ffeeef32b9c950ywan
985233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
986233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             int mi_row, int mi_col,
987233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             int *totalrate, int64_t *totaldist,
988233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
989233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             int64_t best_rd) {
990233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
991233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
992233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
993233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MB_MODE_INFO *mbmi;
994233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct macroblock_plane *const p = x->plane;
995233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct macroblockd_plane *const pd = xd->plane;
996233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const AQ_MODE aq_mode = cpi->oxcf.aq_mode;
997233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i, orig_rdmult;
998233d2500723e5594f3e7c70896ffeeef32b9c950ywan  double rdmult_ratio;
999233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1000233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_clear_system_state();
1001233d2500723e5594f3e7c70896ffeeef32b9c950ywan  rdmult_ratio = 1.0;  // avoid uninitialized warnings
1002233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1003233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Use the lower precision, but faster, 32x32 fdct for mode selection.
1004233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->use_lp32x32fdct = 1;
1005233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1006233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_8X8) {
1007233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
1008233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // there is nothing to be done.
1009233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (x->ab_index != 0) {
1010233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *totalrate = 0;
1011233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *totaldist = 0;
1012233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
1013233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1014233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1015233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1016233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_offsets(cpi, tile, mi_row, mi_col, bsize);
1017233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi = &xd->mi[0]->mbmi;
1018233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->sb_type = bsize;
1019233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1020233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < MAX_MB_PLANE; ++i) {
1021233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].coeff = ctx->coeff_pbuf[i][0];
1022233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].qcoeff = ctx->qcoeff_pbuf[i][0];
1023233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][0];
1024233d2500723e5594f3e7c70896ffeeef32b9c950ywan    p[i].eobs = ctx->eobs_pbuf[i][0];
1025233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1026233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->is_coded = 0;
1027233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->skip_recode = 0;
1028233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1029233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Set to zero to make sure we do not use the previous encoded frame stats
1030233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->skip = 0;
1031233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1032233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->source_variance = get_sby_perpixel_variance(cpi, x, bsize);
1033233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1034233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (aq_mode == VARIANCE_AQ) {
1035233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int energy = bsize <= BLOCK_16X16 ? x->mb_energy
1036233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            : vp9_block_energy(cpi, x, bsize);
1037233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1038233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->frame_type == KEY_FRAME ||
1039233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cpi->refresh_alt_ref_frame ||
1040233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
1041233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mbmi->segment_id = vp9_vaq_segment_id(energy);
1042233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
1043233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const uint8_t *const map = cm->seg.update_map ? cpi->segmentation_map
1044233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    : cm->last_frame_seg_map;
1045233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mbmi->segment_id = vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
1046233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1047233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1048233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rdmult_ratio = vp9_vaq_rdmult_ratio(energy);
1049233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_init_plane_quantizers(cpi, x);
1050233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1051233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1052233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Save rdmult before it might be changed, so it can be restored later.
1053233d2500723e5594f3e7c70896ffeeef32b9c950ywan  orig_rdmult = x->rdmult;
1054233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
1055233d2500723e5594f3e7c70896ffeeef32b9c950ywan    activity_masking(cpi, x);
1056233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1057233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (aq_mode == VARIANCE_AQ) {
1058233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_clear_system_state();
1059233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->rdmult = (int)round(x->rdmult * rdmult_ratio);
1060233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (aq_mode == COMPLEXITY_AQ) {
1061233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int mi_offset = mi_row * cm->mi_cols + mi_col;
1062233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char complexity = cpi->complexity_map[mi_offset];
1063233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int is_edge = (mi_row <= 1) || (mi_row >= (cm->mi_rows - 2)) ||
1064233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (mi_col <= 1) || (mi_col >= (cm->mi_cols - 2));
1065233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!is_edge && (complexity > 128))
1066233d2500723e5594f3e7c70896ffeeef32b9c950ywan      x->rdmult += ((x->rdmult * (complexity - 128)) / 256);
1067233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
1068233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint8_t *const map = cm->seg.update_map ? cpi->segmentation_map
1069233d2500723e5594f3e7c70896ffeeef32b9c950ywan        : cm->last_frame_seg_map;
1070233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // If segment 1, use rdmult for that segment.
1071233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (vp9_get_segment_id(cm, map, bsize, mi_row, mi_col))
1072233d2500723e5594f3e7c70896ffeeef32b9c950ywan      x->rdmult = vp9_cyclic_refresh_get_rdmult(cpi->cyclic_refresh);
1073233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1074233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1075233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Find best coding mode & reconstruct the MB so it is available
1076233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // as a predictor for MBs that follow in the SB
1077233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame_is_intra_only(cm)) {
1078233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_rd_pick_intra_mode_sb(cpi, x, totalrate, totaldist, bsize, ctx,
1079233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              best_rd);
1080233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1081233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (bsize >= BLOCK_8X8)
1082233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_rd_pick_inter_mode_sb(cpi, x, tile, mi_row, mi_col,
1083233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                totalrate, totaldist, bsize, ctx, best_rd);
1084233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
1085233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_rd_pick_inter_mode_sub8x8(cpi, x, tile, mi_row, mi_col, totalrate,
1086233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    totaldist, bsize, ctx, best_rd);
1087233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1088233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1089233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (aq_mode == VARIANCE_AQ) {
1090233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->rdmult = orig_rdmult;
1091233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (*totalrate != INT_MAX) {
1092233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_clear_system_state();
1093233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *totalrate = (int)round(*totalrate * rdmult_ratio);
1094233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1095233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) ||
1096233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)) {
1097233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->rdmult = orig_rdmult;
1098233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1099233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1100233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1101233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void update_stats(VP9_COMP *cpi) {
1102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
1103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MACROBLOCK *const x = &cpi->mb;
1104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MACROBLOCKD *const xd = &x->e_mbd;
1105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MODE_INFO *const mi = xd->mi[0];
1106233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MB_MODE_INFO *const mbmi = &mi->mbmi;
1107233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!frame_is_intra_only(cm)) {
1109233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int seg_ref_active = vp9_segfeature_active(&cm->seg, mbmi->segment_id,
1110233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                     SEG_LVL_REF_FRAME);
1111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!seg_ref_active) {
1112233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FRAME_COUNTS *const counts = &cm->counts;
1113233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int inter_block = is_inter_block(mbmi);
1114233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1115233d2500723e5594f3e7c70896ffeeef32b9c950ywan      counts->intra_inter[vp9_get_intra_inter_context(xd)][inter_block]++;
1116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1117233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // If the segment reference feature is enabled we have only a single
1118233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // reference frame allowed for the segment so exclude it from
1119233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // the reference frame counts used to work out probabilities.
1120233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (inter_block) {
1121233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const MV_REFERENCE_FRAME ref0 = mbmi->ref_frame[0];
1122233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1123233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (cm->reference_mode == REFERENCE_MODE_SELECT)
1124233d2500723e5594f3e7c70896ffeeef32b9c950ywan          counts->comp_inter[vp9_get_reference_mode_context(cm, xd)]
1125233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            [has_second_ref(mbmi)]++;
1126233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1127233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (has_second_ref(mbmi)) {
1128233d2500723e5594f3e7c70896ffeeef32b9c950ywan          counts->comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)]
1129233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          [ref0 == GOLDEN_FRAME]++;
1130233d2500723e5594f3e7c70896ffeeef32b9c950ywan        } else {
1131233d2500723e5594f3e7c70896ffeeef32b9c950ywan          counts->single_ref[vp9_get_pred_context_single_ref_p1(xd)][0]
1132233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            [ref0 != LAST_FRAME]++;
1133233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (ref0 != LAST_FRAME)
1134233d2500723e5594f3e7c70896ffeeef32b9c950ywan            counts->single_ref[vp9_get_pred_context_single_ref_p2(xd)][1]
1135233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              [ref0 != GOLDEN_FRAME]++;
1136233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1137233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1138233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1140233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1141233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1142233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic BLOCK_SIZE *get_sb_partitioning(MACROBLOCK *x, BLOCK_SIZE bsize) {
1143233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (bsize) {
1144233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_64X64:
1145233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->sb64_partitioning;
1146233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_32X32:
1147233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->sb_partitioning[x->sb_index];
1148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_16X16:
1149233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->mb_partitioning[x->sb_index][x->mb_index];
1150233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case BLOCK_8X8:
1151233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return &x->b_partitioning[x->sb_index][x->mb_index][x->b_index];
1152233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default:
1153233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(0);
1154233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return NULL;
1155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1156233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1157233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1158233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void restore_context(VP9_COMP *cpi, int mi_row, int mi_col,
1159233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            ENTROPY_CONTEXT a[16 * MAX_MB_PLANE],
1160233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            ENTROPY_CONTEXT l[16 * MAX_MB_PLANE],
1161233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8],
1162233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            BLOCK_SIZE bsize) {
1163233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
1164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
1165233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int p;
1166233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
1167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
1168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_width = num_8x8_blocks_wide_lookup[bsize];
1169233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_height = num_8x8_blocks_high_lookup[bsize];
1170233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (p = 0; p < MAX_MB_PLANE; p++) {
1171233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memcpy(
1172233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->above_context[p] + ((mi_col * 2) >> xd->plane[p].subsampling_x),
1173233d2500723e5594f3e7c70896ffeeef32b9c950ywan        a + num_4x4_blocks_wide * p,
1174233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
1175233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->plane[p].subsampling_x);
1176233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memcpy(
1177233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->left_context[p]
1178233d2500723e5594f3e7c70896ffeeef32b9c950ywan            + ((mi_row & MI_MASK) * 2 >> xd->plane[p].subsampling_y),
1179233d2500723e5594f3e7c70896ffeeef32b9c950ywan        l + num_4x4_blocks_high * p,
1180233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
1181233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->plane[p].subsampling_y);
1182233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1183233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memcpy(xd->above_seg_context + mi_col, sa,
1184233d2500723e5594f3e7c70896ffeeef32b9c950ywan             sizeof(*xd->above_seg_context) * mi_width);
1185233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memcpy(xd->left_seg_context + (mi_row & MI_MASK), sl,
1186233d2500723e5594f3e7c70896ffeeef32b9c950ywan             sizeof(xd->left_seg_context[0]) * mi_height);
1187233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1188233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void save_context(VP9_COMP *cpi, int mi_row, int mi_col,
1189233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         ENTROPY_CONTEXT a[16 * MAX_MB_PLANE],
1190233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         ENTROPY_CONTEXT l[16 * MAX_MB_PLANE],
1191233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8],
1192233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         BLOCK_SIZE bsize) {
1193233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MACROBLOCK *const x = &cpi->mb;
1194233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MACROBLOCKD *const xd = &x->e_mbd;
1195233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int p;
1196233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
1197233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
1198233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_width = num_8x8_blocks_wide_lookup[bsize];
1199233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_height = num_8x8_blocks_high_lookup[bsize];
1200233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1201233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // buffer the above/left context information of the block in search.
1202233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (p = 0; p < MAX_MB_PLANE; ++p) {
1203233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memcpy(
1204233d2500723e5594f3e7c70896ffeeef32b9c950ywan        a + num_4x4_blocks_wide * p,
1205233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->above_context[p] + (mi_col * 2 >> xd->plane[p].subsampling_x),
1206233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
1207233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->plane[p].subsampling_x);
1208233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memcpy(
1209233d2500723e5594f3e7c70896ffeeef32b9c950ywan        l + num_4x4_blocks_high * p,
1210233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->left_context[p]
1211233d2500723e5594f3e7c70896ffeeef32b9c950ywan            + ((mi_row & MI_MASK) * 2 >> xd->plane[p].subsampling_y),
1212233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
1213233d2500723e5594f3e7c70896ffeeef32b9c950ywan        xd->plane[p].subsampling_y);
1214233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memcpy(sa, xd->above_seg_context + mi_col,
1216233d2500723e5594f3e7c70896ffeeef32b9c950ywan             sizeof(*xd->above_seg_context) * mi_width);
1217233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memcpy(sl, xd->left_seg_context + (mi_row & MI_MASK),
1218233d2500723e5594f3e7c70896ffeeef32b9c950ywan             sizeof(xd->left_seg_context[0]) * mi_height);
1219233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1220233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1221233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_b(VP9_COMP *cpi, const TileInfo *const tile,
1222233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     TOKENEXTRA **tp, int mi_row, int mi_col,
1223233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     int output_enabled, BLOCK_SIZE bsize) {
1224233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
1225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1226233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_8X8) {
1227233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
1228233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // there is nothing to be done.
1229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (x->ab_index > 0)
1230233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
1231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1232233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_offsets(cpi, tile, mi_row, mi_col, bsize);
1233233d2500723e5594f3e7c70896ffeeef32b9c950ywan  update_state(cpi, get_block_context(x, bsize), mi_row, mi_col, bsize,
1234233d2500723e5594f3e7c70896ffeeef32b9c950ywan               output_enabled);
1235233d2500723e5594f3e7c70896ffeeef32b9c950ywan  encode_superblock(cpi, tp, output_enabled, mi_row, mi_col, bsize);
1236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1237233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (output_enabled) {
1238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    update_stats(cpi);
1239233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1240233d2500723e5594f3e7c70896ffeeef32b9c950ywan    (*tp)->token = EOSB_TOKEN;
1241233d2500723e5594f3e7c70896ffeeef32b9c950ywan    (*tp)++;
1242233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1243233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1244233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1245233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_sb(VP9_COMP *cpi, const TileInfo *const tile,
1246233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      TOKENEXTRA **tp, int mi_row, int mi_col,
1247233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      int output_enabled, BLOCK_SIZE bsize) {
1248233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
1249233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
1250233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
1251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1252233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
1253233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int ctx;
1254233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PARTITION_TYPE partition;
1255233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE subsize;
1256233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1257233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
1258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1259233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1260233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize >= BLOCK_8X8) {
1261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
1262233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = *get_sb_partitioning(x, bsize);
1263233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx = 0;
1265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = BLOCK_4X4;
1266233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1267233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1268233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition = partition_lookup[bsl][subsize];
1269233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1270233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (partition) {
1271233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_NONE:
1272233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled && bsize >= BLOCK_8X8)
1273233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_NONE]++;
1274233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1275233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_VERT:
1277233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled)
1278233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_VERT]++;
1279233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1280233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1281233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_col + hbs < cm->mi_cols) {
1282233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
1283233d2500723e5594f3e7c70896ffeeef32b9c950ywan        encode_b(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize);
1284233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1285233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_HORZ:
1287233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled)
1288233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_HORZ]++;
1289233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1290233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1291233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_row + hbs < cm->mi_rows) {
1292233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
1293233d2500723e5594f3e7c70896ffeeef32b9c950ywan        encode_b(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize);
1294233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1295233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1296233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_SPLIT:
1297233d2500723e5594f3e7c70896ffeeef32b9c950ywan      subsize = get_subsize(bsize, PARTITION_SPLIT);
1298233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled)
1299233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_SPLIT]++;
1300233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1301233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1302233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1303233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
1304233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize);
1305233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 2;
1306233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize);
1307233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 3;
1308233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
1309233d2500723e5594f3e7c70896ffeeef32b9c950ywan                subsize);
1310233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1311233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default:
1312233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert("Invalid partition type.");
1313233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1314233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1315233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
1316233d2500723e5594f3e7c70896ffeeef32b9c950ywan    update_partition_context(xd, mi_row, mi_col, subsize, bsize);
1317233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1318233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1319233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Check to see if the given partition size is allowed for a specified number
1320233d2500723e5594f3e7c70896ffeeef32b9c950ywan// of 8x8 block rows and columns remaining in the image.
1321233d2500723e5594f3e7c70896ffeeef32b9c950ywan// If not then return the largest allowed partition size
1322233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic BLOCK_SIZE find_partition_size(BLOCK_SIZE bsize,
1323233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      int rows_left, int cols_left,
1324233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      int *bh, int *bw) {
1325233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rows_left <= 0 || cols_left <= 0) {
1326233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return MIN(bsize, BLOCK_8X8);
1327233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (; bsize > 0; bsize -= 3) {
1329233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *bh = num_8x8_blocks_high_lookup[bsize];
1330233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *bw = num_8x8_blocks_wide_lookup[bsize];
1331233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if ((*bh <= rows_left) && (*bw <= cols_left)) {
1332233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1333233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1334233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1335233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1336233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return bsize;
1337233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1338233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1339233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This function attempts to set all mode info entries in a given SB64
1340233d2500723e5594f3e7c70896ffeeef32b9c950ywan// to the same block partition size.
1341233d2500723e5594f3e7c70896ffeeef32b9c950ywan// However, at the bottom and right borders of the image the requested size
1342233d2500723e5594f3e7c70896ffeeef32b9c950ywan// may not be allowed in which case this code attempts to choose the largest
1343233d2500723e5594f3e7c70896ffeeef32b9c950ywan// allowable partition.
1344233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_fixed_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
1345233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   MODE_INFO **mi_8x8, int mi_row, int mi_col,
1346233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   BLOCK_SIZE bsize) {
1347233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
1348233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
1349233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int row8x8_remaining = tile->mi_row_end - mi_row;
1350233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int col8x8_remaining = tile->mi_col_end - mi_col;
1351233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int block_row, block_col;
1352233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO *mi_upper_left = cm->mi + mi_row * mis + mi_col;
1353233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int bh = num_8x8_blocks_high_lookup[bsize];
1354233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int bw = num_8x8_blocks_wide_lookup[bsize];
1355233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1356233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert((row8x8_remaining > 0) && (col8x8_remaining > 0));
1357233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1358233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Apply the requested partition size to the SB64 if it is all "in image"
1359233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if ((col8x8_remaining >= MI_BLOCK_SIZE) &&
1360233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (row8x8_remaining >= MI_BLOCK_SIZE)) {
1361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (block_row = 0; block_row < MI_BLOCK_SIZE; block_row += bh) {
1362233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (block_col = 0; block_col < MI_BLOCK_SIZE; block_col += bw) {
1363233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int index = block_row * mis + block_col;
1364233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_8x8[index] = mi_upper_left + index;
1365233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_8x8[index]->mbmi.sb_type = bsize;
1366233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1367233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1368233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1369233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Else this is a partial SB64.
1370233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (block_row = 0; block_row < MI_BLOCK_SIZE; block_row += bh) {
1371233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (block_col = 0; block_col < MI_BLOCK_SIZE; block_col += bw) {
1372233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int index = block_row * mis + block_col;
1373233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // Find a partition size that fits
1374233d2500723e5594f3e7c70896ffeeef32b9c950ywan        bsize = find_partition_size(bsize,
1375233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    (row8x8_remaining - block_row),
1376233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    (col8x8_remaining - block_col), &bh, &bw);
1377233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_8x8[index] = mi_upper_left + index;
1378233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_8x8[index]->mbmi.sb_type = bsize;
1379233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1380233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1381233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1382233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1383233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1384233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void copy_partitioning(VP9_COMMON *cm, MODE_INFO **mi_8x8,
1385233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              MODE_INFO **prev_mi_8x8) {
1386233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
1387233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int block_row, block_col;
1388233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1389233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (block_row = 0; block_row < 8; ++block_row) {
1390233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (block_col = 0; block_col < 8; ++block_col) {
1391233d2500723e5594f3e7c70896ffeeef32b9c950ywan      MODE_INFO *const prev_mi = prev_mi_8x8[block_row * mis + block_col];
1392233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const BLOCK_SIZE sb_type = prev_mi ? prev_mi->mbmi.sb_type : 0;
1393233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1394233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (prev_mi) {
1395233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const ptrdiff_t offset = prev_mi - cm->prev_mi;
1396233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_8x8[block_row * mis + block_col] = cm->mi + offset;
1397233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_8x8[block_row * mis + block_col]->mbmi.sb_type = sb_type;
1398233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1399233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1400233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1401233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1402233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1403233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int sb_has_motion(const VP9_COMMON *cm, MODE_INFO **prev_mi_8x8) {
1404233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
1405233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int block_row, block_col;
1406233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1407233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cm->prev_mi) {
1408233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (block_row = 0; block_row < 8; ++block_row) {
1409233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (block_col = 0; block_col < 8; ++block_col) {
1410233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const MODE_INFO *prev_mi = prev_mi_8x8[block_row * mis + block_col];
1411233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (prev_mi) {
1412233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (abs(prev_mi->mbmi.mv[0].as_mv.row) >= 8 ||
1413233d2500723e5594f3e7c70896ffeeef32b9c950ywan              abs(prev_mi->mbmi.mv[0].as_mv.col) >= 8)
1414233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;
1415233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1416233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1417233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1419233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1420233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1421233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1422233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void update_state_rt(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
1423233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            int mi_row, int mi_col, int bsize) {
1424233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
1425233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
1426233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
1427233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
1428233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct segmentation *const seg = &cm->seg;
1429233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1430233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *(xd->mi[0]) = ctx->mic;
1431233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1432233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // For in frame adaptive Q, check for reseting the segment_id and updating
1433233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // the cyclic refresh map.
1434233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if ((cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) && seg->enabled) {
1435233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_cyclic_refresh_update_segment(cpi, &xd->mi[0]->mbmi,
1436233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      mi_row, mi_col, bsize, 1);
1437233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_init_plane_quantizers(cpi, x);
1438233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1439233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (is_inter_block(mbmi)) {
1441233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_update_mv_count(cm, xd);
1442233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->interp_filter == SWITCHABLE) {
1444233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int pred_ctx = vp9_get_pred_context_switchable_interp(xd);
1445233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++cm->counts.switchable_interp[pred_ctx][mbmi->interp_filter];
1446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1447233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1448233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1449233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->skip = ctx->skip;
1450233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1451233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1452233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_b_rt(VP9_COMP *cpi, const TileInfo *const tile,
1453233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        TOKENEXTRA **tp, int mi_row, int mi_col,
1454233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        int output_enabled, BLOCK_SIZE bsize) {
1455233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
1456233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1457233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_8X8) {
1458233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
1459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // there is nothing to be done.
1460233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (x->ab_index > 0)
1461233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
1462233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1463233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1464233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_offsets(cpi, tile, mi_row, mi_col, bsize);
1465233d2500723e5594f3e7c70896ffeeef32b9c950ywan  update_state_rt(cpi, get_block_context(x, bsize), mi_row, mi_col, bsize);
1466233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1467233d2500723e5594f3e7c70896ffeeef32b9c950ywan  encode_superblock(cpi, tp, output_enabled, mi_row, mi_col, bsize);
1468233d2500723e5594f3e7c70896ffeeef32b9c950ywan  update_stats(cpi);
1469233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1470233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (*tp)->token = EOSB_TOKEN;
1471233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (*tp)++;
1472233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1473233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1474233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_sb_rt(VP9_COMP *cpi, const TileInfo *const tile,
1475233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         TOKENEXTRA **tp, int mi_row, int mi_col,
1476233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         int output_enabled, BLOCK_SIZE bsize) {
1477233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
1478233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
1479233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
1480233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1481233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
1482233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int ctx;
1483233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PARTITION_TYPE partition;
1484233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE subsize;
1485233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1486233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
1487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1489233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize >= BLOCK_8X8) {
1490233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MACROBLOCKD *const xd = &cpi->mb.e_mbd;
1491233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int idx_str = xd->mi_stride * mi_row + mi_col;
1492233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MODE_INFO ** mi_8x8 = cm->mi_grid_visible + idx_str;
1493233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
1494233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = mi_8x8[0]->mbmi.sb_type;
1495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx = 0;
1497233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = BLOCK_4X4;
1498233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1500233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition = partition_lookup[bsl][subsize];
1501233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1502233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (partition) {
1503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_NONE:
1504233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled && bsize >= BLOCK_8X8)
1505233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_NONE]++;
1506233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1507233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1508233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_VERT:
1509233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled)
1510233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_VERT]++;
1511233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1512233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1513233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_col + hbs < cm->mi_cols) {
1514233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
1515233d2500723e5594f3e7c70896ffeeef32b9c950ywan        encode_b_rt(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled,
1516233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    subsize);
1517233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1518233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1519233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_HORZ:
1520233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled)
1521233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_HORZ]++;
1522233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1523233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_b_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1524233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_row + hbs < cm->mi_rows) {
1525233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
1526233d2500723e5594f3e7c70896ffeeef32b9c950ywan        encode_b_rt(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled,
1527233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    subsize);
1528233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1529233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_SPLIT:
1531233d2500723e5594f3e7c70896ffeeef32b9c950ywan      subsize = get_subsize(bsize, PARTITION_SPLIT);
1532233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled)
1533233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.partition[ctx][PARTITION_SPLIT]++;
1534233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1535233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1536233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize);
1537233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
1538233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb_rt(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled,
1539233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   subsize);
1540233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 2;
1541233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb_rt(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled,
1542233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   subsize);
1543233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 3;
1544233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_sb_rt(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
1545233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   subsize);
1546233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1547233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default:
1548233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert("Invalid partition type.");
1549233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1550233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1551233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
1552233d2500723e5594f3e7c70896ffeeef32b9c950ywan    update_partition_context(xd, mi_row, mi_col, subsize, bsize);
1553233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1554233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1555233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void rd_use_partition(VP9_COMP *cpi,
1556233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             const TileInfo *const tile,
1557233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             MODE_INFO **mi_8x8,
1558233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             TOKENEXTRA **tp, int mi_row, int mi_col,
1559233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             BLOCK_SIZE bsize, int *rate, int64_t *dist,
1560233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             int do_recon) {
1561233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
1562233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
1563233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
1564233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
1565233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int bsl = b_width_log2(bsize);
1566233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_step = num_4x4_blocks_wide_lookup[bsize] / 2;
1567233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int bss = (1 << bsl) / 4;
1568233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i, pl;
1569233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PARTITION_TYPE partition = PARTITION_NONE;
1570233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE subsize;
1571233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
1572233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PARTITION_CONTEXT sl[8], sa[8];
1573233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int last_part_rate = INT_MAX;
1574233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t last_part_dist = INT64_MAX;
1575233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t last_part_rd = INT64_MAX;
1576233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int none_rate = INT_MAX;
1577233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t none_dist = INT64_MAX;
1578233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t none_rd = INT64_MAX;
1579233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int chosen_rate = INT_MAX;
1580233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t chosen_dist = INT64_MAX;
1581233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t chosen_rd = INT64_MAX;
1582233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE sub_subsize = BLOCK_4X4;
1583233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int splits_below = 0;
1584233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE bs_type = mi_8x8[0]->mbmi.sb_type;
1585233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int do_partition_search = 1;
1586233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1587233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
1588233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1590233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(num_4x4_blocks_wide_lookup[bsize] ==
1591233d2500723e5594f3e7c70896ffeeef32b9c950ywan         num_4x4_blocks_high_lookup[bsize]);
1592233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1593233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition = partition_lookup[bsl][bs_type];
1594233d2500723e5594f3e7c70896ffeeef32b9c950ywan  subsize = get_subsize(bsize, partition);
1595233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1596233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_8X8) {
1597233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
1598233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // there is nothing to be done.
1599233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (x->ab_index != 0) {
1600233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *rate = 0;
1601233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *dist = 0;
1602233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
1603233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1604233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *(get_sb_partitioning(x, bsize)) = subsize;
1606233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1607233d2500723e5594f3e7c70896ffeeef32b9c950ywan  save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
1608233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1609233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize == BLOCK_16X16) {
1610233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_offsets(cpi, tile, mi_row, mi_col, bsize);
1611233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->mb_energy = vp9_block_energy(cpi, x, bsize);
1612233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1613233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->in_active_map = check_active_map(cpi, x, mi_row, mi_col, bsize);
1614233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1615233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1616233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!x->in_active_map) {
1617233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do_partition_search = 0;
1618233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (mi_row + (mi_step >> 1) < cm->mi_rows &&
1619233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_col + (mi_step >> 1) < cm->mi_cols) {
1620233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = bsize;
1621233d2500723e5594f3e7c70896ffeeef32b9c950ywan      bs_type = mi_8x8[0]->mbmi.sb_type = bsize;
1622233d2500723e5594f3e7c70896ffeeef32b9c950ywan      subsize = bsize;
1623233d2500723e5594f3e7c70896ffeeef32b9c950ywan      partition = PARTITION_NONE;
1624233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1625233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1626233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (do_partition_search &&
1627233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->sf.partition_search_type == SEARCH_PARTITION &&
1628233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->sf.adjust_partitioning_from_last_frame) {
1629233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check if any of the sub blocks are further split.
1630233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (partition == PARTITION_SPLIT && subsize > BLOCK_8X8) {
1631233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sub_subsize = get_subsize(subsize, PARTITION_SPLIT);
1632233d2500723e5594f3e7c70896ffeeef32b9c950ywan      splits_below = 1;
1633233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < 4; i++) {
1634233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int jj = i >> 1, ii = i & 0x01;
1635233d2500723e5594f3e7c70896ffeeef32b9c950ywan        MODE_INFO * this_mi = mi_8x8[jj * bss * mis + ii * bss];
1636233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (this_mi && this_mi->mbmi.sb_type >= sub_subsize) {
1637233d2500723e5594f3e7c70896ffeeef32b9c950ywan          splits_below = 0;
1638233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1639233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1640233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1641233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1642233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // If partition is not none try none unless each of the 4 splits are split
1643233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // even further..
1644233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (partition != PARTITION_NONE && !splits_below &&
1645233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_row + (mi_step >> 1) < cm->mi_rows &&
1646233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_col + (mi_step >> 1) < cm->mi_cols) {
1647233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = bsize;
1648233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &none_rate, &none_dist, bsize,
1649233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       get_block_context(x, bsize), INT64_MAX);
1650233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1651233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pl = partition_plane_context(xd, mi_row, mi_col, bsize);
1652233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1653233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (none_rate < INT_MAX) {
1654233d2500723e5594f3e7c70896ffeeef32b9c950ywan        none_rate += x->partition_cost[pl][PARTITION_NONE];
1655233d2500723e5594f3e7c70896ffeeef32b9c950ywan        none_rd = RDCOST(x->rdmult, x->rddiv, none_rate, none_dist);
1656233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1657233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1658233d2500723e5594f3e7c70896ffeeef32b9c950ywan      restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
1659233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mi_8x8[0]->mbmi.sb_type = bs_type;
1660233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = subsize;
1661233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1662233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1663233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1664233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (partition) {
1665233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_NONE:
1666233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate,
1667233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       &last_part_dist, bsize,
1668233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       get_block_context(x, bsize), INT64_MAX);
1669233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1670233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_HORZ:
1671233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1672233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate,
1673233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       &last_part_dist, subsize,
1674233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       get_block_context(x, subsize), INT64_MAX);
1675233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (last_part_rate != INT_MAX &&
1676233d2500723e5594f3e7c70896ffeeef32b9c950ywan          bsize >= BLOCK_8X8 && mi_row + (mi_step >> 1) < cm->mi_rows) {
1677233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int rt = 0;
1678233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int64_t dt = 0;
1679233d2500723e5594f3e7c70896ffeeef32b9c950ywan        update_state(cpi, get_block_context(x, subsize), mi_row, mi_col,
1680233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     subsize, 0);
1681233d2500723e5594f3e7c70896ffeeef32b9c950ywan        encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
1682233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
1683233d2500723e5594f3e7c70896ffeeef32b9c950ywan        rd_pick_sb_modes(cpi, tile, mi_row + (mi_step >> 1), mi_col, &rt, &dt,
1684233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         subsize, get_block_context(x, subsize), INT64_MAX);
1685233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (rt == INT_MAX || dt == INT64_MAX) {
1686233d2500723e5594f3e7c70896ffeeef32b9c950ywan          last_part_rate = INT_MAX;
1687233d2500723e5594f3e7c70896ffeeef32b9c950ywan          last_part_dist = INT64_MAX;
1688233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
1689233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1690233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1691233d2500723e5594f3e7c70896ffeeef32b9c950ywan        last_part_rate += rt;
1692233d2500723e5594f3e7c70896ffeeef32b9c950ywan        last_part_dist += dt;
1693233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1694233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1695233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_VERT:
1696233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
1697233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate,
1698233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       &last_part_dist, subsize,
1699233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       get_block_context(x, subsize), INT64_MAX);
1700233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (last_part_rate != INT_MAX &&
1701233d2500723e5594f3e7c70896ffeeef32b9c950ywan          bsize >= BLOCK_8X8 && mi_col + (mi_step >> 1) < cm->mi_cols) {
1702233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int rt = 0;
1703233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int64_t dt = 0;
1704233d2500723e5594f3e7c70896ffeeef32b9c950ywan        update_state(cpi, get_block_context(x, subsize), mi_row, mi_col,
1705233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     subsize, 0);
1706233d2500723e5594f3e7c70896ffeeef32b9c950ywan        encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
1707233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
1708233d2500723e5594f3e7c70896ffeeef32b9c950ywan        rd_pick_sb_modes(cpi, tile, mi_row, mi_col + (mi_step >> 1), &rt, &dt,
1709233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         subsize, get_block_context(x, subsize), INT64_MAX);
1710233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (rt == INT_MAX || dt == INT64_MAX) {
1711233d2500723e5594f3e7c70896ffeeef32b9c950ywan          last_part_rate = INT_MAX;
1712233d2500723e5594f3e7c70896ffeeef32b9c950ywan          last_part_dist = INT64_MAX;
1713233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
1714233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1715233d2500723e5594f3e7c70896ffeeef32b9c950ywan        last_part_rate += rt;
1716233d2500723e5594f3e7c70896ffeeef32b9c950ywan        last_part_dist += dt;
1717233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1718233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1719233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_SPLIT:
1720233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Split partition.
1721233d2500723e5594f3e7c70896ffeeef32b9c950ywan      last_part_rate = 0;
1722233d2500723e5594f3e7c70896ffeeef32b9c950ywan      last_part_dist = 0;
1723233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < 4; i++) {
1724233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int x_idx = (i & 1) * (mi_step >> 1);
1725233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int y_idx = (i >> 1) * (mi_step >> 1);
1726233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int jj = i >> 1, ii = i & 0x01;
1727233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int rt;
1728233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int64_t dt;
1729233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1730233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
1731233d2500723e5594f3e7c70896ffeeef32b9c950ywan          continue;
1732233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1733233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = i;
1734233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1735233d2500723e5594f3e7c70896ffeeef32b9c950ywan        rd_use_partition(cpi, tile, mi_8x8 + jj * bss * mis + ii * bss, tp,
1736233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         mi_row + y_idx, mi_col + x_idx, subsize, &rt, &dt,
1737233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         i != 3);
1738233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (rt == INT_MAX || dt == INT64_MAX) {
1739233d2500723e5594f3e7c70896ffeeef32b9c950ywan          last_part_rate = INT_MAX;
1740233d2500723e5594f3e7c70896ffeeef32b9c950ywan          last_part_dist = INT64_MAX;
1741233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
1742233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1743233d2500723e5594f3e7c70896ffeeef32b9c950ywan        last_part_rate += rt;
1744233d2500723e5594f3e7c70896ffeeef32b9c950ywan        last_part_dist += dt;
1745233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1746233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1747233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default:
1748233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(0);
1749233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1751233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pl = partition_plane_context(xd, mi_row, mi_col, bsize);
1752233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (last_part_rate < INT_MAX) {
1753233d2500723e5594f3e7c70896ffeeef32b9c950ywan    last_part_rate += x->partition_cost[pl][partition];
1754233d2500723e5594f3e7c70896ffeeef32b9c950ywan    last_part_rd = RDCOST(x->rdmult, x->rddiv, last_part_rate, last_part_dist);
1755233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1756233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1757233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (do_partition_search
1758233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && cpi->sf.adjust_partitioning_from_last_frame
1759233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && cpi->sf.partition_search_type == SEARCH_PARTITION
1760233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && partition != PARTITION_SPLIT && bsize > BLOCK_8X8
1761233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && (mi_row + mi_step < cm->mi_rows ||
1762233d2500723e5594f3e7c70896ffeeef32b9c950ywan          mi_row + (mi_step >> 1) == cm->mi_rows)
1763233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && (mi_col + mi_step < cm->mi_cols ||
1764233d2500723e5594f3e7c70896ffeeef32b9c950ywan          mi_col + (mi_step >> 1) == cm->mi_cols)) {
1765233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BLOCK_SIZE split_subsize = get_subsize(bsize, PARTITION_SPLIT);
1766233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chosen_rate = 0;
1767233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chosen_dist = 0;
1768233d2500723e5594f3e7c70896ffeeef32b9c950ywan    restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
1769233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1770233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Split partition.
1771233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < 4; i++) {
1772233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int x_idx = (i & 1) * (mi_step >> 1);
1773233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int y_idx = (i >> 1) * (mi_step >> 1);
1774233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int rt = 0;
1775233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int64_t dt = 0;
1776233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
1777233d2500723e5594f3e7c70896ffeeef32b9c950ywan      PARTITION_CONTEXT sl[8], sa[8];
1778233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1779233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
1780233d2500723e5594f3e7c70896ffeeef32b9c950ywan        continue;
1781233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1782233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, split_subsize) = i;
1783233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_partitioning(x, bsize) = split_subsize;
1784233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_partitioning(x, split_subsize) = split_subsize;
1785233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1786233d2500723e5594f3e7c70896ffeeef32b9c950ywan      save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
1787233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1788233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_sb_modes(cpi, tile, mi_row + y_idx, mi_col + x_idx, &rt, &dt,
1789233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       split_subsize, get_block_context(x, split_subsize),
1790233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       INT64_MAX);
1791233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1792233d2500723e5594f3e7c70896ffeeef32b9c950ywan      restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
1793233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1794233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (rt == INT_MAX || dt == INT64_MAX) {
1795233d2500723e5594f3e7c70896ffeeef32b9c950ywan        chosen_rate = INT_MAX;
1796233d2500723e5594f3e7c70896ffeeef32b9c950ywan        chosen_dist = INT64_MAX;
1797233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1798233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1799233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1800233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chosen_rate += rt;
1801233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chosen_dist += dt;
1802233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1803233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (i != 3)
1804233d2500723e5594f3e7c70896ffeeef32b9c950ywan        encode_sb(cpi, tile, tp,  mi_row + y_idx, mi_col + x_idx, 0,
1805233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  split_subsize);
1806233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1807233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pl = partition_plane_context(xd, mi_row + y_idx, mi_col + x_idx,
1808233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   split_subsize);
1809233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chosen_rate += x->partition_cost[pl][PARTITION_NONE];
1810233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1811233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pl = partition_plane_context(xd, mi_row, mi_col, bsize);
1812233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (chosen_rate < INT_MAX) {
1813233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chosen_rate += x->partition_cost[pl][PARTITION_SPLIT];
1814233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chosen_rd = RDCOST(x->rdmult, x->rddiv, chosen_rate, chosen_dist);
1815233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1816233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1817233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1818233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If last_part is better set the partitioning to that...
1819233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (last_part_rd < chosen_rd) {
1820233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mi_8x8[0]->mbmi.sb_type = bsize;
1821233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (bsize >= BLOCK_8X8)
1822233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = subsize;
1823233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chosen_rate = last_part_rate;
1824233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chosen_dist = last_part_dist;
1825233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chosen_rd = last_part_rd;
1826233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1827233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If none was better set the partitioning to that...
1828233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (none_rd < chosen_rd) {
1829233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (bsize >= BLOCK_8X8)
1830233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = bsize;
1831233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chosen_rate = none_rate;
1832233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chosen_dist = none_dist;
1833233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1834233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1835233d2500723e5594f3e7c70896ffeeef32b9c950ywan  restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
1836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1837233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // We must have chosen a partitioning and encoding or we'll fail later on.
1838233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // No other opportunities for success.
1839233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if ( bsize == BLOCK_64X64)
1840233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(chosen_rate < INT_MAX && chosen_dist < INT64_MAX);
1841233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1842233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (do_recon) {
1843233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int output_enabled = (bsize == BLOCK_64X64);
1844233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1845233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check the projected output rate for this SB against it's target
1846233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // and and if necessary apply a Q delta using segmentation to get
1847233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // closer to the target.
1848233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
1849233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_select_in_frame_q_segment(cpi, mi_row, mi_col,
1850233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    output_enabled, chosen_rate);
1851233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1852233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1853233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
1854233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
1855233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              chosen_rate, chosen_dist);
1856233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1857233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize);
1858233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1859233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1860233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *rate = chosen_rate;
1861233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *dist = chosen_dist;
1862233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1863233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1864233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const BLOCK_SIZE min_partition_size[BLOCK_SIZES] = {
1865233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_4X4,   BLOCK_4X4,   BLOCK_4X4,
1866233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_4X4,   BLOCK_4X4,   BLOCK_4X4,
1867233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_8X8,   BLOCK_8X8,   BLOCK_8X8,
1868233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
1869233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_16X16
1870233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
1871233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1872233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const BLOCK_SIZE max_partition_size[BLOCK_SIZES] = {
1873233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_8X8,   BLOCK_16X16, BLOCK_16X16,
1874233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_16X16, BLOCK_32X32, BLOCK_32X32,
1875233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_32X32, BLOCK_64X64, BLOCK_64X64,
1876233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_64X64, BLOCK_64X64, BLOCK_64X64,
1877233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_64X64
1878233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
1879233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1880233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Look at all the mode_info entries for blocks that are part of this
1881233d2500723e5594f3e7c70896ffeeef32b9c950ywan// partition and find the min and max values for sb_type.
1882233d2500723e5594f3e7c70896ffeeef32b9c950ywan// At the moment this is designed to work on a 64x64 SB but could be
1883233d2500723e5594f3e7c70896ffeeef32b9c950ywan// adjusted to use a size parameter.
1884233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
1885233d2500723e5594f3e7c70896ffeeef32b9c950ywan// The min and max are assumed to have been initialized prior to calling this
1886233d2500723e5594f3e7c70896ffeeef32b9c950ywan// function so repeat calls can accumulate a min and max of more than one sb64.
1887233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void get_sb_partition_size_range(VP9_COMP *cpi, MODE_INFO ** mi_8x8,
1888233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        BLOCK_SIZE * min_block_size,
1889233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        BLOCK_SIZE * max_block_size ) {
1890233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
1891233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int sb_width_in_blocks = MI_BLOCK_SIZE;
1892233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int sb_height_in_blocks  = MI_BLOCK_SIZE;
1893233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i, j;
1894233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int index = 0;
1895233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1896233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check the sb_type for each block that belongs to this region.
1897233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < sb_height_in_blocks; ++i) {
1898233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (j = 0; j < sb_width_in_blocks; ++j) {
1899233d2500723e5594f3e7c70896ffeeef32b9c950ywan      MODE_INFO * mi = mi_8x8[index+j];
1900233d2500723e5594f3e7c70896ffeeef32b9c950ywan      BLOCK_SIZE sb_type = mi ? mi->mbmi.sb_type : 0;
1901233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *min_block_size = MIN(*min_block_size, sb_type);
1902233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *max_block_size = MAX(*max_block_size, sb_type);
1903233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1904233d2500723e5594f3e7c70896ffeeef32b9c950ywan    index += xd->mi_stride;
1905233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1906233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1907233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1908233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Next square block size less or equal than current block size.
1909233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const BLOCK_SIZE next_square_size[BLOCK_SIZES] = {
1910233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
1911233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_8X8, BLOCK_8X8, BLOCK_8X8,
1912233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
1913233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_32X32, BLOCK_32X32, BLOCK_32X32,
1914233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_64X64
1915233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
1916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1917233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Look at neighboring blocks and set a min and max partition size based on
1918233d2500723e5594f3e7c70896ffeeef32b9c950ywan// what they chose.
1919233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void rd_auto_partition_range(VP9_COMP *cpi, const TileInfo *const tile,
1920233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    int mi_row, int mi_col,
1921233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    BLOCK_SIZE *min_block_size,
1922233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    BLOCK_SIZE *max_block_size) {
1923233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
1924233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
1925233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO **mi_8x8 = xd->mi;
1926233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int left_in_image = xd->left_available && mi_8x8[-1];
1927233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int above_in_image = xd->up_available &&
1928233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             mi_8x8[-xd->mi_stride];
1929233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO **above_sb64_mi_8x8;
1930233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO **left_sb64_mi_8x8;
1931233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1932233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int row8x8_remaining = tile->mi_row_end - mi_row;
1933233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int col8x8_remaining = tile->mi_col_end - mi_col;
1934233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int bh, bw;
1935233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE min_size = BLOCK_4X4;
1936233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE max_size = BLOCK_64X64;
1937233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Trap case where we do not have a prediction.
1938233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (left_in_image || above_in_image || cm->frame_type != KEY_FRAME) {
1939233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Default "min to max" and "max to min"
1940233d2500723e5594f3e7c70896ffeeef32b9c950ywan    min_size = BLOCK_64X64;
1941233d2500723e5594f3e7c70896ffeeef32b9c950ywan    max_size = BLOCK_4X4;
1942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1943233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // NOTE: each call to get_sb_partition_size_range() uses the previous
1944233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // passed in values for min and max as a starting point.
1945233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Find the min and max partition used in previous frame at this location
1946233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->frame_type != KEY_FRAME) {
1947233d2500723e5594f3e7c70896ffeeef32b9c950ywan      MODE_INFO **const prev_mi =
1948233d2500723e5594f3e7c70896ffeeef32b9c950ywan          &cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col];
1949233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_sb_partition_size_range(cpi, prev_mi, &min_size, &max_size);
1950233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1951233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Find the min and max partition sizes used in the left SB64
1952233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (left_in_image) {
1953233d2500723e5594f3e7c70896ffeeef32b9c950ywan      left_sb64_mi_8x8 = &mi_8x8[-MI_BLOCK_SIZE];
1954233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_sb_partition_size_range(cpi, left_sb64_mi_8x8,
1955233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  &min_size, &max_size);
1956233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1957233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Find the min and max partition sizes used in the above SB64.
1958233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (above_in_image) {
1959233d2500723e5594f3e7c70896ffeeef32b9c950ywan      above_sb64_mi_8x8 = &mi_8x8[-xd->mi_stride * MI_BLOCK_SIZE];
1960233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_sb_partition_size_range(cpi, above_sb64_mi_8x8,
1961233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  &min_size, &max_size);
1962233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1963233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // adjust observed min and max
1964233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.auto_min_max_partition_size == RELAXED_NEIGHBORING_MIN_MAX) {
1965233d2500723e5594f3e7c70896ffeeef32b9c950ywan      min_size = min_partition_size[min_size];
1966233d2500723e5594f3e7c70896ffeeef32b9c950ywan      max_size = max_partition_size[max_size];
1967233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1968233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1969233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1970233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check border cases where max and min from neighbors may not be legal.
1971233d2500723e5594f3e7c70896ffeeef32b9c950ywan  max_size = find_partition_size(max_size,
1972233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                 row8x8_remaining, col8x8_remaining,
1973233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                 &bh, &bw);
1974233d2500723e5594f3e7c70896ffeeef32b9c950ywan  min_size = MIN(min_size, max_size);
1975233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1976233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // When use_square_partition_only is true, make sure at least one square
1977233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // partition is allowed by selecting the next smaller square size as
1978233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // *min_block_size.
1979233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.use_square_partition_only &&
1980233d2500723e5594f3e7c70896ffeeef32b9c950ywan      next_square_size[max_size] < min_size) {
1981233d2500723e5594f3e7c70896ffeeef32b9c950ywan     min_size = next_square_size[max_size];
1982233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1983233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *min_block_size = min_size;
1984233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *max_block_size = max_size;
1985233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1987233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic INLINE void store_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
1988233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memcpy(ctx->pred_mv, x->pred_mv, sizeof(x->pred_mv));
1989233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1990233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1991233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic INLINE void load_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
1992233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memcpy(x->pred_mv, ctx->pred_mv, sizeof(x->pred_mv));
1993233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1995233d2500723e5594f3e7c70896ffeeef32b9c950ywan// TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
1996233d2500723e5594f3e7c70896ffeeef32b9c950ywan// unlikely to be selected depending on previous rate-distortion optimization
1997233d2500723e5594f3e7c70896ffeeef32b9c950ywan// results, for encoding speed-up.
1998233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
1999233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              TOKENEXTRA **tp, int mi_row,
2000233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              int mi_col, BLOCK_SIZE bsize, int *rate,
2001233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              int64_t *dist, int do_recon, int64_t best_rd) {
2002233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
2003233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
2004233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
2005233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_step = num_8x8_blocks_wide_lookup[bsize] / 2;
2006233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
2007233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PARTITION_CONTEXT sl[8], sa[8];
2008233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TOKENEXTRA *tp_orig = *tp;
2009233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PICK_MODE_CONTEXT *ctx = get_block_context(x, bsize);
2010233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i, pl;
2011233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE subsize;
2012233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int this_rate, sum_rate = 0, best_rate = INT_MAX;
2013233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t this_dist, sum_dist = 0, best_dist = INT64_MAX;
2014233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t sum_rd = 0;
2015233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int do_split = bsize >= BLOCK_8X8;
2016233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int do_rect = 1;
2017233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Override skipping rectangular partition operations for edge blocks
2018233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int force_horz_split = (mi_row + mi_step >= cm->mi_rows);
2019233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int force_vert_split = (mi_col + mi_step >= cm->mi_cols);
2020233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int xss = x->e_mbd.plane[1].subsampling_x;
2021233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int yss = x->e_mbd.plane[1].subsampling_y;
2022233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2023233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int partition_none_allowed = !force_horz_split && !force_vert_split;
2024233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int partition_horz_allowed = !force_vert_split && yss <= xss &&
2025233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               bsize >= BLOCK_8X8;
2026233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int partition_vert_allowed = !force_horz_split && xss <= yss &&
2027233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               bsize >= BLOCK_8X8;
2028233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (void) *tp_orig;
2029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2030233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_8X8) {
2031233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
2032233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // there is nothing to be done.
2033233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (x->ab_index != 0) {
2034233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *rate = 0;
2035233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *dist = 0;
2036233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
2037233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2038233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2039233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(num_8x8_blocks_wide_lookup[bsize] ==
2040233d2500723e5594f3e7c70896ffeeef32b9c950ywan             num_8x8_blocks_high_lookup[bsize]);
2041233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2042233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize == BLOCK_16X16) {
2043233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_offsets(cpi, tile, mi_row, mi_col, bsize);
2044233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->mb_energy = vp9_block_energy(cpi, x, bsize);
2045233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2046233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->in_active_map = check_active_map(cpi, x, mi_row, mi_col, bsize);
2047233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2048233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2049233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Determine partition types in search according to the speed features.
2050233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // The threshold set here has to be of square block size.
2051233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.auto_min_max_partition_size) {
2052233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_none_allowed &= (bsize <= cpi->sf.max_partition_size &&
2053233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               bsize >= cpi->sf.min_partition_size);
2054233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_horz_allowed &= ((bsize <= cpi->sf.max_partition_size &&
2055233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                bsize >  cpi->sf.min_partition_size) ||
2056233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                force_horz_split);
2057233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_vert_allowed &= ((bsize <= cpi->sf.max_partition_size &&
2058233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                bsize >  cpi->sf.min_partition_size) ||
2059233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                force_vert_split);
2060233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do_split &= bsize > cpi->sf.min_partition_size;
2061233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2062233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.use_square_partition_only) {
2063233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_horz_allowed &= force_horz_split;
2064233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_vert_allowed &= force_vert_split;
2065233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2066233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2067233d2500723e5594f3e7c70896ffeeef32b9c950ywan  save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
2068233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2069233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.disable_split_var_thresh && partition_none_allowed) {
2070233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int source_variancey;
2071233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
2072233d2500723e5594f3e7c70896ffeeef32b9c950ywan    source_variancey = get_sby_perpixel_variance(cpi, x, bsize);
2073233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (source_variancey < cpi->sf.disable_split_var_thresh) {
2074233d2500723e5594f3e7c70896ffeeef32b9c950ywan      do_split = 0;
2075233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (source_variancey < cpi->sf.disable_split_var_thresh / 2)
2076233d2500723e5594f3e7c70896ffeeef32b9c950ywan        do_rect = 0;
2077233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2078233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2079233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2080233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!x->in_active_map && (partition_horz_allowed || partition_vert_allowed))
2081233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do_split = 0;
2082233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_NONE
2083233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition_none_allowed) {
2084233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &this_rate, &this_dist, bsize,
2085233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     ctx, best_rd);
2086233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (this_rate != INT_MAX) {
2087233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (bsize >= BLOCK_8X8) {
2088233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2089233d2500723e5594f3e7c70896ffeeef32b9c950ywan        this_rate += x->partition_cost[pl][PARTITION_NONE];
2090233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2091233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_dist);
2092233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (sum_rd < best_rd) {
2093233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int64_t stop_thresh = 4096;
2094233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int64_t stop_thresh_rd;
2095233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2096233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rate = this_rate;
2097233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_dist = this_dist;
2098233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rd = sum_rd;
2099233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (bsize >= BLOCK_8X8)
2100233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *(get_sb_partitioning(x, bsize)) = bsize;
2101233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2102233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // Adjust threshold according to partition size.
2103233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stop_thresh >>= 8 - (b_width_log2_lookup[bsize] +
2104233d2500723e5594f3e7c70896ffeeef32b9c950ywan            b_height_log2_lookup[bsize]);
2105233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2106233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stop_thresh_rd = RDCOST(x->rdmult, x->rddiv, 0, stop_thresh);
2107233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // If obtained distortion is very small, choose current partition
2108233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // and stop splitting.
2109233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!x->e_mbd.lossless && best_rd < stop_thresh_rd) {
2110233d2500723e5594f3e7c70896ffeeef32b9c950ywan          do_split = 0;
2111233d2500723e5594f3e7c70896ffeeef32b9c950ywan          do_rect = 0;
2112233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
2113233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!x->in_active_map) {
2116233d2500723e5594f3e7c70896ffeeef32b9c950ywan      do_split = 0;
2117233d2500723e5594f3e7c70896ffeeef32b9c950ywan      do_rect = 0;
2118233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
2120233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2121233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // store estimated motion vector
2123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.adaptive_motion_search)
2124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    store_pred_mv(x, ctx);
2125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2126233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_SPLIT
2127233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum_rd = 0;
2128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(jingning): use the motion vectors given by the above search as
2129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // the starting point of motion search in the following partition type check.
2130233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (do_split) {
2131233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = get_subsize(bsize, PARTITION_SPLIT);
2132233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < 4 && sum_rd < best_rd; ++i) {
2133233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int x_idx = (i & 1) * mi_step;
2134233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int y_idx = (i >> 1) * mi_step;
2135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2136233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols)
2137233d2500723e5594f3e7c70896ffeeef32b9c950ywan        continue;
2138233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2139233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = i;
2140233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.adaptive_motion_search)
2141233d2500723e5594f3e7c70896ffeeef32b9c950ywan        load_pred_mv(x, ctx);
2142233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
2143233d2500723e5594f3e7c70896ffeeef32b9c950ywan          partition_none_allowed)
2144233d2500723e5594f3e7c70896ffeeef32b9c950ywan        get_block_context(x, subsize)->pred_interp_filter =
2145233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ctx->mic.mbmi.interp_filter;
2146233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, subsize,
2147233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        &this_rate, &this_dist, i != 3, best_rd - sum_rd);
2148233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2149233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (this_rate == INT_MAX) {
2150233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = INT64_MAX;
2151233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2152233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rate += this_rate;
2153233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_dist += this_dist;
2154233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2155233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd && i == 4) {
2158233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2159233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rate += x->partition_cost[pl][PARTITION_SPLIT];
2160233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2161233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (sum_rd < best_rd) {
2162233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rate = sum_rate;
2163233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_dist = sum_dist;
2164233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rd = sum_rd;
2165233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *(get_sb_partitioning(x, bsize)) = subsize;
2166233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2167233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
2168233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // skip rectangular partition test when larger block size
2169233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // gives better rd cost
2170233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.less_rectangular_check)
2171233d2500723e5594f3e7c70896ffeeef32b9c950ywan        do_rect &= !partition_none_allowed;
2172233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2173233d2500723e5594f3e7c70896ffeeef32b9c950ywan    restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
2174233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2175233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2176233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_HORZ
2177233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition_horz_allowed && do_rect) {
2178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = get_subsize(bsize, PARTITION_HORZ);
2179233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *get_sb_index(x, subsize) = 0;
2180233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.adaptive_motion_search)
2181233d2500723e5594f3e7c70896ffeeef32b9c950ywan      load_pred_mv(x, ctx);
2182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
2183233d2500723e5594f3e7c70896ffeeef32b9c950ywan        partition_none_allowed)
2184233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_block_context(x, subsize)->pred_interp_filter =
2185233d2500723e5594f3e7c70896ffeeef32b9c950ywan          ctx->mic.mbmi.interp_filter;
2186233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize,
2187233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     get_block_context(x, subsize), best_rd);
2188233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd && mi_row + mi_step < cm->mi_rows) {
2191233d2500723e5594f3e7c70896ffeeef32b9c950ywan      update_state(cpi, get_block_context(x, subsize), mi_row, mi_col,
2192233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   subsize, 0);
2193233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
2194233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2195233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
2196233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.adaptive_motion_search)
2197233d2500723e5594f3e7c70896ffeeef32b9c950ywan        load_pred_mv(x, ctx);
2198233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
2199233d2500723e5594f3e7c70896ffeeef32b9c950ywan          partition_none_allowed)
2200233d2500723e5594f3e7c70896ffeeef32b9c950ywan        get_block_context(x, subsize)->pred_interp_filter =
2201233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ctx->mic.mbmi.interp_filter;
2202233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_sb_modes(cpi, tile, mi_row + mi_step, mi_col, &this_rate,
2203233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       &this_dist, subsize, get_block_context(x, subsize),
2204233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       best_rd - sum_rd);
2205233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (this_rate == INT_MAX) {
2206233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = INT64_MAX;
2207233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2208233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rate += this_rate;
2209233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_dist += this_dist;
2210233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2211233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2213233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd) {
2214233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2215233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rate += x->partition_cost[pl][PARTITION_HORZ];
2216233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2217233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (sum_rd < best_rd) {
2218233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rd = sum_rd;
2219233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rate = sum_rate;
2220233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_dist = sum_dist;
2221233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *(get_sb_partitioning(x, bsize)) = subsize;
2222233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2223233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2224233d2500723e5594f3e7c70896ffeeef32b9c950ywan    restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
2225233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2226233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2227233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_VERT
2228233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition_vert_allowed && do_rect) {
2229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = get_subsize(bsize, PARTITION_VERT);
2230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2231233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *get_sb_index(x, subsize) = 0;
2232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.adaptive_motion_search)
2233233d2500723e5594f3e7c70896ffeeef32b9c950ywan      load_pred_mv(x, ctx);
2234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
2235233d2500723e5594f3e7c70896ffeeef32b9c950ywan        partition_none_allowed)
2236233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_block_context(x, subsize)->pred_interp_filter =
2237233d2500723e5594f3e7c70896ffeeef32b9c950ywan          ctx->mic.mbmi.interp_filter;
2238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize,
2239233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     get_block_context(x, subsize), best_rd);
2240233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2241233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd && mi_col + mi_step < cm->mi_cols) {
2242233d2500723e5594f3e7c70896ffeeef32b9c950ywan      update_state(cpi, get_block_context(x, subsize), mi_row, mi_col,
2243233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   subsize, 0);
2244233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
2245233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2246233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
2247233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.adaptive_motion_search)
2248233d2500723e5594f3e7c70896ffeeef32b9c950ywan        load_pred_mv(x, ctx);
2249233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
2250233d2500723e5594f3e7c70896ffeeef32b9c950ywan          partition_none_allowed)
2251233d2500723e5594f3e7c70896ffeeef32b9c950ywan        get_block_context(x, subsize)->pred_interp_filter =
2252233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ctx->mic.mbmi.interp_filter;
2253233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_sb_modes(cpi, tile, mi_row, mi_col + mi_step, &this_rate,
2254233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       &this_dist, subsize, get_block_context(x, subsize),
2255233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       best_rd - sum_rd);
2256233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (this_rate == INT_MAX) {
2257233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = INT64_MAX;
2258233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2259233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rate += this_rate;
2260233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_dist += this_dist;
2261233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2262233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd) {
2265233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2266233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rate += x->partition_cost[pl][PARTITION_VERT];
2267233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2268233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (sum_rd < best_rd) {
2269233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rate = sum_rate;
2270233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_dist = sum_dist;
2271233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rd = sum_rd;
2272233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *(get_sb_partitioning(x, bsize)) = subsize;
2273233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2274233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2275233d2500723e5594f3e7c70896ffeeef32b9c950ywan    restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
2276233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2277233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2278233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(jbb): This code added so that we avoid static analysis
2279233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // warning related to the fact that best_rd isn't used after this
2280233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // point.  This code should be refactored so that the duplicate
2281233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // checks occur in some sub function and thus are used...
2282233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (void) best_rd;
2283233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *rate = best_rate;
2284233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *dist = best_dist;
2285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2286233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (best_rate < INT_MAX && best_dist < INT64_MAX && do_recon) {
2287233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int output_enabled = (bsize == BLOCK_64X64);
2288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2289233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check the projected output rate for this SB against it's target
2290233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // and and if necessary apply a Q delta using segmentation to get
2291233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // closer to the target.
2292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
2293233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled,
2294233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    best_rate);
2295233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2296233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2297233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
2298233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
2299233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              best_rate, best_dist);
2300233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2301233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize);
2302233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2303233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize == BLOCK_64X64) {
2304233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(tp_orig < *tp);
2305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(best_rate < INT_MAX);
2306233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(best_dist < INT64_MAX);
2307233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2308233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(tp_orig == *tp);
2309233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2310233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2311233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2312233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
2313233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             int mi_row, TOKENEXTRA **tp) {
2314233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
2315233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
2316233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_col;
2317233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2318233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Initialize the left context for the new SB row
2319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memset(&xd->left_context, 0, sizeof(xd->left_context));
2320233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memset(xd->left_seg_context, 0, sizeof(xd->left_seg_context));
2321233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2322233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Code each SB in the row
2323233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
2324233d2500723e5594f3e7c70896ffeeef32b9c950ywan       mi_col += MI_BLOCK_SIZE) {
2325233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int dummy_rate;
2326233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int64_t dummy_dist;
2327233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BLOCK_SIZE i;
2329233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MACROBLOCK *x = &cpi->mb;
2330233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2331233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.adaptive_pred_interp_filter) {
2332233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = BLOCK_4X4; i < BLOCK_8X8; ++i) {
2333233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int num_4x4_w = num_4x4_blocks_wide_lookup[i];
2334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int num_4x4_h = num_4x4_blocks_high_lookup[i];
2335233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int num_4x4_blk = MAX(4, num_4x4_w * num_4x4_h);
2336233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (x->sb_index = 0; x->sb_index < 4; ++x->sb_index)
2337233d2500723e5594f3e7c70896ffeeef32b9c950ywan          for (x->mb_index = 0; x->mb_index < 4; ++x->mb_index)
2338233d2500723e5594f3e7c70896ffeeef32b9c950ywan            for (x->b_index = 0; x->b_index < 16 / num_4x4_blk; ++x->b_index)
2339233d2500723e5594f3e7c70896ffeeef32b9c950ywan              get_block_context(x, i)->pred_interp_filter = SWITCHABLE;
2340233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2341233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2342233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2343233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_zero(cpi->mb.pred_mv);
2344233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2345233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((cpi->sf.partition_search_type == SEARCH_PARTITION &&
2346233d2500723e5594f3e7c70896ffeeef32b9c950ywan         cpi->sf.use_lastframe_partitioning) ||
2347233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cpi->sf.partition_search_type == FIXED_PARTITION ||
2348233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cpi->sf.partition_search_type == VAR_BASED_PARTITION ||
2349233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cpi->sf.partition_search_type == VAR_BASED_FIXED_PARTITION) {
2350233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int idx_str = cm->mi_stride * mi_row + mi_col;
2351233d2500723e5594f3e7c70896ffeeef32b9c950ywan      MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
2352233d2500723e5594f3e7c70896ffeeef32b9c950ywan      MODE_INFO **prev_mi_8x8 = cm->prev_mi_grid_visible + idx_str;
2353233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->mb.source_variance = UINT_MAX;
2354233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.partition_search_type == FIXED_PARTITION) {
2355233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
2356233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col,
2357233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               cpi->sf.always_this_block_size);
2358233d2500723e5594f3e7c70896ffeeef32b9c950ywan        rd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
2359233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         &dummy_rate, &dummy_dist, 1);
2360233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (cpi->sf.partition_search_type == VAR_BASED_FIXED_PARTITION) {
2361233d2500723e5594f3e7c70896ffeeef32b9c950ywan        BLOCK_SIZE bsize;
2362233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
2363233d2500723e5594f3e7c70896ffeeef32b9c950ywan        bsize = get_rd_var_based_fixed_partition(cpi, mi_row, mi_col);
2364233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col, bsize);
2365233d2500723e5594f3e7c70896ffeeef32b9c950ywan        rd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
2366233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         &dummy_rate, &dummy_dist, 1);
2367233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (cpi->sf.partition_search_type == VAR_BASED_PARTITION) {
2368233d2500723e5594f3e7c70896ffeeef32b9c950ywan        choose_partitioning(cpi, tile, mi_row, mi_col);
2369233d2500723e5594f3e7c70896ffeeef32b9c950ywan        rd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
2370233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         &dummy_rate, &dummy_dist, 1);
2371233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2372233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cm->current_video_frame
2373233d2500723e5594f3e7c70896ffeeef32b9c950ywan            % cpi->sf.last_partitioning_redo_frequency) == 0
2374233d2500723e5594f3e7c70896ffeeef32b9c950ywan            || cm->prev_mi == 0
2375233d2500723e5594f3e7c70896ffeeef32b9c950ywan            || cm->show_frame == 0
2376233d2500723e5594f3e7c70896ffeeef32b9c950ywan            || cm->frame_type == KEY_FRAME
2377233d2500723e5594f3e7c70896ffeeef32b9c950ywan            || cpi->rc.is_src_frame_alt_ref
2378233d2500723e5594f3e7c70896ffeeef32b9c950ywan            || ((cpi->sf.use_lastframe_partitioning ==
2379233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 LAST_FRAME_PARTITION_LOW_MOTION) &&
2380233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 sb_has_motion(cm, prev_mi_8x8))) {
2381233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // If required set upper and lower partition size limits
2382233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (cpi->sf.auto_min_max_partition_size) {
2383233d2500723e5594f3e7c70896ffeeef32b9c950ywan            set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
2384233d2500723e5594f3e7c70896ffeeef32b9c950ywan            rd_auto_partition_range(cpi, tile, mi_row, mi_col,
2385233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    &cpi->sf.min_partition_size,
2386233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    &cpi->sf.max_partition_size);
2387233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
2388233d2500723e5594f3e7c70896ffeeef32b9c950ywan          rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64,
2389233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            &dummy_rate, &dummy_dist, 1, INT64_MAX);
2390233d2500723e5594f3e7c70896ffeeef32b9c950ywan        } else {
2391233d2500723e5594f3e7c70896ffeeef32b9c950ywan          copy_partitioning(cm, mi_8x8, prev_mi_8x8);
2392233d2500723e5594f3e7c70896ffeeef32b9c950ywan          rd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
2393233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           &dummy_rate, &dummy_dist, 1);
2394233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
2395233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2396233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
2397233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // If required set upper and lower partition size limits
2398233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.auto_min_max_partition_size) {
2399233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
2400233d2500723e5594f3e7c70896ffeeef32b9c950ywan        rd_auto_partition_range(cpi, tile, mi_row, mi_col,
2401233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                &cpi->sf.min_partition_size,
2402233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                &cpi->sf.max_partition_size);
2403233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2404233d2500723e5594f3e7c70896ffeeef32b9c950ywan      rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64,
2405233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        &dummy_rate, &dummy_dist, 1, INT64_MAX);
2406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2407233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2408233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2410233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void init_encode_frame_mb_context(VP9_COMP *cpi) {
2411233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
2412233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
2413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
2414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int aligned_mi_cols = mi_cols_aligned_to_sb(cm->mi_cols);
2415233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2416233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->act_zbin_adj = 0;
2417233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cpi->seg0_idx = 0;
2418233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2419233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Copy data over into macro block data structures.
2420233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_setup_src_planes(x, cpi->Source, 0, 0);
2421233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2422233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(jkoleszar): are these initializations required?
2423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_setup_pre_planes(xd, 0, get_ref_frame_buffer(cpi, LAST_FRAME), 0, 0,
2424233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       NULL);
2425233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_setup_dst_planes(xd, get_frame_new_buffer(cm), 0, 0);
2426233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2427233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
2428233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2429233d2500723e5594f3e7c70896ffeeef32b9c950ywan  xd->mi[0]->mbmi.mode = DC_PRED;
2430233d2500723e5594f3e7c70896ffeeef32b9c950ywan  xd->mi[0]->mbmi.uv_mode = DC_PRED;
2431233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2432233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Note: this memset assumes above_context[0], [1] and [2]
2433233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // are allocated as part of the same buffer.
2434233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memset(xd->above_context[0], 0,
2435233d2500723e5594f3e7c70896ffeeef32b9c950ywan             sizeof(*xd->above_context[0]) *
2436233d2500723e5594f3e7c70896ffeeef32b9c950ywan             2 * aligned_mi_cols * MAX_MB_PLANE);
2437233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memset(xd->above_seg_context, 0,
2438233d2500723e5594f3e7c70896ffeeef32b9c950ywan             sizeof(*xd->above_seg_context) * aligned_mi_cols);
2439233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2440233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2441233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void switch_lossless_mode(VP9_COMP *cpi, int lossless) {
2442233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (lossless) {
2443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // printf("Switching to lossless\n");
2444233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.fwd_txm4x4 = vp9_fwht4x4;
2445233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.e_mbd.itxm_add = vp9_iwht4x4_add;
2446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.optimize = 0;
2447233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->common.lf.filter_level = 0;
2448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->zbin_mode_boost_enabled = 0;
2449233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->common.tx_mode = ONLY_4X4;
2450233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2451233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // printf("Not lossless\n");
2452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.fwd_txm4x4 = vp9_fdct4x4;
2453233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.e_mbd.itxm_add = vp9_idct4x4_add;
2454233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2455233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2456233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2457233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int check_dual_ref_flags(VP9_COMP *cpi) {
2458233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int ref_flags = cpi->ref_frame_flags;
2459233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2460233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (vp9_segfeature_active(&cpi->common.seg, 1, SEG_LVL_REF_FRAME)) {
2461233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
2462233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2463233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (!!(ref_flags & VP9_GOLD_FLAG) + !!(ref_flags & VP9_LAST_FLAG)
2464233d2500723e5594f3e7c70896ffeeef32b9c950ywan        + !!(ref_flags & VP9_ALT_FLAG)) >= 2;
2465233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2466233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2467233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2468233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int get_skip_flag(MODE_INFO **mi_8x8, int mis, int ymbs, int xmbs) {
2469233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int x, y;
2470233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2471233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (y = 0; y < ymbs; y++) {
2472233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (x = 0; x < xmbs; x++) {
2473233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!mi_8x8[y * mis + x]->mbmi.skip)
2474233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
2475233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2476233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2477233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2478233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
2479233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2480233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2481233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void reset_skip_txfm_size(VP9_COMMON *cm, TX_SIZE txfm_max) {
2482233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_row, mi_col;
2483233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
2484233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO **mi_ptr = cm->mi_grid_visible;
2485233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2486233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (mi_row = 0; mi_row < cm->mi_rows; ++mi_row, mi_ptr += mis) {
2487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (mi_col = 0; mi_col < cm->mi_cols; ++mi_col) {
2488233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_ptr[mi_col]->mbmi.tx_size > txfm_max)
2489233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mi_ptr[mi_col]->mbmi.tx_size = txfm_max;
2490233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2491233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2492233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2493233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2494233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic MV_REFERENCE_FRAME get_frame_type(const VP9_COMP *cpi) {
2495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame_is_intra_only(&cpi->common))
2496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return INTRA_FRAME;
2497233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
2498233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return ALTREF_FRAME;
2499233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
2500233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return LAST_FRAME;
2501233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else
2502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return GOLDEN_FRAME;
2503233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2504233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2505233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic TX_MODE select_tx_mode(const VP9_COMP *cpi) {
2506233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->oxcf.lossless) {
2507233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return ONLY_4X4;
2508233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (cpi->common.current_video_frame == 0) {
2509233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return TX_MODE_SELECT;
2510233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2511233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
2512233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return ALLOW_32X32;
2513233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
2514233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
2515233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32] >
2516233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
2517233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     ALLOW_32X32 : TX_MODE_SELECT;
2518233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
2519233d2500723e5594f3e7c70896ffeeef32b9c950ywan      unsigned int total = 0;
2520233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int i;
2521233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < TX_SIZES; ++i)
2522233d2500723e5594f3e7c70896ffeeef32b9c950ywan        total += cpi->tx_stepdown_count[i];
2523233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2524233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (total) {
2525233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const double fraction = (double)cpi->tx_stepdown_count[0] / total;
2526233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return fraction > 0.90 ? ALLOW_32X32 : TX_MODE_SELECT;
2527233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2528233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return cpi->common.tx_mode;
2529233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2531233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2532233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2533233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2534233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Start RTC Exploration
2535233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef enum {
2536233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BOTH_ZERO = 0,
2537233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ZERO_PLUS_PREDICTED = 1,
2538233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BOTH_PREDICTED = 2,
2539233d2500723e5594f3e7c70896ffeeef32b9c950ywan  NEW_PLUS_NON_INTRA = 3,
2540233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BOTH_NEW = 4,
2541233d2500723e5594f3e7c70896ffeeef32b9c950ywan  INTRA_PLUS_NON_INTRA = 5,
2542233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BOTH_INTRA = 6,
2543233d2500723e5594f3e7c70896ffeeef32b9c950ywan  INVALID_CASE = 9
2544233d2500723e5594f3e7c70896ffeeef32b9c950ywan} motion_vector_context;
2545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2546233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_mode_info(MB_MODE_INFO *mbmi, BLOCK_SIZE bsize,
2547233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          MB_PREDICTION_MODE mode) {
2548233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->mode = mode;
2549233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->uv_mode = mode;
2550233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->mv[0].as_int = 0;
2551233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->mv[1].as_int = 0;
2552233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->ref_frame[0] = INTRA_FRAME;
2553233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->ref_frame[1] = NONE;
2554233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->tx_size = max_txsize_lookup[bsize];
2555233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->skip = 0;
2556233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->sb_type = bsize;
2557233d2500723e5594f3e7c70896ffeeef32b9c950ywan  mbmi->segment_id = 0;
2558233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2559233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2560233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void nonrd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
2561233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                int mi_row, int mi_col,
2562233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                int *rate, int64_t *dist,
2563233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                BLOCK_SIZE bsize) {
2564233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
2565233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
2566233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
2567233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_offsets(cpi, tile, mi_row, mi_col, bsize);
2568233d2500723e5594f3e7c70896ffeeef32b9c950ywan  xd->mi[0]->mbmi.sb_type = bsize;
2569233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2570233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!frame_is_intra_only(cm)) {
2571233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_pick_inter_mode(cpi, x, tile, mi_row, mi_col,
2572233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        rate, dist, bsize);
2573233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2574233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MB_PREDICTION_MODE intramode = DC_PRED;
2575233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_mode_info(&xd->mi[0]->mbmi, bsize, intramode);
2576233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2577233d2500723e5594f3e7c70896ffeeef32b9c950ywan  duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
2578233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2579233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2580233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void fill_mode_info_sb(VP9_COMMON *cm, MACROBLOCK *x,
2581233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              int mi_row, int mi_col,
2582233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              BLOCK_SIZE bsize, BLOCK_SIZE subsize) {
2583233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *xd = &x->e_mbd;
2584233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
2585233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PARTITION_TYPE partition = partition_lookup[bsl][subsize];
2586233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2587233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(bsize >= BLOCK_8X8);
2588233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2589233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
2590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
2591233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2592233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (partition) {
2593233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_NONE:
2594233d2500723e5594f3e7c70896ffeeef32b9c950ywan      set_modeinfo_offsets(cm, xd, mi_row, mi_col);
2595233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(xd->mi[0]) = get_block_context(x, subsize)->mic;
2596233d2500723e5594f3e7c70896ffeeef32b9c950ywan      duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
2597233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2598233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_VERT:
2599233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
2600233d2500723e5594f3e7c70896ffeeef32b9c950ywan      set_modeinfo_offsets(cm, xd, mi_row, mi_col);
2601233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(xd->mi[0]) = get_block_context(x, subsize)->mic;
2602233d2500723e5594f3e7c70896ffeeef32b9c950ywan      duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
2603233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2604233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_col + hbs < cm->mi_cols) {
2605233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
2606233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_modeinfo_offsets(cm, xd, mi_row, mi_col + hbs);
2607233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *(xd->mi[0]) = get_block_context(x, subsize)->mic;
2608233d2500723e5594f3e7c70896ffeeef32b9c950ywan        duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col + hbs, bsize);
2609233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2610233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2611233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_HORZ:
2612233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
2613233d2500723e5594f3e7c70896ffeeef32b9c950ywan      set_modeinfo_offsets(cm, xd, mi_row, mi_col);
2614233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(xd->mi[0]) = get_block_context(x, subsize)->mic;
2615233d2500723e5594f3e7c70896ffeeef32b9c950ywan      duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
2616233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_row + hbs < cm->mi_rows) {
2617233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
2618233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_modeinfo_offsets(cm, xd, mi_row + hbs, mi_col);
2619233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *(xd->mi[0]) = get_block_context(x, subsize)->mic;
2620233d2500723e5594f3e7c70896ffeeef32b9c950ywan        duplicate_mode_info_in_sb(cm, xd, mi_row + hbs, mi_col, bsize);
2621233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2622233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2623233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_SPLIT:
2624233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
2625233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fill_mode_info_sb(cm, x, mi_row, mi_col, subsize,
2626233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        *(get_sb_partitioning(x, subsize)));
2627233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
2628233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fill_mode_info_sb(cm, x, mi_row, mi_col + hbs, subsize,
2629233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        *(get_sb_partitioning(x, subsize)));
2630233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 2;
2631233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fill_mode_info_sb(cm, x, mi_row + hbs, mi_col, subsize,
2632233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        *(get_sb_partitioning(x, subsize)));
2633233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 3;
2634233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fill_mode_info_sb(cm, x, mi_row + hbs, mi_col + hbs, subsize,
2635233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        *(get_sb_partitioning(x, subsize)));
2636233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2637233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default:
2638233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2639233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2640233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2641233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2642233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void nonrd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
2643233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                 TOKENEXTRA **tp, int mi_row,
2644233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                 int mi_col, BLOCK_SIZE bsize, int *rate,
2645233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                 int64_t *dist, int do_recon, int64_t best_rd) {
2646233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
2647233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
2648233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
2649233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int ms = num_8x8_blocks_wide_lookup[bsize] / 2;
2650233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TOKENEXTRA *tp_orig = *tp;
2651233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PICK_MODE_CONTEXT *ctx = get_block_context(x, bsize);
2652233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i;
2653233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE subsize;
2654233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int this_rate, sum_rate = 0, best_rate = INT_MAX;
2655233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t this_dist, sum_dist = 0, best_dist = INT64_MAX;
2656233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t sum_rd = 0;
2657233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int do_split = bsize >= BLOCK_8X8;
2658233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int do_rect = 1;
2659233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Override skipping rectangular partition operations for edge blocks
2660233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int force_horz_split = (mi_row + ms >= cm->mi_rows);
2661233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int force_vert_split = (mi_col + ms >= cm->mi_cols);
2662233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int xss = x->e_mbd.plane[1].subsampling_x;
2663233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int yss = x->e_mbd.plane[1].subsampling_y;
2664233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2665233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int partition_none_allowed = !force_horz_split && !force_vert_split;
2666233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int partition_horz_allowed = !force_vert_split && yss <= xss &&
2667233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               bsize >= BLOCK_8X8;
2668233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int partition_vert_allowed = !force_horz_split && xss <= yss &&
2669233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               bsize >= BLOCK_8X8;
2670233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (void) *tp_orig;
2671233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2672233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_8X8) {
2673233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0
2674233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // there is nothing to be done.
2675233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (x->ab_index != 0) {
2676233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *rate = 0;
2677233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *dist = 0;
2678233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
2679233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2680233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2681233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2682233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(num_8x8_blocks_wide_lookup[bsize] ==
2683233d2500723e5594f3e7c70896ffeeef32b9c950ywan             num_8x8_blocks_high_lookup[bsize]);
2684233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2685233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->in_active_map = check_active_map(cpi, x, mi_row, mi_col, bsize);
2686233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2687233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Determine partition types in search according to the speed features.
2688233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // The threshold set here has to be of square block size.
2689233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.auto_min_max_partition_size) {
2690233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_none_allowed &= (bsize <= cpi->sf.max_partition_size &&
2691233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               bsize >= cpi->sf.min_partition_size);
2692233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_horz_allowed &= ((bsize <= cpi->sf.max_partition_size &&
2693233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                bsize >  cpi->sf.min_partition_size) ||
2694233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                force_horz_split);
2695233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_vert_allowed &= ((bsize <= cpi->sf.max_partition_size &&
2696233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                bsize >  cpi->sf.min_partition_size) ||
2697233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                force_vert_split);
2698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do_split &= bsize > cpi->sf.min_partition_size;
2699233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2700233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.use_square_partition_only) {
2701233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_horz_allowed &= force_horz_split;
2702233d2500723e5594f3e7c70896ffeeef32b9c950ywan    partition_vert_allowed &= force_vert_split;
2703233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2704233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2705233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!x->in_active_map && (partition_horz_allowed || partition_vert_allowed))
2706233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do_split = 0;
2707233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2708233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_NONE
2709233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition_none_allowed) {
2710233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col,
2711233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        &this_rate, &this_dist, bsize);
2712233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->mic.mbmi = xd->mi[0]->mbmi;
2713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2714233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (this_rate != INT_MAX) {
2715233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2716233d2500723e5594f3e7c70896ffeeef32b9c950ywan      this_rate += x->partition_cost[pl][PARTITION_NONE];
2717233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_dist);
2718233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (sum_rd < best_rd) {
2719233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int64_t stop_thresh = 4096;
2720233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int64_t stop_thresh_rd;
2721233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2722233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rate = this_rate;
2723233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_dist = this_dist;
2724233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_rd = sum_rd;
2725233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (bsize >= BLOCK_8X8)
2726233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *(get_sb_partitioning(x, bsize)) = bsize;
2727233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2728233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // Adjust threshold according to partition size.
2729233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stop_thresh >>= 8 - (b_width_log2_lookup[bsize] +
2730233d2500723e5594f3e7c70896ffeeef32b9c950ywan            b_height_log2_lookup[bsize]);
2731233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2732233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stop_thresh_rd = RDCOST(x->rdmult, x->rddiv, 0, stop_thresh);
2733233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // If obtained distortion is very small, choose current partition
2734233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // and stop splitting.
2735233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!x->e_mbd.lossless && best_rd < stop_thresh_rd) {
2736233d2500723e5594f3e7c70896ffeeef32b9c950ywan          do_split = 0;
2737233d2500723e5594f3e7c70896ffeeef32b9c950ywan          do_rect = 0;
2738233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
2739233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2740233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2741233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!x->in_active_map) {
2742233d2500723e5594f3e7c70896ffeeef32b9c950ywan      do_split = 0;
2743233d2500723e5594f3e7c70896ffeeef32b9c950ywan      do_rect = 0;
2744233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2745233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2747233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // store estimated motion vector
2748233d2500723e5594f3e7c70896ffeeef32b9c950ywan  store_pred_mv(x, ctx);
2749233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2750233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_SPLIT
2751233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum_rd = 0;
2752233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (do_split) {
2753233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2754233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sum_rate += x->partition_cost[pl][PARTITION_SPLIT];
2755233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = get_subsize(bsize, PARTITION_SPLIT);
2756233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < 4 && sum_rd < best_rd; ++i) {
2757233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int x_idx = (i & 1) * ms;
2758233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int y_idx = (i >> 1) * ms;
2759233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2760233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols)
2761233d2500723e5594f3e7c70896ffeeef32b9c950ywan        continue;
2762233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2763233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = i;
2764233d2500723e5594f3e7c70896ffeeef32b9c950ywan      load_pred_mv(x, ctx);
2765233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2766233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx,
2767233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           subsize, &this_rate, &this_dist, 0,
2768233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           best_rd - sum_rd);
2769233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2770233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (this_rate == INT_MAX) {
2771233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = INT64_MAX;
2772233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2773233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rate += this_rate;
2774233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_dist += this_dist;
2775233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2776233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2777233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2778233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2779233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd) {
2780233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_rate = sum_rate;
2781233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_dist = sum_dist;
2782233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_rd = sum_rd;
2783233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = subsize;
2784233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
2785233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // skip rectangular partition test when larger block size
2786233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // gives better rd cost
2787233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cpi->sf.less_rectangular_check)
2788233d2500723e5594f3e7c70896ffeeef32b9c950ywan        do_rect &= !partition_none_allowed;
2789233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2790233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2791233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2792233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_HORZ
2793233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition_horz_allowed && do_rect) {
2794233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = get_subsize(bsize, PARTITION_HORZ);
2795233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *get_sb_index(x, subsize) = 0;
2796233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.adaptive_motion_search)
2797233d2500723e5594f3e7c70896ffeeef32b9c950ywan      load_pred_mv(x, ctx);
2798233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2799233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col,
2800233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        &this_rate, &this_dist, subsize);
2801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2802233d2500723e5594f3e7c70896ffeeef32b9c950ywan    get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2803233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2804233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2805233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2806233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd && mi_row + ms < cm->mi_rows) {
2807233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
2808233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2809233d2500723e5594f3e7c70896ffeeef32b9c950ywan      load_pred_mv(x, ctx);
2810233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2811233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_pick_sb_modes(cpi, tile, mi_row + ms, mi_col,
2812233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          &this_rate, &this_dist, subsize);
2813233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2814233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2815233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2816233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (this_rate == INT_MAX) {
2817233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = INT64_MAX;
2818233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2819233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2820233d2500723e5594f3e7c70896ffeeef32b9c950ywan        this_rate += x->partition_cost[pl][PARTITION_HORZ];
2821233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rate += this_rate;
2822233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_dist += this_dist;
2823233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2824233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2825233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2826233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd) {
2827233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_rd = sum_rd;
2828233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_rate = sum_rate;
2829233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_dist = sum_dist;
2830233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = subsize;
2831233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2832233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2833233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2834233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // PARTITION_VERT
2835233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (partition_vert_allowed && do_rect) {
2836233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = get_subsize(bsize, PARTITION_VERT);
2837233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2838233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *get_sb_index(x, subsize) = 0;
2839233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.adaptive_motion_search)
2840233d2500723e5594f3e7c70896ffeeef32b9c950ywan      load_pred_mv(x, ctx);
2841233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2842233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col,
2843233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        &this_rate, &this_dist, subsize);
2844233d2500723e5594f3e7c70896ffeeef32b9c950ywan    get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2845233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2846233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd && mi_col + ms < cm->mi_cols) {
2847233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
2848233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2849233d2500723e5594f3e7c70896ffeeef32b9c950ywan      load_pred_mv(x, ctx);
2850233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2851233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col + ms,
2852233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          &this_rate, &this_dist, subsize);
2853233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2854233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2855233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2856233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (this_rate == INT_MAX) {
2857233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = INT64_MAX;
2858233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
2859233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
2860233d2500723e5594f3e7c70896ffeeef32b9c950ywan        this_rate += x->partition_cost[pl][PARTITION_VERT];
2861233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rate += this_rate;
2862233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_dist += this_dist;
2863233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist);
2864233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2865233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2866233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (sum_rd < best_rd) {
2867233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_rate = sum_rate;
2868233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_dist = sum_dist;
2869233d2500723e5594f3e7c70896ffeeef32b9c950ywan      best_rd = sum_rd;
2870233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *(get_sb_partitioning(x, bsize)) = subsize;
2871233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2872233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2873233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2874233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *rate = best_rate;
2875233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *dist = best_dist;
2876233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2877233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (best_rate == INT_MAX)
2878233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
2879233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2880233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // update mode info array
2881233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fill_mode_info_sb(cm, x, mi_row, mi_col, bsize,
2882233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    *(get_sb_partitioning(x, bsize)));
2883233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2884233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (best_rate < INT_MAX && best_dist < INT64_MAX && do_recon) {
2885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int output_enabled = (bsize == BLOCK_64X64);
2886233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2887233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check the projected output rate for this SB against it's target
2888233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // and and if necessary apply a Q delta using segmentation to get
2889233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // closer to the target.
2890233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
2891233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled,
2892233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    best_rate);
2893233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2894233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2895233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
2896233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
2897233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              best_rate, best_dist);
2898233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encode_sb_rt(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize);
2900233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2901233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2902233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize == BLOCK_64X64) {
2903233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(tp_orig < *tp);
2904233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(best_rate < INT_MAX);
2905233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(best_dist < INT64_MAX);
2906233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2907233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(tp_orig == *tp);
2908233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2909233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2910233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2911233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void nonrd_use_partition(VP9_COMP *cpi,
2912233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                const TileInfo *const tile,
2913233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                MODE_INFO **mi_8x8,
2914233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                TOKENEXTRA **tp,
2915233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                int mi_row, int mi_col,
2916233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                BLOCK_SIZE bsize, int output_enabled,
2917233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                int *totrate, int64_t *totdist) {
2918233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
2919233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
2920233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
2921233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
2922233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
2923233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PARTITION_TYPE partition;
2924233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE subsize;
2925233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int rate = INT_MAX;
2926233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t dist = INT64_MAX;
2927233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2928233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
2929233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
2930233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2931233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize >= BLOCK_8X8) {
2932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = mi_8x8[0]->mbmi.sb_type;
2933233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2934233d2500723e5594f3e7c70896ffeeef32b9c950ywan    subsize = BLOCK_4X4;
2935233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2936233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2937233d2500723e5594f3e7c70896ffeeef32b9c950ywan  partition = partition_lookup[bsl][subsize];
2938233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2939233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (partition) {
2940233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_NONE:
2941233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col, totrate, totdist, subsize);
2942233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2943233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2944233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_VERT:
2945233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
2946233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col, totrate, totdist, subsize);
2947233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2948233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_col + hbs < cm->mi_cols) {
2949233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
2950233d2500723e5594f3e7c70896ffeeef32b9c950ywan        nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col + hbs,
2951233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            &rate, &dist, subsize);
2952233d2500723e5594f3e7c70896ffeeef32b9c950ywan        get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2953233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (rate != INT_MAX && dist != INT64_MAX &&
2954233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *totrate != INT_MAX && *totdist != INT64_MAX) {
2955233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *totrate += rate;
2956233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *totdist += dist;
2957233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
2958233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2959233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2960233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_HORZ:
2961233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
2962233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_pick_sb_modes(cpi, tile, mi_row, mi_col, totrate, totdist, subsize);
2963233d2500723e5594f3e7c70896ffeeef32b9c950ywan      get_block_context(x, subsize)->mic.mbmi = xd->mi[0]->mbmi;
2964233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mi_row + hbs < cm->mi_rows) {
2965233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *get_sb_index(x, subsize) = 1;
2966233d2500723e5594f3e7c70896ffeeef32b9c950ywan        nonrd_pick_sb_modes(cpi, tile, mi_row + hbs, mi_col,
2967233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            &rate, &dist, subsize);
2968233d2500723e5594f3e7c70896ffeeef32b9c950ywan        get_block_context(x, subsize)->mic.mbmi = mi_8x8[0]->mbmi;
2969233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (rate != INT_MAX && dist != INT64_MAX &&
2970233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *totrate != INT_MAX && *totdist != INT64_MAX) {
2971233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *totrate += rate;
2972233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *totdist += dist;
2973233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
2974233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2975233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
2976233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case PARTITION_SPLIT:
2977233d2500723e5594f3e7c70896ffeeef32b9c950ywan      subsize = get_subsize(bsize, PARTITION_SPLIT);
2978233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 0;
2979233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col,
2980233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          subsize, output_enabled, totrate, totdist);
2981233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 1;
2982233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_use_partition(cpi, tile, mi_8x8 + hbs, tp,
2983233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          mi_row, mi_col + hbs, subsize, output_enabled,
2984233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          &rate, &dist);
2985233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (rate != INT_MAX && dist != INT64_MAX &&
2986233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *totrate != INT_MAX && *totdist != INT64_MAX) {
2987233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *totrate += rate;
2988233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *totdist += dist;
2989233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2990233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 2;
2991233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_use_partition(cpi, tile, mi_8x8 + hbs * mis, tp,
2992233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          mi_row + hbs, mi_col, subsize, output_enabled,
2993233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          &rate, &dist);
2994233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (rate != INT_MAX && dist != INT64_MAX &&
2995233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *totrate != INT_MAX && *totdist != INT64_MAX) {
2996233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *totrate += rate;
2997233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *totdist += dist;
2998233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2999233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *get_sb_index(x, subsize) = 3;
3000233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nonrd_use_partition(cpi, tile, mi_8x8 + hbs * mis + hbs, tp,
3001233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          mi_row + hbs, mi_col + hbs, subsize, output_enabled,
3002233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          &rate, &dist);
3003233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (rate != INT_MAX && dist != INT64_MAX &&
3004233d2500723e5594f3e7c70896ffeeef32b9c950ywan          *totrate != INT_MAX && *totdist != INT64_MAX) {
3005233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *totrate += rate;
3006233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *totdist += dist;
3007233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3008233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
3009233d2500723e5594f3e7c70896ffeeef32b9c950ywan    default:
3010233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert("Invalid partition type.");
3011233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3012233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3013233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize == BLOCK_64X64 && output_enabled) {
3014233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
3015233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
3016233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              *totrate, *totdist);
3017233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encode_sb_rt(cpi, tile, tp, mi_row, mi_col, 1, bsize);
3018233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3019233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3020233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3021233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_nonrd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
3022233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                int mi_row, TOKENEXTRA **tp) {
3023233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *cm = &cpi->common;
3024233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *xd = &cpi->mb.e_mbd;
3025233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_col;
3026233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3027233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Initialize the left context for the new SB row
3028233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memset(&xd->left_context, 0, sizeof(xd->left_context));
3029233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_memset(xd->left_seg_context, 0, sizeof(xd->left_seg_context));
3030233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3031233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Code each SB in the row
3032233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
3033233d2500723e5594f3e7c70896ffeeef32b9c950ywan       mi_col += MI_BLOCK_SIZE) {
3034233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int dummy_rate = 0;
3035233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int64_t dummy_dist = 0;
3036233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int idx_str = cm->mi_stride * mi_row + mi_col;
3037233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
3038233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MODE_INFO **prev_mi_8x8 = cm->prev_mi_grid_visible + idx_str;
3039233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3040233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BLOCK_SIZE bsize = cpi->sf.partition_search_type == FIXED_PARTITION ?
3041233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cpi->sf.always_this_block_size :
3042233d2500723e5594f3e7c70896ffeeef32b9c950ywan        get_nonrd_var_based_fixed_partition(cpi, mi_row, mi_col);
3043233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3044233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.source_variance = UINT_MAX;
3045233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_zero(cpi->mb.pred_mv);
3046233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3047233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Set the partition type of the 64X64 block
3048233d2500723e5594f3e7c70896ffeeef32b9c950ywan    switch (cpi->sf.partition_search_type) {
3049233d2500723e5594f3e7c70896ffeeef32b9c950ywan      case VAR_BASED_PARTITION:
3050233d2500723e5594f3e7c70896ffeeef32b9c950ywan        choose_partitioning(cpi, tile, mi_row, mi_col);
3051233d2500723e5594f3e7c70896ffeeef32b9c950ywan        nonrd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
3052233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            1, &dummy_rate, &dummy_dist);
3053233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
3054233d2500723e5594f3e7c70896ffeeef32b9c950ywan      case VAR_BASED_FIXED_PARTITION:
3055233d2500723e5594f3e7c70896ffeeef32b9c950ywan      case FIXED_PARTITION:
3056233d2500723e5594f3e7c70896ffeeef32b9c950ywan        set_fixed_partitioning(cpi, tile, mi_8x8, mi_row, mi_col, bsize);
3057233d2500723e5594f3e7c70896ffeeef32b9c950ywan        nonrd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col, BLOCK_64X64,
3058233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            1, &dummy_rate, &dummy_dist);
3059233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
3060233d2500723e5594f3e7c70896ffeeef32b9c950ywan      case REFERENCE_PARTITION:
3061233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (cpi->sf.partition_check || sb_has_motion(cm, prev_mi_8x8)) {
3062233d2500723e5594f3e7c70896ffeeef32b9c950ywan          nonrd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64,
3063233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               &dummy_rate, &dummy_dist, 1, INT64_MAX);
3064233d2500723e5594f3e7c70896ffeeef32b9c950ywan        } else {
3065233d2500723e5594f3e7c70896ffeeef32b9c950ywan          copy_partitioning(cm, mi_8x8, prev_mi_8x8);
3066233d2500723e5594f3e7c70896ffeeef32b9c950ywan          nonrd_use_partition(cpi, tile, mi_8x8, tp, mi_row, mi_col,
3067233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              BLOCK_64X64, 1, &dummy_rate, &dummy_dist);
3068233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3069233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
3070233d2500723e5594f3e7c70896ffeeef32b9c950ywan      default:
3071233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(0);
3072233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3073233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3074233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3075233d2500723e5594f3e7c70896ffeeef32b9c950ywan// end RTC play code
3076233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3077233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_frame_internal(VP9_COMP *cpi) {
3078233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mi_row;
3079233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
3080233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
3081233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
3082233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3083233d2500723e5594f3e7c70896ffeeef32b9c950ywan//  fprintf(stderr, "encode_frame_internal frame %d (%d) type %d\n",
3084233d2500723e5594f3e7c70896ffeeef32b9c950ywan//           cpi->common.current_video_frame, cpi->common.show_frame,
3085233d2500723e5594f3e7c70896ffeeef32b9c950ywan//           cm->frame_type);
3086233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3087233d2500723e5594f3e7c70896ffeeef32b9c950ywan  xd->mi = cm->mi_grid_visible;
3088233d2500723e5594f3e7c70896ffeeef32b9c950ywan  xd->mi[0] = cm->mi;
3089233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3090233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(cm->counts);
3091233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(cpi->coef_counts);
3092233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(cpi->tx_stepdown_count);
3093233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3094233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Set frame level transform size use case
3095233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cm->tx_mode = select_tx_mode(cpi);
3096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3097233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cpi->mb.e_mbd.lossless = cm->base_qindex == 0 && cm->y_dc_delta_q == 0
3098233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
3099233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch_lossless_mode(cpi, cpi->mb.e_mbd.lossless);
3100233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_frame_init_quantizer(cpi);
3102233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_initialize_rd_consts(cpi);
3104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_initialize_me_consts(cpi, cm->base_qindex);
3105233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3106233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
3107233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Initialize encode frame context.
3108233d2500723e5594f3e7c70896ffeeef32b9c950ywan    init_encode_frame_mb_context(cpi);
3109233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3110233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Build a frame level activity map
3111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    build_activity_map(cpi);
3112233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Re-initialize encode frame context.
3115233d2500723e5594f3e7c70896ffeeef32b9c950ywan  init_encode_frame_mb_context(cpi);
3116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3117233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(cpi->rd_comp_pred_diff);
3118233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(cpi->rd_filter_diff);
3119233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(cpi->rd_tx_select_diff);
3120233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_zero(cpi->rd_tx_select_threshes);
3121233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_prev_mi(cm);
3123233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3124233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.use_nonrd_pick_mode) {
3125233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Initialize internal buffer pointers for rtc coding, where non-RD
3126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // mode decision is used and hence no buffer pointer swap needed.
3127233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int i;
3128233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct macroblock_plane *const p = x->plane;
3129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct macroblockd_plane *const pd = xd->plane;
3130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    PICK_MODE_CONTEXT *ctx = &cpi->mb.sb64_context;
3131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3132233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < MAX_MB_PLANE; ++i) {
3133233d2500723e5594f3e7c70896ffeeef32b9c950ywan      p[i].coeff = ctx->coeff_pbuf[i][0];
3134233d2500723e5594f3e7c70896ffeeef32b9c950ywan      p[i].qcoeff = ctx->qcoeff_pbuf[i][0];
3135233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][0];
3136233d2500723e5594f3e7c70896ffeeef32b9c950ywan      p[i].eobs = ctx->eobs_pbuf[i][0];
3137233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3138233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_zero(x->zcoeff_blk);
3139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {
3142233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct vpx_usec_timer emr_timer;
3143233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_usec_timer_start(&emr_timer);
3144233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3146233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Take tiles into account and give start/end MB
3147233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int tile_col, tile_row;
3148233d2500723e5594f3e7c70896ffeeef32b9c950ywan      TOKENEXTRA *tp = cpi->tok;
3149233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int tile_cols = 1 << cm->log2_tile_cols;
3150233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int tile_rows = 1 << cm->log2_tile_rows;
3151233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3152233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (tile_row = 0; tile_row < tile_rows; tile_row++) {
3153233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (tile_col = 0; tile_col < tile_cols; tile_col++) {
3154233d2500723e5594f3e7c70896ffeeef32b9c950ywan          TileInfo tile;
3155233d2500723e5594f3e7c70896ffeeef32b9c950ywan          TOKENEXTRA *tp_old = tp;
3156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3157233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // For each row of SBs in the frame
3158233d2500723e5594f3e7c70896ffeeef32b9c950ywan          vp9_tile_init(&tile, cm, tile_row, tile_col);
3159233d2500723e5594f3e7c70896ffeeef32b9c950ywan          for (mi_row = tile.mi_row_start;
3160233d2500723e5594f3e7c70896ffeeef32b9c950ywan               mi_row < tile.mi_row_end; mi_row += MI_BLOCK_SIZE) {
3161233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (cpi->sf.use_nonrd_pick_mode && cm->frame_type != KEY_FRAME)
3162233d2500723e5594f3e7c70896ffeeef32b9c950ywan              encode_nonrd_sb_row(cpi, &tile, mi_row, &tp);
3163233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else
3164233d2500723e5594f3e7c70896ffeeef32b9c950ywan              encode_rd_sb_row(cpi, &tile, mi_row, &tp);
3165233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
3166233d2500723e5594f3e7c70896ffeeef32b9c950ywan          cpi->tok_count[tile_row][tile_col] = (unsigned int)(tp - tp_old);
3167233d2500723e5594f3e7c70896ffeeef32b9c950ywan          assert(tp - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
3168233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3169233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3170233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3171233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3172233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_usec_timer_mark(&emr_timer);
3173233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->time_encode_sb_row += vpx_usec_timer_elapsed(&emr_timer);
3174233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3175233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3176233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.skip_encode_sb) {
3177233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int j;
3178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int intra_count = 0, inter_count = 0;
3179233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (j = 0; j < INTRA_INTER_CONTEXTS; ++j) {
3180233d2500723e5594f3e7c70896ffeeef32b9c950ywan      intra_count += cm->counts.intra_inter[j][0];
3181233d2500723e5594f3e7c70896ffeeef32b9c950ywan      inter_count += cm->counts.intra_inter[j][1];
3182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3183233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->sf.skip_encode_frame = (intra_count << 2) < inter_count &&
3184233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                cm->frame_type != KEY_FRAME &&
3185233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                cm->show_frame;
3186233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
3187233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->sf.skip_encode_frame = 0;
3188233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3190233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
3191233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Keep record of the total distortion this time around for future use
3192233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cpi->last_frame_distortion = cpi->frame_distortion;
3193233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
3194233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3195233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3196233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_encode_frame(VP9_COMP *cpi) {
3197233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
3198233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3199233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // In the longer term the encoder should be generalized to match the
3200233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // decoder such that we allow compound where one of the 3 buffers has a
3201233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // different sign bias and that buffer is then the fixed ref. However, this
3202233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // requires further work in the rd loop. For now the only supported encoder
3203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // side behavior is where the ALT ref buffer has opposite sign bias to
3204233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // the other two.
3205233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!frame_is_intra_only(cm)) {
3206233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((cm->ref_frame_sign_bias[ALTREF_FRAME] ==
3207233d2500723e5594f3e7c70896ffeeef32b9c950ywan             cm->ref_frame_sign_bias[GOLDEN_FRAME]) ||
3208233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (cm->ref_frame_sign_bias[ALTREF_FRAME] ==
3209233d2500723e5594f3e7c70896ffeeef32b9c950ywan             cm->ref_frame_sign_bias[LAST_FRAME])) {
3210233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cm->allow_comp_inter_inter = 0;
3211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
3212233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cm->allow_comp_inter_inter = 1;
3213233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cm->comp_fixed_ref = ALTREF_FRAME;
3214233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cm->comp_var_ref[0] = LAST_FRAME;
3215233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cm->comp_var_ref[1] = GOLDEN_FRAME;
3216233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3217233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3219233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cpi->sf.frame_parameter_update) {
3220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int i;
3221233d2500723e5594f3e7c70896ffeeef32b9c950ywan    REFERENCE_MODE reference_mode;
3222233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /*
3223233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * This code does a single RD pass over the whole frame assuming
3224233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * either compound, single or hybrid prediction as per whatever has
3225233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * worked best for that type of frame in the past.
3226233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * It also predicts whether another coding mode would have worked
3227233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * better that this coding mode. If that is the case, it remembers
3228233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * that for subsequent frames.
3229233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * It does the same analysis for transform size selection also.
3230233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
3231233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
3232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int64_t *mode_thresh = cpi->rd_prediction_type_threshes[frame_type];
3233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int64_t *filter_thresh = cpi->rd_filter_threshes[frame_type];
3234233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* prediction (compound, single or hybrid) mode selection */
3236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (frame_type == 3 || !cm->allow_comp_inter_inter)
3237233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reference_mode = SINGLE_REFERENCE;
3238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (mode_thresh[COMPOUND_REFERENCE] > mode_thresh[SINGLE_REFERENCE] &&
3239233d2500723e5594f3e7c70896ffeeef32b9c950ywan             mode_thresh[COMPOUND_REFERENCE] >
3240233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 mode_thresh[REFERENCE_MODE_SELECT] &&
3241233d2500723e5594f3e7c70896ffeeef32b9c950ywan             check_dual_ref_flags(cpi) &&
3242233d2500723e5594f3e7c70896ffeeef32b9c950ywan             cpi->static_mb_pct == 100)
3243233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reference_mode = COMPOUND_REFERENCE;
3244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (mode_thresh[SINGLE_REFERENCE] > mode_thresh[REFERENCE_MODE_SELECT])
3245233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reference_mode = SINGLE_REFERENCE;
3246233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
3247233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reference_mode = REFERENCE_MODE_SELECT;
3248233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3249233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->interp_filter == SWITCHABLE) {
3250233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (frame_type != ALTREF_FRAME &&
3251233d2500723e5594f3e7c70896ffeeef32b9c950ywan          filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP] &&
3252233d2500723e5594f3e7c70896ffeeef32b9c950ywan          filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP_SHARP] &&
3253233d2500723e5594f3e7c70896ffeeef32b9c950ywan          filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[SWITCHABLE - 1]) {
3254233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->interp_filter = EIGHTTAP_SMOOTH;
3255233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (filter_thresh[EIGHTTAP_SHARP] > filter_thresh[EIGHTTAP] &&
3256233d2500723e5594f3e7c70896ffeeef32b9c950ywan          filter_thresh[EIGHTTAP_SHARP] > filter_thresh[SWITCHABLE - 1]) {
3257233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->interp_filter = EIGHTTAP_SHARP;
3258233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (filter_thresh[EIGHTTAP] > filter_thresh[SWITCHABLE - 1]) {
3259233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->interp_filter = EIGHTTAP;
3260233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3262233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.e_mbd.lossless = cpi->oxcf.lossless;
3264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->reference_mode = reference_mode;
3265233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3266233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encode_frame_internal(cpi);
3267233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < REFERENCE_MODES; ++i) {
3269233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int diff = (int) (cpi->rd_comp_pred_diff[i] / cm->MBs);
3270233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->rd_prediction_type_threshes[frame_type][i] += diff;
3271233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->rd_prediction_type_threshes[frame_type][i] >>= 1;
3272233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3273233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3274233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
3275233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int64_t diff = cpi->rd_filter_diff[i] / cm->MBs;
3276233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->rd_filter_threshes[frame_type][i] =
3277233d2500723e5594f3e7c70896ffeeef32b9c950ywan          (cpi->rd_filter_threshes[frame_type][i] + diff) / 2;
3278233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3279233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < TX_MODES; ++i) {
3281233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int64_t pd = cpi->rd_tx_select_diff[i];
3282233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int diff;
3283233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (i == TX_MODE_SELECT)
3284233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pd -= RDCOST(cpi->mb.rdmult, cpi->mb.rddiv, 2048 * (TX_SIZES - 1), 0);
3285233d2500723e5594f3e7c70896ffeeef32b9c950ywan      diff = (int) (pd / cm->MBs);
3286233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->rd_tx_select_threshes[frame_type][i] += diff;
3287233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->rd_tx_select_threshes[frame_type][i] /= 2;
3288233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3289233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3290233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
3291233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int single_count_zero = 0;
3292233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int comp_count_zero = 0;
3293233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3294233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < COMP_INTER_CONTEXTS; i++) {
3295233d2500723e5594f3e7c70896ffeeef32b9c950ywan        single_count_zero += cm->counts.comp_inter[i][0];
3296233d2500723e5594f3e7c70896ffeeef32b9c950ywan        comp_count_zero += cm->counts.comp_inter[i][1];
3297233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3298233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3299233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (comp_count_zero == 0) {
3300233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->reference_mode = SINGLE_REFERENCE;
3301233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp9_zero(cm->counts.comp_inter);
3302233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (single_count_zero == 0) {
3303233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->reference_mode = COMPOUND_REFERENCE;
3304233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp9_zero(cm->counts.comp_inter);
3305233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3306233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3307233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3308233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->tx_mode == TX_MODE_SELECT) {
3309233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int count4x4 = 0;
3310233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int count8x8_lp = 0, count8x8_8x8p = 0;
3311233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int count16x16_16x16p = 0, count16x16_lp = 0;
3312233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int count32x32 = 0;
3313233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3314233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < TX_SIZE_CONTEXTS; ++i) {
3315233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count4x4 += cm->counts.tx.p32x32[i][TX_4X4];
3316233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count4x4 += cm->counts.tx.p16x16[i][TX_4X4];
3317233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count4x4 += cm->counts.tx.p8x8[i][TX_4X4];
3318233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3319233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count8x8_lp += cm->counts.tx.p32x32[i][TX_8X8];
3320233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count8x8_lp += cm->counts.tx.p16x16[i][TX_8X8];
3321233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count8x8_8x8p += cm->counts.tx.p8x8[i][TX_8X8];
3322233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3323233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count16x16_16x16p += cm->counts.tx.p16x16[i][TX_16X16];
3324233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count16x16_lp += cm->counts.tx.p32x32[i][TX_16X16];
3325233d2500723e5594f3e7c70896ffeeef32b9c950ywan        count32x32 += cm->counts.tx.p32x32[i][TX_32X32];
3326233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3327233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3328233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 &&
3329233d2500723e5594f3e7c70896ffeeef32b9c950ywan          count32x32 == 0) {
3330233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->tx_mode = ALLOW_8X8;
3331233d2500723e5594f3e7c70896ffeeef32b9c950ywan        reset_skip_txfm_size(cm, TX_8X8);
3332233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (count8x8_8x8p == 0 && count16x16_16x16p == 0 &&
3333233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) {
3334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->tx_mode = ONLY_4X4;
3335233d2500723e5594f3e7c70896ffeeef32b9c950ywan        reset_skip_txfm_size(cm, TX_4X4);
3336233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) {
3337233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->tx_mode = ALLOW_32X32;
3338233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else if (count32x32 == 0 && count8x8_lp == 0 && count4x4 == 0) {
3339233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->tx_mode = ALLOW_16X16;
3340233d2500723e5594f3e7c70896ffeeef32b9c950ywan        reset_skip_txfm_size(cm, TX_16X16);
3341233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3342233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3343233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
3344233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->mb.e_mbd.lossless = cpi->oxcf.lossless;
3345233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->reference_mode = SINGLE_REFERENCE;
3346233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Force the usage of the BILINEAR interp_filter.
3347233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->interp_filter = BILINEAR;
3348233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encode_frame_internal(cpi);
3349233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3350233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3351233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3352233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) {
3353233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MB_PREDICTION_MODE y_mode = mi->mbmi.mode;
3354233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const MB_PREDICTION_MODE uv_mode = mi->mbmi.uv_mode;
3355233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const BLOCK_SIZE bsize = mi->mbmi.sb_type;
3356233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3357233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bsize < BLOCK_8X8) {
3358233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int idx, idy;
3359233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
3360233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
3361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (idy = 0; idy < 2; idy += num_4x4_h)
3362233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (idx = 0; idx < 2; idx += num_4x4_w)
3363233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++counts->y_mode[0][mi->bmi[idy * 2 + idx].as_mode];
3364233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
3365233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++counts->y_mode[size_group_lookup[bsize]][y_mode];
3366233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3367233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3368233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ++counts->uv_mode[y_mode][uv_mode];
3369233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3370233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3371233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Experimental stub function to create a per MB zbin adjustment based on
3372233d2500723e5594f3e7c70896ffeeef32b9c950ywan// some previously calculated measure of MB activity.
3373233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void adjust_act_zbin(VP9_COMP *cpi, MACROBLOCK *x) {
3374233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if USE_ACT_INDEX
3375233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->act_zbin_adj = *(x->mb_activity_ptr);
3376233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
3377233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Apply the masking to the RD multiplier.
3378233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64_t act = *(x->mb_activity_ptr);
3379233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64_t a = act + 4 * cpi->activity_avg;
3380233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64_t b = 4 * act + cpi->activity_avg;
3381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3382233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (act > cpi->activity_avg)
3383233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->act_zbin_adj = (int) (((int64_t) b + (a >> 1)) / a) - 1;
3384233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else
3385233d2500723e5594f3e7c70896ffeeef32b9c950ywan    x->act_zbin_adj = 1 - (int) (((int64_t) a + (b >> 1)) / b);
3386233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
3387233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3388233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3389233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int get_zbin_mode_boost(const MB_MODE_INFO *mbmi, int enabled) {
3390233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (enabled) {
3391233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (is_inter_block(mbmi)) {
3392233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (mbmi->mode == ZEROMV) {
3393233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return mbmi->ref_frame[0] != LAST_FRAME ? GF_ZEROMV_ZBIN_BOOST
3394233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                : LF_ZEROMV_ZBIN_BOOST;
3395233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
3396233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return mbmi->sb_type < BLOCK_8X8 ? SPLIT_MV_ZBIN_BOOST
3397233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         : MV_ZBIN_BOOST;
3398233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3399233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
3400233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return INTRA_ZBIN_BOOST;
3401233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3402233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
3403233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
3404233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3405233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3406233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3407233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
3408233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              int mi_row, int mi_col, BLOCK_SIZE bsize) {
3409233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
3410233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCK *const x = &cpi->mb;
3411233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MACROBLOCKD *const xd = &x->e_mbd;
3412233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO **mi_8x8 = xd->mi;
3413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MODE_INFO *mi = mi_8x8[0];
3414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MB_MODE_INFO *mbmi = &mi->mbmi;
3415233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PICK_MODE_CONTEXT *ctx = get_block_context(x, bsize);
3416233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int segment_id = mbmi->segment_id;
3417233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mis = cm->mi_stride;
3418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_width = num_8x8_blocks_wide_lookup[bsize];
3419233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int mi_height = num_8x8_blocks_high_lookup[bsize];
3420233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3421233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->skip_recode = !x->select_txfm_size && mbmi->sb_type >= BLOCK_8X8 &&
3422233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   cpi->oxcf.aq_mode != COMPLEXITY_AQ &&
3423233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   cpi->oxcf.aq_mode != CYCLIC_REFRESH_AQ &&
3424233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   cpi->sf.allow_skip_recode;
3425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3426233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->skip_optimize = ctx->is_coded;
3427233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->is_coded = 1;
3428233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->use_lp32x32fdct = cpi->sf.use_lp32x32fdct;
3429233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x->skip_encode = (!output_enabled && cpi->sf.skip_encode_frame &&
3430233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    x->q_index < QIDX_SKIP_THRESH);
3431233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3432233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (x->skip_encode)
3433233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
3434233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3435233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cm->frame_type == KEY_FRAME) {
3436233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
3437233d2500723e5594f3e7c70896ffeeef32b9c950ywan      adjust_act_zbin(cpi, x);
3438233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_update_zbin_extra(cpi, x);
3439233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
3441233d2500723e5594f3e7c70896ffeeef32b9c950ywan    set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
3442233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
3444233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Adjust the zbin based on this MB rate.
3445233d2500723e5594f3e7c70896ffeeef32b9c950ywan      adjust_act_zbin(cpi, x);
3446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3447233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Experimental code. Special case for gf and arf zeromv modes.
3449233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Increase zbin size to suppress noise
3450233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cpi->zbin_mode_boost = get_zbin_mode_boost(mbmi,
3451233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               cpi->zbin_mode_boost_enabled);
3452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_update_zbin_extra(cpi, x);
3453233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3454233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3455233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!is_inter_block(mbmi)) {
3456233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int plane;
3457233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbmi->skip = 1;
3458233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (plane = 0; plane < MAX_MB_PLANE; ++plane)
3459233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_encode_intra_block_plane(x, MAX(bsize, BLOCK_8X8), plane);
3460233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (output_enabled)
3461233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sum_intra_stats(&cm->counts, mi);
3462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_tokenize_sb(cpi, t, !output_enabled, MAX(bsize, BLOCK_8X8));
3463233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
3464233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int ref;
3465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int is_compound = has_second_ref(mbmi);
3466233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (ref = 0; ref < 1 + is_compound; ++ref) {
3467233d2500723e5594f3e7c70896ffeeef32b9c950ywan      YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi,
3468233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                     mbmi->ref_frame[ref]);
3469233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
3470233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           &xd->block_refs[ref]->sf);
3471233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3472233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_build_inter_predictors_sb(xd, mi_row, mi_col, MAX(bsize, BLOCK_8X8));
3473233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3474233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!x->skip) {
3475233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mbmi->skip = 1;
3476233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_encode_sb(x, MAX(bsize, BLOCK_8X8));
3477233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vp9_tokenize_sb(cpi, t, !output_enabled, MAX(bsize, BLOCK_8X8));
3478233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
3479233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mbmi->skip = 1;
3480233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (output_enabled)
3481233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->counts.skip[vp9_get_skip_context(xd)][1]++;
3482233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reset_skip_context(xd, MAX(bsize, BLOCK_8X8));
3483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3484233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3485233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3486233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (output_enabled) {
3487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->tx_mode == TX_MODE_SELECT &&
3488233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mbmi->sb_type >= BLOCK_8X8  &&
3489233d2500723e5594f3e7c70896ffeeef32b9c950ywan        !(is_inter_block(mbmi) &&
3490233d2500723e5594f3e7c70896ffeeef32b9c950ywan            (mbmi->skip ||
3491233d2500723e5594f3e7c70896ffeeef32b9c950ywan             vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)))) {
3492233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++get_tx_counts(max_txsize_lookup[bsize], vp9_get_tx_size_context(xd),
3493233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      &cm->counts.tx)[mbmi->tx_size];
3494233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
3495233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int x, y;
3496233d2500723e5594f3e7c70896ffeeef32b9c950ywan      TX_SIZE tx_size;
3497233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // The new intra coding scheme requires no change of transform size
3498233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (is_inter_block(&mi->mbmi)) {
3499233d2500723e5594f3e7c70896ffeeef32b9c950ywan        tx_size = MIN(tx_mode_to_biggest_tx_size[cm->tx_mode],
3500233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      max_txsize_lookup[bsize]);
3501233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
3502233d2500723e5594f3e7c70896ffeeef32b9c950ywan        tx_size = (bsize >= BLOCK_8X8) ? mbmi->tx_size : TX_4X4;
3503233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3504233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3505233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (y = 0; y < mi_height; y++)
3506233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (x = 0; x < mi_width; x++)
3507233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (mi_col + x < cm->mi_cols && mi_row + y < cm->mi_rows)
3508233d2500723e5594f3e7c70896ffeeef32b9c950ywan            mi_8x8[mis * y + x]->mbmi.tx_size = tx_size;
3509233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3510233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3511233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3512