Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aom/av1/encoder/encodeframe.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3
 *
4
 * This source code is subject to the terms of the BSD 2 Clause License and
5
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6
 * was not distributed with this source code in the LICENSE file, you can
7
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8
 * Media Patent License 1.0 was not distributed with this source code in the
9
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
 */
11
12
#include <limits.h>
13
#include <float.h>
14
#include <math.h>
15
#include <stdbool.h>
16
#include <stdio.h>
17
18
#include "config/aom_config.h"
19
#include "config/aom_dsp_rtcd.h"
20
#include "config/aom_scale_rtcd.h"
21
#include "config/av1_rtcd.h"
22
23
#include "aom_dsp/aom_dsp_common.h"
24
#include "aom_dsp/binary_codes_writer.h"
25
#include "aom_ports/mem.h"
26
#include "aom_ports/aom_timer.h"
27
#include "aom_util/aom_pthread.h"
28
#if CONFIG_MISMATCH_DEBUG
29
#include "aom_util/debug_util.h"
30
#endif  // CONFIG_MISMATCH_DEBUG
31
32
#include "av1/common/cfl.h"
33
#include "av1/common/common.h"
34
#include "av1/common/common_data.h"
35
#include "av1/common/entropy.h"
36
#include "av1/common/entropymode.h"
37
#include "av1/common/idct.h"
38
#include "av1/common/mv.h"
39
#include "av1/common/mvref_common.h"
40
#include "av1/common/pred_common.h"
41
#include "av1/common/quant_common.h"
42
#include "av1/common/reconintra.h"
43
#include "av1/common/reconinter.h"
44
#include "av1/common/seg_common.h"
45
#include "av1/common/tile_common.h"
46
#include "av1/common/warped_motion.h"
47
48
#include "av1/encoder/allintra_vis.h"
49
#include "av1/encoder/aq_complexity.h"
50
#include "av1/encoder/aq_cyclicrefresh.h"
51
#include "av1/encoder/aq_variance.h"
52
#include "av1/encoder/av1_quantize.h"
53
#include "av1/encoder/global_motion_facade.h"
54
#include "av1/encoder/encodeframe.h"
55
#include "av1/encoder/encodeframe_utils.h"
56
#include "av1/encoder/encodemb.h"
57
#include "av1/encoder/encodemv.h"
58
#include "av1/encoder/encodetxb.h"
59
#include "av1/encoder/ethread.h"
60
#include "av1/encoder/extend.h"
61
#include "av1/encoder/intra_mode_search_utils.h"
62
#include "av1/encoder/ml.h"
63
#include "av1/encoder/motion_search_facade.h"
64
#include "av1/encoder/partition_strategy.h"
65
#if !CONFIG_REALTIME_ONLY
66
#include "av1/encoder/partition_model_weights.h"
67
#endif
68
#include "av1/encoder/partition_search.h"
69
#include "av1/encoder/rd.h"
70
#include "av1/encoder/rdopt.h"
71
#include "av1/encoder/reconinter_enc.h"
72
#include "av1/encoder/segmentation.h"
73
#include "av1/encoder/tokenize.h"
74
#include "av1/encoder/tpl_model.h"
75
#include "av1/encoder/var_based_part.h"
76
77
#if CONFIG_TUNE_VMAF
78
#include "av1/encoder/tune_vmaf.h"
79
#endif
80
81
/*!\cond */
82
// This is used as a reference when computing the source variance for the
83
//  purposes of activity masking.
84
// Eventually this should be replaced by custom no-reference routines,
85
//  which will be faster.
86
static const uint8_t AV1_VAR_OFFS[MAX_SB_SIZE] = {
87
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
88
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
89
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
90
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
91
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
92
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
93
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
94
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
95
  128, 128, 128, 128, 128, 128, 128, 128
96
};
97
98
#if CONFIG_AV1_HIGHBITDEPTH
99
static const uint16_t AV1_HIGH_VAR_OFFS_8[MAX_SB_SIZE] = {
100
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
101
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
102
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
103
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
104
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
105
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
106
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
107
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
108
  128, 128, 128, 128, 128, 128, 128, 128
109
};
110
111
static const uint16_t AV1_HIGH_VAR_OFFS_10[MAX_SB_SIZE] = {
112
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
113
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
114
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
115
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
116
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
117
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
118
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
119
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
120
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
121
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
122
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
123
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
124
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
125
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
126
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
127
  128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4
128
};
129
130
static const uint16_t AV1_HIGH_VAR_OFFS_12[MAX_SB_SIZE] = {
131
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
132
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
133
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
134
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
135
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
136
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
137
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
138
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
139
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
140
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
141
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
142
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
143
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
144
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
145
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
146
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
147
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
148
  128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
149
  128 * 16, 128 * 16
150
};
151
#endif  // CONFIG_AV1_HIGHBITDEPTH
152
/*!\endcond */
153
154
// For the given bit depth, returns a constant array used to assist the
155
// calculation of source block variance, which will then be used to decide
156
// adaptive quantizers.
157
0
static const uint8_t *get_var_offs(int use_hbd, int bd) {
158
0
#if CONFIG_AV1_HIGHBITDEPTH
159
0
  if (use_hbd) {
160
0
    assert(bd == 8 || bd == 10 || bd == 12);
161
0
    const int off_index = (bd - 8) >> 1;
162
0
    static const uint16_t *high_var_offs[3] = { AV1_HIGH_VAR_OFFS_8,
163
0
                                                AV1_HIGH_VAR_OFFS_10,
164
0
                                                AV1_HIGH_VAR_OFFS_12 };
165
0
    return CONVERT_TO_BYTEPTR(high_var_offs[off_index]);
166
0
  }
167
#else
168
  (void)use_hbd;
169
  (void)bd;
170
  assert(!use_hbd);
171
#endif
172
0
  assert(bd == 8);
173
0
  return AV1_VAR_OFFS;
174
0
}
175
176
0
void av1_init_rtc_counters(MACROBLOCK *const x) {
177
0
  av1_init_cyclic_refresh_counters(x);
178
0
  x->cnt_zeromv = 0;
179
0
  x->sb_col_scroll = 0;
180
0
  x->sb_row_scroll = 0;
181
0
}
182
183
0
void av1_accumulate_rtc_counters(AV1_COMP *cpi, const MACROBLOCK *const x) {
184
0
  if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ)
185
0
    av1_accumulate_cyclic_refresh_counters(cpi->cyclic_refresh, x);
186
0
  cpi->rc.cnt_zeromv += x->cnt_zeromv;
187
0
  cpi->rc.num_col_blscroll_last_tl0 += x->sb_col_scroll;
188
0
  cpi->rc.num_row_blscroll_last_tl0 += x->sb_row_scroll;
189
0
}
190
191
unsigned int av1_get_perpixel_variance(const AV1_COMP *cpi,
192
                                       const MACROBLOCKD *xd,
193
                                       const struct buf_2d *ref,
194
                                       BLOCK_SIZE bsize, int plane,
195
0
                                       int use_hbd) {
196
0
  const int subsampling_x = xd->plane[plane].subsampling_x;
197
0
  const int subsampling_y = xd->plane[plane].subsampling_y;
198
0
  const BLOCK_SIZE plane_bsize =
199
0
      get_plane_block_size(bsize, subsampling_x, subsampling_y);
200
0
  unsigned int sse;
201
0
  const unsigned int var = cpi->ppi->fn_ptr[plane_bsize].vf(
202
0
      ref->buf, ref->stride, get_var_offs(use_hbd, xd->bd), 0, &sse);
203
0
  return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[plane_bsize]);
204
0
}
205
206
unsigned int av1_get_perpixel_variance_facade(const AV1_COMP *cpi,
207
                                              const MACROBLOCKD *xd,
208
                                              const struct buf_2d *ref,
209
0
                                              BLOCK_SIZE bsize, int plane) {
210
0
  const int use_hbd = is_cur_buf_hbd(xd);
211
0
  return av1_get_perpixel_variance(cpi, xd, ref, bsize, plane, use_hbd);
212
0
}
213
214
void av1_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
215
                          int mi_row, int mi_col, const int num_planes,
216
0
                          BLOCK_SIZE bsize) {
217
  // Set current frame pointer.
218
0
  x->e_mbd.cur_buf = src;
219
220
  // We use AOMMIN(num_planes, MAX_MB_PLANE) instead of num_planes to quiet
221
  // the static analysis warnings.
222
0
  for (int i = 0; i < AOMMIN(num_planes, MAX_MB_PLANE); i++) {
223
0
    const int is_uv = i > 0;
224
0
    setup_pred_plane(
225
0
        &x->plane[i].src, bsize, src->buffers[i], src->crop_widths[is_uv],
226
0
        src->crop_heights[is_uv], src->strides[is_uv], mi_row, mi_col, NULL,
227
0
        x->e_mbd.plane[i].subsampling_x, x->e_mbd.plane[i].subsampling_y);
228
0
  }
229
0
}
230
231
#if !CONFIG_REALTIME_ONLY
232
/*!\brief Assigns different quantization parameters to each superblock
233
 * based on statistics relevant to the selected delta-q mode (variance).
234
 * This is the non-rd version.
235
 *
236
 * \param[in]     cpi         Top level encoder instance structure
237
 * \param[in,out] td          Thread data structure
238
 * \param[in,out] x           Superblock level data for this block.
239
 * \param[in]     tile_info   Tile information / identification
240
 * \param[in]     mi_row      Block row (in "MI_SIZE" units) index
241
 * \param[in]     mi_col      Block column (in "MI_SIZE" units) index
242
 * \param[out]    num_planes  Number of image planes (e.g. Y,U,V)
243
 *
244
 * \remark No return value but updates superblock and thread data
245
 * related to the q / q delta to be used.
246
 */
247
static inline void setup_delta_q_nonrd(AV1_COMP *const cpi, ThreadData *td,
248
                                       MACROBLOCK *const x,
249
                                       const TileInfo *const tile_info,
250
0
                                       int mi_row, int mi_col, int num_planes) {
251
0
  AV1_COMMON *const cm = &cpi->common;
252
0
  const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
253
0
  assert(delta_q_info->delta_q_present_flag);
254
255
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
256
0
  av1_setup_src_planes(x, cpi->source, mi_row, mi_col, num_planes, sb_size);
257
258
0
  const int delta_q_res = delta_q_info->delta_q_res;
259
0
  int current_qindex = cm->quant_params.base_qindex;
260
261
0
  if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_VARIANCE_BOOST) {
262
0
    current_qindex = av1_get_sbq_variance_boost(cpi, x);
263
0
  }
264
265
0
  x->rdmult_cur_qindex = current_qindex;
266
0
  MACROBLOCKD *const xd = &x->e_mbd;
267
0
  current_qindex = av1_adjust_q_from_delta_q_res(
268
0
      delta_q_res, xd->current_base_qindex, current_qindex);
269
270
0
  x->delta_qindex = current_qindex - cm->quant_params.base_qindex;
271
0
  x->rdmult_delta_qindex = x->delta_qindex;
272
273
0
  av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
274
0
  xd->mi[0]->current_qindex = current_qindex;
275
0
  av1_init_plane_quantizers(cpi, x, xd->mi[0]->segment_id, 0);
276
277
  // keep track of any non-zero delta-q used
278
0
  td->deltaq_used |= (x->delta_qindex != 0);
279
0
}
280
281
/*!\brief Assigns different quantization parameters to each superblock
282
 * based on statistics relevant to the selected delta-q mode (TPL weight,
283
 * variance, HDR, etc).
284
 *
285
 * \ingroup tpl_modelling
286
 *
287
 * \param[in]     cpi         Top level encoder instance structure
288
 * \param[in,out] td          Thread data structure
289
 * \param[in,out] x           Superblock level data for this block.
290
 * \param[in]     tile_info   Tile information / identification
291
 * \param[in]     mi_row      Block row (in "MI_SIZE" units) index
292
 * \param[in]     mi_col      Block column (in "MI_SIZE" units) index
293
 * \param[out]    num_planes  Number of image planes (e.g. Y,U,V)
294
 *
295
 * \remark No return value but updates superblock and thread data
296
 * related to the q / q delta to be used.
297
 */
298
static inline void setup_delta_q(AV1_COMP *const cpi, ThreadData *td,
299
                                 MACROBLOCK *const x,
300
                                 const TileInfo *const tile_info, int mi_row,
301
0
                                 int mi_col, int num_planes) {
302
0
  AV1_COMMON *const cm = &cpi->common;
303
0
  const CommonModeInfoParams *const mi_params = &cm->mi_params;
304
0
  const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
305
306
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
307
0
  av1_setup_src_planes(x, cpi->source, mi_row, mi_col, num_planes, sb_size);
308
309
0
  const int delta_q_res = delta_q_info->delta_q_res;
310
0
  int current_qindex = cm->quant_params.base_qindex;
311
0
  const int sb_row = mi_row >> cm->seq_params->mib_size_log2;
312
0
  const int sb_col = mi_col >> cm->seq_params->mib_size_log2;
313
0
  const int sb_cols =
314
0
      CEIL_POWER_OF_TWO(cm->mi_params.mi_cols, cm->seq_params->mib_size_log2);
315
0
  const int sb_index = sb_row * sb_cols + sb_col;
316
0
  if (cpi->use_ducky_encode && cpi->ducky_encode_info.frame_info.qp_mode ==
317
0
                                   DUCKY_ENCODE_FRAME_MODE_QINDEX) {
318
0
    current_qindex =
319
0
        cpi->ducky_encode_info.frame_info.superblock_encode_qindex[sb_index];
320
0
  } else if (cpi->ext_ratectrl.ready &&
321
0
             (cpi->ext_ratectrl.funcs.rc_type & AOM_RC_QP) != 0 &&
322
0
             cpi->ext_ratectrl.funcs.get_encodeframe_decision != NULL &&
323
0
             cpi->ext_ratectrl.sb_params_list != NULL) {
324
0
    if (cpi->ext_ratectrl.use_delta_q) {
325
      // Only used for per-coding-block RD mult calculation later.
326
0
      current_qindex = av1_get_q_for_deltaq_objective(cpi, td, NULL, sb_size,
327
0
                                                      mi_row, mi_col);
328
329
0
      const int q_index = cpi->ext_ratectrl.sb_params_list[sb_index].q_index;
330
0
      if (q_index != AOM_DEFAULT_Q) {
331
0
        current_qindex = q_index;
332
0
      }
333
0
    }
334
0
  } else if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_PERCEPTUAL) {
335
0
    if (DELTA_Q_PERCEPTUAL_MODULATION == 1) {
336
0
      const int block_wavelet_energy_level =
337
0
          av1_block_wavelet_energy_level(cpi, x, sb_size);
338
0
      x->sb_energy_level = block_wavelet_energy_level;
339
0
      current_qindex = av1_compute_q_from_energy_level_deltaq_mode(
340
0
          cpi, block_wavelet_energy_level);
341
0
    } else {
342
0
      const int block_var_level = av1_log_block_var(cpi, x, sb_size);
343
0
      x->sb_energy_level = block_var_level;
344
0
      current_qindex =
345
0
          av1_compute_q_from_energy_level_deltaq_mode(cpi, block_var_level);
346
0
    }
347
0
  } else if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_OBJECTIVE &&
348
0
             cpi->oxcf.algo_cfg.enable_tpl_model) {
349
    // Setup deltaq based on tpl stats
350
0
    current_qindex =
351
0
        av1_get_q_for_deltaq_objective(cpi, td, NULL, sb_size, mi_row, mi_col);
352
0
  } else if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_PERCEPTUAL_AI) {
353
0
    current_qindex = av1_get_sbq_perceptual_ai(cpi, sb_size, mi_row, mi_col);
354
0
  } else if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_USER_RATING_BASED) {
355
0
    current_qindex = av1_get_sbq_user_rating_based(cpi, mi_row, mi_col);
356
0
  } else if (cpi->oxcf.q_cfg.enable_hdr_deltaq) {
357
0
    current_qindex = av1_get_q_for_hdr(cpi, x, sb_size, mi_row, mi_col);
358
0
  } else if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_VARIANCE_BOOST) {
359
0
    current_qindex = av1_get_sbq_variance_boost(cpi, x);
360
0
  }
361
362
0
  x->rdmult_cur_qindex = current_qindex;
363
0
  MACROBLOCKD *const xd = &x->e_mbd;
364
0
  const int adjusted_qindex = av1_adjust_q_from_delta_q_res(
365
0
      delta_q_res, xd->current_base_qindex, current_qindex);
366
0
  if (cpi->use_ducky_encode) {
367
0
    assert(adjusted_qindex == current_qindex);
368
0
  }
369
0
  current_qindex = adjusted_qindex;
370
371
0
  x->delta_qindex = cm->delta_q_info.delta_q_present_flag
372
0
                        ? current_qindex - cm->quant_params.base_qindex
373
0
                        : 0;
374
0
  x->rdmult_delta_qindex = current_qindex - cm->quant_params.base_qindex;
375
376
0
  av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
377
0
  xd->mi[0]->current_qindex = cm->delta_q_info.delta_q_present_flag
378
0
                                  ? current_qindex
379
0
                                  : cm->quant_params.base_qindex;
380
0
  av1_init_plane_quantizers(cpi, x, xd->mi[0]->segment_id, 0);
381
382
  // keep track of any non-zero delta-q used
383
0
  td->deltaq_used |= (x->delta_qindex != 0);
384
385
0
  if (cpi->oxcf.tool_cfg.enable_deltalf_mode &&
386
0
      cm->delta_q_info.delta_q_present_flag) {
387
0
    const int delta_lf_res = delta_q_info->delta_lf_res;
388
0
    const int lfmask = ~(delta_lf_res - 1);
389
0
    const int delta_lf_from_base =
390
0
        ((x->delta_qindex / 4 + delta_lf_res / 2) & lfmask);
391
0
    const int8_t delta_lf =
392
0
        (int8_t)clamp(delta_lf_from_base, -MAX_LOOP_FILTER, MAX_LOOP_FILTER);
393
0
    const int frame_lf_count =
394
0
        av1_num_planes(cm) > 1 ? FRAME_LF_COUNT : FRAME_LF_COUNT - 2;
395
0
    const int mib_size = cm->seq_params->mib_size;
396
397
    // pre-set the delta lf for loop filter. Note that this value is set
398
    // before mi is assigned for each block in current superblock
399
0
    for (int j = 0; j < AOMMIN(mib_size, mi_params->mi_rows - mi_row); j++) {
400
0
      for (int k = 0; k < AOMMIN(mib_size, mi_params->mi_cols - mi_col); k++) {
401
0
        const int grid_idx = get_mi_grid_idx(mi_params, mi_row + j, mi_col + k);
402
0
        mi_params->mi_alloc[grid_idx].delta_lf_from_base = delta_lf;
403
0
        for (int lf_id = 0; lf_id < frame_lf_count; ++lf_id) {
404
0
          mi_params->mi_alloc[grid_idx].delta_lf[lf_id] = delta_lf;
405
0
        }
406
0
      }
407
0
    }
408
0
  }
