encodeframe.c 243 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4
5
6
7
8
9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10
11
12
13
14
15
 */

#include <limits.h>
#include <math.h>
#include <stdio.h>

Yaowu Xu's avatar
Yaowu Xu committed
16
17
18
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "./aom_config.h"
Jingning Han's avatar
Jingning Han committed
19

Yaowu Xu's avatar
Yaowu Xu committed
20
#include "aom_dsp/aom_dsp_common.h"
21
#include "aom_ports/mem.h"
Yaowu Xu's avatar
Yaowu Xu committed
22
#include "aom_ports/aom_timer.h"
23
#include "aom_ports/system_state.h"
Jingning Han's avatar
Jingning Han committed
24

25
26
27
28
29
30
31
32
33
34
35
#include "av1/common/common.h"
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
#include "av1/common/idct.h"
#include "av1/common/mvref_common.h"
#include "av1/common/pred_common.h"
#include "av1/common/quant_common.h"
#include "av1/common/reconintra.h"
#include "av1/common/reconinter.h"
#include "av1/common/seg_common.h"
#include "av1/common/tile_common.h"
Jingning Han's avatar
Jingning Han committed
36

37
38
39
#include "av1/encoder/aq_complexity.h"
#include "av1/encoder/aq_cyclicrefresh.h"
#include "av1/encoder/aq_variance.h"
40
#if CONFIG_SUPERTX
41
#include "av1/encoder/cost.h"
42
#endif
43
#if CONFIG_GLOBAL_MOTION
44
#include "av1/common/warped_motion.h"
45
#include "av1/encoder/global_motion.h"
46
#endif
47
48
49
50
51
52
53
54
55
#include "av1/encoder/encodeframe.h"
#include "av1/encoder/encodemb.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/ethread.h"
#include "av1/encoder/extend.h"
#include "av1/encoder/rd.h"
#include "av1/encoder/rdopt.h"
#include "av1/encoder/segmentation.h"
#include "av1/encoder/tokenize.h"
56
57
58
#if CONFIG_PVQ
#include "av1/encoder/pvq_encoder.h"
#endif
Yaowu Xu's avatar
Yaowu Xu committed
59
#if CONFIG_AOM_HIGHBITDEPTH
60
#define IF_HBD(...) __VA_ARGS__
61
#else
62
#define IF_HBD(...)
Yaowu Xu's avatar
Yaowu Xu committed
63
#endif  // CONFIG_AOM_HIGHBITDEPTH
64

65
66
67
68
static void encode_superblock(const AV1_COMP *const cpi, ThreadData *td,
                              TOKENEXTRA **t, RUN_TYPE dry_run, int mi_row,
                              int mi_col, BLOCK_SIZE bsize,
                              PICK_MODE_CONTEXT *ctx, int *rate);
Jingning Han's avatar
Jingning Han committed
69

70
71
72
#if CONFIG_SUPERTX
static int check_intra_b(PICK_MODE_CONTEXT *ctx);

73
74
75
76
static int check_intra_sb(const AV1_COMP *cpi, const TileInfo *const tile,
                          int mi_row, int mi_col, BLOCK_SIZE bsize,
                          PC_TREE *pc_tree);
static void predict_superblock(const AV1_COMP *const cpi, ThreadData *td,
77
78
79
#if CONFIG_EXT_INTER
                               int mi_row_ori, int mi_col_ori,
#endif  // CONFIG_EXT_INTER
80
81
82
83
                               int mi_row_pred, int mi_col_pred,
                               BLOCK_SIZE bsize_pred, int b_sub8x8, int block);
static int check_supertx_sb(BLOCK_SIZE bsize, TX_SIZE supertx_size,
                            PC_TREE *pc_tree);
84
static void predict_sb_complex(const AV1_COMP *const cpi, ThreadData *td,
85
86
                               const TileInfo *const tile, int mi_row,
                               int mi_col, int mi_row_ori, int mi_col_ori,
87
                               RUN_TYPE dry_run, BLOCK_SIZE bsize,
88
89
                               BLOCK_SIZE top_bsize, uint8_t *dst_buf[3],
                               int dst_stride[3], PC_TREE *pc_tree);
90
static void update_state_sb_supertx(const AV1_COMP *const cpi, ThreadData *td,
91
92
                                    const TileInfo *const tile, int mi_row,
                                    int mi_col, BLOCK_SIZE bsize,
93
                                    RUN_TYPE dry_run, PC_TREE *pc_tree);
94
static void rd_supertx_sb(const AV1_COMP *const cpi, ThreadData *td,
95
96
97
                          const TileInfo *const tile, int mi_row, int mi_col,
                          BLOCK_SIZE bsize, int *tmp_rate, int64_t *tmp_dist,
                          TX_TYPE *best_tx, PC_TREE *pc_tree);
98
99
#endif  // CONFIG_SUPERTX

Jingning Han's avatar
Jingning Han committed
100
101
102
103
// This is used as a reference when computing the source variance for the
//  purposes of activity masking.
// Eventually this should be replaced by custom no-reference routines,
//  which will be faster.
Yaowu Xu's avatar
Yaowu Xu committed
104
static const uint8_t AV1_VAR_OFFS[MAX_SB_SIZE] = {
105
106
107
108
109
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
110
#if CONFIG_EXT_PARTITION
111
112
113
114
115
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
116
#endif  // CONFIG_EXT_PARTITION
Jingning Han's avatar
Jingning Han committed
117
118
};

Yaowu Xu's avatar
Yaowu Xu committed
119
120
#if CONFIG_AOM_HIGHBITDEPTH
static const uint16_t AV1_HIGH_VAR_OFFS_8[MAX_SB_SIZE] = {
121
122
123
124
125
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
126
#if CONFIG_EXT_PARTITION
127
128
129
130
131
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
132
#endif  // CONFIG_EXT_PARTITION
Jingning Han's avatar
Jingning Han committed
133
134
};

Yaowu Xu's avatar
Yaowu Xu committed
135
static const uint16_t AV1_HIGH_VAR_OFFS_10[MAX_SB_SIZE] = {
136
137
138
139
140
141
142
143
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
144
#if CONFIG_EXT_PARTITION
145
146
147
148
149
150
151
152
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4
153
#endif  // CONFIG_EXT_PARTITION
Jingning Han's avatar
Jingning Han committed
154
155
};

