Coverage Report

Created: 2026-07-25 07:03

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