409
0
}
410
411
static void init_ref_frame_space(AV1_COMP *cpi, ThreadData *td, int mi_row,
412
0
                                 int mi_col) {
413
0
  const AV1_COMMON *cm = &cpi->common;
414
0
  const GF_GROUP *const gf_group = &cpi->ppi->gf_group;
415
0
  const CommonModeInfoParams *const mi_params = &cm->mi_params;
416
0
  MACROBLOCK *x = &td->mb;
417
0
  const int frame_idx = cpi->gf_frame_index;
418
0
  TplParams *const tpl_data = &cpi->ppi->tpl_data;
419
0
  const uint8_t block_mis_log2 = tpl_data->tpl_stats_block_mis_log2;
420
421
0
  av1_zero(x->tpl_keep_ref_frame);
422
423
0
  if (!av1_tpl_stats_ready(tpl_data, frame_idx)) return;
424
0
  if (!is_frame_tpl_eligible(gf_group, cpi->gf_frame_index)) return;
425
0
  if (cpi->oxcf.q_cfg.aq_mode != NO_AQ) return;
426
427
0
  const int is_overlay =
428
0
      cpi->ppi->gf_group.update_type[frame_idx] == OVERLAY_UPDATE;
429
0
  if (is_overlay) {
430
0
    memset(x->tpl_keep_ref_frame, 1, sizeof(x->tpl_keep_ref_frame));
431
0
    return;
432
0
  }
433
434
0
  TplDepFrame *tpl_frame = &tpl_data->tpl_frame[frame_idx];
435
0
  TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
436
0
  const int tpl_stride = tpl_frame->stride;
437
0
  int64_t inter_cost[INTER_REFS_PER_FRAME] = { 0 };
438
0
  const int step = 1 << block_mis_log2;
439
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
440
441
0
  const int mi_row_end =
442
0
      AOMMIN(mi_size_high[sb_size] + mi_row, mi_params->mi_rows);
443
0
  const int mi_cols_sr = av1_pixels_to_mi(cm->superres_upscaled_width);
444
0
  const int mi_col_sr =
445
0
      coded_to_superres_mi(mi_col, cm->superres_scale_denominator);
446
0
  const int mi_col_end_sr =
447
0
      AOMMIN(coded_to_superres_mi(mi_col + mi_size_wide[sb_size],
448
0
                                  cm->superres_scale_denominator),
449
0
             mi_cols_sr);
450
0
  const int row_step = step;
451
0
  const int col_step_sr =
452
0
      coded_to_superres_mi(step, cm->superres_scale_denominator);
453
0
  for (int row = mi_row; row < mi_row_end; row += row_step) {
454
0
    for (int col = mi_col_sr; col < mi_col_end_sr; col += col_step_sr) {
455
0
      const TplDepStats *this_stats =
456
0
          &tpl_stats[av1_tpl_ptr_pos(row, col, tpl_stride, block_mis_log2)];
457
0
      int64_t tpl_pred_error[INTER_REFS_PER_FRAME] = { 0 };
458
      // Find the winner ref frame idx for the current block
459
0
      int64_t best_inter_cost = this_stats->pred_error[0];
460
0
      int best_rf_idx = 0;
461
0
      for (int idx = 1; idx < INTER_REFS_PER_FRAME; ++idx) {
462
0
        if ((this_stats->pred_error[idx] < best_inter_cost) &&
463
0
            (this_stats->pred_error[idx] != 0)) {
464
0
          best_inter_cost = this_stats->pred_error[idx];
465
0
          best_rf_idx = idx;
466
0
        }
467
0
      }
468
      // tpl_pred_error is the pred_error reduction of best_ref w.r.t.
469
      // LAST_FRAME.
470
0
      tpl_pred_error[best_rf_idx] = this_stats->pred_error[best_rf_idx] -
471
0
                                    this_stats->pred_error[LAST_FRAME - 1];
472
473
0
      for (int rf_idx = 1; rf_idx < INTER_REFS_PER_FRAME; ++rf_idx)
474
0
        inter_cost[rf_idx] += tpl_pred_error[rf_idx];
475
0
    }
476
0
  }
477
478
0
  int rank_index[INTER_REFS_PER_FRAME - 1];
479
0
  for (int idx = 0; idx < INTER_REFS_PER_FRAME - 1; ++idx) {
480
0
    rank_index[idx] = idx + 1;
481
0
    for (int i = idx; i > 0; --i) {
482
0
      if (inter_cost[rank_index[i - 1]] > inter_cost[rank_index[i]]) {
483
0
        const int tmp = rank_index[i - 1];
484
0
        rank_index[i - 1] = rank_index[i];
485
0
        rank_index[i] = tmp;
486
0
      }
487
0
    }
488
0
  }
489
490
0
  x->tpl_keep_ref_frame[INTRA_FRAME] = 1;
491
0
  x->tpl_keep_ref_frame[LAST_FRAME] = 1;
492
493
0
  int cutoff_ref = 0;
494
0
  for (int idx = 0; idx < INTER_REFS_PER_FRAME - 1; ++idx) {
495
0
    x->tpl_keep_ref_frame[rank_index[idx] + LAST_FRAME] = 1;
496
0
    if (idx > 2) {
497
0
      if (!cutoff_ref) {
498
        // If the predictive coding gains are smaller than the previous more
499
        // relevant frame over certain amount, discard this frame and all the
500
        // frames afterwards.
501
0
        if (llabs(inter_cost[rank_index[idx]]) <
502
0
                llabs(inter_cost[rank_index[idx - 1]]) / 8 ||
503
0
            inter_cost[rank_index[idx]] == 0)
504
0
          cutoff_ref = 1;
505
0
      }
506
507
0
      if (cutoff_ref) x->tpl_keep_ref_frame[rank_index[idx] + LAST_FRAME] = 0;
508
0
    }
509
0
  }
510
0
}
511
512
static inline void adjust_rdmult_tpl_model(AV1_COMP *cpi, MACROBLOCK *x,
513
0
                                           int mi_row, int mi_col) {
514
0
  const BLOCK_SIZE sb_size = cpi->common.seq_params->sb_size;
515
0
  const int orig_rdmult = cpi->rd.RDMULT;
516
517
0
  assert(IMPLIES(cpi->ppi->gf_group.size > 0,
518
0
                 cpi->gf_frame_index < cpi->ppi->gf_group.size));
519
0
  const int gf_group_index = cpi->gf_frame_index;
520
0
  if (cpi->oxcf.algo_cfg.enable_tpl_model && cpi->oxcf.q_cfg.aq_mode == NO_AQ &&
521
0
      cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q && gf_group_index > 0 &&
522
0
      cpi->ppi->gf_group.update_type[gf_group_index] == ARF_UPDATE) {
523
0
    const int dr =
524
0
        av1_get_rdmult_delta(cpi, sb_size, mi_row, mi_col, orig_rdmult);
525
0
    x->rdmult = dr;
526
0
  }
527
0
}
528
#endif  // !CONFIG_REALTIME_ONLY
529
530
#if CONFIG_RT_ML_PARTITIONING
531
// Get a prediction(stored in x->est_pred) for the whole superblock.
532
static void get_estimated_pred(AV1_COMP *cpi, const TileInfo *const tile,
533
                               MACROBLOCK *x, int mi_row, int mi_col) {
534
  AV1_COMMON *const cm = &cpi->common;
535
  const int is_key_frame = frame_is_intra_only(cm);
536
  MACROBLOCKD *xd = &x->e_mbd;
537
538
  // TODO(kyslov) Extend to 128x128
539
  assert(cm->seq_params->sb_size == BLOCK_64X64);
540
541
  av1_set_offsets(cpi, tile, x, mi_row, mi_col, BLOCK_64X64);
542
543
  if (!is_key_frame) {
544
    MB_MODE_INFO *mi = xd->mi[0];
545
    const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_yv12_buf(cm, LAST_FRAME);
546
547
    assert(yv12 != NULL);
548
549
    av1_setup_pre_planes(xd, 0, yv12, mi_row, mi_col,
550
                         get_ref_scale_factors(cm, LAST_FRAME), 1);
551
    mi->ref_frame[0] = LAST_FRAME;
552
    mi->ref_frame[1] = NONE;
553
    mi->bsize = BLOCK_64X64;
554
    mi->mv[0].as_int = 0;
555
    mi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
556
557
    set_ref_ptrs(cm, xd, mi->ref_frame[0], mi->ref_frame[1]);
558
559
    xd->plane[0].dst.buf = x->est_pred;
560
    xd->plane[0].dst.stride = 64;
561
    av1_enc_build_inter_predictor_y(xd, mi_row, mi_col);
562
  } else {
563
#if CONFIG_AV1_HIGHBITDEPTH
564
    switch (xd->bd) {
565
      case 8: memset(x->est_pred, 128, 64 * 64 * sizeof(x->est_pred[0])); break;
566
      case 10:
567
        memset(x->est_pred, 128 * 4, 64 * 64 * sizeof(x->est_pred[0]));
568
        break;
569
      case 12:
570
        memset(x->est_pred, 128 * 16, 64 * 64 * sizeof(x->est_pred[0]));
571
        break;
572
    }
573
#else
574
    memset(x->est_pred, 128, 64 * 64 * sizeof(x->est_pred[0]));
575
#endif  // CONFIG_VP9_HIGHBITDEPTH
576
  }
577
}
578
#endif  // CONFIG_RT_ML_PARTITIONING
579
580
0
#define AVG_CDF_WEIGHT_LEFT 3
581
0
#define AVG_CDF_WEIGHT_TOP_RIGHT 1
582
583
/*!\brief Encode a superblock (minimal RD search involved)
584
 *
585
 * \ingroup partition_search
586
 * Encodes the superblock by a pre-determined partition pattern, only minor
587
 * rd-based searches are allowed to adjust the initial pattern. It is only used
588
 * by realtime encoding.
589
 */
590
static inline void encode_nonrd_sb(AV1_COMP *cpi, ThreadData *td,
591
                                   TileDataEnc *tile_data, TokenExtra **tp,
592
                                   const int mi_row, const int mi_col,
593
0
                                   const int seg_skip) {
594
0
  AV1_COMMON *const cm = &cpi->common;
595
0
  MACROBLOCK *const x = &td->mb;
596
0
  const SPEED_FEATURES *const sf = &cpi->sf;
597
0
  const TileInfo *const tile_info = &tile_data->tile_info;
598
0
  MB_MODE_INFO **mi = cm->mi_params.mi_grid_base +
599
0
                      get_mi_grid_idx(&cm->mi_params, mi_row, mi_col);
600
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
601
0
  PC_TREE *const pc_root = td->pc_root;
602
603
0
#if !CONFIG_REALTIME_ONLY
604
0
  if (cm->delta_q_info.delta_q_present_flag) {
605
0
    const int num_planes = av1_num_planes(cm);
606
607
0
    setup_delta_q_nonrd(cpi, td, x, tile_info, mi_row, mi_col, num_planes);
608
0
  }
609
0
#endif
610
#if CONFIG_RT_ML_PARTITIONING
611
  if (sf->part_sf.partition_search_type == ML_BASED_PARTITION) {
612
    RD_STATS dummy_rdc;
613
    get_estimated_pred(cpi, tile_info, x, mi_row, mi_col);
614
    av1_nonrd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col,
615
                             BLOCK_64X64, &dummy_rdc, 1, INT64_MAX, pc_root);
616
    return;
617
  }
618
#endif
619
  // Set the partition
620
0
  if (sf->part_sf.partition_search_type == FIXED_PARTITION || seg_skip ||
621
0
      (sf->rt_sf.use_fast_fixed_part && x->sb_force_fixed_part == 1 &&
622
0
       (!frame_is_intra_only(cm) &&
623
0
        (!cpi->ppi->use_svc ||
624
0
         !cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)))) {
625
    // set a fixed-size partition
626
0
    av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
627
0
    BLOCK_SIZE bsize_select = sf->part_sf.fixed_partition_size;
628
0
    if (sf->rt_sf.use_fast_fixed_part &&
629
0
        x->content_state_sb.source_sad_nonrd < kLowSad) {
630
0
      bsize_select = cm->seq_params->sb_size;
631
0
    }
632
0
    if (cpi->sf.rt_sf.skip_encoding_non_reference_slide_change &&
633
0
        cpi->rc.high_source_sad && cpi->ppi->rtc_ref.non_reference_frame) {
634
0
      bsize_select = cm->seq_params->sb_size;
635
0
      x->force_zeromv_skip_for_sb = 1;
636
0
    }
637
0
    const BLOCK_SIZE bsize = seg_skip ? sb_size : bsize_select;
638
0
    if (x->content_state_sb.source_sad_nonrd > kZeroSad)
639
0
      x->force_color_check_block_level = 1;
640
0
    av1_set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
641
0
  } else if (sf->part_sf.partition_search_type == VAR_BASED_PARTITION) {
642
    // set a variance-based partition
643
0
    av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
644
0
    av1_choose_var_based_partitioning(cpi, tile_info, td, x, mi_row, mi_col);
645
0
  }
646
0
  assert(sf->part_sf.partition_search_type == FIXED_PARTITION || seg_skip ||
647
0
         sf->part_sf.partition_search_type == VAR_BASED_PARTITION);
648
0
  set_cb_offsets(td->mb.cb_offset, 0, 0);
649
650
  // Initialize the flag to skip cdef to 1.
651
0
  if (sf->rt_sf.skip_cdef_sb) {
652
0
    const int block64_in_sb = (sb_size == BLOCK_128X128) ? 2 : 1;
653
    // If 128x128 block is used, we need to set the flag for all 4 64x64 sub
654
    // "blocks".
655
0
    for (int r = 0; r < block64_in_sb; ++r) {
656
0
      for (int c = 0; c < block64_in_sb; ++c) {
657
0
        const int idx_in_sb =
658
0
            r * MI_SIZE_64X64 * cm->mi_params.mi_stride + c * MI_SIZE_64X64;
659
0
        if (mi[idx_in_sb]) mi[idx_in_sb]->cdef_strength = 1;
660
0
      }
661
0
    }
662
0
  }
663
664
#if CONFIG_COLLECT_COMPONENT_TIMING
665
  start_timing(cpi, nonrd_use_partition_time);
666
#endif
667
0
  av1_nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
668
0
                          pc_root);
669
#if CONFIG_COLLECT_COMPONENT_TIMING
670
  end_timing(cpi, nonrd_use_partition_time);
671
#endif
672
0
}
673
674
// This function initializes the stats for encode_rd_sb.
675
static inline void init_encode_rd_sb(AV1_COMP *cpi, ThreadData *td,
676
                                     const TileDataEnc *tile_data,
677
                                     SIMPLE_MOTION_DATA_TREE *sms_root,
678
                                     RD_STATS *rd_cost, int mi_row, int mi_col,
679
                                     int gather_tpl_data) {
680
  const AV1_COMMON *cm = &cpi->common;
681
  const TileInfo *tile_info = &tile_data->tile_info;
682
  MACROBLOCK *x = &td->mb;
683
684
  const SPEED_FEATURES *sf = &cpi->sf;
685
  const int use_simple_motion_search =
686
      (sf->part_sf.simple_motion_search_split ||
687
       sf->part_sf.simple_motion_search_prune_rect ||
688
       sf->part_sf.simple_motion_search_early_term_none ||
689
       sf->part_sf.ml_early_term_after_part_split_level) &&
690
      !frame_is_intra_only(cm);
691
  if (use_simple_motion_search) {
692
    av1_init_simple_motion_search_mvs_for_sb(cpi, tile_info, x, sms_root,
693
                                             mi_row, mi_col);
694
  }
695
696
#if !CONFIG_REALTIME_ONLY
697
  if (!(has_no_stats_stage(cpi) && cpi->oxcf.mode == REALTIME &&
698
        cpi->oxcf.gf_cfg.lag_in_frames == 0)) {
699
    init_ref_frame_space(cpi, td, mi_row, mi_col);
700
    x->sb_energy_level = 0;
701
    x->part_search_info.cnn_output_valid = 0;
702
    if (gather_tpl_data) {
703
      if (cpi->cb_delta_rdmult_enabled) {
704
        const int num_planes = av1_num_planes(cm);
705
        const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
706
        setup_delta_q(cpi, td, x, tile_info, mi_row, mi_col, num_planes);
707
        av1_tpl_rdmult_setup_sb(cpi, x, sb_size, mi_row, mi_col);
708
      }
709
710
      // TODO(jingning): revisit this function.
711
      if (cpi->oxcf.algo_cfg.enable_tpl_model && (0)) {
712
        adjust_rdmult_tpl_model(cpi, x, mi_row, mi_col);
713
      }
714
    }
715
  }
716
#else
717
  (void)tile_info;
718
  (void)mi_row;
719
  (void)mi_col;
720
  (void)gather_tpl_data;
721
#endif
722
723
  x->reuse_inter_pred = false;
724
  x->txfm_search_params.mode_eval_type = DEFAULT_EVAL;
725
  reset_mb_rd_record(x->txfm_search_info.mb_rd_record);
726
  av1_zero(x->picked_ref_frames_mask);
727
  av1_invalid_rd_stats(rd_cost);
728
}
729
730
#if !CONFIG_REALTIME_ONLY
731
static void sb_qp_sweep_init_quantizers(AV1_COMP *cpi, ThreadData *td,
732
                                        const TileDataEnc *tile_data,
733
                                        SIMPLE_MOTION_DATA_TREE *sms_tree,
734
                                        RD_STATS *rd_cost, int mi_row,
735
0
                                        int mi_col, int delta_qp_ofs) {
736
0
  AV1_COMMON *const cm = &cpi->common;
737
0
  MACROBLOCK *const x = &td->mb;
738
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
739
0
  const TileInfo *tile_info = &tile_data->tile_info;
740
0
  const CommonModeInfoParams *const mi_params = &cm->mi_params;
741
0
  const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
742
0
  assert(delta_q_info->delta_q_present_flag);
743
0
  const int delta_q_res = delta_q_info->delta_q_res;
744
745
0
  const SPEED_FEATURES *sf = &cpi->sf;
746
0
  const int use_simple_motion_search =
747
0
      (sf->part_sf.simple_motion_search_split ||
748
0
       sf->part_sf.simple_motion_search_prune_rect ||
749
0
       sf->part_sf.simple_motion_search_early_term_none ||
750
0
       sf->part_sf.ml_early_term_after_part_split_level) &&
751
0
      !frame_is_intra_only(cm);
752
0
  if (use_simple_motion_search) {
753
0
    av1_init_simple_motion_search_mvs_for_sb(cpi, tile_info, x, sms_tree,
754
0
                                             mi_row, mi_col);
755
0
  }
756
757
0
  int current_qindex = x->rdmult_cur_qindex + delta_qp_ofs;
758
759
0
  MACROBLOCKD *const xd = &x->e_mbd;
760
0
  current_qindex = av1_adjust_q_from_delta_q_res(
761
0
      delta_q_res, xd->current_base_qindex, current_qindex);
762
763
0
  x->delta_qindex = current_qindex - cm->quant_params.base_qindex;
764
765
0
  av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
766
0
  xd->mi[0]->current_qindex = current_qindex;
767
0
  av1_init_plane_quantizers(cpi, x, xd->mi[0]->segment_id, 0);
768
769
  // keep track of any non-zero delta-q used
770
0
  td->deltaq_used |= (x->delta_qindex != 0);
771
772
0
  if (cpi->oxcf.tool_cfg.enable_deltalf_mode) {
773
0
    const int delta_lf_res = delta_q_info->delta_lf_res;
774
0
    const int lfmask = ~(delta_lf_res - 1);
775
0
    const int delta_lf_from_base =
776
0
        ((x->delta_qindex / 4 + delta_lf_res / 2) & lfmask);
777
0
    const int8_t delta_lf =
778
0
        (int8_t)clamp(delta_lf_from_base, -MAX_LOOP_FILTER, MAX_LOOP_FILTER);
779
0
    const int frame_lf_count =
780
0
        av1_num_planes(cm) > 1 ? FRAME_LF_COUNT : FRAME_LF_COUNT - 2;
781
0
    const int mib_size = cm->seq_params->mib_size;
782
783
    // pre-set the delta lf for loop filter. Note that this value is set
784
    // before mi is assigned for each block in current superblock
785
0
    for (int j = 0; j < AOMMIN(mib_size, mi_params->mi_rows - mi_row); j++) {
786
0
      for (int k = 0; k < AOMMIN(mib_size, mi_params->mi_cols - mi_col); k++) {
787
0
        const int grid_idx = get_mi_grid_idx(mi_params, mi_row + j, mi_col + k);
788
0
        mi_params->mi_alloc[grid_idx].delta_lf_from_base = delta_lf;
789
0
        for (int lf_id = 0; lf_id < frame_lf_count; ++lf_id) {
790
0
          mi_params->mi_alloc[grid_idx].delta_lf[lf_id] = delta_lf;
791
0
        }
792
0
      }
793
0
    }
794
0
  }
795
796
0
  x->reuse_inter_pred = false;
797
0
  x->txfm_search_params.mode_eval_type = DEFAULT_EVAL;
798
0
  reset_mb_rd_record(x->txfm_search_info.mb_rd_record);
799
0
  av1_zero(x->picked_ref_frames_mask);
800
0
  av1_invalid_rd_stats(rd_cost);
801
0
}
802
803
static int sb_qp_sweep(AV1_COMP *const cpi, ThreadData *td,
804
                       TileDataEnc *tile_data, TokenExtra **tp, int mi_row,
805
                       int mi_col, BLOCK_SIZE bsize,
806
                       SIMPLE_MOTION_DATA_TREE *sms_tree,
807
0
                       SB_FIRST_PASS_STATS *sb_org_stats) {
808
0
  AV1_COMMON *const cm = &cpi->common;
809
0
  MACROBLOCK *const x = &td->mb;
810
0
  RD_STATS rdc_winner, cur_rdc;
811
0
  av1_invalid_rd_stats(&rdc_winner);
812
813
0
  int best_qindex = td->mb.rdmult_delta_qindex;
814
0
  const int start = cm->current_frame.frame_type == KEY_FRAME ? -20 : -12;
815
0
  const int end = cm->current_frame.frame_type == KEY_FRAME ? 20 : 12;
816
0
  const int step = cm->delta_q_info.delta_q_res;
817
818
0
  for (int sweep_qp_delta = start; sweep_qp_delta <= end;
819
0
       sweep_qp_delta += step) {
820
0
    sb_qp_sweep_init_quantizers(cpi, td, tile_data, sms_tree, &cur_rdc, mi_row,
821
0
                                mi_col, sweep_qp_delta);
822
823
0
    const int alloc_mi_idx = get_alloc_mi_idx(&cm->mi_params, mi_row, mi_col);
824
0
    const int backup_current_qindex =
825
0
        cm->mi_params.mi_alloc[alloc_mi_idx].current_qindex;
826
827
0
    av1_reset_mbmi(&cm->mi_params, bsize, mi_row, mi_col);
828
0
    av1_restore_sb_state(sb_org_stats, cpi, td, tile_data, mi_row, mi_col);
829
0
    cm->mi_params.mi_alloc[alloc_mi_idx].current_qindex = backup_current_qindex;
830
831
0
    td->pc_root = av1_alloc_pc_tree_node(bsize);
832
0
    if (!td->pc_root)
833
0
      aom_internal_error(x->e_mbd.error_info, AOM_CODEC_MEM_ERROR,
834
0
                         "Failed to allocate PC_TREE");
835
0
    av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, bsize,
836
0
                          &cur_rdc, cur_rdc, td->pc_root, sms_tree, NULL,
837
0
                          SB_DRY_PASS, NULL);
838
839
0
    if ((rdc_winner.rdcost > cur_rdc.rdcost) ||
840
0
        (abs(sweep_qp_delta) < abs(best_qindex - x->rdmult_delta_qindex) &&
841
0
         rdc_winner.rdcost == cur_rdc.rdcost)) {
842
0
      rdc_winner = cur_rdc;
843
0
      best_qindex = x->rdmult_delta_qindex + sweep_qp_delta;
844
0
    }
845
0
  }