Yaowu Xu's avatar
Yaowu Xu committed
156
static const uint16_t AV1_HIGH_VAR_OFFS_12[MAX_SB_SIZE] = {
157
158
159
160
161
162
163
164
165
166
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16,
167
#if CONFIG_EXT_PARTITION
168
169
170
171
172
173
174
175
176
177
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
  128 * 16
178
#endif  // CONFIG_EXT_PARTITION
Jingning Han's avatar
Jingning Han committed
179
};
Yaowu Xu's avatar
Yaowu Xu committed
180
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
181

182
unsigned int av1_get_sby_perpixel_variance(const AV1_COMP *cpi,
Yaowu Xu's avatar
Yaowu Xu committed
183
184
                                           const struct buf_2d *ref,
                                           BLOCK_SIZE bs) {
Jingning Han's avatar
Jingning Han committed
185
  unsigned int sse;
186
  const unsigned int var =
Yaowu Xu's avatar
Yaowu Xu committed
187
      cpi->fn_ptr[bs].vf(ref->buf, ref->stride, AV1_VAR_OFFS, 0, &sse);
Jingning Han's avatar
Jingning Han committed
188
189
190
  return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
}

Yaowu Xu's avatar
Yaowu Xu committed
191
#if CONFIG_AOM_HIGHBITDEPTH
192
unsigned int av1_high_get_sby_perpixel_variance(const AV1_COMP *cpi,
Yaowu Xu's avatar
Yaowu Xu committed
193
194
                                                const struct buf_2d *ref,
                                                BLOCK_SIZE bs, int bd) {
Jingning Han's avatar
Jingning Han committed
195
196
197
  unsigned int var, sse;
  switch (bd) {
    case 10:
Yaowu Xu's avatar
Yaowu Xu committed
198
199
200
      var =
          cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
                             CONVERT_TO_BYTEPTR(AV1_HIGH_VAR_OFFS_10), 0, &sse);
Jingning Han's avatar
Jingning Han committed
201
202
      break;
    case 12:
Yaowu Xu's avatar
Yaowu Xu committed
203
204
205
      var =
          cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
                             CONVERT_TO_BYTEPTR(AV1_HIGH_VAR_OFFS_12), 0, &sse);
Jingning Han's avatar
Jingning Han committed
206
207
208
      break;
    case 8:
    default:
209
210
      var =
          cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
Yaowu Xu's avatar
Yaowu Xu committed
211
                             CONVERT_TO_BYTEPTR(AV1_HIGH_VAR_OFFS_8), 0, &sse);
Jingning Han's avatar
Jingning Han committed
212
213
214
215
      break;
  }
  return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
}
Yaowu Xu's avatar
Yaowu Xu committed
216
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
217

218
static unsigned int get_sby_perpixel_diff_variance(const AV1_COMP *const cpi,
Jingning Han's avatar
Jingning Han committed
219
220
221
222
223
224
225
226
227
228
229
230
231
232
                                                   const struct buf_2d *ref,
                                                   int mi_row, int mi_col,
                                                   BLOCK_SIZE bs) {
  unsigned int sse, var;
  uint8_t *last_y;
  const YV12_BUFFER_CONFIG *last = get_ref_frame_buffer(cpi, LAST_FRAME);

  assert(last != NULL);
  last_y =
      &last->y_buffer[mi_row * MI_SIZE * last->y_stride + mi_col * MI_SIZE];
  var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride, last_y, last->y_stride, &sse);
  return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
}

Yaowu Xu's avatar
Yaowu Xu committed
233
234
static BLOCK_SIZE get_rd_var_based_fixed_partition(AV1_COMP *cpi, MACROBLOCK *x,
                                                   int mi_row, int mi_col) {
235
236
  unsigned int var = get_sby_perpixel_diff_variance(
      cpi, &x->plane[0].src, mi_row, mi_col, BLOCK_64X64);
Jingning Han's avatar
Jingning Han committed
237
238
239
240
241
242
243
244
245
246
247
248
  if (var < 8)
    return BLOCK_64X64;
  else if (var < 128)
    return BLOCK_32X32;
  else if (var < 2048)
    return BLOCK_16X16;
  else
    return BLOCK_8X8;
}

// Lighter version of set_offsets that only sets the mode info
// pointers.
249
250
251
252
static void set_mode_info_offsets(const AV1_COMP *const cpi,
                                  MACROBLOCK *const x, MACROBLOCKD *const xd,
                                  int mi_row, int mi_col) {
  const AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
253
254
255
  const int idx_str = xd->mi_stride * mi_row + mi_col;
  xd->mi = cm->mi_grid_visible + idx_str;
  xd->mi[0] = cm->mi + idx_str;
256
  x->mbmi_ext = cpi->mbmi_ext_base + (mi_row * cm->mi_cols + mi_col);
Jingning Han's avatar
Jingning Han committed
257
258
}

259
static void set_offsets_without_segment_id(const AV1_COMP *const cpi,
260
                                           const TileInfo *const tile,
261
262
                                           MACROBLOCK *const x, int mi_row,
                                           int mi_col, BLOCK_SIZE bsize) {
263
  const AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
264
265
266
  MACROBLOCKD *const xd = &x->e_mbd;
  const int mi_width = num_8x8_blocks_wide_lookup[bsize];
  const int mi_height = num_8x8_blocks_high_lookup[bsize];
267
268
  const int bwl = b_width_log2_lookup[AOMMAX(bsize, BLOCK_8X8)];
  const int bhl = b_height_log2_lookup[AOMMAX(bsize, BLOCK_8X8)];
Jingning Han's avatar
Jingning Han committed
269
270
271

  set_skip_context(xd, mi_row, mi_col);

272
  set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
Jingning Han's avatar
Jingning Han committed
273

274
275
#if CONFIG_VAR_TX
  xd->above_txfm_context = cm->above_txfm_context + mi_col;
276
  xd->left_txfm_context =
277
      xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
278
  xd->max_tx_size = max_txsize_lookup[bsize];
279
280
#endif

Jingning Han's avatar
Jingning Han committed
281
  // Set up destination pointers.
Yaowu Xu's avatar
Yaowu Xu committed
282
  av1_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
Jingning Han's avatar
Jingning Han committed
283
284
285

  // Set up limit values for MV components.
  // Mv beyond the range do not produce new/different prediction block.
Yaowu Xu's avatar
Yaowu Xu committed
286
287
288
289
  x->mv_row_min = -(((mi_row + mi_height) * MI_SIZE) + AOM_INTERP_EXTEND);
  x->mv_col_min = -(((mi_col + mi_width) * MI_SIZE) + AOM_INTERP_EXTEND);
  x->mv_row_max = (cm->mi_rows - mi_row) * MI_SIZE + AOM_INTERP_EXTEND;
  x->mv_col_max = (cm->mi_cols - mi_col) * MI_SIZE + AOM_INTERP_EXTEND;
Jingning Han's avatar
Jingning Han committed
290

291
292
  set_plane_n4(xd, mi_width, mi_height, bwl, bhl);

Jingning Han's avatar
Jingning Han committed
293
294
  // Set up distance of MB to edge of frame in 1/8th pel units.
  assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
295
296
  set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width, cm->mi_rows,
                 cm->mi_cols);