846
847
0
  return best_qindex;
848
0
}
849
#endif  //! CONFIG_REALTIME_ONLY
850
851
/*!\brief Encode a superblock (RD-search-based)
852
 *
853
 * \ingroup partition_search
854
 * Conducts partition search for a superblock, based on rate-distortion costs,
855
 * from scratch or adjusting from a pre-calculated partition pattern.
856
 */
857
static inline void encode_rd_sb(AV1_COMP *cpi, ThreadData *td,
858
                                TileDataEnc *tile_data, TokenExtra **tp,
859
                                const int mi_row, const int mi_col,
860
0
                                const int seg_skip) {
861
0
  AV1_COMMON *const cm = &cpi->common;
862
0
  MACROBLOCK *const x = &td->mb;
863
0
  MACROBLOCKD *const xd = &x->e_mbd;
864
0
  const SPEED_FEATURES *const sf = &cpi->sf;
865
0
  const TileInfo *const tile_info = &tile_data->tile_info;
866
0
  MB_MODE_INFO **mi = cm->mi_params.mi_grid_base +
867
0
                      get_mi_grid_idx(&cm->mi_params, mi_row, mi_col);
868
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
869
0
  const int num_planes = av1_num_planes(cm);
870
0
  int dummy_rate;
871
0
  int64_t dummy_dist;
872
0
  RD_STATS dummy_rdc;
873
0
  SIMPLE_MOTION_DATA_TREE *const sms_root = td->sms_root;
874
875
#if CONFIG_REALTIME_ONLY
876
  (void)seg_skip;
877
#endif  // CONFIG_REALTIME_ONLY
878
879
0
  init_encode_rd_sb(cpi, td, tile_data, sms_root, &dummy_rdc, mi_row, mi_col,
880
0
                    1);
881
882
  // Encode the superblock
883
0
  if (sf->part_sf.partition_search_type == VAR_BASED_PARTITION) {
884
    // partition search starting from a variance-based partition
885
0
    av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
886
0
    av1_choose_var_based_partitioning(cpi, tile_info, td, x, mi_row, mi_col);
887
888
#if CONFIG_COLLECT_COMPONENT_TIMING
889
    start_timing(cpi, rd_use_partition_time);
890
#endif
891
0
    td->pc_root = av1_alloc_pc_tree_node(sb_size);
892
0
    if (!td->pc_root)
893
0
      aom_internal_error(xd->error_info, AOM_CODEC_MEM_ERROR,
894
0
                         "Failed to allocate PC_TREE");
895
0
    av1_rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
896
0
                         &dummy_rate, &dummy_dist, 1, td->pc_root);
897
0
    av1_free_pc_tree_recursive(td->pc_root, num_planes, 0, 0,
898
0
                               sf->part_sf.partition_search_type);
899
0
    td->pc_root = NULL;
900
#if CONFIG_COLLECT_COMPONENT_TIMING
901
    end_timing(cpi, rd_use_partition_time);
902
#endif
903
0
  }
904
0
#if !CONFIG_REALTIME_ONLY
905
0
  else if (sf->part_sf.partition_search_type == FIXED_PARTITION || seg_skip) {
906
    // partition search by adjusting a fixed-size partition
907
0
    av1_set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
908
0
    const BLOCK_SIZE bsize =
909
0
        seg_skip ? sb_size : sf->part_sf.fixed_partition_size;
910
0
    av1_set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
911
0
    td->pc_root = av1_alloc_pc_tree_node(sb_size);
912
0
    if (!td->pc_root)
913
0
      aom_internal_error(xd->error_info, AOM_CODEC_MEM_ERROR,
914
0
                         "Failed to allocate PC_TREE");
915
0
    av1_rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
916
0
                         &dummy_rate, &dummy_dist, 1, td->pc_root);
917
0
    av1_free_pc_tree_recursive(td->pc_root, num_planes, 0, 0,
918
0
                               sf->part_sf.partition_search_type);
919
0
    td->pc_root = NULL;
920
0
  } else {
921
    // The most exhaustive recursive partition search
922
0
    SuperBlockEnc *sb_enc = &x->sb_enc;
923
    // No stats for overlay frames. Exclude key frame.
924
0
    av1_get_tpl_stats_sb(cpi, sb_size, mi_row, mi_col, sb_enc);
925
926
    // Reset the tree for simple motion search data
927
0
    av1_reset_simple_motion_tree_partition(sms_root, sb_size);
928
929
#if CONFIG_COLLECT_COMPONENT_TIMING
930
    start_timing(cpi, rd_pick_partition_time);
931
#endif
932
933
    // Estimate the maximum square partition block size, which will be used
934
    // as the starting block size for partitioning the sb
935
0
    set_max_min_partition_size(sb_enc, cpi, x, sf, sb_size, mi_row, mi_col);
936
937
    // The superblock can be searched only once, or twice consecutively for
938
    // better quality. Note that the meaning of passes here is different from
939
    // the general concept of 1-pass/2-pass encoders.
940
0
    const int num_passes =
941
0
        cpi->oxcf.unit_test_cfg.sb_multipass_unit_test ? 2 : 1;
942
943
0
    if (cpi->oxcf.sb_qp_sweep &&
944
0
        !(has_no_stats_stage(cpi) && cpi->oxcf.mode == REALTIME &&
945
0
          cpi->oxcf.gf_cfg.lag_in_frames == 0) &&
946
0
        cm->delta_q_info.delta_q_present_flag) {
947
0
      AOM_CHECK_MEM_ERROR(
948
0
          x->e_mbd.error_info, td->mb.sb_stats_cache,
949
0
          (SB_FIRST_PASS_STATS *)aom_malloc(sizeof(*td->mb.sb_stats_cache)));
950
0
      av1_backup_sb_state(td->mb.sb_stats_cache, cpi, td, tile_data, mi_row,
951
0
                          mi_col);
952
0
      assert(x->rdmult_delta_qindex == x->delta_qindex);
953
954
0
      const int best_qp_diff =
955
0
          sb_qp_sweep(cpi, td, tile_data, tp, mi_row, mi_col, sb_size, sms_root,
956
0
                      td->mb.sb_stats_cache) -
957
0
          x->rdmult_delta_qindex;
958
959
0
      sb_qp_sweep_init_quantizers(cpi, td, tile_data, sms_root, &dummy_rdc,
960
0
                                  mi_row, mi_col, best_qp_diff);
961
962
0
      const int alloc_mi_idx = get_alloc_mi_idx(&cm->mi_params, mi_row, mi_col);
963
0
      const int backup_current_qindex =
964
0
          cm->mi_params.mi_alloc[alloc_mi_idx].current_qindex;
965
966
0
      av1_reset_mbmi(&cm->mi_params, sb_size, mi_row, mi_col);
967
0
      av1_restore_sb_state(td->mb.sb_stats_cache, cpi, td, tile_data, mi_row,
968
0
                           mi_col);
969
970
0
      cm->mi_params.mi_alloc[alloc_mi_idx].current_qindex =
971
0
          backup_current_qindex;
972
0
      aom_free(td->mb.sb_stats_cache);
973
0
      td->mb.sb_stats_cache = NULL;
974
0
    }
975
0
    if (num_passes == 1) {
976
#if CONFIG_PARTITION_SEARCH_ORDER
977
      if (cpi->ext_part_controller.ready && !frame_is_intra_only(cm)) {
978
        av1_reset_part_sf(&cpi->sf.part_sf);
979
        av1_reset_sf_for_ext_part(cpi);
980
        RD_STATS this_rdc;
981
        av1_rd_partition_search(cpi, td, tile_data, tp, sms_root, mi_row,
982
                                mi_col, sb_size, &this_rdc);
983
      } else {
984
        td->pc_root = av1_alloc_pc_tree_node(sb_size);
985
        if (!td->pc_root)
986
          aom_internal_error(xd->error_info, AOM_CODEC_MEM_ERROR,
987
                             "Failed to allocate PC_TREE");
988
        av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, sb_size,
989
                              &dummy_rdc, dummy_rdc, td->pc_root, sms_root,
990
                              NULL, SB_SINGLE_PASS, NULL);
991
      }
992
#else
993
0
      td->pc_root = av1_alloc_pc_tree_node(sb_size);
994
0
      if (!td->pc_root)
995
0
        aom_internal_error(xd->error_info, AOM_CODEC_MEM_ERROR,
996
0
                           "Failed to allocate PC_TREE");
997
0
      av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, sb_size,
998
0
                            &dummy_rdc, dummy_rdc, td->pc_root, sms_root, NULL,
999
0
                            SB_SINGLE_PASS, NULL);
1000
0
#endif  // CONFIG_PARTITION_SEARCH_ORDER
1001
0
    } else {
1002
      // First pass
1003
0
      AOM_CHECK_MEM_ERROR(
1004
0
          x->e_mbd.error_info, td->mb.sb_fp_stats,
1005
0
          (SB_FIRST_PASS_STATS *)aom_malloc(sizeof(*td->mb.sb_fp_stats)));
1006
0
      av1_backup_sb_state(td->mb.sb_fp_stats, cpi, td, tile_data, mi_row,
1007
0
                          mi_col);
1008
0
      td->pc_root = av1_alloc_pc_tree_node(sb_size);
1009
0
      if (!td->pc_root)
1010
0
        aom_internal_error(xd->error_info, AOM_CODEC_MEM_ERROR,
1011
0
                           "Failed to allocate PC_TREE");
1012
0
      av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, sb_size,
1013
0
                            &dummy_rdc, dummy_rdc, td->pc_root, sms_root, NULL,
1014
0
                            SB_DRY_PASS, NULL);
1015
1016
      // Second pass
1017
0
      init_encode_rd_sb(cpi, td, tile_data, sms_root, &dummy_rdc, mi_row,
1018
0
                        mi_col, 0);
1019
0
      av1_reset_mbmi(&cm->mi_params, sb_size, mi_row, mi_col);
1020
0
      av1_reset_simple_motion_tree_partition(sms_root, sb_size);
1021
1022
0
      av1_restore_sb_state(td->mb.sb_fp_stats, cpi, td, tile_data, mi_row,
1023
0
                           mi_col);
1024
1025
0
      td->pc_root = av1_alloc_pc_tree_node(sb_size);
1026
0
      if (!td->pc_root)
1027
0
        aom_internal_error(xd->error_info, AOM_CODEC_MEM_ERROR,
1028
0
                           "Failed to allocate PC_TREE");
1029
0
      av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, sb_size,
1030
0
                            &dummy_rdc, dummy_rdc, td->pc_root, sms_root, NULL,
1031
0
                            SB_WET_PASS, NULL);
1032
0
      aom_free(td->mb.sb_fp_stats);
1033
0
      td->mb.sb_fp_stats = NULL;
1034
0
    }
1035
1036
    // Reset to 0 so that it wouldn't be used elsewhere mistakenly.
1037
0
    sb_enc->tpl_data_count = 0;
1038
#if CONFIG_COLLECT_COMPONENT_TIMING
1039
    end_timing(cpi, rd_pick_partition_time);
1040
#endif
1041
0
  }
1042
0
#endif  // !CONFIG_REALTIME_ONLY
1043
1044
  // Update the inter rd model
1045
  // TODO(angiebird): Let inter_mode_rd_model_estimation support multi-tile.
1046
0
  if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1 &&
1047
0
      cm->tiles.cols == 1 && cm->tiles.rows == 1) {
1048
0
    av1_inter_mode_data_fit(tile_data, x->rdmult);
1049
0
  }
1050
0
}
1051
1052
// Check if the cost update of symbols mode, coeff and dv are tile or off.
1053
static inline int is_mode_coeff_dv_upd_freq_tile_or_off(
1054
0
    const AV1_COMP *const cpi) {
1055
0
  const INTER_MODE_SPEED_FEATURES *const inter_sf = &cpi->sf.inter_sf;
1056
1057
0
  return (inter_sf->coeff_cost_upd_level <= INTERNAL_COST_UPD_TILE &&
1058
0
          inter_sf->mode_cost_upd_level <= INTERNAL_COST_UPD_TILE &&
1059
0
          cpi->sf.intra_sf.dv_cost_upd_level <= INTERNAL_COST_UPD_TILE);
1060
0
}
1061
1062
// When row-mt is enabled and cost update frequencies are set to off/tile,
1063
// processing of current SB can start even before processing of top-right SB
1064
// is finished. This function checks if it is sufficient to wait for top SB
1065
// to finish processing before current SB starts processing.
1066
0
static inline int delay_wait_for_top_right_sb(const AV1_COMP *const cpi) {
1067
0
  const MODE mode = cpi->oxcf.mode;
1068
0
  if (mode == GOOD) return 0;
1069
1070
0
  if (mode == ALLINTRA)
1071
0
    return is_mode_coeff_dv_upd_freq_tile_or_off(cpi);
1072
0
  else if (mode == REALTIME)
1073
0
    return (is_mode_coeff_dv_upd_freq_tile_or_off(cpi) &&
1074
0
            cpi->sf.inter_sf.mv_cost_upd_level <= INTERNAL_COST_UPD_TILE);
1075
0
  else
1076
0
    return 0;
1077
0
}
1078
1079
/*!\brief Calculate source SAD at superblock level using 64x64 block source SAD
1080
 *
1081
 * \ingroup partition_search
1082
 * \callgraph
1083
 * \callergraph
1084
 */
1085
static inline uint64_t get_sb_source_sad(const AV1_COMP *cpi, int mi_row,
1086
0
                                         int mi_col) {
1087
0
  if (cpi->src_sad_blk_64x64 == NULL) return UINT64_MAX;
1088
1089
0
  const AV1_COMMON *const cm = &cpi->common;
1090
0
  const int blk_64x64_in_mis = (cm->seq_params->sb_size == BLOCK_128X128)
1091
0
                                   ? (cm->seq_params->mib_size >> 1)
1092
0
                                   : cm->seq_params->mib_size;
1093
0
  const int num_blk_64x64_cols =
1094
0
      (cm->mi_params.mi_cols + blk_64x64_in_mis - 1) / blk_64x64_in_mis;
1095
0
  const int num_blk_64x64_rows =
1096
0
      (cm->mi_params.mi_rows + blk_64x64_in_mis - 1) / blk_64x64_in_mis;
1097
0
  const int blk_64x64_col_index = mi_col / blk_64x64_in_mis;
1098
0
  const int blk_64x64_row_index = mi_row / blk_64x64_in_mis;
1099
0
  uint64_t curr_sb_sad = UINT64_MAX;
1100
  // Avoid the border as sad_blk_64x64 may not be set for the border
1101
  // in the scene detection.
1102
0
  if ((blk_64x64_row_index >= num_blk_64x64_rows - 1) ||
1103
0
      (blk_64x64_col_index >= num_blk_64x64_cols - 1)) {
1104
0
    return curr_sb_sad;
1105
0
  }
1106
0
  const uint64_t *const src_sad_blk_64x64_data =
1107
0
      &cpi->src_sad_blk_64x64[blk_64x64_col_index +
1108
0
                              blk_64x64_row_index * num_blk_64x64_cols];
1109
0
  if (cm->seq_params->sb_size == BLOCK_128X128) {
1110
    // Calculate SB source SAD by accumulating source SAD of 64x64 blocks in the
1111
    // superblock
1112
0
    curr_sb_sad = src_sad_blk_64x64_data[0] + src_sad_blk_64x64_data[1] +
1113
0
                  src_sad_blk_64x64_data[num_blk_64x64_cols] +
1114
0
                  src_sad_blk_64x64_data[num_blk_64x64_cols + 1];
1115
0
  } else if (cm->seq_params->sb_size == BLOCK_64X64) {
1116
0
    curr_sb_sad = src_sad_blk_64x64_data[0];
1117
0
  }
1118
0
  return curr_sb_sad;
1119
0
}
1120
1121
/*!\brief Determine whether grading content can be skipped based on sad stat
1122
 *
1123
 * \ingroup partition_search
1124
 * \callgraph
1125
 * \callergraph
1126
 */