Jingning Han's avatar
Jingning Han committed
297
298

  // Set up source buffers.
Yaowu Xu's avatar
Yaowu Xu committed
299
  av1_setup_src_planes(x, cpi->Source, mi_row, mi_col);
Jingning Han's avatar
Jingning Han committed
300
301
302
303
304

  // R/D setup.
  x->rddiv = cpi->rd.RDDIV;
  x->rdmult = cpi->rd.RDMULT;

Yaowu Xu's avatar
Yaowu Xu committed
305
  // required by av1_append_sub8x8_mvs_for_idx() and av1_find_best_ref_mvs()
306
307
308
  xd->tile = *tile;
}

309
static void set_offsets(const AV1_COMP *const cpi, const TileInfo *const tile,
310
311
                        MACROBLOCK *const x, int mi_row, int mi_col,
                        BLOCK_SIZE bsize) {
312
  const AV1_COMMON *const cm = &cpi->common;
313
314
315
316
317
318
319
320
  MACROBLOCKD *const xd = &x->e_mbd;
  MB_MODE_INFO *mbmi;
  const struct segmentation *const seg = &cm->seg;

  set_offsets_without_segment_id(cpi, tile, x, mi_row, mi_col, bsize);

  mbmi = &xd->mi[0]->mbmi;

Jingning Han's avatar
Jingning Han committed
321
322
  // Setup segment ID.
  if (seg->enabled) {
Geza Lore's avatar
Geza Lore committed
323
    if (!cpi->vaq_refresh) {
324
325
      const uint8_t *const map =
          seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
Jingning Han's avatar
Jingning Han committed
326
327
      mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
    }
Yaowu Xu's avatar
Yaowu Xu committed
328
    av1_init_plane_quantizers(cpi, x, mbmi->segment_id);
Jingning Han's avatar
Jingning Han committed
329
330
331
  } else {
    mbmi->segment_id = 0;
  }
332
333
334
335

#if CONFIG_SUPERTX
  mbmi->segment_id_supertx = MAX_SEGMENTS;
#endif  // CONFIG_SUPERTX
Jingning Han's avatar
Jingning Han committed
336
337
}

338
#if CONFIG_SUPERTX
339
static void set_offsets_supertx(const AV1_COMP *const cpi, ThreadData *td,
340
341
                                const TileInfo *const tile, int mi_row,
                                int mi_col, BLOCK_SIZE bsize) {
342
  MACROBLOCK *const x = &td->mb;
343
  const AV1_COMMON *const cm = &cpi->common;
344
345
346
347
348
349
350
351
  MACROBLOCKD *const xd = &x->e_mbd;
  const int mi_width = num_8x8_blocks_wide_lookup[bsize];
  const int mi_height = num_8x8_blocks_high_lookup[bsize];

  set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);

  // Set up distance of MB to edge of frame in 1/8th pel units.
  assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
352
353
  set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width, cm->mi_rows,
                 cm->mi_cols);
354
355
}

356
static void set_offsets_extend(const AV1_COMP *const cpi, ThreadData *td,
357
358
                               const TileInfo *const tile, int mi_row_pred,
                               int mi_col_pred, int mi_row_ori, int mi_col_ori,
359
                               BLOCK_SIZE bsize_pred) {
360
361
362
363
  // Used in supertx
  // (mi_row_ori, mi_col_ori, bsize_ori): region for mv
  // (mi_row_pred, mi_col_pred, bsize_pred): region to predict
  MACROBLOCK *const x = &td->mb;
364
  const AV1_COMMON *const cm = &cpi->common;
365
366
367
368
369
370
371
372
  MACROBLOCKD *const xd = &x->e_mbd;
  const int mi_width = num_8x8_blocks_wide_lookup[bsize_pred];
  const int mi_height = num_8x8_blocks_high_lookup[bsize_pred];

  set_mode_info_offsets(cpi, x, xd, mi_row_ori, mi_col_ori);

  // Set up limit values for MV components.
  // Mv beyond the range do not produce new/different prediction block.
Yaowu Xu's avatar
Yaowu Xu committed
373
374
375
376
  x->mv_row_min = -(((mi_row_pred + mi_height) * MI_SIZE) + AOM_INTERP_EXTEND);
  x->mv_col_min = -(((mi_col_pred + mi_width) * MI_SIZE) + AOM_INTERP_EXTEND);
  x->mv_row_max = (cm->mi_rows - mi_row_pred) * MI_SIZE + AOM_INTERP_EXTEND;
  x->mv_col_max = (cm->mi_cols - mi_col_pred) * MI_SIZE + AOM_INTERP_EXTEND;
377
378
379
380
381

  // Set up distance of MB to edge of frame in 1/8th pel units.
  assert(!(mi_col_pred & (mi_width - 1)) && !(mi_row_pred & (mi_height - 1)));
  set_mi_row_col(xd, tile, mi_row_pred, mi_height, mi_col_pred, mi_width,
                 cm->mi_rows, cm->mi_cols);
382
383
  xd->up_available = (mi_row_ori > tile->mi_row_start);
  xd->left_available = (mi_col_ori > tile->mi_col_start);
384
385
386
387

  // R/D setup.
  x->rddiv = cpi->rd.RDDIV;
  x->rdmult = cpi->rd.RDMULT;
388
}
389