1127
static inline bool is_calc_src_content_needed(AV1_COMP *cpi,
1128
                                              MACROBLOCK *const x, int mi_row,
1129
0
                                              int mi_col) {
1130
0
  if (cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
1131
0
    return true;
1132
0
  const uint64_t curr_sb_sad = get_sb_source_sad(cpi, mi_row, mi_col);
1133
0
  if (curr_sb_sad == UINT64_MAX) return true;
1134
0
  if (curr_sb_sad == 0) {
1135
0
    x->content_state_sb.source_sad_nonrd = kZeroSad;
1136
0
    return false;
1137
0
  }
1138
0
  AV1_COMMON *const cm = &cpi->common;
1139
0
  bool do_calc_src_content = true;
1140
1141
0
  if (cpi->oxcf.speed < 9) return do_calc_src_content;
1142
1143
  // TODO(yunqing): Tune/validate the thresholds for 128x128 SB size.
1144
0
  if (AOMMIN(cm->width, cm->height) < 360) {
1145
    // Derive Average 64x64 block source SAD from SB source SAD
1146
0
    const uint64_t avg_64x64_blk_sad =
1147
0
        (cm->seq_params->sb_size == BLOCK_128X128) ? ((curr_sb_sad + 2) >> 2)
1148
0
                                                   : curr_sb_sad;
1149
1150
    // The threshold is determined based on kLowSad and kHighSad threshold and
1151
    // test results.
1152
0
    uint64_t thresh_low = 15000;
1153
0
    uint64_t thresh_high = 40000;
1154
1155
0
    if (cpi->sf.rt_sf.increase_source_sad_thresh) {
1156
0
      thresh_low = thresh_low << 1;
1157
0
      thresh_high = thresh_high << 1;
1158
0
    }
1159
1160
0
    if (avg_64x64_blk_sad > thresh_low && avg_64x64_blk_sad < thresh_high) {
1161
0
      do_calc_src_content = false;
1162
      // Note: set x->content_state_sb.source_sad_rd as well if this is extended
1163
      // to RTC rd path.
1164
0
      x->content_state_sb.source_sad_nonrd = kMedSad;
1165
0
    }
1166
0
  }
1167
1168
0
  return do_calc_src_content;
1169
0
}
1170
1171
/*!\brief Determine whether grading content is needed based on sf and frame stat
1172
 *
1173
 * \ingroup partition_search
1174
 * \callgraph
1175
 * \callergraph
1176
 */
1177
// TODO(any): consolidate sfs to make interface cleaner
1178
static inline void grade_source_content_sb(AV1_COMP *cpi, MACROBLOCK *const x,
1179
                                           TileDataEnc *tile_data, int mi_row,
1180
0
                                           int mi_col) {
1181
0
  AV1_COMMON *const cm = &cpi->common;
1182
0
  if (cm->current_frame.frame_type == KEY_FRAME ||
1183
0
      (cpi->ppi->use_svc &&
1184
0
       cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)) {
1185
0
    assert(x->content_state_sb.source_sad_nonrd == kMedSad);
1186
0
    assert(x->content_state_sb.source_sad_rd == kMedSad);
1187
0
    return;
1188
0
  }
1189
0
  bool calc_src_content = false;
1190
1191
0
  if (cpi->sf.rt_sf.source_metrics_sb_nonrd) {
1192
0
    if (!cpi->sf.rt_sf.check_scene_detection || cpi->rc.frame_source_sad > 0) {
1193
0
      calc_src_content = is_calc_src_content_needed(cpi, x, mi_row, mi_col);
1194
0
    } else {
1195
0
      x->content_state_sb.source_sad_nonrd = kZeroSad;
1196
0
    }
1197
0
  } else if ((cpi->sf.rt_sf.var_part_based_on_qidx >= 1) &&
1198
0
             (cm->width * cm->height <= 352 * 288)) {
1199
0
    if (cpi->rc.frame_source_sad > 0)
1200
0
      calc_src_content = true;
1201
0
    else
1202
0
      x->content_state_sb.source_sad_rd = kZeroSad;
1203
0
  }
1204
0
  if (calc_src_content)
1205
0
    av1_source_content_sb(cpi, x, tile_data, mi_row, mi_col);
1206
0
}
1207
1208
0
static uint8_t get_sb_segment_id(const AV1_COMP *cpi, int mi_row, int mi_col) {
1209
0
  const AV1_COMMON *const cm = &cpi->common;
1210
0
  const struct segmentation *const seg = &cm->seg;
1211
0
  const uint8_t *const map =
1212
0
      seg->update_map ? cpi->enc_seg.map : cm->last_frame_seg_map;
1213
0
  if (!map) return 0;
1214
0
  return get_segment_id(&cm->mi_params, map, cm->seq_params->sb_size, mi_row,
1215
0
                        mi_col);
1216
0
}
1217
1218
// Returns true when skip segment superblocks of this frame may be copied from
1219
// their reference before they are coded.
1220
0
static bool can_copy_skip_sbs(const AV1_COMP *cpi) {
1221
0
  const AV1_COMMON *const cm = &cpi->common;
1222
0
  if (!cm->seg.enabled || frame_is_intra_only(cm) ||
1223
0
      !cpi->sf.rt_sf.use_nonrd_pick_mode)
1224
0
    return false;
1225
1226
  // Segmentation without a skip segment, like cyclic refresh, has nothing to
1227
  // copy, so this saves the segment lookups of the whole frame.
1228
0
  for (int i = 0; i < MAX_SEGMENTS; ++i) {
1229
0
    if (segfeature_active(&cm->seg, i, SEG_LVL_SKIP)) return true;
1230
0
  }
1231
0
  return false;
1232
0
}
1233
1234
// Returns the reference that a superblock in this segment predicts from with
1235
// a plain copy, or NONE_FRAME when it needs the normal prediction build.
1236
static MV_REFERENCE_FRAME get_skip_sb_copy_ref(const AV1_COMMON *cm,
1237
0
                                               uint8_t segment_id) {
1238
0
  const struct segmentation *const seg = &cm->seg;
1239
0
  if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) return NONE_FRAME;
1240
1241
  // Same reference as av1_nonrd_pick_inter_mode_sb_seg_skip().
1242
0
  const MV_REFERENCE_FRAME ref =
1243
0
      segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)
1244
0
          ? (MV_REFERENCE_FRAME)get_segdata(seg, segment_id, SEG_LVL_REF_FRAME)
1245
0
          : LAST_FRAME;
1246
0
  if (ref <= INTRA_FRAME || cm->global_motion[ref].wmtype != IDENTITY)
1247
0
    return NONE_FRAME;
1248
1249
0
  const YV12_BUFFER_CONFIG *const ref_buf = get_ref_frame_yv12_buf(cm, ref);
1250
0
  if (!ref_buf || (ref_buf->flags & YV12_FLAG_HIGHBITDEPTH) ||
1251
0
      av1_is_scaled(get_ref_scale_factors_const(cm, ref)))
1252
0
    return NONE_FRAME;
1253
0
  return ref;
1254
0
}
1255
1256
// Copies the reference into the superblocks from mi_col_start to mi_col_end
1257
// of one superblock row, inside the frame area.
1258
static void copy_sb_span(const AV1_COMMON *cm, MV_REFERENCE_FRAME ref,
1259
0
                         int mi_row, int mi_col_start, int mi_col_end) {
1260
0
  const YV12_BUFFER_CONFIG *const src = get_ref_frame_yv12_buf(cm, ref);
1261
0
  YV12_BUFFER_CONFIG *const dst = &cm->cur_frame->buf;
1262
0
  const int x0 = mi_col_start * MI_SIZE;
1263
0
  const int x1 = AOMMIN(mi_col_end, cm->mi_params.mi_cols) * MI_SIZE;
1264
0
  const int y0 = mi_row * MI_SIZE;
1265
0
  const int y1 =
1266
0
      AOMMIN(mi_row + cm->seq_params->mib_size, cm->mi_params.mi_rows) *
1267
0
      MI_SIZE;
1268
0
  aom_yv12_partial_coloc_copy_y(src, dst, x0, x1, y0, y1);
1269
0
  if (av1_num_planes(cm) == 1) return;
1270
1271
0
  const int ss_x = cm->seq_params->subsampling_x;
1272
0
  const int ss_y = cm->seq_params->subsampling_y;
1273
0
  aom_yv12_partial_coloc_copy_u(src, dst, x0 >> ss_x, x1 >> ss_x, y0 >> ss_y,
1274
0
                                y1 >> ss_y);
1275
0
  aom_yv12_partial_coloc_copy_v(src, dst, x0 >> ss_x, x1 >> ss_x, y0 >> ss_y,
1276
0
                                y1 >> ss_y);
1277
0
}
1278
1279
// Gets the segment id of each superblock of a tile row. The map of a
1280
// superblock only changes while it is coded, so the ids hold for the row.
1281
static void get_sb_segment_ids_of_row(const AV1_COMP *cpi,
1282
                                      const TileInfo *tile_info, int mi_row,
1283
0
                                      uint8_t *segment_ids) {
1284
0
  const int mib_size = cpi->common.seq_params->mib_size;
1285
0
  for (int mi_col = tile_info->mi_col_start; mi_col < tile_info->mi_col_end;
1286
0
       mi_col += mib_size) {
1287
0
    *segment_ids++ = get_sb_segment_id(cpi, mi_row, mi_col);
1288
0
  }
1289
0
}
1290
1291
// Fills the skip segment superblocks of a row from their reference before the
1292
// row is coded. Wide row copies are much faster than copying every 64x64 block
1293
// plane by plane, so encode_superblock() then skips their prediction.
1294
static void copy_skip_sbs_of_row(const AV1_COMP *cpi, const TileInfo *tile_info,
1295
0
                                 int mi_row, const uint8_t *segment_ids) {
1296
0
  if (!can_copy_skip_sbs(cpi)) return;
1297
1298
0
  const AV1_COMMON *const cm = &cpi->common;
1299
0
  const int mib_size = cm->seq_params->mib_size;
1300
0
  int span_start = -1;
1301
0
  MV_REFERENCE_FRAME span_ref = NONE_FRAME;
1302
1303
0
  for (int mi_col = tile_info->mi_col_start, sb_col = 0;;
1304
0
       mi_col += mib_size, ++sb_col) {
1305
0
    const int in_tile = mi_col < tile_info->mi_col_end;
1306
0
    const MV_REFERENCE_FRAME ref =
1307
0
        in_tile ? get_skip_sb_copy_ref(cm, segment_ids[sb_col]) : NONE_FRAME;
1308
0
    if (span_start >= 0 && ref != span_ref) {
1309
0
      copy_sb_span(cm, span_ref, mi_row, span_start, mi_col);
1310
0
      span_start = -1;
1311
0
    }
1312
0
    if (span_start < 0 && ref != NONE_FRAME) {
1313
0
      span_start = mi_col;
1314
0
      span_ref = ref;
1315
0
    }
1316
0
    if (!in_tile) break;
1317
0
  }
1318
0
}
1319
1320
/*!\brief Encode a superblock row by breaking it into superblocks
1321
 *
1322
 * \ingroup partition_search
1323
 * \callgraph
1324
 * \callergraph
1325
 * Do partition and mode search for an sb row: one row of superblocks filling up
1326
 * the width of the current tile.
1327
 */
1328
static inline void encode_sb_row(AV1_COMP *cpi, ThreadData *td,
1329
                                 TileDataEnc *tile_data, int mi_row,
1330
0
                                 TokenExtra **tp) {
1331
0
  AV1_COMMON *const cm = &cpi->common;
1332
0
  const TileInfo *const tile_info = &tile_data->tile_info;
1333
0
  MultiThreadInfo *const mt_info = &cpi->mt_info;
1334
0
  AV1EncRowMultiThreadInfo *const enc_row_mt = &mt_info->enc_row_mt;
1335
0
  AV1EncRowMultiThreadSync *const row_mt_sync = &tile_data->row_mt_sync;
1336
0
  bool row_mt_enabled = mt_info->row_mt_enabled;
1337
0
  MACROBLOCK *const x = &td->mb;
1338
0
  MACROBLOCKD *const xd = &x->e_mbd;
1339
0
  const int sb_cols_in_tile = av1_get_sb_cols_in_tile(cm, tile_info);
1340
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
1341
0
  const int mib_size = cm->seq_params->mib_size;
1342
0
  const int mib_size_log2 = cm->seq_params->mib_size_log2;
1343
0
  const int sb_row = (mi_row - tile_info->mi_row_start) >> mib_size_log2;
1344
0
  const int use_nonrd_mode = cpi->sf.rt_sf.use_nonrd_pick_mode;
1345
1346
#if CONFIG_COLLECT_COMPONENT_TIMING
1347
  start_timing(cpi, encode_sb_row_time);
1348
#endif
1349
1350
  // Initialize the left context for the new SB row
1351
0
  av1_zero_left_context(xd);
1352
1353
  // Reset delta for quantizer and loof filters at the beginning of every tile
1354
0
  if (mi_row == tile_info->mi_row_start || row_mt_enabled) {
1355
0
    if (cpi->cb_delta_rdmult_enabled)
1356
0
      xd->current_base_qindex = cm->quant_params.base_qindex;
1357
0
    if (cm->delta_q_info.delta_lf_present_flag) {
1358
0
      av1_reset_loop_filter_delta(xd, av1_num_planes(cm));
1359
0
    }
1360
0
  }
1361
1362
0
  reset_thresh_freq_fact(x);
1363
1364
0
  const struct segmentation *const seg = &cm->seg;
1365
0
  uint8_t sb_segment_ids[MAX_TILE_WIDTH >> MIN_SB_SIZE_LOG2] = { 0 };
1366
0
  assert(sb_cols_in_tile <= (int)sizeof(sb_segment_ids));
1367
0
  if (seg->enabled) {
1368
0
    get_sb_segment_ids_of_row(cpi, tile_info, mi_row, sb_segment_ids);
1369
0
    copy_skip_sbs_of_row(cpi, tile_info, mi_row, sb_segment_ids);
1370
0
  }
1371
1372
  // Code each SB in the row
1373
0
  for (int mi_col = tile_info->mi_col_start, sb_col_in_tile = 0;
1374
0
       mi_col < tile_info->mi_col_end; mi_col += mib_size, sb_col_in_tile++) {
1375
    // In realtime/allintra mode and when frequency of cost updates is off/tile,
1376
    // wait for the top superblock to finish encoding. Otherwise, wait for the
1377
    // top-right superblock to finish encoding.
1378
0
    enc_row_mt->sync_read_ptr(
1379
0
        row_mt_sync, sb_row, sb_col_in_tile - delay_wait_for_top_right_sb(cpi));
1380
1381
0
#if CONFIG_MULTITHREAD
1382
0
    if (row_mt_enabled) {
1383
0
      pthread_mutex_lock(enc_row_mt->mutex_);
1384
0
      const bool row_mt_exit = enc_row_mt->row_mt_exit;
1385
0
      pthread_mutex_unlock(enc_row_mt->mutex_);
1386
      // Exit in case any worker has encountered an error.
1387
0
      if (row_mt_exit) return;
1388
0
    }
1389
0
#endif
1390
1391
0
    const int update_cdf = tile_data->allow_update_cdf && row_mt_enabled;
1392
0
    if (update_cdf && (tile_info->mi_row_start != mi_row)) {
1393
0
      if ((tile_info->mi_col_start == mi_col)) {
1394
        // restore frame context at the 1st column sb
1395
0
        *xd->tile_ctx = *x->row_ctx;
1396
0
      } else {
1397
        // update context
1398
0
        int wt_left = AVG_CDF_WEIGHT_LEFT;
1399
0
        int wt_tr = AVG_CDF_WEIGHT_TOP_RIGHT;
1400
0
        if (tile_info->mi_col_end > (mi_col + mib_size))
1401
0
          av1_avg_cdf_symbols(xd->tile_ctx, x->row_ctx + sb_col_in_tile,
1402
0
                              wt_left, wt_tr);
1403
0
        else
1404
0
          av1_avg_cdf_symbols(xd->tile_ctx, x->row_ctx + sb_col_in_tile - 1,
1405
0
                              wt_left, wt_tr);
1406
0
      }
1407
0
    }
1408
1409
    // Update the rate cost tables for some symbols
1410
0
    av1_set_cost_upd_freq(cpi, td, tile_info, mi_row, mi_col);
1411
1412
    // Reset color coding related parameters
1413
0
    av1_zero(x->color_sensitivity_sb);
1414
0
    av1_zero(x->color_sensitivity_sb_g);
1415
0
    av1_zero(x->color_sensitivity_sb_alt);
1416
0
    av1_zero(x->color_sensitivity);
1417
0
    x->content_state_sb.source_sad_nonrd = kMedSad;
1418
0
    x->content_state_sb.source_sad_rd = kMedSad;
1419
0
    x->content_state_sb.lighting_change = 0;
1420
0
    x->content_state_sb.low_sumdiff = 0;
1421
0
    x->force_zeromv_skip_for_sb = 0;
1422
0
    x->sb_me_block = 0;
1423
0
    x->sb_me_partition = 0;
1424
0
    x->sb_me_mv.as_int = 0;
1425
0
    x->sb_force_fixed_part = 1;
1426
    // Superblocks coded without the variance partitioning must not use the
1427
    // low variance flags of an earlier superblock.
1428
0
    av1_zero(x->part_search_info.variance_low);
1429
0
    x->color_palette_thresh = 64;
1430
0
    x->force_color_check_block_level = 0;
1431
0
    x->nonrd_prune_ref_frame_search =
1432
0
        cpi->sf.rt_sf.nonrd_prune_ref_frame_search;
1433
1434
0
    if (cpi->oxcf.mode == ALLINTRA) {
1435
0
      x->intra_sb_rdmult_modifier = 128;
1436
0
    }
1437
1438
0
    xd->cur_frame_force_integer_mv = cm->features.cur_frame_force_integer_mv;
1439
0
    x->source_variance = UINT_MAX;
1440
0
    td->mb.cb_coef_buff = av1_get_cb_coeff_buffer(cpi, mi_row, mi_col);
1441
1442
    // Get segment id and skip flag
1443
0
    int seg_skip = 0;
1444
0
    x->sb_copied_ref = NONE_FRAME;
1445
0
    if (seg->enabled) {
1446
0
      const uint8_t segment_id = sb_segment_ids[sb_col_in_tile];
1447
0
      seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
1448
0
      if (seg_skip && !frame_is_intra_only(cm) && use_nonrd_mode)
1449
0
        x->sb_copied_ref = get_skip_sb_copy_ref(cm, segment_id);
1450
0
    }
1451
1452
0
    produce_gradients_for_sb(cpi, x, sb_size, mi_row, mi_col);
1453
1454
0
    init_src_var_info_of_4x4_sub_blocks(cpi, x->src_var_info_of_4x4_sub_blocks,
1455
0
                                        sb_size);
1456
1457
    // Grade the temporal variation of the sb, the grade will be used to decide
1458
    // fast mode search strategy for coding blocks
1459
0
    if (!seg_skip) grade_source_content_sb(cpi, x, tile_data, mi_row, mi_col);
1460
1461
    // encode the superblock
1462
0
    if (use_nonrd_mode) {
1463
0
      encode_nonrd_sb(cpi, td, tile_data, tp, mi_row, mi_col, seg_skip);
1464
0
    } else {
1465
0
      encode_rd_sb(cpi, td, tile_data, tp, mi_row, mi_col, seg_skip);
1466
0
    }
1467
1468
    // Update the top-right context in row_mt coding
1469
0
    if (update_cdf && (tile_info->mi_row_end > (mi_row + mib_size))) {
1470
0
      if (sb_cols_in_tile == 1)
1471
0
        x->row_ctx[0] = *xd->tile_ctx;
1472
0
      else if (sb_col_in_tile >= 1)
1473
0
        x->row_ctx[sb_col_in_tile - 1] = *xd->tile_ctx;
1474
0
    }
1475
0
    enc_row_mt->sync_write_ptr(row_mt_sync, sb_row, sb_col_in_tile,
1476
0
                               sb_cols_in_tile);
1477
0
  }
1478
1479
#if CONFIG_COLLECT_COMPONENT_TIMING
1480
  end_timing(cpi, encode_sb_row_time);
1481
#endif
1482
0
}
1483
1484
0
static inline void init_encode_frame_mb_context(AV1_COMP *cpi) {
1485
0
  AV1_COMMON *const cm = &cpi->common;
1486
0
  const int num_planes = av1_num_planes(cm);
1487
0
  MACROBLOCK *const x = &cpi->td.mb;
1488
0
  MACROBLOCKD *const xd = &x->e_mbd;
1489
1490
  // Copy data over into macro block data structures.
1491
0
  av1_setup_src_planes(x, cpi->source, 0, 0, num_planes,
1492
0
                       cm->seq_params->sb_size);
1493
1494
0
  av1_setup_block_planes(xd, cm->seq_params->subsampling_x,
1495
0
                         cm->seq_params->subsampling_y, num_planes);
1496
0
}
1497
1498
0
void av1_alloc_tile_data(AV1_COMP *cpi) {
1499
0
  AV1_COMMON *const cm = &cpi->common;
1500
0
  const int tile_cols = cm->tiles.cols;
1501
0
  const int tile_rows = cm->tiles.rows;
1502
1503
0
  av1_row_mt_mem_dealloc(cpi);
1504
1505
0
  aom_free(cpi->tile_data);
1506
0
  cpi->allocated_tiles = 0;
1507
1508
0
  CHECK_MEM_ERROR(
1509
0
      cm, cpi->tile_data,
1510
0
      aom_memalign(32, tile_cols * tile_rows * sizeof(*cpi->tile_data)));
1511
1512
0
  cpi->allocated_tiles = tile_cols * tile_rows;
1513
0
  for (int tile_row = 0; tile_row < tile_rows; ++tile_row) {
1514
0
    for (int tile_col = 0; tile_col < tile_cols; ++tile_col) {
1515
0
      const int tile_index = tile_row * tile_cols + tile_col;
1516
0
      TileDataEnc *const this_tile = &cpi->tile_data[tile_index];
1517
0
      av1_zero(this_tile->row_mt_sync);
1518
0
      this_tile->row_ctx = NULL;
1519
0
    }
1520
0
  }
1521
0
}
1522
1523
0
void av1_init_tile_data(AV1_COMP *cpi) {
1524
0
  AV1_COMMON *const cm = &cpi->common;
1525
0
  const int num_planes = av1_num_planes(cm);
1526
0
  const int tile_cols = cm->tiles.cols;
1527
0
  const int tile_rows = cm->tiles.rows;
1528
0
  int tile_col, tile_row;
1529
0
  TokenInfo *const token_info = &cpi->token_info;
1530
0
  TokenExtra *pre_tok = token_info->tile_tok[0][0];
1531
0
  TokenList *tplist = token_info->tplist[0][0];
1532
0
  unsigned int tile_tok = 0;
1533
0
  int tplist_count = 0;
1534
1535
0
  if (!is_stat_generation_stage(cpi) &&
1536
0
      cm->features.allow_screen_content_tools) {
1537
    // Number of tokens for which token info needs to be allocated.
1538
0
    unsigned int tokens_required =
1539
0
        get_token_alloc(cm->mi_params.mb_rows, cm->mi_params.mb_cols,
1540
0
                        MAX_SB_SIZE_LOG2, num_planes);
1541
    // Allocate/reallocate memory for token related info if the number of tokens
1542
    // required is more than the number of tokens already allocated. This could
1543
    // occur in case of the following:
1544
    // 1) If the memory is not yet allocated
1545
    // 2) If the frame dimensions have changed
1546
0
    const bool realloc_tokens = tokens_required > token_info->tokens_allocated;
1547
0
    if (realloc_tokens) {
1548
0
      free_token_info(token_info);
1549
0
      alloc_token_info(cm, token_info, tokens_required);
1550
0
      pre_tok = token_info->tile_tok[0][0];
1551
0
      tplist = token_info->tplist[0][0];
1552
0
    }
1553
0
  }
1554
1555
0
  for (tile_row = 0; tile_row < tile_rows; ++tile_row) {
1556
0
    for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
1557
0
      TileDataEnc *const tile_data =
1558
0
          &cpi->tile_data[tile_row * tile_cols + tile_col];
1559
0
      TileInfo *const tile_info = &tile_data->tile_info;
1560
0
      av1_tile_init(tile_info, cm, tile_row, tile_col);
1561
0
      tile_data->firstpass_top_mv = kZeroMv;
1562
0
      tile_data->abs_sum_level = 0;
1563
1564
0
      if (is_token_info_allocated(token_info)) {
1565
0
        token_info->tile_tok[tile_row][tile_col] = pre_tok + tile_tok;
1566
0
        pre_tok = token_info->tile_tok[tile_row][tile_col];
1567
0
        tile_tok = allocated_tokens(
1568
0
            tile_info, cm->seq_params->mib_size_log2 + MI_SIZE_LOG2,
1569
0
            num_planes);
1570
0
        token_info->tplist[tile_row][tile_col] = tplist + tplist_count;
1571
0
        tplist = token_info->tplist[tile_row][tile_col];
1572
0
        tplist_count = av1_get_sb_rows_in_tile(cm, tile_info);
1573
0
      }
1574
0
      tile_data->allow_update_cdf = !cm->tiles.large_scale;
1575
0
      tile_data->allow_update_cdf = tile_data->allow_update_cdf &&
1576
0
                                    !cm->features.disable_cdf_update &&
1577
0
                                    !delay_wait_for_top_right_sb(cpi);
1578
0
      tile_data->tctx = *cm->fc;
1579
0
    }
1580
0
  }