Yaowu Xu's avatar
Yaowu Xu committed
390
static void set_segment_id_supertx(const AV1_COMP *const cpi,
391
392
                                   MACROBLOCK *const x, const int mi_row,
                                   const int mi_col, const BLOCK_SIZE bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
393
  const AV1_COMMON *cm = &cpi->common;
394
395
  const struct segmentation *seg = &cm->seg;
  const int miw =
Yaowu Xu's avatar
Yaowu Xu committed
396
      AOMMIN(num_8x8_blocks_wide_lookup[bsize], cm->mi_cols - mi_col);
397
  const int mih =
Yaowu Xu's avatar
Yaowu Xu committed
398
      AOMMIN(num_8x8_blocks_high_lookup[bsize], cm->mi_rows - mi_row);
399
400
401
402
  const int mi_offset = mi_row * cm->mi_stride + mi_col;
  MODE_INFO **const mip = cm->mi_grid_visible + mi_offset;
  int r, c;
  int seg_id_supertx = MAX_SEGMENTS;
403

404
405
406
407
  if (!seg->enabled) {
    seg_id_supertx = 0;
  } else {
    // Find the minimum segment_id
408
409
410
    for (r = 0; r < mih; r++)
      for (c = 0; c < miw; c++)
        seg_id_supertx =
Yaowu Xu's avatar
Yaowu Xu committed
411
            AOMMIN(mip[r * cm->mi_stride + c]->mbmi.segment_id, seg_id_supertx);
412
413
414
    assert(0 <= seg_id_supertx && seg_id_supertx < MAX_SEGMENTS);

    // Initialize plane quantisers
Yaowu Xu's avatar
Yaowu Xu committed
415
    av1_init_plane_quantizers(cpi, x, seg_id_supertx);
416
  }
417
418

  // Assign the the segment_id back to segment_id_supertx
419
420
  for (r = 0; r < mih; r++)
    for (c = 0; c < miw; c++)
421
      mip[r * cm->mi_stride + c]->mbmi.segment_id_supertx = seg_id_supertx;
422
423
424
}
#endif  // CONFIG_SUPERTX