1581
0
}
1582
1583
// Populate the start palette token info prior to encoding an SB row.
1584
static inline void get_token_start(AV1_COMP *cpi, const TileInfo *tile_info,
1585
                                   int tile_row, int tile_col, int mi_row,
1586
0
                                   TokenExtra **tp) {
1587
0
  const TokenInfo *token_info = &cpi->token_info;
1588
0
  if (!is_token_info_allocated(token_info)) return;
1589
1590
0
  const AV1_COMMON *cm = &cpi->common;
1591
0
  const int num_planes = av1_num_planes(cm);
1592
0
  TokenList *const tplist = cpi->token_info.tplist[tile_row][tile_col];
1593
0
  const int sb_row_in_tile =
1594
0
      (mi_row - tile_info->mi_row_start) >> cm->seq_params->mib_size_log2;
1595
1596
0
  get_start_tok(cpi, tile_row, tile_col, mi_row, tp,
1597
0
                cm->seq_params->mib_size_log2 + MI_SIZE_LOG2, num_planes);
1598
0
  assert(tplist != NULL);
1599
0
  tplist[sb_row_in_tile].start = *tp;
1600
0
}
1601
1602
// Populate the token count after encoding an SB row.
1603
static inline void populate_token_count(AV1_COMP *cpi,
1604
                                        const TileInfo *tile_info, int tile_row,
1605
                                        int tile_col, int mi_row,
1606
0
                                        TokenExtra *tok) {
1607
0
  const TokenInfo *token_info = &cpi->token_info;
1608
0
  if (!is_token_info_allocated(token_info)) return;
1609
1610
0
  const AV1_COMMON *cm = &cpi->common;
1611
0
  const int num_planes = av1_num_planes(cm);
1612
0
  TokenList *const tplist = token_info->tplist[tile_row][tile_col];
1613
0
  const int sb_row_in_tile =
1614
0
      (mi_row - tile_info->mi_row_start) >> cm->seq_params->mib_size_log2;
1615
0
  const int tile_mb_cols =
1616
0
      (tile_info->mi_col_end - tile_info->mi_col_start + 2) >> 2;
1617
0
  const int num_mb_rows_in_sb =
1618
0
      ((1 << (cm->seq_params->mib_size_log2 + MI_SIZE_LOG2)) + 8) >> 4;
1619
0
  tplist[sb_row_in_tile].count =
1620
0
      (unsigned int)(tok - tplist[sb_row_in_tile].start);
1621
1622
0
  assert((unsigned int)(tok - tplist[sb_row_in_tile].start) <=
1623
0
         get_token_alloc(num_mb_rows_in_sb, tile_mb_cols,
1624
0
                         cm->seq_params->mib_size_log2 + MI_SIZE_LOG2,
1625
0
                         num_planes));
1626
1627
0
  (void)num_planes;
1628
0
  (void)tile_mb_cols;
1629
0
  (void)num_mb_rows_in_sb;
1630
0
}
1631
1632
/*!\brief Encode a superblock row
1633
 *
1634
 * \ingroup partition_search
1635
 */
1636
void av1_encode_sb_row(AV1_COMP *cpi, ThreadData *td, int tile_row,
1637
0
                       int tile_col, int mi_row) {
1638
0
  AV1_COMMON *const cm = &cpi->common;
1639
0
  const int tile_cols = cm->tiles.cols;
1640
0
  TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols + tile_col];
1641
0
  const TileInfo *const tile_info = &this_tile->tile_info;
1642
0
  TokenExtra *tok = NULL;
1643
1644
0
  get_token_start(cpi, tile_info, tile_row, tile_col, mi_row, &tok);
1645
1646
0
  encode_sb_row(cpi, td, this_tile, mi_row, &tok);
1647
1648
0
  populate_token_count(cpi, tile_info, tile_row, tile_col, mi_row, tok);
1649
0
}
1650
1651
/*!\brief Encode a tile
1652
 *
1653
 * \ingroup partition_search
1654
 */
1655
void av1_encode_tile(AV1_COMP *cpi, ThreadData *td, int tile_row,
1656
0
                     int tile_col) {
1657
0
  AV1_COMMON *const cm = &cpi->common;
1658
0
  TileDataEnc *const this_tile =
1659
0
      &cpi->tile_data[tile_row * cm->tiles.cols + tile_col];
1660
0
  const TileInfo *const tile_info = &this_tile->tile_info;
1661
1662
0
  if (!cpi->sf.rt_sf.use_nonrd_pick_mode) av1_inter_mode_data_init(this_tile);
1663
1664
0
  av1_zero_above_context(cm, &td->mb.e_mbd, tile_info->mi_col_start,
1665
0
                         tile_info->mi_col_end, tile_row);
1666
0
  av1_init_above_context(&cm->above_contexts, av1_num_planes(cm), tile_row,
1667
0
                         &td->mb.e_mbd);
1668
1669
0
#if !CONFIG_REALTIME_ONLY
1670
0
  if (cpi->oxcf.intra_mode_cfg.enable_cfl_intra)
1671
0
    cfl_init(&td->mb.e_mbd.cfl, cm->seq_params);
1672
0
#endif
1673
1674
0
  if (td->mb.txfm_search_info.mb_rd_record != NULL) {
1675
0
    av1_crc32c_calculator_init(
1676
0
        &td->mb.txfm_search_info.mb_rd_record->crc_calculator);
1677
0
  }
1678
1679
0
  for (int mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
1680
0
       mi_row += cm->seq_params->mib_size) {
1681
0
    av1_encode_sb_row(cpi, td, tile_row, tile_col, mi_row);
1682
0
  }
1683
0
  this_tile->abs_sum_level = td->abs_sum_level;
1684
0
}
1685
1686
/*!\brief Break one frame into tiles and encode the tiles
1687
 *
1688
 * \ingroup partition_search
1689
 *
1690
 * \param[in]    cpi    Top-level encoder structure
1691
 */
1692
0
static inline void encode_tiles(AV1_COMP *cpi) {
1693
0
  AV1_COMMON *const cm = &cpi->common;
1694
0
  const int tile_cols = cm->tiles.cols;
1695
0
  const int tile_rows = cm->tiles.rows;
1696
0
  int tile_col, tile_row;
1697
1698
0
  MACROBLOCK *const mb = &cpi->td.mb;
1699
0
  assert(IMPLIES(cpi->tile_data == NULL, cpi->allocated_tiles == 0));
1700
0
  if (cpi->allocated_tiles != tile_cols * tile_rows) av1_alloc_tile_data(cpi);
1701
1702
0
  av1_init_tile_data(cpi);
1703
0
  av1_alloc_mb_data(cpi, mb);
1704
1705
0
  for (tile_row = 0; tile_row < tile_rows; ++tile_row) {
1706
0
    for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
1707
0
      TileDataEnc *const this_tile =
1708
0
          &cpi->tile_data[tile_row * cm->tiles.cols + tile_col];
1709
0
      cpi->td.intrabc_used = 0;
1710
0
      cpi->td.deltaq_used = 0;
1711
0
      cpi->td.abs_sum_level = 0;
1712
0
      cpi->td.mb.e_mbd.tile_ctx = &this_tile->tctx;
1713
0
      cpi->td.mb.tile_pb_ctx = &this_tile->tctx;
1714
0
      av1_init_rtc_counters(&cpi->td.mb);
1715
0
      cpi->td.mb.palette_pixels = 0;
1716
0
      av1_encode_tile(cpi, &cpi->td, tile_row, tile_col);
1717
0
      if (!frame_is_intra_only(&cpi->common))
1718
0
        av1_accumulate_rtc_counters(cpi, &cpi->td.mb);
1719
0
      cpi->palette_pixel_num += cpi->td.mb.palette_pixels;
1720
0
      cpi->intrabc_used |= cpi->td.intrabc_used;
1721
0
      cpi->deltaq_used |= cpi->td.deltaq_used;
1722
0
    }
1723
0
  }
1724
1725
0
  av1_dealloc_mb_data(mb, av1_num_planes(cm));
1726
0
}
1727
1728
// Set the relative distance of a reference frame w.r.t. current frame
1729
static inline void set_rel_frame_dist(
1730
    const AV1_COMMON *const cm, RefFrameDistanceInfo *const ref_frame_dist_info,
1731
0
    const int ref_frame_flags) {
1732
0
  MV_REFERENCE_FRAME ref_frame;
1733
0
  int min_past_dist = INT32_MAX, min_future_dist = INT32_MAX;
1734
0
  ref_frame_dist_info->nearest_past_ref = NONE_FRAME;
1735
0
  ref_frame_dist_info->nearest_future_ref = NONE_FRAME;
1736
0
  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
1737
0
    ref_frame_dist_info->ref_relative_dist[ref_frame - LAST_FRAME] = 0;
1738
0
    if (ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
1739
0
      int dist = av1_encoder_get_relative_dist(
1740
0
          cm->cur_frame->ref_display_order_hint[ref_frame - LAST_FRAME],
1741
0
          cm->current_frame.display_order_hint);
1742
0
      ref_frame_dist_info->ref_relative_dist[ref_frame - LAST_FRAME] = dist;
1743
      // Get the nearest ref_frame in the past
1744
0
      if (abs(dist) < min_past_dist && dist < 0) {
1745
0
        ref_frame_dist_info->nearest_past_ref = ref_frame;
1746
0
        min_past_dist = abs(dist);
1747
0
      }
1748
      // Get the nearest ref_frame in the future
1749
0
      if (dist < min_future_dist && dist > 0) {
1750
0
        ref_frame_dist_info->nearest_future_ref = ref_frame;
1751
0
        min_future_dist = dist;
1752
0
      }
1753
0
    }
1754
0
  }
1755
0
}
1756
1757
0
static inline int refs_are_one_sided(const AV1_COMMON *cm) {
1758
0
  assert(!frame_is_intra_only(cm));
1759
1760
0
  int one_sided_refs = 1;
1761
0
  const int cur_display_order_hint = cm->current_frame.display_order_hint;
1762
0
  for (int ref = LAST_FRAME; ref <= ALTREF_FRAME; ++ref) {
1763
0
    const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref);
1764
0
    if (buf == NULL) continue;
1765
0
    if (av1_encoder_get_relative_dist(buf->display_order_hint,
1766
0
                                      cur_display_order_hint) > 0) {
1767
0
      one_sided_refs = 0;  // bwd reference
1768
0
      break;
1769
0
    }
1770
0
  }
1771
0
  return one_sided_refs;
1772
0
}
1773
1774
static inline void get_skip_mode_ref_offsets(const AV1_COMMON *cm,
1775
0
                                             int ref_order_hint[2]) {
1776
0
  const SkipModeInfo *const skip_mode_info = &cm->current_frame.skip_mode_info;
1777
0
  ref_order_hint[0] = ref_order_hint[1] = 0;
1778
0
  if (!skip_mode_info->skip_mode_allowed) return;
1779
1780
0
  const RefCntBuffer *const buf_0 =
1781
0
      get_ref_frame_buf(cm, LAST_FRAME + skip_mode_info->ref_frame_idx_0);
1782
0
  const RefCntBuffer *const buf_1 =
1783
0
      get_ref_frame_buf(cm, LAST_FRAME + skip_mode_info->ref_frame_idx_1);
1784
0
  assert(buf_0 != NULL && buf_1 != NULL);
1785
1786
0
  ref_order_hint[0] = buf_0->order_hint;
1787
0
  ref_order_hint[1] = buf_1->order_hint;
1788
0
}
1789
1790
0
static int check_skip_mode_enabled(AV1_COMP *const cpi) {
1791
0
  AV1_COMMON *const cm = &cpi->common;
1792
1793
0
  av1_setup_skip_mode_allowed(cm);
1794
0
  if (!cm->current_frame.skip_mode_info.skip_mode_allowed) return 0;
1795
1796
  // Turn off skip mode if the temporal distances of the reference pair to the
1797
  // current frame are different by more than 1 frame.
1798
0
  const int cur_offset = (int)cm->current_frame.order_hint;
1799
0
  int ref_offset[2];
1800
0
  get_skip_mode_ref_offsets(cm, ref_offset);
1801
0
  const int cur_to_ref0 = get_relative_dist(&cm->seq_params->order_hint_info,
1802
0
                                            cur_offset, ref_offset[0]);
1803
0
  const int cur_to_ref1 = abs(get_relative_dist(
1804
0
      &cm->seq_params->order_hint_info, cur_offset, ref_offset[1]));
1805
0
  if (abs(cur_to_ref0 - cur_to_ref1) > 1) return 0;
1806
1807
  // High Latency: Turn off skip mode if all refs are fwd.
1808
0
  if (cpi->all_one_sided_refs && cpi->oxcf.gf_cfg.lag_in_frames > 0) return 0;
1809
1810
0
  const int ref_frame[2] = {
1811
0
    cm->current_frame.skip_mode_info.ref_frame_idx_0 + LAST_FRAME,
1812
0
    cm->current_frame.skip_mode_info.ref_frame_idx_1 + LAST_FRAME
1813
0
  };
1814
0
  if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame[0]]) ||
1815
0
      !(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame[1]]))
1816
0
    return 0;
1817
1818
0
  return 1;
1819
0
}
1820
1821
static inline void set_default_interp_skip_flags(
1822
0
    const AV1_COMMON *cm, InterpSearchFlags *interp_search_flags) {
1823
0
  const int num_planes = av1_num_planes(cm);
1824
0
  interp_search_flags->default_interp_skip_flags =
1825
0
      (num_planes == 1) ? INTERP_SKIP_LUMA_EVAL_CHROMA
1826
0
                        : INTERP_SKIP_LUMA_SKIP_CHROMA;
1827
0
}
1828
1829
/*!\cond */
1830
typedef struct {
1831
  // Scoring function for usefulness of references (the lower score, the more
1832
  // useful)
1833
  int score;
1834
  // Index in the reference buffer
1835
  int index;
1836
} RefScoreData;
1837
/*!\endcond */
1838
1839
// Comparison function to sort reference frames in ascending score order.
1840
0
static int compare_score_data_asc(const void *a, const void *b) {
1841
0
  const RefScoreData *ra = (const RefScoreData *)a;
1842
0
  const RefScoreData *rb = (const RefScoreData *)b;
1843
1844
0
  const int score_diff = ra->score - rb->score;
1845
0
  if (score_diff != 0) return score_diff;
1846
1847
0
  return ra->index - rb->index;
1848
0
}
1849
1850
// Determines whether a given reference frame is "good" based on temporal
1851
// distance and base_qindex. The "good" reference frames are not allowed to be
1852
// pruned by the speed feature "prune_single_ref" and "prune_comp_ref_frames"
1853
// at block level.
1854
0
static inline void setup_keep_ref_frame_mask(AV1_COMP *cpi) {
1855
0
  const int prune_single_ref = cpi->sf.inter_sf.prune_single_ref;
1856
0
  const int prune_comp_ref_frames = cpi->sf.inter_sf.prune_comp_ref_frames;
1857
0
  const AV1_COMMON *const cm = &cpi->common;
1858
0
  cpi->keep_single_ref_frame_mask = 0;
1859
0
  cpi->keep_comp_ref_frame_mask = 0;
1860
0
  if (frame_is_intra_only(cm)) return;
1861
1862
0
  RefScoreData ref_score_data[INTER_REFS_PER_FRAME];
1863
0
  for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
1864
0
    ref_score_data[i].score = INT_MAX;
1865
0
    ref_score_data[i].index = i;
1866
0
  }
1867
1868
  // Calculate score for each reference frame based on relative distance to
1869
  // the current frame and its base_qindex. A lower score means that the
1870
  // reference is potentially more useful.
1871
0
  for (MV_REFERENCE_FRAME ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME;
1872
0
       ++ref_frame) {
1873
0
    if (cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
1874
0
      const RefFrameDistanceInfo *const ref_frame_dist_info =
1875
0
          &cpi->ref_frame_dist_info;
1876
0
      const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame);
1877
0
      ref_score_data[ref_frame - LAST_FRAME].score =
1878
0
          abs(ref_frame_dist_info->ref_relative_dist[ref_frame - LAST_FRAME]) +
1879
0
          buf->base_qindex;
1880
0
    }
1881
0
  }
1882
1883
0
  qsort(ref_score_data, INTER_REFS_PER_FRAME, sizeof(ref_score_data[0]),
1884
0
        compare_score_data_asc);
1885
1886
  // Decide the number of reference frames for which pruning via the speed
1887
  // feature prune_single_ref is disallowed.
1888
  // prune_single_ref = 0 => None of the 7 reference frames are pruned.
1889
  // prune_single_ref = 1 => The best 5 reference frames are not pruned.
1890
  // prune_single_ref = 2 => The best 3 reference frames are not pruned.
1891
  // prune_single_ref = 3, 4 => All the 7 references are allowed to be pruned.
1892
0
  static const int num_single_ref_to_keep_lookup[5] = { INTER_REFS_PER_FRAME, 5,
1893
0
                                                        3, 0, 0 };
1894
0
  assert(prune_single_ref >= 0 && prune_single_ref <= 4);
1895
0
  const int num_single_ref_to_keep =
1896
0
      num_single_ref_to_keep_lookup[prune_single_ref];
1897
0
  for (int i = 0; i < num_single_ref_to_keep; ++i) {
1898
0
    const int idx = ref_score_data[i].index;
1899
0
    cpi->keep_single_ref_frame_mask |= 1 << idx;
1900
0
  }
1901
1902
  // Decide the number of reference frame pairs for which pruning via the speed
1903
  // feature "prune_comp_ref_frames" is disallowed.
1904
  // prune_comp_ref_frames = 0    => None of the allowed reference frame pairs
1905
  //                                 are pruned.
1906
  // prune_comp_ref_frames = 1    => The best 3 reference frame pairs are not
1907
  //                                 allowed to be pruned, i.e, reference frame
1908
  //                                 pairs with rank (1, 2), (1, 3), (2, 3) are
1909
  //                                 not  pruned.
1910
  // prune_comp_ref_frames = 2, 3 => All the reference frame pairs are allowed
1911
  //                                 to be pruned.
1912
0
  static const int num_comp_ref_to_keep_lookup[4] = { INTER_REFS_PER_FRAME, 3,
1913
0
                                                      0, 0 };
1914
0
  assert(prune_comp_ref_frames >= 0 && prune_comp_ref_frames <= 3);
1915
0
  const int num_comp_ref_to_keep =
1916
0
      num_comp_ref_to_keep_lookup[prune_comp_ref_frames];
1917
0
  for (int i = 0; i < num_comp_ref_to_keep; ++i) {
1918
0
    const int idx = ref_score_data[i].index;
1919
0
    cpi->keep_comp_ref_frame_mask |= 1 << idx;
1920
0
  }
1921
0
}
1922
1923
0
static inline void setup_prune_ref_frame_mask(AV1_COMP *cpi) {
1924
0
  if ((!cpi->oxcf.ref_frm_cfg.enable_onesided_comp ||
1925
0
       cpi->sf.inter_sf.disable_onesided_comp) &&
1926
0
      cpi->all_one_sided_refs) {
1927
    // Disable all compound references
1928
0
    cpi->prune_ref_frame_mask = (1 << MODE_CTX_REF_FRAMES) - (1 << REF_FRAMES);
1929
0
  } else if (!cpi->sf.rt_sf.use_nonrd_pick_mode &&
1930
0
             cpi->sf.inter_sf.selective_ref_frame >= 1) {
1931
0
    AV1_COMMON *const cm = &cpi->common;
1932
0
    const int cur_frame_display_order_hint =
1933
0
        cm->current_frame.display_order_hint;
1934
0
    unsigned int *ref_display_order_hint =
1935
0
        cm->cur_frame->ref_display_order_hint;
1936
0
    const int arf2_dist = av1_encoder_get_relative_dist(
1937
0
        ref_display_order_hint[ALTREF2_FRAME - LAST_FRAME],
1938
0
        cur_frame_display_order_hint);
1939
0
    const int bwd_dist = av1_encoder_get_relative_dist(
1940
0
        ref_display_order_hint[BWDREF_FRAME - LAST_FRAME],
1941
0
        cur_frame_display_order_hint);
1942
1943
0
    for (int ref_idx = REF_FRAMES; ref_idx < MODE_CTX_REF_FRAMES; ++ref_idx) {
1944
0
      MV_REFERENCE_FRAME rf[2];
1945
0
      av1_set_ref_frame(rf, ref_idx);
1946
0
      if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[0]]) ||
1947
0
          !(cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[1]])) {
1948
0
        continue;
1949
0
      }
1950
1951
0
      if (!cpi->all_one_sided_refs) {
1952
0
        int ref_dist[2];
1953
0
        for (int i = 0; i < 2; ++i) {
1954
0
          ref_dist[i] = av1_encoder_get_relative_dist(
1955
0
              ref_display_order_hint[rf[i] - LAST_FRAME],
1956
0
              cur_frame_display_order_hint);
1957
0
        }
1958
1959
        // One-sided compound is used only when all reference frames are
1960
        // one-sided.
1961
0
        if ((ref_dist[0] > 0) == (ref_dist[1] > 0)) {
1962
0
          cpi->prune_ref_frame_mask |= 1 << ref_idx;
1963
0
        }
1964
0
      }
1965
1966
0
      if (cpi->sf.inter_sf.selective_ref_frame >= 4 &&
1967
0
          (rf[0] == ALTREF2_FRAME || rf[1] == ALTREF2_FRAME) &&
1968
0
          (cpi->ref_frame_flags & av1_ref_frame_flag_list[BWDREF_FRAME])) {
1969
        // Check if both ALTREF2_FRAME and BWDREF_FRAME are future references.
1970
0
        if (arf2_dist > 0 && bwd_dist > 0 && bwd_dist <= arf2_dist) {
1971
          // Drop ALTREF2_FRAME as a reference if BWDREF_FRAME is a closer
1972
          // reference to the current frame than ALTREF2_FRAME
1973
0
          cpi->prune_ref_frame_mask |= 1 << ref_idx;
1974
0
        }
1975
0
      }
1976
0
    }
1977
0
  }
1978
0
}
1979
1980
0
static int allow_deltaq_mode(AV1_COMP *cpi) {
1981
0
#if !CONFIG_REALTIME_ONLY
1982
0
  AV1_COMMON *const cm = &cpi->common;
1983
0
  BLOCK_SIZE sb_size = cm->seq_params->sb_size;
1984
0
  int sbs_wide = mi_size_wide[sb_size];
1985
0
  int sbs_high = mi_size_high[sb_size];
1986
1987
0
  int64_t delta_rdcost = 0;
1988
0
  for (int mi_row = 0; mi_row < cm->mi_params.mi_rows; mi_row += sbs_high) {
1989
0
    for (int mi_col = 0; mi_col < cm->mi_params.mi_cols; mi_col += sbs_wide) {
1990
0
      int64_t this_delta_rdcost = 0;
1991
0
      av1_get_q_for_deltaq_objective(cpi, &cpi->td, &this_delta_rdcost, sb_size,
1992
0
                                     mi_row, mi_col);
1993
0
      delta_rdcost += this_delta_rdcost;
1994
0
    }
1995
0
  }
1996
0
  return delta_rdcost < 0;
1997
#else
1998
  (void)cpi;
1999
  return 1;
2000
#endif  // !CONFIG_REALTIME_ONLY
2001
0
}
2002
2003
0
static inline int disable_deltaq_for_intl_arfs(const AV1_COMP *cpi) {
2004
0
  if (cpi->oxcf.mode == GOOD && is_stat_consumption_stage_twopass(cpi) &&
2005
0
      cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_OBJECTIVE &&
2006
0
      cpi->oxcf.algo_cfg.enable_tpl_model && cpi->oxcf.q_cfg.aq_mode == NO_AQ &&
2007
0
      !cpi->common.seg.enabled && !cpi->roi.enabled && !cpi->oxcf.sb_qp_sweep &&
2008
0
      !cpi->use_ducky_encode) {
2009
0
    return 1;
2010
0
  }
2011
0
  return 0;
2012
0
}
2013
2014
0
static inline int enable_delta_rdmult(const AV1_COMP *cpi) {
2015
0
  if (!disable_deltaq_for_intl_arfs(cpi))
2016
0
    return cpi->common.delta_q_info.delta_q_present_flag;
2017
2018
0
  const GF_GROUP *gf_group = &cpi->ppi->gf_group;
2019
0
  return gf_group->update_type[cpi->gf_frame_index] != LF_UPDATE;
2020
0
}
2021
2022
0
static inline int enable_delta_q(const AV1_COMP *cpi) {
2023
0
  const GF_GROUP *gf_group = &cpi->ppi->gf_group;
2024
0
  if (!disable_deltaq_for_intl_arfs(cpi))
2025
0
    return gf_group->update_type[cpi->gf_frame_index] != LF_UPDATE;
2026
2027
0
  return cpi->common.current_frame.pyramid_level <= 1;
2028
0
}
2029
2030
0
#define FORCE_ZMV_SKIP_128X128_BLK_DIFF 10000
2031
#define FORCE_ZMV_SKIP_MAX_PER_PIXEL_DIFF 4
2032
2033
// Populates block level thresholds for force zeromv-skip decision
2034
0
static void populate_thresh_to_force_zeromv_skip(AV1_COMP *cpi) {
2035
0
  if (cpi->sf.rt_sf.part_early_exit_zeromv == 0) return;
2036
2037
  // Threshold for forcing zeromv-skip decision is as below:
2038
  // For 128x128 blocks, threshold is 10000 and per pixel threshold is 0.6103.
2039
  // For 64x64 blocks, threshold is 5000 and per pixel threshold is 1.221
2040
  // allowing slightly higher error for smaller blocks.
2041
  // Per Pixel Threshold of 64x64 block        Area of 64x64 block         1  1
2042
  // ------------------------------------=sqrt(---------------------)=sqrt(-)=-
2043
  // Per Pixel Threshold of 128x128 block      Area of 128x128 block       4  2
2044
  // Thus, per pixel thresholds for blocks of size 32x32, 16x16,...  can be
2045
  // chosen as 2.442, 4.884,.... As the per pixel error tends to be higher for
2046
  // small blocks, the same is clipped to 4.
2047
0
  const unsigned int thresh_exit_128x128_part = FORCE_ZMV_SKIP_128X128_BLK_DIFF;
2048
0
  const int num_128x128_pix =
2049
0
      block_size_wide[BLOCK_128X128] * block_size_high[BLOCK_128X128];
2050
2051
0
  for (BLOCK_SIZE bsize = BLOCK_4X4; bsize < BLOCK_SIZES_ALL; bsize++) {
2052
0
    const int num_block_pix = block_size_wide[bsize] * block_size_high[bsize];
2053
2054
    // Calculate the threshold for zeromv-skip decision based on area of the
2055
    // partition
2056
0
    unsigned int thresh_exit_part_blk =
2057
0
        (unsigned int)(thresh_exit_128x128_part *
2058
0
                           sqrt((double)num_block_pix / num_128x128_pix) +
2059
0
                       0.5);
2060
0
    thresh_exit_part_blk = AOMMIN(
2061
0
        thresh_exit_part_blk,
2062
0
        (unsigned int)(FORCE_ZMV_SKIP_MAX_PER_PIXEL_DIFF * num_block_pix));
2063
0
    cpi->zeromv_skip_thresh_exit_part[bsize] = thresh_exit_part_blk;
2064
0
  }
2065
0
}
2066
2067
0
static void free_block_hash_buffers(uint32_t *block_hash_values[2]) {
2068
0
  for (int j = 0; j < 2; ++j) {
2069
0
    aom_free(block_hash_values[j]);
2070
0
  }
2071
0
}
2072
2073
/*!\brief Determines delta_q_res value for Variance Boost modulation.
2074
 */
2075
0
static int aom_get_variance_boost_delta_q_res(int qindex) {
2076
  // Signaling delta_q changes across superblocks comes with inherent syntax
2077
  // element overhead, which adds up to total payload size. This overhead
2078
  // becomes proportionally bigger the higher the base qindex (i.e. lower
2079
  // quality, smaller file size), so a balance needs to be struck.
2080
  // - Smaller delta_q_res: more granular delta_q control, more bits spent
2081
  // signaling deltas.
2082
  // - Larger delta_q_res: coarser delta_q control, less bits spent signaling
2083
  // deltas.
2084
  //
2085
  // At the same time, SB qindex fluctuations become larger the higher
2086
  // the base qindex (between lowest and highest-variance regions):
2087
  // - For QP 5: up to 8 qindexes
2088
  // - For QP 60: up to 52 qindexes
2089
  //
2090
  // With these factors in mind, it was found that the best strategy that
2091
  // maximizes quality per bitrate is by having very finely-grained delta_q
2092
  // values for the lowest picture qindexes (to preserve tiny qindex SB deltas),
2093
  // and progressively making them coarser as base qindex increases (to reduce
2094
  // total signaling overhead).
2095
0
  int delta_q_res = 1;
2096
2097
0
  if (qindex >= 160) {
2098
0
    delta_q_res = 8;
2099
0
  } else if (qindex >= 120) {
2100
0
    delta_q_res = 4;
2101
0
  } else if (qindex >= 80) {
2102
0
    delta_q_res = 2;
2103
0
  } else {
2104
0
    delta_q_res = 1;
2105
0
  }
2106
2107
0
  return delta_q_res;
2108
0
}
2109
2110
#if !CONFIG_REALTIME_ONLY
2111
0
static float get_thresh_based_on_q(int qindex, int speed) {
2112
0
  const float min_threshold_arr[3] = { 0.084f, 0.087f, 0.126f };
2113
0
  const float max_threshold_arr[3] = { 0.140f, 0.150f, 0.182f };
2114
0
  const int idx = (speed >= 3) ? 2 : (speed - 1);
2115
0
  const float min_thresh = min_threshold_arr[idx];
2116
0
  const float max_thresh = max_threshold_arr[idx];
2117
0
  const float thresh = min_thresh + (max_thresh - min_thresh) *
2118
0
                                        ((float)MAXQ - (float)qindex) /
2119
0
                                        (float)(MAXQ - MINQ);
2120
0
  return thresh;
2121
0
}
2122
2123
0
static int get_mv_err(MV cur_mv, MV ref_mv) {
2124
0
  const MV diff = { cur_mv.row - ref_mv.row, cur_mv.col - ref_mv.col };
2125
0
  const MV abs_diff = { abs(diff.row), abs(diff.col) };
2126
0
  const int mv_err = (abs_diff.row + abs_diff.col);
2127
0
  return mv_err;
2128
0
}
2129
2130
0
static void check_mv_err_and_update(MV cur_mv, MV ref_mv, int *best_mv_err) {
2131
0
  const int mv_err = get_mv_err(cur_mv, ref_mv);
2132
0
  *best_mv_err = AOMMIN(mv_err, *best_mv_err);
2133
0
}
2134
2135
static int is_inside_frame_border(int mi_row, int mi_col, int row_offset,
2136
                                  int col_offset, int num_mi_rows,
2137
0
                                  int num_mi_cols) {
2138
0
  if (mi_row + row_offset < 0 || mi_row + row_offset >= num_mi_rows ||
2139
0
      mi_col + col_offset < 0 || mi_col + col_offset >= num_mi_cols)
2140
0
    return 0;
2141
2142
0
  return 1;
2143
0
}
2144
2145
// Compute the minimum MV error between current MV and spatial MV predictors.
2146
static int get_spatial_mvpred_err(AV1_COMMON *cm, TplParams *const tpl_data,
2147
                                  int tpl_idx, int mi_row, int mi_col,
2148
                                  int ref_idx, int_mv cur_mv, int allow_hp,
2149
0
                                  int is_integer) {
2150
0
  const TplDepFrame *tpl_frame = &tpl_data->tpl_frame[tpl_idx];
2151
0
  TplDepStats *tpl_ptr = tpl_frame->tpl_stats_ptr;
2152
0
  const uint8_t block_mis_log2 = tpl_data->tpl_stats_block_mis_log2;
2153
2154
0
  int mv_err = INT32_MAX;
2155
0
  const int step = 1 << block_mis_log2;
2156
0
  const int mv_pred_pos_in_mis[8][2] = {
2157
0
    { -step, 0 },     { 0, -step },     { -step, step },  { -step, -step },
2158
0
    { -2 * step, 0 }, { 0, -2 * step }, { -3 * step, 0 }, { 0, -3 * step },
2159
0
  };
2160
2161
0
  for (int i = 0; i < 8; i++) {
2162
0
    int row_offset = mv_pred_pos_in_mis[i][0];
2163
0
    int col_offset = mv_pred_pos_in_mis[i][1];
2164
0
    if (!is_inside_frame_border(mi_row, mi_col, row_offset, col_offset,
2165
0
                                tpl_frame->mi_rows, tpl_frame->mi_cols)) {
2166
0
      continue;
2167
0
    }
2168
2169
0
    const TplDepStats *tpl_stats =
2170
0
        &tpl_ptr[av1_tpl_ptr_pos(mi_row + row_offset, mi_col + col_offset,
2171
0
                                 tpl_frame->stride, block_mis_log2)];
2172
0
    int_mv this_refmv = tpl_stats->mv[ref_idx];
2173
0
    lower_mv_precision(&this_refmv.as_mv, allow_hp, is_integer);
2174
0
    check_mv_err_and_update(cur_mv.as_mv, this_refmv.as_mv, &mv_err);
2175
0
  }
2176
2177
  // Check MV error w.r.t. Global MV / Zero MV
2178
0
  int_mv gm_mv = { 0 };
2179
0
  if (cm->global_motion[ref_idx + LAST_FRAME].wmtype > TRANSLATION) {
2180
0
    const BLOCK_SIZE bsize = convert_length_to_bsize(tpl_data->tpl_bsize_1d);
2181
0
    gm_mv = gm_get_motion_vector(&cm->global_motion[ref_idx + LAST_FRAME],
2182
0
                                 allow_hp, bsize, mi_col, mi_row, is_integer);
2183
0
  }
2184
0
  check_mv_err_and_update(cur_mv.as_mv, gm_mv.as_mv, &mv_err);
2185
2186
0
  return mv_err;
2187
0
}
2188
2189
// Compute the minimum MV error between current MV and temporal MV predictors.
2190
static int get_temporal_mvpred_err(AV1_COMMON *cm, int mi_row, int mi_col,
2191
                                   int num_mi_rows, int num_mi_cols,
2192
                                   int ref_idx, int_mv cur_mv, int allow_hp,
2193
0
                                   int is_integer) {
2194
0
  const RefCntBuffer *ref_buf = get_ref_frame_buf(cm, ref_idx + LAST_FRAME);
2195
0
  if (ref_buf == NULL) return INT32_MAX;
2196
0
  int cur_to_ref_dist =
2197
0
      get_relative_dist(&cm->seq_params->order_hint_info,
2198
0
                        cm->cur_frame->order_hint, ref_buf->order_hint);
2199
2200
0
  int mv_err = INT32_MAX;
2201
0
  const int mv_pred_pos_in_mis[7][2] = {
2202
0
    { 0, 0 }, { 0, 2 }, { 2, 0 }, { 2, 2 }, { 4, -2 }, { 4, 4 }, { 2, 4 },
2203
0
  };
2204
2205
0
  for (int i = 0; i < 7; i++) {
2206
0
    int row_offset = mv_pred_pos_in_mis[i][0];
2207
0
    int col_offset = mv_pred_pos_in_mis[i][1];
2208
0
    if (!is_inside_frame_border(mi_row, mi_col, row_offset, col_offset,
2209
0
                                num_mi_rows, num_mi_cols)) {
2210
0
      continue;
2211
0
    }
2212
0
    const TPL_MV_REF *ref_mvs =
2213
0
        cm->tpl_mvs +
2214
0
        ((mi_row + row_offset) >> 1) * (cm->mi_params.mi_stride >> 1) +
2215
0
        ((mi_col + col_offset) >> 1);
2216
0
    if (ref_mvs->mfmv0.as_int == INVALID_MV) continue;
2217
2218
0
    int_mv this_refmv;
2219
0
    av1_get_mv_projection(&this_refmv.as_mv, ref_mvs->mfmv0.as_mv,
2220
0
                          cur_to_ref_dist, ref_mvs->ref_frame_offset);
2221
0
    lower_mv_precision(&this_refmv.as_mv, allow_hp, is_integer);
2222
0
    check_mv_err_and_update(cur_mv.as_mv, this_refmv.as_mv, &mv_err);
2223
0
  }
2224
2225
0
  return mv_err;
2226
0
}
2227
2228
// Determine whether to disable temporal MV prediction for the current frame
2229
// based on TPL and motion field data. Temporal MV prediction is disabled if the
2230
// reduction in MV error by including temporal MVs as MV predictors is small.
2231
0
static void check_to_disable_ref_frame_mvs(AV1_COMP *cpi) {
2232
0
  AV1_COMMON *cm = &cpi->common;
2233
0
  if (!cm->features.allow_ref_frame_mvs || cpi->sf.hl_sf.ref_frame_mvs_lvl != 1)
2234
0
    return;
2235
2236
0
  const int tpl_idx = cpi->gf_frame_index;
2237
0
  TplParams *const tpl_data = &cpi->ppi->tpl_data;
2238
0
  if (!av1_tpl_stats_ready(tpl_data, tpl_idx)) return;
2239
2240
0
  const SUBPEL_FORCE_STOP tpl_subpel_precision =
2241
0
      cpi->sf.tpl_sf.subpel_force_stop;
2242
0
  const int allow_high_precision_mv = tpl_subpel_precision == EIGHTH_PEL &&
2243
0
                                      cm->features.allow_high_precision_mv;
2244
0
  const int force_integer_mv = tpl_subpel_precision == FULL_PEL ||
2245
0
                               cm->features.cur_frame_force_integer_mv;
2246
2247
0
  const TplDepFrame *tpl_frame = &tpl_data->tpl_frame[tpl_idx];
2248
0
  TplDepStats *tpl_ptr = tpl_frame->tpl_stats_ptr;
2249
0
  const uint8_t block_mis_log2 = tpl_data->tpl_stats_block_mis_log2;
2250
0
  const int step = 1 << block_mis_log2;
2251
2252
0
  uint64_t accum_spatial_mvpred_err = 0;
2253
0
  uint64_t accum_best_err = 0;
2254
2255
0
  for (int mi_row = 0; mi_row < tpl_frame->mi_rows; mi_row += step) {
2256
0
    for (int mi_col = 0; mi_col < tpl_frame->mi_cols; mi_col += step) {
2257
0
      TplDepStats *tpl_stats_ptr = &tpl_ptr[av1_tpl_ptr_pos(
2258
0
          mi_row, mi_col, tpl_frame->stride, block_mis_log2)];
2259
0
      const int cur_best_ref_idx = tpl_stats_ptr->ref_frame_index[0];
2260
0
      if (cur_best_ref_idx == NONE_FRAME) continue;
2261
2262
0
      int_mv cur_mv = tpl_stats_ptr->mv[cur_best_ref_idx];
2263
0
      lower_mv_precision(&cur_mv.as_mv, allow_high_precision_mv,
2264
0
                         force_integer_mv);
2265
2266
0
      const int cur_spatial_mvpred_err = get_spatial_mvpred_err(
2267
0
          cm, tpl_data, tpl_idx, mi_row, mi_col, cur_best_ref_idx, cur_mv,
2268
0
          allow_high_precision_mv, force_integer_mv);
2269
2270
0
      const int cur_temporal_mvpred_err = get_temporal_mvpred_err(
2271
0
          cm, mi_row, mi_col, tpl_frame->mi_rows, tpl_frame->mi_cols,
2272
0
          cur_best_ref_idx, cur_mv, allow_high_precision_mv, force_integer_mv);
2273
2274
0
      const int cur_best_err =
2275
0
          AOMMIN(cur_spatial_mvpred_err, cur_temporal_mvpred_err);
2276
0
      accum_spatial_mvpred_err += cur_spatial_mvpred_err;
2277
0
      accum_best_err += cur_best_err;
2278
0
    }
2279
0
  }
2280
2281
0
  const float threshold =
2282
0
      get_thresh_based_on_q(cm->quant_params.base_qindex, cpi->oxcf.speed);
2283
0
  const float mv_err_reduction =
2284
0
      (float)(accum_spatial_mvpred_err - accum_best_err);
2285
2286
0
  if (mv_err_reduction <= threshold * accum_spatial_mvpred_err)
2287
0
    cm->features.allow_ref_frame_mvs = 0;
2288
0
}
2289
#endif  // !CONFIG_REALTIME_ONLY
2290
2291
/*!\brief Encoder setup(only for the current frame), encoding, and recontruction
2292
 * for a single frame
2293
 *
2294
 * \ingroup high_level_algo
2295
 */