Yaowu Xu's avatar
Yaowu Xu committed
425
static void set_block_size(AV1_COMP *const cpi, MACROBLOCK *const x,
426
                           MACROBLOCKD *const xd, int mi_row, int mi_col,
Jingning Han's avatar
Jingning Han committed
427
428
                           BLOCK_SIZE bsize) {
  if (cpi->common.mi_cols > mi_col && cpi->common.mi_rows > mi_row) {
429
    set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
Jingning Han's avatar
Jingning Han committed
430
431
432
433
    xd->mi[0]->mbmi.sb_type = bsize;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
434
static void set_vt_partitioning(AV1_COMP *cpi, MACROBLOCK *const x,
435
436
437
                                MACROBLOCKD *const xd, VAR_TREE *vt, int mi_row,
                                int mi_col, const int64_t *const threshold,
                                const BLOCK_SIZE *const bsize_min) {
Yaowu Xu's avatar
Yaowu Xu committed
438
  AV1_COMMON *const cm = &cpi->common;
439
440
441
442
  const int hbw = num_8x8_blocks_wide_lookup[vt->bsize] / 2;
  const int hbh = num_8x8_blocks_high_lookup[vt->bsize] / 2;
  const int has_cols = mi_col + hbw < cm->mi_cols;
  const int has_rows = mi_row + hbh < cm->mi_rows;
Jingning Han's avatar
Jingning Han committed
443

444
  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
Jingning Han's avatar
Jingning Han committed
445

446
447
448
449
  assert(vt->bsize >= BLOCK_8X8);

  assert(hbh == hbw);

450
451
452
453
454
  if (vt->bsize == BLOCK_8X8 && cm->frame_type != KEY_FRAME) {
    set_block_size(cpi, x, xd, mi_row, mi_col, BLOCK_8X8);
    return;
  }

455
  if (vt->force_split || (!has_cols && !has_rows)) goto split;
Jingning Han's avatar
Jingning Han committed
456
457
458
459

  // For bsize=bsize_min (16x16/8x8 for 8x8/4x4 downsampling), select if
  // variance is below threshold, otherwise split will be selected.
  // No check for vert/horiz split as too few samples for variance.
460
  if (vt->bsize == bsize_min[0]) {
461
    if (has_cols && has_rows && vt->variances.none.variance < threshold[0]) {
462
463
464
465
466
467
468
469
470
471
472
      set_block_size(cpi, x, xd, mi_row, mi_col, vt->bsize);
      return;
    } else {
      BLOCK_SIZE subsize = get_subsize(vt->bsize, PARTITION_SPLIT);
      set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
      if (vt->bsize > BLOCK_8X8) {
        set_block_size(cpi, x, xd, mi_row, mi_col + hbw, subsize);
        set_block_size(cpi, x, xd, mi_row + hbh, mi_col, subsize);
        set_block_size(cpi, x, xd, mi_row + hbh, mi_col + hbw, subsize);
      }
      return;
Jingning Han's avatar
Jingning Han committed
473
    }
474
  } else if (vt->bsize > bsize_min[0]) {
Jingning Han's avatar
Jingning Han committed
475
476
    // For key frame: take split for bsize above 32X32 or very high variance.
    if (cm->frame_type == KEY_FRAME &&
477
        (vt->bsize > BLOCK_32X32 ||
478
         vt->variances.none.variance > (threshold[0] << 4))) {
479
      goto split;
Jingning Han's avatar
Jingning Han committed
480
481
    }
    // If variance is low, take the bsize (no split).
482
    if (has_cols && has_rows && vt->variances.none.variance < threshold[0]) {
483
484
      set_block_size(cpi, x, xd, mi_row, mi_col, vt->bsize);
      return;
Jingning Han's avatar
Jingning Han committed
485
486
487
    }

    // Check vertical split.
488
489
490
491
    if (has_rows) {
      BLOCK_SIZE subsize = get_subsize(vt->bsize, PARTITION_VERT);
      if (vt->variances.vert[0].variance < threshold[0] &&
          vt->variances.vert[1].variance < threshold[0] &&
Jingning Han's avatar
Jingning Han committed
492
493
          get_plane_block_size(subsize, &xd->plane[1]) < BLOCK_INVALID) {
        set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
494
495
        set_block_size(cpi, x, xd, mi_row, mi_col + hbw, subsize);
        return;
Jingning Han's avatar
Jingning Han committed
496
497
498
      }
    }
    // Check horizontal split.
499
500
501
502
    if (has_cols) {
      BLOCK_SIZE subsize = get_subsize(vt->bsize, PARTITION_HORZ);
      if (vt->variances.horz[0].variance < threshold[0] &&
          vt->variances.horz[1].variance < threshold[0] &&
Jingning Han's avatar
Jingning Han committed
503
504
          get_plane_block_size(subsize, &xd->plane[1]) < BLOCK_INVALID) {
        set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
505
506
        set_block_size(cpi, x, xd, mi_row + hbh, mi_col, subsize);
        return;
Jingning Han's avatar
Jingning Han committed
507
508
      }
    }
509
  }
Jingning Han's avatar
Jingning Han committed
510

511
512
513
514
515
516
517
518
519
520
521
split : {
  set_vt_partitioning(cpi, x, xd, vt->split[0], mi_row, mi_col, threshold + 1,
                      bsize_min + 1);
  set_vt_partitioning(cpi, x, xd, vt->split[1], mi_row, mi_col + hbw,
                      threshold + 1, bsize_min + 1);
  set_vt_partitioning(cpi, x, xd, vt->split[2], mi_row + hbh, mi_col,
                      threshold + 1, bsize_min + 1);
  set_vt_partitioning(cpi, x, xd, vt->split[3], mi_row + hbh, mi_col + hbw,
                      threshold + 1, bsize_min + 1);
  return;
}
Jingning Han's avatar
Jingning Han committed
522
523
524
525
526
527
}

// Set the variance split thresholds for following the block sizes:
// 0 - threshold_64x64, 1 - threshold_32x32, 2 - threshold_16x16,
// 3 - vbp_threshold_8x8. vbp_threshold_8x8 (to split to 4x4 partition) is
// currently only used on key frame.
Yaowu Xu's avatar
Yaowu Xu committed
528
529
static void set_vbp_thresholds(AV1_COMP *cpi, int64_t thresholds[], int q) {
  AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
530
531
  const int is_key_frame = (cm->frame_type == KEY_FRAME);
  const int threshold_multiplier = is_key_frame ? 20 : 1;
532
533
  const int64_t threshold_base =
      (int64_t)(threshold_multiplier * cpi->y_dequant[q][1]);
Jingning Han's avatar
Jingning Han committed
534
  if (is_key_frame) {
535
    thresholds[1] = threshold_base;
Jingning Han's avatar
Jingning Han committed
536
    thresholds[2] = threshold_base >> 2;
537
538
    thresholds[3] = threshold_base >> 2;
    thresholds[4] = threshold_base << 2;
Jingning Han's avatar
Jingning Han committed
539
  } else {
540
    thresholds[2] = threshold_base;
Jingning Han's avatar
Jingning Han committed
541
    if (cm->width <= 352 && cm->height <= 288) {
542
543
      thresholds[1] = threshold_base >> 2;
      thresholds[3] = threshold_base << 3;
Jingning Han's avatar
Jingning Han committed
544
    } else {
545
546
      thresholds[1] = threshold_base;
      thresholds[2] = (5 * threshold_base) >> 2;
Jingning Han's avatar
Jingning Han committed
547
      if (cm->width >= 1920 && cm->height >= 1080)
548
549
        thresholds[2] = (7 * threshold_base) >> 2;
      thresholds[3] = threshold_base << cpi->oxcf.speed;
Jingning Han's avatar
Jingning Han committed
550
551
    }
  }
552
  thresholds[0] = INT64_MIN;
Jingning Han's avatar
Jingning Han committed
553
554
}

Yaowu Xu's avatar
Yaowu Xu committed
555
556
void av1_set_variance_partition_thresholds(AV1_COMP *cpi, int q) {
  AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
  SPEED_FEATURES *const sf = &cpi->sf;
  const int is_key_frame = (cm->frame_type == KEY_FRAME);
  if (sf->partition_search_type != VAR_BASED_PARTITION &&
      sf->partition_search_type != REFERENCE_PARTITION) {
    return;
  } else {
    set_vbp_thresholds(cpi, cpi->vbp_thresholds, q);
    // The thresholds below are not changed locally.
    if (is_key_frame) {
      cpi->vbp_threshold_sad = 0;
      cpi->vbp_bsize_min = BLOCK_8X8;
    } else {
      if (cm->width <= 352 && cm->height <= 288)
        cpi->vbp_threshold_sad = 100;
      else
572
573
574
        cpi->vbp_threshold_sad = (cpi->y_dequant[q][1] << 1) > 1000
                                     ? (cpi->y_dequant[q][1] << 1)
                                     : 1000;
Jingning Han's avatar
Jingning Han committed
575
576
577
578
579
580
581
      cpi->vbp_bsize_min = BLOCK_16X16;
    }
    cpi->vbp_threshold_minmax = 15 + (q >> 3);
  }
}

// Compute the minmax over the 8x8 subblocks.
582
583
static int compute_minmax_8x8(const uint8_t *src, int src_stride,
                              const uint8_t *ref, int ref_stride,
Yaowu Xu's avatar
Yaowu Xu committed
584
#if CONFIG_AOM_HIGHBITDEPTH
585
                              int highbd,
Jingning Han's avatar
Jingning Han committed
586
#endif
587
                              int pixels_wide, int pixels_high) {
Jingning Han's avatar
Jingning Han committed
588
589
590
591
592
  int k;
  int minmax_max = 0;
  int minmax_min = 255;
  // Loop over the 4 8x8 subblocks.
  for (k = 0; k < 4; k++) {
593
594
    const int x8_idx = ((k & 1) << 3);
    const int y8_idx = ((k >> 1) << 3);
Jingning Han's avatar
Jingning Han committed
595
596
597
    int min = 0;
    int max = 0;
    if (x8_idx < pixels_wide && y8_idx < pixels_high) {
598
599
      const int src_offset = y8_idx * src_stride + x8_idx;
      const int ref_offset = y8_idx * ref_stride + x8_idx;
Yaowu Xu's avatar
Yaowu Xu committed
600
#if CONFIG_AOM_HIGHBITDEPTH
601
      if (highbd) {
Yaowu Xu's avatar
Yaowu Xu committed
602
        aom_highbd_minmax_8x8(src + src_offset, src_stride, ref + ref_offset,
603
                              ref_stride, &min, &max);
Jingning Han's avatar
Jingning Han committed
604
      } else {
Yaowu Xu's avatar
Yaowu Xu committed
605
        aom_minmax_8x8(src + src_offset, src_stride, ref + ref_offset,
606
                       ref_stride, &min, &max);
Jingning Han's avatar
Jingning Han committed
607
608
      }
#else
Yaowu Xu's avatar
Yaowu Xu committed
609
      aom_minmax_8x8(src + src_offset, src_stride, ref + ref_offset, ref_stride,
Jingning Han's avatar
Jingning Han committed
610
611
                     &min, &max);
#endif
612
613
      if ((max - min) > minmax_max) minmax_max = (max - min);
      if ((max - min) < minmax_min) minmax_min = (max - min);
Jingning Han's avatar
Jingning Han committed
614
615
616
617
618
    }
  }
  return (minmax_max - minmax_min);
}

Yaowu Xu's avatar
Yaowu Xu committed
619
#if CONFIG_AOM_HIGHBITDEPTH
620
621
622
static INLINE int avg_4x4(const uint8_t *const src, const int stride,
                          const int highbd) {
  if (highbd) {
Yaowu Xu's avatar
Yaowu Xu committed
623
    return aom_highbd_avg_4x4(src, stride);
624
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
625
    return aom_avg_4x4(src, stride);
626
627
  }
}
Jingning Han's avatar
Jingning Han committed
628
#else
629
static INLINE int avg_4x4(const uint8_t *const src, const int stride) {
Yaowu Xu's avatar
Yaowu Xu committed
630
  return aom_avg_4x4(src, stride);
631
}
Jingning Han's avatar
Jingning Han committed
632
#endif
633

Yaowu Xu's avatar
Yaowu Xu committed
634
#if CONFIG_AOM_HIGHBITDEPTH
635
636
637
static INLINE int avg_8x8(const uint8_t *const src, const int stride,
                          const int highbd) {
  if (highbd) {
Yaowu Xu's avatar
Yaowu Xu committed
638
    return aom_highbd_avg_8x8(src, stride);
639
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
640
    return aom_avg_8x8(src, stride);
Jingning Han's avatar
Jingning Han committed
641
642
  }
}
643
644
#else
static INLINE int avg_8x8(const uint8_t *const src, const int stride) {
Yaowu Xu's avatar
Yaowu Xu committed
645
  return aom_avg_8x8(src, stride);
646
647
}
#endif
Jingning Han's avatar
Jingning Han committed
648

649
static void init_variance_tree(VAR_TREE *const vt,
Yaowu Xu's avatar
Yaowu Xu committed
650
#if CONFIG_AOM_HIGHBITDEPTH
651
                               const int highbd,
Jingning Han's avatar
Jingning Han committed
652
#endif
653
                               BLOCK_SIZE bsize, BLOCK_SIZE leaf_size,
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
                               const int width, const int height,
                               const uint8_t *const src, const int src_stride,
                               const uint8_t *const ref, const int ref_stride) {
  assert(bsize >= leaf_size);

  vt->bsize = bsize;

  vt->force_split = 0;

  vt->src = src;
  vt->src_stride = src_stride;
  vt->ref = ref;
  vt->ref_stride = ref_stride;

  vt->width = width;
  vt->height = height;

Yaowu Xu's avatar
Yaowu Xu committed
671
#if CONFIG_AOM_HIGHBITDEPTH
672
  vt->highbd = highbd;
Yaowu Xu's avatar
Yaowu Xu committed
673
#endif  // CONFIG_AOM_HIGHBITDEPTH
674
675
676
677
678
679

  if (bsize > leaf_size) {
    const BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_SPLIT);
    const int px = num_4x4_blocks_wide_lookup[subsize] * 4;

    init_variance_tree(vt->split[0],
Yaowu Xu's avatar
Yaowu Xu committed
680
#if CONFIG_AOM_HIGHBITDEPTH
681
                       highbd,
Yaowu Xu's avatar
Yaowu Xu committed
682
683
684
#endif  // CONFIG_AOM_HIGHBITDEPTH
                       subsize, leaf_size, AOMMIN(px, width),
                       AOMMIN(px, height), src, src_stride, ref, ref_stride);
685
    init_variance_tree(vt->split[1],
Yaowu Xu's avatar
Yaowu Xu committed
686
#if CONFIG_AOM_HIGHBITDEPTH
687
                       highbd,
Yaowu Xu's avatar
Yaowu Xu committed
688
689
#endif  // CONFIG_AOM_HIGHBITDEPTH
                       subsize, leaf_size, width - px, AOMMIN(px, height),
690
                       src + px, src_stride, ref + px, ref_stride);
691
    init_variance_tree(vt->split[2],
Yaowu Xu's avatar
Yaowu Xu committed
692
#if CONFIG_AOM_HIGHBITDEPTH
693
                       highbd,
Yaowu Xu's avatar
Yaowu Xu committed
694
695
#endif  // CONFIG_AOM_HIGHBITDEPTH
                       subsize, leaf_size, AOMMIN(px, width), height - px,
696
697
                       src + px * src_stride, src_stride, ref + px * ref_stride,
                       ref_stride);
698
    init_variance_tree(vt->split[3],
Yaowu Xu's avatar
Yaowu Xu committed
699
#if CONFIG_AOM_HIGHBITDEPTH
700
                       highbd,
Yaowu Xu's avatar
Yaowu Xu committed
701
#endif  // CONFIG_AOM_HIGHBITDEPTH
702
                       subsize, leaf_size, width - px, height - px,
703
704
705
706
707
708
709
                       src + px * src_stride + px, src_stride,
                       ref + px * ref_stride + px, ref_stride);
  }
}

// Fill the variance tree based on averaging pixel values (sub-sampling), at
// the leaf node size.
710
static void fill_variance_tree(VAR_TREE *const vt, const BLOCK_SIZE leaf_size) {
711
712
713
714
715
716
717
718
719
  if (vt->bsize > leaf_size) {
    fill_variance_tree(vt->split[0], leaf_size);
    fill_variance_tree(vt->split[1], leaf_size);
    fill_variance_tree(vt->split[2], leaf_size);
    fill_variance_tree(vt->split[3], leaf_size);
    fill_variance_node(vt);
  } else if (vt->width <= 0 || vt->height <= 0) {
    fill_variance(0, 0, 0, &vt->variances.none);
  } else {
Jingning Han's avatar
Jingning Han committed
720
721
    unsigned int sse = 0;
    int sum = 0;
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
    int src_avg;
    int ref_avg;
    assert(leaf_size == BLOCK_4X4 || leaf_size == BLOCK_8X8);
    if (leaf_size == BLOCK_4X4) {
      src_avg = avg_4x4(vt->src, vt->src_stride IF_HBD(, vt->highbd));
      ref_avg = avg_4x4(vt->ref, vt->ref_stride IF_HBD(, vt->highbd));
    } else {
      src_avg = avg_8x8(vt->src, vt->src_stride IF_HBD(, vt->highbd));
      ref_avg = avg_8x8(vt->ref, vt->ref_stride IF_HBD(, vt->highbd));
    }
    sum = src_avg - ref_avg;
    sse = sum * sum;
    fill_variance(sse, sum, 0, &vt->variances.none);
  }
}

static void refine_variance_tree(VAR_TREE *const vt, const int64_t threshold) {
  if (vt->bsize >= BLOCK_8X8) {
    if (vt->bsize == BLOCK_16X16) {
      if (vt->variances.none.variance <= threshold)
        return;
      else
        vt->force_split = 0;
    }

    refine_variance_tree(vt->split[0], threshold);
    refine_variance_tree(vt->split[1], threshold);
    refine_variance_tree(vt->split[2], threshold);
    refine_variance_tree(vt->split[3], threshold);

752
    if (vt->bsize <= BLOCK_16X16) fill_variance_node(vt);
753
754
755
756
757
758
  } else if (vt->width <= 0 || vt->height <= 0) {
    fill_variance(0, 0, 0, &vt->variances.none);
  } else {
    const int src_avg = avg_4x4(vt->src, vt->src_stride IF_HBD(, vt->highbd));
    const int ref_avg = avg_4x4(vt->ref, vt->ref_stride IF_HBD(, vt->highbd));
    const int sum = src_avg - ref_avg;
759
    const unsigned int sse = sum * sum;
760
761
762
763
764
    assert(vt->bsize == BLOCK_4X4);
    fill_variance(sse, sum, 0, &vt->variances.none);
  }
}

765
static int check_split_key_frame(VAR_TREE *const vt, const int64_t threshold) {
766
767
768
769
770
771
772
773
774
775
776
  if (vt->bsize == BLOCK_32X32) {
    vt->force_split = vt->variances.none.variance > threshold;
  } else {
    vt->force_split |= check_split_key_frame(vt->split[0], threshold);
    vt->force_split |= check_split_key_frame(vt->split[1], threshold);
    vt->force_split |= check_split_key_frame(vt->split[2], threshold);
    vt->force_split |= check_split_key_frame(vt->split[3], threshold);
  }
  return vt->force_split;
}

Yaowu Xu's avatar
Yaowu Xu committed
777
static int check_split(AV1_COMP *const cpi, VAR_TREE *const vt,
778
                       const int segment_id, const int64_t *const thresholds) {
779
780
  if (vt->bsize == BLOCK_16X16) {
    vt->force_split = vt->variances.none.variance > thresholds[0];
781
782
    if (!vt->force_split && vt->variances.none.variance > thresholds[-1] &&
        !cyclic_refresh_segment_id_boosted(segment_id)) {
783
784
785
      // We have some nominal amount of 16x16 variance (based on average),
      // compute the minmax over the 8x8 sub-blocks, and if above threshold,
      // force split to 8x8 block for this 16x16 block.
786
787
      int minmax =
          compute_minmax_8x8(vt->src, vt->src_stride, vt->ref, vt->ref_stride,
Yaowu Xu's avatar
Yaowu Xu committed
788
#if CONFIG_AOM_HIGHBITDEPTH
789
                             vt->highbd,
Jingning Han's avatar
Jingning Han committed
790
#endif
791
                             vt->width, vt->height);
792
793
794
      vt->force_split = minmax > cpi->vbp_threshold_minmax;
    }
  } else {
795
796
797
798
799
800
801
802
    vt->force_split |=
        check_split(cpi, vt->split[0], segment_id, thresholds + 1);
    vt->force_split |=
        check_split(cpi, vt->split[1], segment_id, thresholds + 1);
    vt->force_split |=
        check_split(cpi, vt->split[2], segment_id, thresholds + 1);
    vt->force_split |=
        check_split(cpi, vt->split[3], segment_id, thresholds + 1);
803
804
805

    if (vt->bsize == BLOCK_32X32 && !vt->force_split) {
      vt->force_split = vt->variances.none.variance > thresholds[0];
Jingning Han's avatar
Jingning Han committed
806
807
    }
  }
808
809

  return vt->force_split;
Jingning Han's avatar
Jingning Han committed
810
811
812
}

// This function chooses partitioning based on the variance between source and
813
814
// reconstructed last (or golden), where variance is computed for down-sampled
// inputs.
Yaowu Xu's avatar
Yaowu Xu committed
815
static void choose_partitioning(AV1_COMP *const cpi, ThreadData *const td,
816
                                const TileInfo *const tile, MACROBLOCK *const x,
817
                                const int mi_row, const int mi_col) {
Yaowu Xu's avatar
Yaowu Xu committed
818
  AV1_COMMON *const cm = &cpi->common;
819
820
  MACROBLOCKD *const xd = &x->e_mbd;
  VAR_TREE *const vt = td->var_root[cm->mib_size_log2 - MIN_MIB_SIZE_LOG2];
821
#if CONFIG_DUAL_FILTER
822
  int i;
823
#endif
824
825
826
827
  const uint8_t *src;
  const uint8_t *ref;
  int src_stride;
  int ref_stride;
828
829
  int pixels_wide = 8 * num_8x8_blocks_wide_lookup[cm->sb_size];
  int pixels_high = 8 * num_8x8_blocks_high_lookup[cm->sb_size];
830
  int64_t thresholds[5] = {
831
832
    cpi->vbp_thresholds[0], cpi->vbp_thresholds[1], cpi->vbp_thresholds[2],
    cpi->vbp_thresholds[3], cpi->vbp_thresholds[4],
833
  };
834
835
  BLOCK_SIZE bsize_min[5] = { BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
                              cpi->vbp_bsize_min, BLOCK_8X8 };
836
837
838
  const int start_level = cm->sb_size == BLOCK_64X64 ? 1 : 0;
  const int64_t *const thre = thresholds + start_level;
  const BLOCK_SIZE *const bmin = bsize_min + start_level;
Jingning Han's avatar
Jingning Han committed
839
840
841
842
843

  const int is_key_frame = (cm->frame_type == KEY_FRAME);
  const int low_res = (cm->width <= 352 && cm->height <= 288);

  int segment_id = CR_SEGMENT_ID_BASE;
844

Jingning Han's avatar
Jingning Han committed
845
  if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled) {
846
847
    const uint8_t *const map =
        cm->seg.update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
848
    segment_id = get_segment_id(cm, map, cm->sb_size, mi_row, mi_col);
Jingning Han's avatar
Jingning Han committed
849
850

    if (cyclic_refresh_segment_id_boosted(segment_id)) {
Yaowu Xu's avatar
Yaowu Xu committed
851
      int q = av1_get_qindex(&cm->seg, segment_id, cm->base_qindex);
Jingning Han's avatar
Jingning Han committed
852
853
854
855
      set_vbp_thresholds(cpi, thresholds, q);
    }
  }

856
  set_offsets(cpi, tile, x, mi_row, mi_col, cm->sb_size);
Jingning Han's avatar
Jingning Han committed
857

858
859
  if (xd->mb_to_right_edge < 0) pixels_wide += (xd->mb_to_right_edge >> 3);
  if (xd->mb_to_bottom_edge < 0) pixels_high += (xd->mb_to_bottom_edge >> 3);
Jingning Han's avatar
Jingning Han committed
860

861
862
  src = x->plane[0].src.buf;
  src_stride = x->plane[0].src.stride;
Jingning Han's avatar
Jingning Han committed
863

Yunqing Wang's avatar
Yunqing Wang committed
864
  if (!is_key_frame) {
Jingning Han's avatar
Jingning Han committed
865
866
    MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
    const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
867
    const YV12_BUFFER_CONFIG *yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
Jingning Han's avatar
Jingning Han committed
868
    unsigned int y_sad, y_sad_g;
869

870
871
872
    const int hbs = cm->mib_size / 2;
    const int split_vert = mi_col + hbs >= cm->mi_cols;
    const int split_horz = mi_row + hbs >= cm->mi_rows;
873
874
    BLOCK_SIZE bsize;

875
    if (split_vert && split_horz)
876
      bsize = get_subsize(cm->sb_size, PARTITION_SPLIT);
877
    else if (split_vert)
878
      bsize = get_subsize(cm->sb_size, PARTITION_VERT);
879
    else if (split_horz)
880
      bsize = get_subsize(cm->sb_size, PARTITION_HORZ);
881
    else
882
      bsize = cm->sb_size;
Jingning Han's avatar
Jingning Han committed
883
884
885
886

    assert(yv12 != NULL);

    if (yv12_g && yv12_g != yv12) {
Yaowu Xu's avatar
Yaowu Xu committed
887
888
      av1_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
                           &cm->frame_refs[GOLDEN_FRAME - 1].sf);
889
890
891
      y_sad_g = cpi->fn_ptr[bsize].sdf(
          x->plane[0].src.buf, x->plane[0].src.stride, xd->plane[0].pre[0].buf,
          xd->plane[0].pre[0].stride);
Jingning Han's avatar
Jingning Han committed
892
893
894
895
    } else {
      y_sad_g = UINT_MAX;
    }

Yaowu Xu's avatar
Yaowu Xu committed
896
897
    av1_setup_pre_planes(xd, 0, yv12, mi_row, mi_col,
                         &cm->frame_refs[LAST_FRAME - 1].sf);
Jingning Han's avatar
Jingning Han committed
898
899
    mbmi->ref_frame[0] = LAST_FRAME;
    mbmi->ref_frame[1] = NONE;
900
    mbmi->sb_type = cm->sb_size;
Jingning Han's avatar
Jingning Han committed
901
    mbmi->mv[0].as_int = 0;
902
#if CONFIG_DUAL_FILTER
903
    for (i = 0; i < 4; ++i) mbmi->interp_filter[i] = BILINEAR;
904
#else
Jingning Han's avatar
Jingning Han committed
905
    mbmi->interp_filter = BILINEAR;
906
#endif
Jingning Han's avatar
Jingning Han committed
907

Yaowu Xu's avatar
Yaowu Xu committed
908
    y_sad = av1_int_pro_motion_estimation(cpi, x, bsize, mi_row, mi_col);
909

Jingning Han's avatar
Jingning Han committed
910
    if (y_sad_g < y_sad) {
Yaowu Xu's avatar
Yaowu Xu committed
911
912
      av1_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
                           &cm->frame_refs[GOLDEN_FRAME - 1].sf);
Jingning Han's avatar
Jingning Han committed
913
914
915
916
917
918
919
      mbmi->ref_frame[0] = GOLDEN_FRAME;
      mbmi->mv[0].as_int = 0;
      y_sad = y_sad_g;
    } else {
      x->pred_mv[LAST_FRAME] = mbmi->mv[0].as_mv;
    }

Yaowu Xu's avatar
Yaowu Xu committed
920
    av1_build_inter_predictors_sb(xd, mi_row, mi_col, cm->sb_size);
Jingning Han's avatar
Jingning Han committed
921

922
923
    ref = xd->plane[0].dst.buf;
    ref_stride = xd->plane[0].dst.stride;
Jingning Han's avatar
Jingning Han committed
924

925
926
927
    // If the y_sad is very small, take the largest partition and exit.
    // Don't check on boosted segment for now, as largest is suppressed there.
    if (segment_id == CR_SEGMENT_ID_BASE && y_sad < cpi->vbp_threshold_sad) {
928
      if (!split_vert && !split_horz) {
929
        set_block_size(cpi, x, xd, mi_row, mi_col, cm->sb_size);
930
        return;
Jingning Han's avatar
Jingning Han committed
931
932
933
      }
    }
  } else {