2296
0
static inline void encode_frame_internal(AV1_COMP *cpi) {
2297
0
  ThreadData *const td = &cpi->td;
2298
0
  MACROBLOCK *const x = &td->mb;
2299
0
  AV1_COMMON *const cm = &cpi->common;
2300
0
  CommonModeInfoParams *const mi_params = &cm->mi_params;
2301
0
  FeatureFlags *const features = &cm->features;
2302
0
  MACROBLOCKD *const xd = &x->e_mbd;
2303
0
  RD_COUNTS *const rdc = &cpi->td.rd_counts;
2304
#if CONFIG_FPMT_TEST
2305
  FrameProbInfo *const temp_frame_probs = &cpi->ppi->temp_frame_probs;
2306
  FrameProbInfo *const temp_frame_probs_simulation =
2307
      &cpi->ppi->temp_frame_probs_simulation;
2308
#endif
2309
0
  FrameProbInfo *const frame_probs = &cpi->ppi->frame_probs;
2310
0
  IntraBCHashInfo *const intrabc_hash_info = &x->intrabc_hash_info;
2311
0
  MultiThreadInfo *const mt_info = &cpi->mt_info;
2312
0
  AV1EncRowMultiThreadInfo *const enc_row_mt = &mt_info->enc_row_mt;
2313
0
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
2314
0
  const DELTAQ_MODE deltaq_mode = oxcf->q_cfg.deltaq_mode;
2315
0
  int i;
2316
2317
0
  if (!cpi->sf.rt_sf.use_nonrd_pick_mode) {
2318
0
    mi_params->setup_mi(mi_params);
2319
0
  }
2320
2321
0
  set_mi_offsets(mi_params, xd, 0, 0);
2322
2323
0
  av1_zero(*td->counts);
2324
0
  av1_zero(rdc->tx_type_used);
2325
0
  av1_zero(rdc->obmc_used);
2326
0
  av1_zero(rdc->warped_used);
2327
0
  av1_zero(rdc->seg_tmp_pred_cost);
2328
2329
  // Reset the flag.
2330
0
  cpi->intrabc_used = 0;
2331
  // Need to disable intrabc when superres is selected
2332
0
  if (av1_superres_scaled(cm)) {
2333
0
    features->allow_intrabc = 0;
2334
0
  }
2335
2336
0
  features->allow_intrabc &= (oxcf->kf_cfg.enable_intrabc);
2337
2338
0
  if (features->allow_warped_motion &&
2339
0
      cpi->sf.inter_sf.prune_warped_prob_thresh > 0) {
2340
0
    const FRAME_UPDATE_TYPE update_type =
2341
0
        get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
2342
0
    int warped_probability =
2343
#if CONFIG_FPMT_TEST
2344
        cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE
2345
            ? temp_frame_probs->warped_probs[update_type]
2346
            :
2347
#endif  // CONFIG_FPMT_TEST
2348
0
            frame_probs->warped_probs[update_type];
2349
0
    if (warped_probability < cpi->sf.inter_sf.prune_warped_prob_thresh)
2350
0
      features->allow_warped_motion = 0;
2351
0
  }
2352
2353
0
  if (!is_stat_generation_stage(cpi) && av1_use_hash_me(cpi) &&
2354
0
      (!cpi->sf.rt_sf.use_nonrd_pick_mode || cpi->sf.rt_sf.rt_use_intrabc)) {
2355
    // TODO(any): move this outside of the recoding loop to avoid recalculating
2356
    // the hash table.
2357
    // add to hash table
2358
0
    const int pic_width = cpi->source->y_crop_width;
2359
0
    const int pic_height = cpi->source->y_crop_height;
2360
0
    uint32_t *block_hash_values[2] = { NULL };  // two buffers used ping-pong
2361
0
    bool error = false;
2362
2363
0
    for (int j = 0; j < 2; ++j) {
2364
0
      block_hash_values[j] = (uint32_t *)aom_malloc(
2365
0
          sizeof(*block_hash_values[j]) * pic_width * pic_height);
2366
0
      if (!block_hash_values[j]) {
2367
0
        error = true;
2368
0
        break;
2369
0
      }
2370
0
    }
2371
2372
0
    av1_hash_table_init(intrabc_hash_info);
2373
0
    if (error ||
2374
0
        !av1_hash_table_create(&intrabc_hash_info->intrabc_hash_table)) {
2375
0
      free_block_hash_buffers(block_hash_values);
2376
0
      aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR,
2377
0
                         "Error allocating intrabc_hash_table and buffers");
2378
0
    }
2379
0
    av1_generate_block_2x2_hash_value(cpi->source, block_hash_values[0]);
2380
    // Hash data generated for screen contents is used for intraBC ME
2381
0
    const int min_alloc_size = block_size_wide[mi_params->mi_alloc_bsize];
2382
0
    int max_sb_size = (1 << (cm->seq_params->mib_size_log2 + MI_SIZE_LOG2));
2383
2384
0
    if (cpi->sf.mv_sf.hash_max_8x8_intrabc_blocks) {
2385
0
      max_sb_size = AOMMIN(8, max_sb_size);
2386
0
    }
2387
2388
0
    int src_idx = 0;
2389
0
    for (int size = 4; size <= max_sb_size; size *= 2, src_idx = !src_idx) {
2390
0
      const int dst_idx = !src_idx;
2391
0
      av1_generate_block_hash_value(intrabc_hash_info, cpi->source, size,
2392
0
                                    block_hash_values[src_idx],
2393
0
                                    block_hash_values[dst_idx]);
2394
0
      if (size >= min_alloc_size &&
2395
0
          !av1_add_to_hash_map_by_row_with_precal_data(
2396
0
              &intrabc_hash_info->intrabc_hash_table,
2397
0
              block_hash_values[dst_idx], pic_width, pic_height, size)) {
2398
0
        error = true;
2399
0
        break;
2400
0
      }
2401
0
    }
2402
2403
0
    free_block_hash_buffers(block_hash_values);
2404
2405
0
    if (error) {
2406
0
      aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR,
2407
0
                         "Error adding data to intrabc_hash_table");
2408
0
    }
2409
0
  }
2410
2411
0
  const CommonQuantParams *quant_params = &cm->quant_params;
2412
0
  for (i = 0; i < MAX_SEGMENTS; ++i) {
2413
0
    const int qindex =
2414
0
        cm->seg.enabled ? av1_get_qindex(&cm->seg, i, quant_params->base_qindex)
2415
0
                        : quant_params->base_qindex;
2416
0
    xd->lossless[i] =
2417
0
        qindex == 0 && quant_params->y_dc_delta_q == 0 &&
2418
0
        quant_params->u_dc_delta_q == 0 && quant_params->u_ac_delta_q == 0 &&
2419
0
        quant_params->v_dc_delta_q == 0 && quant_params->v_ac_delta_q == 0;
2420
0
    if (xd->lossless[i]) cpi->enc_seg.has_lossless_segment = 1;
2421
0
    xd->qindex[i] = qindex;
2422
0
    if (xd->lossless[i]) {
2423
0
      cpi->optimize_seg_arr[i] = NO_TRELLIS_OPT;
2424
0
    } else {
2425
0
      cpi->optimize_seg_arr[i] = cpi->sf.rd_sf.optimize_coefficients;
2426
0
    }
2427
0
  }
2428
0
  features->coded_lossless = is_coded_lossless(cm, xd);
2429
0
  features->all_lossless = features->coded_lossless && !av1_superres_scaled(cm);
2430
2431
  // Fix delta q resolution for the moment
2432
2433
0
  cm->delta_q_info.delta_q_res = 0;
2434
0
  if (cpi->use_ducky_encode) {
2435
0
    cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_DUCKY_ENCODE;
2436
0
  } else if (cpi->oxcf.q_cfg.aq_mode != CYCLIC_REFRESH_AQ &&
2437
0
             !cpi->roi.enabled) {
2438
0
    if (deltaq_mode == DELTA_Q_OBJECTIVE)
2439
0
      cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_OBJECTIVE;
2440
0
    else if (deltaq_mode == DELTA_Q_PERCEPTUAL)
2441
0
      cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_PERCEPTUAL;
2442
0
    else if (deltaq_mode == DELTA_Q_PERCEPTUAL_AI)
2443
0
      cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_PERCEPTUAL;
2444
0
    else if (deltaq_mode == DELTA_Q_USER_RATING_BASED)
2445
0
      cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_PERCEPTUAL;
2446
0
    else if (deltaq_mode == DELTA_Q_HDR)
2447
0
      cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_PERCEPTUAL;
2448
0
    else if (deltaq_mode == DELTA_Q_VARIANCE_BOOST)
2449
0
      cm->delta_q_info.delta_q_res =
2450
0
          aom_get_variance_boost_delta_q_res(quant_params->base_qindex);
2451
    // Set delta_q_present_flag before it is used for the first time
2452
0
    cm->delta_q_info.delta_lf_res = DEFAULT_DELTA_LF_RES;
2453
0
    cm->delta_q_info.delta_q_present_flag = deltaq_mode != NO_DELTA_Q;
2454
2455
    // Turn off cm->delta_q_info.delta_q_present_flag if objective delta_q
2456
    // is used for ineligible frames. That effectively will turn off row_mt
2457
    // usage. Note objective delta_q and tpl eligible frames are only altref
2458
    // frames currently.
2459
0
    if (cm->delta_q_info.delta_q_present_flag) {
2460
0
      if (deltaq_mode == DELTA_Q_OBJECTIVE && !enable_delta_q(cpi))
2461
0
        cm->delta_q_info.delta_q_present_flag = 0;
2462
2463
0
      if (deltaq_mode == DELTA_Q_OBJECTIVE &&
2464
0
          cm->delta_q_info.delta_q_present_flag) {
2465
0
        cm->delta_q_info.delta_q_present_flag &= allow_deltaq_mode(cpi);
2466
0
      }
2467
0
    }
2468
2469
    // Reset delta_q_used flag
2470
0
    cpi->deltaq_used = 0;
2471
2472
0
    cm->delta_q_info.delta_lf_present_flag =
2473
0
        cm->delta_q_info.delta_q_present_flag &&
2474
0
        oxcf->tool_cfg.enable_deltalf_mode;
2475
0
    cm->delta_q_info.delta_lf_multi = DEFAULT_DELTA_LF_MULTI;
2476
2477
    // update delta_q_present_flag and delta_lf_present_flag based on
2478
    // base_qindex
2479
0
    cm->delta_q_info.delta_q_present_flag &= quant_params->base_qindex > 0;
2480
0
    cm->delta_q_info.delta_lf_present_flag &= quant_params->base_qindex > 0;
2481
0
  } else if (cpi->cyclic_refresh->apply_cyclic_refresh ||
2482
0
             cpi->svc.number_temporal_layers == 1) {
2483
0
    cpi->cyclic_refresh->actual_num_seg1_blocks = 0;
2484
0
    cpi->cyclic_refresh->actual_num_seg2_blocks = 0;
2485
0
  }
2486
0
  cpi->rc.cnt_zeromv = 0;
2487
0
  cpi->cb_delta_rdmult_enabled = enable_delta_rdmult(cpi);
2488
2489
0
  av1_frame_init_quantizer(cpi);
2490
0
  init_encode_frame_mb_context(cpi);
2491
0
  set_default_interp_skip_flags(cm, &cpi->interp_search_flags);
2492
2493
  // Like the decoder, only use the previous segment map if it has the size of
2494
  // this frame.
2495
0
  if (cm->prev_frame && cm->prev_frame->seg.enabled &&
2496
0
      cpi->svc.number_spatial_layers == 1 &&
2497
0
      cm->prev_frame->mi_rows == cm->mi_params.mi_rows &&
2498
0
      cm->prev_frame->mi_cols == cm->mi_params.mi_cols)
2499
0
    cm->last_frame_seg_map = cm->prev_frame->seg_map;
2500
0
  else
2501
0
    cm->last_frame_seg_map = NULL;
2502
0
  if (features->allow_intrabc || features->coded_lossless) {
2503
0
    av1_set_default_ref_deltas(cm->lf.ref_deltas);
2504
0
    av1_set_default_mode_deltas(cm->lf.mode_deltas);
2505
0
  } else if (cm->prev_frame) {
2506
0
    memcpy(cm->lf.ref_deltas, cm->prev_frame->ref_deltas, REF_FRAMES);
2507
0
    memcpy(cm->lf.mode_deltas, cm->prev_frame->mode_deltas, MAX_MODE_LF_DELTAS);
2508
0
  }
2509
0
  cm->lf.mode_ref_delta_enabled = oxcf->algo_cfg.mode_ref_delta_enabled;
2510
0
  memcpy(cm->cur_frame->ref_deltas, cm->lf.ref_deltas, REF_FRAMES);
2511
0
  memcpy(cm->cur_frame->mode_deltas, cm->lf.mode_deltas, MAX_MODE_LF_DELTAS);
2512
2513
0
  cpi->all_one_sided_refs =
2514
0
      frame_is_intra_only(cm) ? 0 : refs_are_one_sided(cm);
2515
2516
0
  cpi->prune_ref_frame_mask = 0;
2517
  // Figure out which ref frames can be skipped at frame level.
2518
0
  setup_prune_ref_frame_mask(cpi);
2519
  // Disable certain reference frame pruning based on temporal distance and
2520
  // quality of that reference frame.
2521
0
  setup_keep_ref_frame_mask(cpi);
2522
2523
0
  x->txfm_search_info.txb_split_count = 0;
2524
#if CONFIG_SPEED_STATS
2525
  x->txfm_search_info.tx_search_count = 0;
2526
#endif  // CONFIG_SPEED_STATS
2527
2528
0
#if !CONFIG_REALTIME_ONLY
2529
#if CONFIG_COLLECT_COMPONENT_TIMING
2530
  start_timing(cpi, av1_compute_global_motion_time);
2531
#endif
2532
0
  av1_compute_global_motion_facade(cpi);
2533
#if CONFIG_COLLECT_COMPONENT_TIMING
2534
  end_timing(cpi, av1_compute_global_motion_time);
2535
#endif
2536
0
#endif  // !CONFIG_REALTIME_ONLY
2537
2538
#if CONFIG_COLLECT_COMPONENT_TIMING
2539
  start_timing(cpi, av1_setup_motion_field_time);
2540
#endif
2541
0
  av1_calculate_ref_frame_side(cm);
2542
2543
0
  features->allow_ref_frame_mvs &= !(cpi->sf.hl_sf.ref_frame_mvs_lvl == 2);
2544
0
  if (features->allow_ref_frame_mvs) av1_setup_motion_field(cm);
2545
0
#if !CONFIG_REALTIME_ONLY
2546
0
  check_to_disable_ref_frame_mvs(cpi);
2547
0
#endif  // !CONFIG_REALTIME_ONLY
2548
2549
#if CONFIG_COLLECT_COMPONENT_TIMING
2550
  end_timing(cpi, av1_setup_motion_field_time);
2551
#endif
2552
2553
0
  cm->current_frame.skip_mode_info.skip_mode_flag =
2554
0
      check_skip_mode_enabled(cpi);
2555
2556
  // Initialization of skip mode cost depends on the value of
2557
  // 'skip_mode_flag'. This initialization happens in the function
2558
  // av1_fill_mode_rates(), which is in turn called in
2559
  // av1_initialize_rd_consts(). Thus, av1_initialize_rd_consts()
2560
  // has to be called after 'skip_mode_flag' is initialized.
2561
0
  av1_initialize_rd_consts(cpi);
2562
0
  av1_set_sad_per_bit(cpi, &x->sadperbit, quant_params->base_qindex);
2563
0
  populate_thresh_to_force_zeromv_skip(cpi);
2564
2565
0
  enc_row_mt->sync_read_ptr = av1_row_mt_sync_read_dummy;
2566
0
  enc_row_mt->sync_write_ptr = av1_row_mt_sync_write_dummy;
2567
0
  mt_info->row_mt_enabled = 0;
2568
0
  mt_info->pack_bs_mt_enabled = AOMMIN(mt_info->num_mod_workers[MOD_PACK_BS],
2569
0
                                       cm->tiles.cols * cm->tiles.rows) > 1;
2570
2571
0
  if (oxcf->row_mt && (mt_info->num_mod_workers[MOD_ENC] > 1)) {
2572
0
    mt_info->row_mt_enabled = 1;
2573
0
    enc_row_mt->sync_read_ptr = av1_row_mt_sync_read;
2574
0
    enc_row_mt->sync_write_ptr = av1_row_mt_sync_write;
2575
0
    av1_encode_tiles_row_mt(cpi);
2576
0
  } else {
2577
0
    const int num_workers = AOMMIN(mt_info->num_mod_workers[MOD_ENC],
2578
0
                                   cm->tiles.cols * cm->tiles.rows);
2579
0
    if (num_workers > 1) {
2580
0
      av1_encode_tiles_mt(cpi);
2581
0
    } else {
2582
      // Preallocate the pc_tree for realtime coding to reduce the cost of
2583
      // memory allocation.
2584
0
      const int use_nonrd_mode = cpi->sf.rt_sf.use_nonrd_pick_mode;
2585
0
      if (use_nonrd_mode) {
2586
0
        td->pc_root = av1_alloc_pc_tree_node(cm->seq_params->sb_size);
2587
0
        if (!td->pc_root)
2588
0
          aom_internal_error(xd->error_info, AOM_CODEC_MEM_ERROR,
2589
0
                             "Failed to allocate PC_TREE");
2590
0
      } else {
2591
0
        td->pc_root = NULL;
2592
0
      }
2593
2594
0
      encode_tiles(cpi);
2595
0
      av1_free_pc_tree_recursive(td->pc_root, av1_num_planes(cm), 0, 0,
2596
0
                                 cpi->sf.part_sf.partition_search_type);
2597
0
      td->pc_root = NULL;
2598
0
    }
2599
0
  }
2600
2601
  // If intrabc is allowed but never selected, reset the allow_intrabc flag.
2602
0
  if (features->allow_intrabc && !cpi->intrabc_used) {
2603
0
    features->allow_intrabc = 0;
2604
0
  }
2605
0
  if (features->allow_intrabc) {
2606
0
    cm->delta_q_info.delta_lf_present_flag = 0;
2607
0
  }
2608
2609
0
  if (cm->delta_q_info.delta_q_present_flag && cpi->deltaq_used == 0) {
2610
0
    cm->delta_q_info.delta_q_present_flag = 0;
2611
0
  }
2612
2613
  // Set the transform size appropriately before bitstream creation
2614
0
  const MODE_EVAL_TYPE eval_type =
2615
0
      cpi->sf.winner_mode_sf.enable_winner_mode_for_tx_size_srch
2616
0
          ? WINNER_MODE_EVAL
2617
0
          : DEFAULT_EVAL;
2618
0
  const TX_SIZE_SEARCH_METHOD tx_search_type =
2619
0
      cpi->winner_mode_params.tx_size_search_methods[eval_type];
2620
0
  assert(oxcf->txfm_cfg.enable_tx64 || tx_search_type != USE_LARGESTALL);
2621
0
  features->tx_mode = select_tx_mode(cm, tx_search_type);
2622
2623
  // Retain the frame level probability update conditions for parallel frames.
2624
  // These conditions will be consumed during postencode stage to update the
2625
  // probability.
2626
0
  if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
2627
0
    cpi->do_update_frame_probs_txtype[cpi->num_frame_recode] =
2628
0
        cpi->sf.tx_sf.tx_type_search.prune_tx_type_using_stats;
2629
0
    cpi->do_update_frame_probs_obmc[cpi->num_frame_recode] =
2630
0
        (cpi->sf.inter_sf.prune_obmc_prob_thresh > 0 &&
2631
0
         cpi->sf.inter_sf.prune_obmc_prob_thresh < INT_MAX);
2632
0
    cpi->do_update_frame_probs_warp[cpi->num_frame_recode] =
2633
0
        (features->allow_warped_motion &&
2634
0
         cpi->sf.inter_sf.prune_warped_prob_thresh > 0);
2635
0
    cpi->do_update_frame_probs_interpfilter[cpi->num_frame_recode] =
2636
0
        (cm->current_frame.frame_type != KEY_FRAME &&
2637
0
         cpi->sf.interp_sf.adaptive_interp_filter_search == 2 &&
2638
0
         features->interp_filter == SWITCHABLE);
2639
0
  }
2640
2641
0
  if (cpi->sf.tx_sf.tx_type_search.prune_tx_type_using_stats ||
2642
0
      ((cpi->sf.tx_sf.tx_type_search.fast_inter_tx_type_prob_thresh !=
2643
0
        INT_MAX) &&
2644
0
       (cpi->sf.tx_sf.tx_type_search.fast_inter_tx_type_prob_thresh != 0))) {
2645
0
    const FRAME_UPDATE_TYPE update_type =
2646
0
        get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
2647
0
    for (i = 0; i < TX_SIZES_ALL; i++) {
2648
0
      int sum = 0;
2649
0
      int j;
2650
0
      int left = MAX_TX_TYPE_PROB;
2651
2652
0
      for (j = 0; j < TX_TYPES; j++)
2653
0
        sum += cpi->td.rd_counts.tx_type_used[i][j];
2654
2655
0
      for (j = TX_TYPES - 1; j >= 0; j--) {
2656
0
        int update_txtype_frameprobs = 1;
2657
0
        const int new_prob =
2658
0
            sum ? (int)((int64_t)MAX_TX_TYPE_PROB *
2659
0
                        cpi->td.rd_counts.tx_type_used[i][j] / sum)
2660
0
                : (j ? 0 : MAX_TX_TYPE_PROB);
2661
#if CONFIG_FPMT_TEST
2662
        if (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) {
2663
          if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] ==
2664
              0) {
2665
            int prob =
2666
                (temp_frame_probs_simulation->tx_type_probs[update_type][i][j] +
2667
                 new_prob) >>
2668
                1;
2669
            left -= prob;
2670
            if (j == 0) prob += left;
2671
            temp_frame_probs_simulation->tx_type_probs[update_type][i][j] =
2672
                prob;
2673
            // Copy temp_frame_probs_simulation to temp_frame_probs
2674
            for (int update_type_idx = 0; update_type_idx < FRAME_UPDATE_TYPES;
2675
                 update_type_idx++) {
2676
              temp_frame_probs->tx_type_probs[update_type_idx][i][j] =
2677
                  temp_frame_probs_simulation
2678
                      ->tx_type_probs[update_type_idx][i][j];
2679
            }
2680
          }
2681
          update_txtype_frameprobs = 0;
2682
        }
2683
#endif  // CONFIG_FPMT_TEST
2684
        // Track the frame probabilities of parallel encode frames to update
2685
        // during postencode stage.
2686
0
        if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
2687
0
          update_txtype_frameprobs = 0;
2688
0
          cpi->frame_new_probs[cpi->num_frame_recode]
2689
0
              .tx_type_probs[update_type][i][j] = new_prob;
2690
0
        }
2691
0
        if (update_txtype_frameprobs) {
2692
0
          int prob =
2693
0
              (frame_probs->tx_type_probs[update_type][i][j] + new_prob) >> 1;
2694
0
          left -= prob;
2695
0
          if (j == 0) prob += left;
2696
0
          frame_probs->tx_type_probs[update_type][i][j] = prob;
2697
0
        }
2698
0
      }
2699
0
    }
2700
0
  }
2701
2702
0
  if (cm->seg.enabled) {
2703
0
    cm->seg.temporal_update = 1;
2704
0
    if (rdc->seg_tmp_pred_cost[0] < rdc->seg_tmp_pred_cost[1])
2705
0
      cm->seg.temporal_update = 0;
2706
0
  }
2707
2708
0
  if (cpi->sf.inter_sf.prune_obmc_prob_thresh > 0 &&
2709
0
      cpi->sf.inter_sf.prune_obmc_prob_thresh < INT_MAX) {
2710
0
    const FRAME_UPDATE_TYPE update_type =
2711
0
        get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
2712
2713
0
    for (i = 0; i < BLOCK_SIZES_ALL; i++) {
2714
0
      int sum = 0;
2715
0
      int update_obmc_frameprobs = 1;
2716
0
      for (int j = 0; j < 2; j++) sum += cpi->td.rd_counts.obmc_used[i][j];
2717
2718
0
      const int new_prob =
2719
0
          sum ? 128 * cpi->td.rd_counts.obmc_used[i][1] / sum : 0;
2720
#if CONFIG_FPMT_TEST
2721
      if (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) {
2722
        if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] == 0) {
2723
          temp_frame_probs_simulation->obmc_probs[update_type][i] =
2724
              (temp_frame_probs_simulation->obmc_probs[update_type][i] +
2725
               new_prob) >>
2726
              1;
2727
          // Copy temp_frame_probs_simulation to temp_frame_probs
2728
          for (int update_type_idx = 0; update_type_idx < FRAME_UPDATE_TYPES;
2729
               update_type_idx++) {
2730
            temp_frame_probs->obmc_probs[update_type_idx][i] =
2731
                temp_frame_probs_simulation->obmc_probs[update_type_idx][i];
2732
          }
2733
        }
2734
        update_obmc_frameprobs = 0;
2735
      }
2736
#endif  // CONFIG_FPMT_TEST
2737
      // Track the frame probabilities of parallel encode frames to update
2738
      // during postencode stage.
2739
0
      if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
2740
0
        update_obmc_frameprobs = 0;
2741
0
        cpi->frame_new_probs[cpi->num_frame_recode].obmc_probs[update_type][i] =
2742
0
            new_prob;
2743
0
      }
2744
0
      if (update_obmc_frameprobs) {
2745
0
        frame_probs->obmc_probs[update_type][i] =
2746
0
            (frame_probs->obmc_probs[update_type][i] + new_prob) >> 1;
2747
0
      }
2748
0
    }
2749
0
  }
2750
2751
0
  if (features->allow_warped_motion &&
2752
0
      cpi->sf.inter_sf.prune_warped_prob_thresh > 0) {
2753
0
    const FRAME_UPDATE_TYPE update_type =
2754
0
        get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
2755
0
    int update_warp_frameprobs = 1;
2756
0
    int sum = 0;
2757
0
    for (i = 0; i < 2; i++) sum += cpi->td.rd_counts.warped_used[i];
2758
0
    const int new_prob = sum ? 128 * cpi->td.rd_counts.warped_used[1] / sum : 0;
2759
#if CONFIG_FPMT_TEST
2760
    if (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) {
2761
      if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] == 0) {
2762
        temp_frame_probs_simulation->warped_probs[update_type] =
2763
            (temp_frame_probs_simulation->warped_probs[update_type] +
2764
             new_prob) >>
2765
            1;
2766
        // Copy temp_frame_probs_simulation to temp_frame_probs
2767
        for (int update_type_idx = 0; update_type_idx < FRAME_UPDATE_TYPES;
2768
             update_type_idx++) {
2769
          temp_frame_probs->warped_probs[update_type_idx] =
2770
              temp_frame_probs_simulation->warped_probs[update_type_idx];
2771
        }
2772
      }
2773
      update_warp_frameprobs = 0;
2774
    }
2775
#endif  // CONFIG_FPMT_TEST
2776
    // Track the frame probabilities of parallel encode frames to update
2777
    // during postencode stage.
2778
0
    if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
2779
0
      update_warp_frameprobs = 0;
2780
0
      cpi->frame_new_probs[cpi->num_frame_recode].warped_probs[update_type] =
2781
0
          new_prob;
2782
0
    }
2783
0
    if (update_warp_frameprobs) {
2784
0
      frame_probs->warped_probs[update_type] =
2785
0
          (frame_probs->warped_probs[update_type] + new_prob) >> 1;
2786
0
    }
2787
0
  }
2788
2789
0
  if (cm->current_frame.frame_type != KEY_FRAME &&
2790
0
      cpi->sf.interp_sf.adaptive_interp_filter_search == 2 &&
2791
0
      features->interp_filter == SWITCHABLE) {
2792
0
    const FRAME_UPDATE_TYPE update_type =
2793
0
        get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
2794
2795
0
    for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
2796
0
      int sum = 0;
2797
0
      int j;
2798
0
      int left = 1536;
2799
2800
0
      for (j = 0; j < SWITCHABLE_FILTERS; j++) {
2801
0
        sum += cpi->td.counts->switchable_interp[i][j];
2802
0
      }
2803
2804
0
      for (j = SWITCHABLE_FILTERS - 1; j >= 0; j--) {
2805
0
        int update_interpfilter_frameprobs = 1;
2806
0
        const int new_prob =
2807
0
            sum ? 1536 * cpi->td.counts->switchable_interp[i][j] / sum
2808
0
                : (j ? 0 : 1536);
2809
#if CONFIG_FPMT_TEST
2810
        if (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) {
2811
          if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] ==
2812
              0) {
2813
            int prob = (temp_frame_probs_simulation
2814
                            ->switchable_interp_probs[update_type][i][j] +
2815
                        new_prob) >>
2816
                       1;
2817
            left -= prob;
2818
            if (j == 0) prob += left;
2819
            temp_frame_probs_simulation
2820
                ->switchable_interp_probs[update_type][i][j] = prob;
2821
            // Copy temp_frame_probs_simulation to temp_frame_probs
2822
            for (int update_type_idx = 0; update_type_idx < FRAME_UPDATE_TYPES;
2823
                 update_type_idx++) {
2824
              temp_frame_probs->switchable_interp_probs[update_type_idx][i][j] =
2825
                  temp_frame_probs_simulation
2826
                      ->switchable_interp_probs[update_type_idx][i][j];
2827
            }
2828
          }
2829
          update_interpfilter_frameprobs = 0;
2830
        }
2831
#endif  // CONFIG_FPMT_TEST
2832
        // Track the frame probabilities of parallel encode frames to update
2833
        // during postencode stage.
2834
0
        if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
2835
0
          update_interpfilter_frameprobs = 0;
2836
0
          cpi->frame_new_probs[cpi->num_frame_recode]
2837
0
              .switchable_interp_probs[update_type][i][j] = new_prob;
2838
0
        }
2839
0
        if (update_interpfilter_frameprobs) {
2840
0
          int prob = (frame_probs->switchable_interp_probs[update_type][i][j] +
2841
0
                      new_prob) >>
2842
0
                     1;
2843
0
          left -= prob;
2844
0
          if (j == 0) prob += left;
2845
0
          frame_probs->switchable_interp_probs[update_type][i][j] = prob;
2846
0
        }
2847
0
      }
2848
0
    }
2849
0
  }
2850
0
}
2851
2852
/*!\brief Setup reference frame buffers and encode a frame
2853
 *
2854
 * \ingroup high_level_algo
2855
 * \callgraph
2856
 * \callergraph
2857
 *
2858
 * \param[in]    cpi    Top-level encoder structure
2859
 */
2860
0
void av1_encode_frame(AV1_COMP *cpi) {
2861
0
  AV1_COMMON *const cm = &cpi->common;
2862
0
  CurrentFrame *const current_frame = &cm->current_frame;
2863
0
  FeatureFlags *const features = &cm->features;
2864
0
  RD_COUNTS *const rdc = &cpi->td.rd_counts;
2865
0
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
2866
  // Indicates whether or not to use a default reduced set for ext-tx
2867
  // rather than the potential full set of 16 transforms
2868
0
  features->reduced_tx_set_used = oxcf->txfm_cfg.reduced_tx_type_set;
2869
2870
  // Make sure segment_id is no larger than last_active_segid.
2871
0
  if (cm->seg.enabled && cm->seg.update_map) {
2872
0
    const int mi_rows = cm->mi_params.mi_rows;
2873
0
    const int mi_cols = cm->mi_params.mi_cols;
2874
0
    const int last_active_segid = cm->seg.last_active_segid;
2875
0
    uint8_t *map = cpi->enc_seg.map;
2876
0
    for (int mi_row = 0; mi_row < mi_rows; ++mi_row) {
2877
0
      for (int mi_col = 0; mi_col < mi_cols; ++mi_col) {
2878
0
        map[mi_col] = AOMMIN(map[mi_col], last_active_segid);
2879
0
      }
2880
0
      map += mi_cols;
2881
0
    }
2882
0
  }
2883
2884
0
  av1_setup_frame_buf_refs(cm);
2885
0
  enforce_max_ref_frames(cpi, &cpi->ref_frame_flags,
2886
0
                         cm->cur_frame->ref_display_order_hint,
2887
0
                         cm->current_frame.display_order_hint);
2888
0
  set_rel_frame_dist(&cpi->common, &cpi->ref_frame_dist_info,
2889
0
                     cpi->ref_frame_flags);
2890
0
  av1_setup_frame_sign_bias(cm);
2891
2892
  // If global motion is enabled, then every buffer which is used as either
2893
  // a source or a ref frame should have an image pyramid allocated.
2894
  // Check here so that issues can be caught early in debug mode
2895
0
#if !defined(NDEBUG) && !CONFIG_REALTIME_ONLY
2896
0
  if (cpi->alloc_pyramid) {
2897
0
    assert(cpi->source->y_pyramid);
2898
0
    for (int ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
2899
0
      const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame);
2900
0
      if (buf != NULL) {
2901
0
        assert(buf->buf.y_pyramid);
2902
0
      }
2903
0
    }
2904
0
  }
2905
0
#endif  // !defined(NDEBUG) && !CONFIG_REALTIME_ONLY
2906
2907
#if CONFIG_MISMATCH_DEBUG
2908
  mismatch_reset_frame(av1_num_planes(cm));
2909
#endif
2910
2911
0
  rdc->newmv_or_intra_blocks = 0;
2912
0
  cpi->palette_pixel_num = 0;
2913
2914
0
  if (cpi->sf.hl_sf.frame_parameter_update ||
2915
0
      cpi->sf.rt_sf.use_comp_ref_nonrd) {
2916
0
    if (frame_is_intra_only(cm))
2917
0
      current_frame->reference_mode = SINGLE_REFERENCE;
2918
0
    else
2919
0
      current_frame->reference_mode = REFERENCE_MODE_SELECT;
2920
2921
0
    features->interp_filter = SWITCHABLE;
2922
0
    if (cm->tiles.large_scale) features->interp_filter = EIGHTTAP_REGULAR;
2923
2924
0
    features->switchable_motion_mode = is_switchable_motion_mode_allowed(
2925
0
        features->allow_warped_motion, oxcf->motion_mode_cfg.enable_obmc);
2926
2927
0
    rdc->compound_ref_used_flag = 0;
2928
0
    rdc->skip_mode_used_flag = 0;
2929
2930
0
    encode_frame_internal(cpi);
2931
2932
0
    if (current_frame->reference_mode == REFERENCE_MODE_SELECT) {
2933
      // Use a flag that includes 4x4 blocks
2934
0
      if (rdc->compound_ref_used_flag == 0) {
2935
0
        current_frame->reference_mode = SINGLE_REFERENCE;
2936
#if CONFIG_ENTROPY_STATS
2937
        av1_zero(cpi->td.counts->comp_inter);
2938
#endif  // CONFIG_ENTROPY_STATS
2939
0
      }
2940
0
    }
2941
    // Re-check on the skip mode status as reference mode may have been
2942
    // changed.
2943
0
    SkipModeInfo *const skip_mode_info = &current_frame->skip_mode_info;
2944
0
    if (frame_is_intra_only(cm) ||
2945
0
        current_frame->reference_mode == SINGLE_REFERENCE) {
2946
0
      skip_mode_info->skip_mode_allowed = 0;
2947
0
      skip_mode_info->skip_mode_flag = 0;
2948
0
    }
2949
0
    if (skip_mode_info->skip_mode_flag && rdc->skip_mode_used_flag == 0)
2950
0
      skip_mode_info->skip_mode_flag = 0;
2951
2952
0
    if (!cm->tiles.large_scale) {
2953
0
      if (features->tx_mode == TX_MODE_SELECT &&
2954
0
          cpi->td.mb.txfm_search_info.txb_split_count == 0)
2955
0
        features->tx_mode = TX_MODE_LARGEST;
2956
0
    }
2957
0
  } else {
2958
    // This is needed if real-time speed setting is changed on the fly
2959
    // from one using compound prediction to one using single reference.
2960
0
    if (current_frame->reference_mode == REFERENCE_MODE_SELECT)
2961
0
      current_frame->reference_mode = SINGLE_REFERENCE;
2962
0
    encode_frame_internal(cpi);
2963
0
  }
2964
0
}