Coverage Report

Created: 2026-11-12 08:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aom/av1/encoder/rdopt.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 <assert.h>
13
#include <math.h>
14
#include <stdbool.h>
15
#include <stdint.h>
16
#include <string.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/blend.h"
24
#include "aom_mem/aom_mem.h"
25
#include "aom_ports/aom_timer.h"
26
#include "aom_ports/mem.h"
27
28
#include "av1/common/av1_common_int.h"
29
#include "av1/common/cfl.h"
30
#include "av1/common/blockd.h"
31
#include "av1/common/common.h"
32
#include "av1/common/common_data.h"
33
#include "av1/common/entropy.h"
34
#include "av1/common/entropymode.h"
35
#include "av1/common/enums.h"
36
#include "av1/common/idct.h"
37
#include "av1/common/mvref_common.h"
38
#include "av1/common/obmc.h"
39
#include "av1/common/pred_common.h"
40
#include "av1/common/quant_common.h"
41
#include "av1/common/reconinter.h"
42
#include "av1/common/reconintra.h"
43
#include "av1/common/scan.h"
44
#include "av1/common/seg_common.h"
45
#include "av1/common/txb_common.h"
46
#include "av1/common/warped_motion.h"
47
48
#include "av1/encoder/aq_variance.h"
49
#include "av1/encoder/av1_quantize.h"
50
#include "av1/encoder/block.h"
51
#include "av1/encoder/cost.h"
52
#include "av1/encoder/compound_type.h"
53
#include "av1/encoder/encodemb.h"
54
#include "av1/encoder/encodemv.h"
55
#include "av1/encoder/encoder.h"
56
#include "av1/encoder/encodetxb.h"
57
#include "av1/encoder/hybrid_fwd_txfm.h"
58
#include "av1/encoder/interp_search.h"
59
#include "av1/encoder/intra_mode_search.h"
60
#include "av1/encoder/intra_mode_search_utils.h"
61
#include "av1/encoder/mcomp.h"
62
#include "av1/encoder/ml.h"
63
#include "av1/encoder/mode_prune_model_weights.h"
64
#include "av1/encoder/model_rd.h"
65
#include "av1/encoder/motion_search_facade.h"
66
#include "av1/encoder/palette.h"
67
#include "av1/encoder/pustats.h"
68
#include "av1/encoder/random.h"
69
#include "av1/encoder/ratectrl.h"
70
#include "av1/encoder/rd.h"
71
#include "av1/encoder/rdopt.h"
72
#include "av1/encoder/reconinter_enc.h"
73
#include "av1/encoder/tokenize.h"
74
#include "av1/encoder/tpl_model.h"
75
#include "av1/encoder/tx_search.h"
76
#include "av1/encoder/var_based_part.h"
77
78
0
#define LAST_NEW_MV_INDEX 6
79
80
// Mode_threshold multiplication factor table for prune_inter_modes_if_skippable
81
// The values are kept in Q12 format and equation used to derive is
82
// (2.5 - ((float)x->qindex / MAXQ) * 1.5)
83
0
#define MODE_THRESH_QBITS 12
84
static const int mode_threshold_mul_factor[QINDEX_RANGE] = {
85
  10240, 10216, 10192, 10168, 10144, 10120, 10095, 10071, 10047, 10023, 9999,
86
  9975,  9951,  9927,  9903,  9879,  9854,  9830,  9806,  9782,  9758,  9734,
87
  9710,  9686,  9662,  9638,  9614,  9589,  9565,  9541,  9517,  9493,  9469,
88
  9445,  9421,  9397,  9373,  9349,  9324,  9300,  9276,  9252,  9228,  9204,
89
  9180,  9156,  9132,  9108,  9083,  9059,  9035,  9011,  8987,  8963,  8939,
90
  8915,  8891,  8867,  8843,  8818,  8794,  8770,  8746,  8722,  8698,  8674,
91
  8650,  8626,  8602,  8578,  8553,  8529,  8505,  8481,  8457,  8433,  8409,
92
  8385,  8361,  8337,  8312,  8288,  8264,  8240,  8216,  8192,  8168,  8144,
93
  8120,  8096,  8072,  8047,  8023,  7999,  7975,  7951,  7927,  7903,  7879,
94
  7855,  7831,  7806,  7782,  7758,  7734,  7710,  7686,  7662,  7638,  7614,
95
  7590,  7566,  7541,  7517,  7493,  7469,  7445,  7421,  7397,  7373,  7349,
96
  7325,  7301,  7276,  7252,  7228,  7204,  7180,  7156,  7132,  7108,  7084,
97
  7060,  7035,  7011,  6987,  6963,  6939,  6915,  6891,  6867,  6843,  6819,
98
  6795,  6770,  6746,  6722,  6698,  6674,  6650,  6626,  6602,  6578,  6554,
99
  6530,  6505,  6481,  6457,  6433,  6409,  6385,  6361,  6337,  6313,  6289,
100
  6264,  6240,  6216,  6192,  6168,  6144,  6120,  6096,  6072,  6048,  6024,
101
  5999,  5975,  5951,  5927,  5903,  5879,  5855,  5831,  5807,  5783,  5758,
102
  5734,  5710,  5686,  5662,  5638,  5614,  5590,  5566,  5542,  5518,  5493,
103
  5469,  5445,  5421,  5397,  5373,  5349,  5325,  5301,  5277,  5253,  5228,
104
  5204,  5180,  5156,  5132,  5108,  5084,  5060,  5036,  5012,  4987,  4963,
105
  4939,  4915,  4891,  4867,  4843,  4819,  4795,  4771,  4747,  4722,  4698,
106
  4674,  4650,  4626,  4602,  4578,  4554,  4530,  4506,  4482,  4457,  4433,
107
  4409,  4385,  4361,  4337,  4313,  4289,  4265,  4241,  4216,  4192,  4168,
108
  4144,  4120,  4096
109
};
110
111
static const THR_MODES av1_default_mode_order[MAX_MODES] = {
112
  THR_NEARESTMV,
113
  THR_NEARESTL2,
114
  THR_NEARESTL3,
115
  THR_NEARESTB,
116
  THR_NEARESTA2,
117
  THR_NEARESTA,
118
  THR_NEARESTG,
119
120
  THR_NEWMV,
121
  THR_NEWL2,
122
  THR_NEWL3,
123
  THR_NEWB,
124
  THR_NEWA2,
125
  THR_NEWA,
126
  THR_NEWG,
127
128
  THR_NEARMV,
129
  THR_NEARL2,
130
  THR_NEARL3,
131
  THR_NEARB,
132
  THR_NEARA2,
133
  THR_NEARA,
134
  THR_NEARG,
135
136
  THR_GLOBALMV,
137
  THR_GLOBALL2,
138
  THR_GLOBALL3,
139
  THR_GLOBALB,
140
  THR_GLOBALA2,
141
  THR_GLOBALA,
142
  THR_GLOBALG,
143
144
  THR_COMP_NEAREST_NEARESTLA,
145
  THR_COMP_NEAREST_NEARESTL2A,
146
  THR_COMP_NEAREST_NEARESTL3A,
147
  THR_COMP_NEAREST_NEARESTGA,
148
  THR_COMP_NEAREST_NEARESTLB,
149
  THR_COMP_NEAREST_NEARESTL2B,
150
  THR_COMP_NEAREST_NEARESTL3B,
151
  THR_COMP_NEAREST_NEARESTGB,
152
  THR_COMP_NEAREST_NEARESTLA2,
153
  THR_COMP_NEAREST_NEARESTL2A2,
154
  THR_COMP_NEAREST_NEARESTL3A2,
155
  THR_COMP_NEAREST_NEARESTGA2,
156
  THR_COMP_NEAREST_NEARESTLL2,
157
  THR_COMP_NEAREST_NEARESTLL3,
158
  THR_COMP_NEAREST_NEARESTLG,
159
  THR_COMP_NEAREST_NEARESTBA,
160
161
  THR_COMP_NEAR_NEARLB,
162
  THR_COMP_NEW_NEWLB,
163
  THR_COMP_NEW_NEARESTLB,
164
  THR_COMP_NEAREST_NEWLB,
165
  THR_COMP_NEW_NEARLB,
166
  THR_COMP_NEAR_NEWLB,
167
  THR_COMP_GLOBAL_GLOBALLB,
168
169
  THR_COMP_NEAR_NEARLA,
170
  THR_COMP_NEW_NEWLA,
171
  THR_COMP_NEW_NEARESTLA,
172
  THR_COMP_NEAREST_NEWLA,
173
  THR_COMP_NEW_NEARLA,
174
  THR_COMP_NEAR_NEWLA,
175
  THR_COMP_GLOBAL_GLOBALLA,
176
177
  THR_COMP_NEAR_NEARL2A,
178
  THR_COMP_NEW_NEWL2A,
179
  THR_COMP_NEW_NEARESTL2A,
180
  THR_COMP_NEAREST_NEWL2A,
181
  THR_COMP_NEW_NEARL2A,
182
  THR_COMP_NEAR_NEWL2A,
183
  THR_COMP_GLOBAL_GLOBALL2A,
184
185
  THR_COMP_NEAR_NEARL3A,
186
  THR_COMP_NEW_NEWL3A,
187
  THR_COMP_NEW_NEARESTL3A,
188
  THR_COMP_NEAREST_NEWL3A,
189
  THR_COMP_NEW_NEARL3A,
190
  THR_COMP_NEAR_NEWL3A,
191
  THR_COMP_GLOBAL_GLOBALL3A,
192
193
  THR_COMP_NEAR_NEARGA,
194
  THR_COMP_NEW_NEWGA,
195
  THR_COMP_NEW_NEARESTGA,
196
  THR_COMP_NEAREST_NEWGA,
197
  THR_COMP_NEW_NEARGA,
198
  THR_COMP_NEAR_NEWGA,
199
  THR_COMP_GLOBAL_GLOBALGA,
200
201
  THR_COMP_NEAR_NEARL2B,
202
  THR_COMP_NEW_NEWL2B,
203
  THR_COMP_NEW_NEARESTL2B,
204
  THR_COMP_NEAREST_NEWL2B,
205
  THR_COMP_NEW_NEARL2B,
206
  THR_COMP_NEAR_NEWL2B,
207
  THR_COMP_GLOBAL_GLOBALL2B,
208
209
  THR_COMP_NEAR_NEARL3B,
210
  THR_COMP_NEW_NEWL3B,
211
  THR_COMP_NEW_NEARESTL3B,
212
  THR_COMP_NEAREST_NEWL3B,
213
  THR_COMP_NEW_NEARL3B,
214
  THR_COMP_NEAR_NEWL3B,
215
  THR_COMP_GLOBAL_GLOBALL3B,
216
217
  THR_COMP_NEAR_NEARGB,
218
  THR_COMP_NEW_NEWGB,
219
  THR_COMP_NEW_NEARESTGB,
220
  THR_COMP_NEAREST_NEWGB,
221
  THR_COMP_NEW_NEARGB,
222
  THR_COMP_NEAR_NEWGB,
223
  THR_COMP_GLOBAL_GLOBALGB,
224
225
  THR_COMP_NEAR_NEARLA2,
226
  THR_COMP_NEW_NEWLA2,
227
  THR_COMP_NEW_NEARESTLA2,
228
  THR_COMP_NEAREST_NEWLA2,
229
  THR_COMP_NEW_NEARLA2,
230
  THR_COMP_NEAR_NEWLA2,
231
  THR_COMP_GLOBAL_GLOBALLA2,
232
233
  THR_COMP_NEAR_NEARL2A2,
234
  THR_COMP_NEW_NEWL2A2,
235
  THR_COMP_NEW_NEARESTL2A2,
236
  THR_COMP_NEAREST_NEWL2A2,
237
  THR_COMP_NEW_NEARL2A2,
238
  THR_COMP_NEAR_NEWL2A2,
239
  THR_COMP_GLOBAL_GLOBALL2A2,
240
241
  THR_COMP_NEAR_NEARL3A2,
242
  THR_COMP_NEW_NEWL3A2,
243
  THR_COMP_NEW_NEARESTL3A2,
244
  THR_COMP_NEAREST_NEWL3A2,
245
  THR_COMP_NEW_NEARL3A2,
246
  THR_COMP_NEAR_NEWL3A2,
247
  THR_COMP_GLOBAL_GLOBALL3A2,
248
249
  THR_COMP_NEAR_NEARGA2,
250
  THR_COMP_NEW_NEWGA2,
251
  THR_COMP_NEW_NEARESTGA2,
252
  THR_COMP_NEAREST_NEWGA2,
253
  THR_COMP_NEW_NEARGA2,
254
  THR_COMP_NEAR_NEWGA2,
255
  THR_COMP_GLOBAL_GLOBALGA2,
256
257
  THR_COMP_NEAR_NEARLL2,
258
  THR_COMP_NEW_NEWLL2,
259
  THR_COMP_NEW_NEARESTLL2,
260
  THR_COMP_NEAREST_NEWLL2,
261
  THR_COMP_NEW_NEARLL2,
262
  THR_COMP_NEAR_NEWLL2,
263
  THR_COMP_GLOBAL_GLOBALLL2,
264
265
  THR_COMP_NEAR_NEARLL3,
266
  THR_COMP_NEW_NEWLL3,
267
  THR_COMP_NEW_NEARESTLL3,
268
  THR_COMP_NEAREST_NEWLL3,
269
  THR_COMP_NEW_NEARLL3,
270
  THR_COMP_NEAR_NEWLL3,
271
  THR_COMP_GLOBAL_GLOBALLL3,
272
273
  THR_COMP_NEAR_NEARLG,
274
  THR_COMP_NEW_NEWLG,
275
  THR_COMP_NEW_NEARESTLG,
276
  THR_COMP_NEAREST_NEWLG,
277
  THR_COMP_NEW_NEARLG,
278
  THR_COMP_NEAR_NEWLG,
279
  THR_COMP_GLOBAL_GLOBALLG,
280
281
  THR_COMP_NEAR_NEARBA,
282
  THR_COMP_NEW_NEWBA,
283
  THR_COMP_NEW_NEARESTBA,
284
  THR_COMP_NEAREST_NEWBA,
285
  THR_COMP_NEW_NEARBA,
286
  THR_COMP_NEAR_NEWBA,
287
  THR_COMP_GLOBAL_GLOBALBA,
288
289
  THR_DC,
290
  THR_PAETH,
291
  THR_SMOOTH,
292
  THR_SMOOTH_V,
293
  THR_SMOOTH_H,
294
  THR_H_PRED,
295
  THR_V_PRED,
296
  THR_D135_PRED,
297
  THR_D203_PRED,
298
  THR_D157_PRED,
299
  THR_D67_PRED,
300
  THR_D113_PRED,
301
  THR_D45_PRED,
302
};
303
304
/*!\cond */
305
typedef struct SingleInterModeState {
306
  int64_t rd;
307
  MV_REFERENCE_FRAME ref_frame;
308
  int valid;
309
} SingleInterModeState;
310
311
typedef struct InterModeSearchState {
312
  int64_t best_rd;
313
  int64_t best_skip_rd[2];
314
  MB_MODE_INFO best_mbmode;
315
  int best_rate_y;
316
  int best_rate_uv;
317
  int best_mode_skippable;
318
  int best_skip2;
319
  THR_MODES best_mode_index;
320
  int num_available_refs;
321
  int64_t dist_refs[REF_FRAMES];
322
  int dist_order_refs[REF_FRAMES];
323
  int64_t mode_threshold[MAX_MODES];
324
  int64_t best_intra_rd;
325
  unsigned int best_pred_sse;
326
327
  /*!
328
   * \brief Keep track of best intra rd for use in compound mode.
329
   */
330
  int64_t best_pred_rd[REFERENCE_MODES];
331
  // Save a set of single_newmv for each checked ref_mv.
332
  int_mv single_newmv[MAX_REF_MV_SEARCH][REF_FRAMES];
333
  int single_newmv_rate[MAX_REF_MV_SEARCH][REF_FRAMES];
334
  int single_newmv_valid[MAX_REF_MV_SEARCH][REF_FRAMES];
335
  int64_t modelled_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES];
336
  // The rd of simple translation in single inter modes
337
  int64_t simple_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES];
338
  int64_t best_single_rd[REF_FRAMES];
339
  PREDICTION_MODE best_single_mode[REF_FRAMES];
340
341
  // Single search results by [directions][modes][reference frames]
342
  SingleInterModeState single_state[2][SINGLE_INTER_MODE_NUM][FWD_REFS];
343
  int single_state_cnt[2][SINGLE_INTER_MODE_NUM];
344
  SingleInterModeState single_state_modelled[2][SINGLE_INTER_MODE_NUM]
345
                                            [FWD_REFS];
346
  int single_state_modelled_cnt[2][SINGLE_INTER_MODE_NUM];
347
  MV_REFERENCE_FRAME single_rd_order[2][SINGLE_INTER_MODE_NUM][FWD_REFS];
348
  IntraModeSearchState intra_search_state;
349
  RD_STATS best_y_rdcost;
350
} InterModeSearchState;
351
/*!\endcond */
352
353
0
void av1_inter_mode_data_init(TileDataEnc *tile_data) {
354
0
  for (int i = 0; i < BLOCK_SIZES_ALL; ++i) {
355
0
    InterModeRdModel *md = &tile_data->inter_mode_rd_models[i];
356
0
    md->ready = 0;
357
0
    md->num = 0;
358
0
    md->dist_sum = 0;
359
0
    md->ld_sum = 0;
360
0
    md->sse_sum = 0;
361
0
    md->sse_sse_sum = 0;
362
0
    md->sse_ld_sum = 0;
363
0
  }
364
0
}
365
366
static int get_est_rate_dist(const TileDataEnc *tile_data, BLOCK_SIZE bsize,
367
                             int64_t sse, int *est_residue_cost,
368
0
                             int64_t *est_dist) {
369
0
  const InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
370
0
  if (md->ready) {
371
0
    if (sse < md->dist_mean) {
372
0
      *est_residue_cost = 0;
373
0
      *est_dist = sse;
374
0
    } else {
375
0
      *est_dist = (int64_t)round(md->dist_mean);
376
0
      const double est_ld = md->a * sse + md->b;
377
      // Clamp estimated rate cost by INT_MAX / 2.
378
      // TODO(angiebird@google.com): find better solution than clamping.
379
0
      if (fabs(est_ld) < 1e-2) {
380
0
        *est_residue_cost = INT_MAX / 2;
381
0
      } else {
382
0
        double est_residue_cost_dbl = ((sse - md->dist_mean) / est_ld);
383
0
        if (est_residue_cost_dbl < 0) {
384
0
          *est_residue_cost = 0;
385
0
        } else {
386
0
          *est_residue_cost =
387
0
              (int)AOMMIN((int64_t)round(est_residue_cost_dbl), INT_MAX / 2);
388
0
        }
389
0
      }
390
0
      if (*est_residue_cost <= 0) {
391
0
        *est_residue_cost = 0;
392
0
        *est_dist = sse;
393
0
      }
394
0
    }
395
0
    return 1;
396
0
  }
397
0
  return 0;
398
0
}
399
400
0
void av1_inter_mode_data_fit(TileDataEnc *tile_data, int rdmult) {
401
0
  for (int bsize = 0; bsize < BLOCK_SIZES_ALL; ++bsize) {
402
0
    const int block_idx = inter_mode_data_block_idx(bsize);
403
0
    InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
404
0
    if (block_idx == -1) continue;
405
0
    if ((md->ready == 0 && md->num < 200) || (md->ready == 1 && md->num < 64)) {
406
0
      continue;
407
0
    } else {
408
0
      if (md->ready == 0) {
409
0
        md->dist_mean = md->dist_sum / md->num;
410
0
        md->ld_mean = md->ld_sum / md->num;
411
0
        md->sse_mean = md->sse_sum / md->num;
412
0
        md->sse_sse_mean = md->sse_sse_sum / md->num;
413
0
        md->sse_ld_mean = md->sse_ld_sum / md->num;
414
0
      } else {
415
0
        const double factor = 3;
416
0
        md->dist_mean =
417
0
            (md->dist_mean * factor + (md->dist_sum / md->num)) / (factor + 1);
418
0
        md->ld_mean =
419
0
            (md->ld_mean * factor + (md->ld_sum / md->num)) / (factor + 1);
420
0
        md->sse_mean =
421
0
            (md->sse_mean * factor + (md->sse_sum / md->num)) / (factor + 1);
422
0
        md->sse_sse_mean =
423
0
            (md->sse_sse_mean * factor + (md->sse_sse_sum / md->num)) /
424
0
            (factor + 1);
425
0
        md->sse_ld_mean =
426
0
            (md->sse_ld_mean * factor + (md->sse_ld_sum / md->num)) /
427
0
            (factor + 1);
428
0
      }
429
430
0
      const double my = md->ld_mean;
431
0
      const double mx = md->sse_mean;
432
0
      const double dx = sqrt(md->sse_sse_mean);
433
0
      const double dxy = md->sse_ld_mean;
434
435
0
      md->a = (dxy - mx * my) / (dx * dx - mx * mx);
436
0
      md->b = my - md->a * mx;
437
0
      md->ready = 1;
438
439
0
      md->num = 0;
440
0
      md->dist_sum = 0;
441
0
      md->ld_sum = 0;
442
0
      md->sse_sum = 0;
443
0
      md->sse_sse_sum = 0;
444
0
      md->sse_ld_sum = 0;
445
0
    }
446
0
    (void)rdmult;
447
0
  }
448
0
}
449
450
static inline void inter_mode_data_push(TileDataEnc *tile_data,
451
                                        BLOCK_SIZE bsize, int64_t sse,
452
0
                                        int64_t dist, int residue_cost) {
453
0
  if (residue_cost == 0 || sse == dist) return;
454
0
  const int block_idx = inter_mode_data_block_idx(bsize);
455
0
  if (block_idx == -1) return;
456
0
  InterModeRdModel *rd_model = &tile_data->inter_mode_rd_models[bsize];
457
0
  if (rd_model->num < INTER_MODE_RD_DATA_OVERALL_SIZE) {
458
0
    const double ld = (sse - dist) * 1. / residue_cost;
459
0
    ++rd_model->num;
460
0
    rd_model->dist_sum += dist;
461
0
    rd_model->ld_sum += ld;
462
0
    rd_model->sse_sum += sse;
463
0
    rd_model->sse_sse_sum += (double)sse * (double)sse;
464
0
    rd_model->sse_ld_sum += sse * ld;
465
0
  }
466
0
}
467
468
static inline void inter_modes_info_push(InterModesInfo *inter_modes_info,
469
                                         int mode_rate, int64_t sse, int64_t rd,
470
                                         RD_STATS *rd_cost, RD_STATS *rd_cost_y,
471
                                         RD_STATS *rd_cost_uv,
472
0
                                         const MB_MODE_INFO *mbmi) {
473
0
  const int num = inter_modes_info->num;
474
0
  assert(num < MAX_INTER_MODES);
475
0
  inter_modes_info->mbmi_arr[num] = *mbmi;
476
0
  inter_modes_info->mode_rate_arr[num] = mode_rate;
477
0
  inter_modes_info->sse_arr[num] = sse;
478
0
  inter_modes_info->est_rd_arr[num] = rd;
479
0
  inter_modes_info->rd_cost_arr[num] = *rd_cost;
480
0
  inter_modes_info->rd_cost_y_arr[num] = *rd_cost_y;
481
0
  inter_modes_info->rd_cost_uv_arr[num] = *rd_cost_uv;
482
0
  ++inter_modes_info->num;
483
0
}
484
485
0
static int compare_rd_idx_pair(const void *a, const void *b) {
486
0
  if (((RdIdxPair *)a)->rd == ((RdIdxPair *)b)->rd) {
487
    // To avoid inconsistency in qsort() ordering when two elements are equal,
488
    // using idx as tie breaker. Refer aomedia:2928
489
0
    if (((RdIdxPair *)a)->idx == ((RdIdxPair *)b)->idx)
490
0
      return 0;
491
0
    else if (((RdIdxPair *)a)->idx > ((RdIdxPair *)b)->idx)
492
0
      return 1;
493
0
    else
494
0
      return -1;
495
0
  } else if (((const RdIdxPair *)a)->rd > ((const RdIdxPair *)b)->rd) {
496
0
    return 1;
497
0
  } else {
498
0
    return -1;
499
0
  }
500
0
}
501
502
static inline void inter_modes_info_sort(const InterModesInfo *inter_modes_info,
503
0
                                         RdIdxPair *rd_idx_pair_arr) {
504
0
  if (inter_modes_info->num == 0) {
505
0
    return;
506
0
  }
507
0
  for (int i = 0; i < inter_modes_info->num; ++i) {
508
0
    rd_idx_pair_arr[i].idx = i;
509
0
    rd_idx_pair_arr[i].rd = inter_modes_info->est_rd_arr[i];
510
0
  }
511
0
  qsort(rd_idx_pair_arr, inter_modes_info->num, sizeof(rd_idx_pair_arr[0]),
512
0
        compare_rd_idx_pair);
513
0
}
514
515
// Initialize estimated RD Cost records of compound average.
516
static inline void init_comp_avg_est_rd(
517
0
    struct macroblock *x, int skip_cmp_using_top_cmp_avg_est_rd_lvl) {
518
0
  if (!skip_cmp_using_top_cmp_avg_est_rd_lvl) return;
519
520
0
  for (int j = 0; j < TOP_COMP_AVG_EST_RD_COUNT; j++) {
521
0
    x->top_comp_avg_est_rd[j] = INT64_MAX;
522
0
  }
523
0
}
524
525
// Initialize estimated RD Cost records of smooth interintra.
526
static inline void init_smooth_interintra_est_rd(
527
0
    struct macroblock *x, int skip_interintra_using_top_smooth_rd_lvl) {
528
0
  if (!skip_interintra_using_top_smooth_rd_lvl) return;
529
530
0
  for (int j = 0; j < TOP_SMOOTH_INTERINTRA_RD_COUNT; ++j) {
531
0
    x->top_smooth_interintra_rd[j] = INT64_MAX;
532
0
  }
533
0
}
534
535
// Similar to get_horver_correlation, but also takes into account first
536
// row/column, when computing horizontal/vertical correlation.
537
void av1_get_horver_correlation_full_c(const int16_t *diff, int stride,
538
                                       int width, int height, float *hcorr,
539
0
                                       float *vcorr) {
540
  // The following notation is used:
541
  // x - current pixel
542
  // y - left neighbor pixel
543
  // z - top neighbor pixel
544
0
  int64_t x_sum = 0, x2_sum = 0, xy_sum = 0, xz_sum = 0;
545
0
  int64_t x_firstrow = 0, x_finalrow = 0, x_firstcol = 0, x_finalcol = 0;
546
0
  int64_t x2_firstrow = 0, x2_finalrow = 0, x2_firstcol = 0, x2_finalcol = 0;
547
548
  // First, process horizontal correlation on just the first row
549
0
  x_sum += diff[0];
550
0
  x2_sum += diff[0] * diff[0];
551
0
  x_firstrow += diff[0];
552
0
  x2_firstrow += diff[0] * diff[0];
553
0
  for (int j = 1; j < width; ++j) {
554
0
    const int16_t x = diff[j];
555
0
    const int16_t y = diff[j - 1];
556
0
    x_sum += x;
557
0
    x_firstrow += x;
558
0
    x2_sum += x * x;
559
0
    x2_firstrow += x * x;
560
0
    xy_sum += x * y;
561
0
  }
562
563
  // Process vertical correlation in the first column
564
0
  x_firstcol += diff[0];
565
0
  x2_firstcol += diff[0] * diff[0];
566
0
  for (int i = 1; i < height; ++i) {
567
0
    const int16_t x = diff[i * stride];
568
0
    const int16_t z = diff[(i - 1) * stride];
569
0
    x_sum += x;
570
0
    x_firstcol += x;
571
0
    x2_sum += x * x;
572
0
    x2_firstcol += x * x;
573
0
    xz_sum += x * z;
574
0
  }
575
576
  // Now process horiz and vert correlation through the rest unit
577
0
  for (int i = 1; i < height; ++i) {
578
0
    for (int j = 1; j < width; ++j) {
579
0
      const int16_t x = diff[i * stride + j];
580
0
      const int16_t y = diff[i * stride + j - 1];
581
0
      const int16_t z = diff[(i - 1) * stride + j];
582
0
      x_sum += x;
583
0
      x2_sum += x * x;
584
0
      xy_sum += x * y;
585
0
      xz_sum += x * z;
586
0
    }
587
0
  }
588
589
0
  for (int j = 0; j < width; ++j) {
590
0
    x_finalrow += diff[(height - 1) * stride + j];
591
0
    x2_finalrow +=
592
0
        diff[(height - 1) * stride + j] * diff[(height - 1) * stride + j];
593
0
  }
594
0
  for (int i = 0; i < height; ++i) {
595
0
    x_finalcol += diff[i * stride + width - 1];
596
0
    x2_finalcol += diff[i * stride + width - 1] * diff[i * stride + width - 1];
597
0
  }
598
599
0
  int64_t xhor_sum = x_sum - x_finalcol;
600
0
  int64_t xver_sum = x_sum - x_finalrow;
601
0
  int64_t y_sum = x_sum - x_firstcol;
602
0
  int64_t z_sum = x_sum - x_firstrow;
603
0
  int64_t x2hor_sum = x2_sum - x2_finalcol;
604
0
  int64_t x2ver_sum = x2_sum - x2_finalrow;
605
0
  int64_t y2_sum = x2_sum - x2_firstcol;
606
0
  int64_t z2_sum = x2_sum - x2_firstrow;
607
608
0
  const float num_hor = (float)(height * (width - 1));
609
0
  const float num_ver = (float)((height - 1) * width);
610
611
0
  const float xhor_var_n = x2hor_sum - (xhor_sum * xhor_sum) / num_hor;
612
0
  const float xver_var_n = x2ver_sum - (xver_sum * xver_sum) / num_ver;
613
614
0
  const float y_var_n = y2_sum - (y_sum * y_sum) / num_hor;
615
0
  const float z_var_n = z2_sum - (z_sum * z_sum) / num_ver;
616
617
0
  const float xy_var_n = xy_sum - (xhor_sum * y_sum) / num_hor;
618
0
  const float xz_var_n = xz_sum - (xver_sum * z_sum) / num_ver;
619
620
0
  if (xhor_var_n > 0 && y_var_n > 0) {
621
0
    *hcorr = xy_var_n / sqrtf(xhor_var_n * y_var_n);
622
0
    *hcorr = *hcorr < 0 ? 0 : *hcorr;
623
0
  } else {
624
0
    *hcorr = 1.0;
625
0
  }
626
0
  if (xver_var_n > 0 && z_var_n > 0) {
627
0
    *vcorr = xz_var_n / sqrtf(xver_var_n * z_var_n);
628
0
    *vcorr = *vcorr < 0 ? 0 : *vcorr;
629
0
  } else {
630
0
    *vcorr = 1.0;
631
0
  }
632
0
}
633
634
#if CONFIG_AV1_HIGHBITDEPTH
635
static void get_variance_stats_hbd(const MACROBLOCK *x, int64_t *src_var,
636
0
                                   int64_t *rec_var) {
637
0
  const MACROBLOCKD *xd = &x->e_mbd;
638
0
  const MB_MODE_INFO *mbmi = xd->mi[0];
639
0
  const struct macroblockd_plane *const pd = &xd->plane[AOM_PLANE_Y];
640
0
  const struct macroblock_plane *const p = &x->plane[AOM_PLANE_Y];
641
642
0
  BLOCK_SIZE bsize = mbmi->bsize;
643
0
  int bw = block_size_wide[bsize];
644
0
  int bh = block_size_high[bsize];
645
0
  const int shift = 2 * (xd->bd - 8);
646
647
0
  *rec_var = aom_highbd_calc_variance_stat(CONVERT_TO_SHORTPTR(pd->dst.buf),
648
0
                                           pd->dst.stride, bw, bh);
649
0
  *src_var = aom_highbd_calc_variance_stat(CONVERT_TO_SHORTPTR(p->src.buf),
650
0
                                           p->src.stride, bw, bh);
651
652
0
  *rec_var = ROUND_POWER_OF_TWO(*rec_var, shift);
653
0
  *src_var = ROUND_POWER_OF_TWO(*src_var, shift);
654
0
}
655
#endif  // CONFIG_AV1_HIGHBITDEPTH
656
657
void av1_get_variance_stats(const MACROBLOCK *x, int64_t *src_var,
658
0
                            int64_t *rec_var) {
659
0
#if CONFIG_AV1_HIGHBITDEPTH
660
0
  if (is_cur_buf_hbd(&x->e_mbd)) {
661
0
    get_variance_stats_hbd(x, src_var, rec_var);
662
0
    return;
663
0
  }
664
0
#endif  // CONFIG_AV1_HIGHBITDEPTH
665
0
  const MACROBLOCKD *xd = &x->e_mbd;
666
0
  const MB_MODE_INFO *mbmi = xd->mi[0];
667
0
  const struct macroblockd_plane *const pd = &xd->plane[AOM_PLANE_Y];
668
0
  const struct macroblock_plane *const p = &x->plane[AOM_PLANE_Y];
669
670
0
  BLOCK_SIZE bsize = mbmi->bsize;
671
0
  int bw = block_size_wide[bsize];
672
0
  int bh = block_size_high[bsize];
673
674
0
  *rec_var = aom_calc_variance_stat(pd->dst.buf, pd->dst.stride, bw, bh);
675
0
  *src_var = aom_calc_variance_stat(p->src.buf, p->src.stride, bw, bh);
676
0
}
677
678
int av1_is_skip_txfm_penalized(const AV1_COMP *cpi, const MACROBLOCK *x,
679
0
                               BLOCK_SIZE bsize) {
680
0
#if CONFIG_AV1_HIGHBITDEPTH
681
0
  const MACROBLOCKD *xd = &x->e_mbd;
682
0
  if (xd->bd > 8 && cpi->oxcf.algo_cfg.sharpness == 3 &&
683
0
      !frame_is_kf_gf_arf(cpi)) {
684
0
    int64_t src_var, rec_var;
685
0
    av1_get_variance_stats(x, &src_var, &rec_var);
686
0
    if (src_var > rec_var) {
687
0
      const int num_pixels = block_size_wide[bsize] * block_size_high[bsize];
688
0
      const int64_t src_var_per_px = src_var / num_pixels;
689
0
      if (src_var_per_px < 64) return 1;
690
0
    }
691
0
  }
692
#else
693
  (void)cpi;
694
  (void)x;
695
  (void)bsize;
696
#endif
697
0
  return 0;
698
0
}
699
700
void av1_get_tx_skip_dist(const AV1_COMP *cpi, const MACROBLOCK *x,
701
                          BLOCK_SIZE bsize, int64_t dist, int64_t sse,
702
0
                          int64_t *no_skip_dist, int64_t *skip_dist) {
703
0
  *no_skip_dist = dist;
704
0
  *skip_dist = sse;
705
0
#if CONFIG_AV1_HIGHBITDEPTH
706
0
  const MACROBLOCKD *xd = &x->e_mbd;
707
0
  if (xd->bd > 8 && cpi->oxcf.algo_cfg.sharpness == 3 &&
708
0
      !frame_is_kf_gf_arf(cpi)) {
709
0
    int64_t src_var, rec_var;
710
0
    av1_get_variance_stats(x, &src_var, &rec_var);
711
0
    if (src_var > rec_var) {
712
0
      int64_t var_offset = src_var - rec_var;
713
0
      const int num_pixels = block_size_wide[bsize] * block_size_high[bsize];
714
0
      const int64_t src_var_per_px = src_var / num_pixels;
715
0
      *no_skip_dist += var_offset;
716
0
      *skip_dist += (src_var_per_px < 64) ? (var_offset * 4) : var_offset;
717
0
    }
718
0
  }
719
#else
720
  (void)cpi;
721
  (void)x;
722
  (void)bsize;
723
#endif
724
0
}
725
726
#if CONFIG_AV1_HIGHBITDEPTH
727
static int get_sub_block_energy_diff(const AV1_COMP *cpi, const MACROBLOCK *x,
728
0
                                     BLOCK_SIZE bsize) {
729
0
  if (x->sub_block_energy_bsize == bsize) {
730
0
    return x->sub_block_energy_diff;
731
0
  }
732
733
0
  const MACROBLOCKD *const xd = &x->e_mbd;
734
0
  const struct macroblock_plane *const p = &x->plane[AOM_PLANE_Y];
735
0
  const int bw = block_size_wide[bsize];
736
0
  const int bh = block_size_high[bsize];
737
738
0
  if (bw < 16 || bh < 16) {
739
0
    ((MACROBLOCK *)x)->sub_block_energy_diff = 0;
740
0
    ((MACROBLOCK *)x)->sub_block_energy_bsize = bsize;
741
0
    return 0;
742
0
  }
743
744
0
  DECLARE_ALIGNED(16, static const uint16_t, av1_highbd_all_zeros[64]) = { 0 };
745
0
  DECLARE_ALIGNED(16, static const uint8_t, av1_all_zeros[64]) = { 0 };
746
0
  const uint8_t *all_zeros = is_cur_buf_hbd(xd)
747
0
                                 ? CONVERT_TO_BYTEPTR(av1_highbd_all_zeros)
748
0
                                 : av1_all_zeros;
749
0
  aom_variance_fn_t vf = cpi->ppi->fn_ptr[BLOCK_8X8].vf;
750
0
  unsigned int min_var = UINT_MAX;
751
0
  unsigned int max_var = 0;
752
753
0
  for (int r = 0; r < bh; r += 8) {
754
0
    for (int c = 0; c < bw; c += 8) {
755
0
      unsigned int sse;
756
0
      const uint8_t *src_ptr = p->src.buf + r * p->src.stride + c;
757
0
      unsigned int var = vf(src_ptr, p->src.stride, all_zeros, 0, &sse) / 64;
758
0
      min_var = AOMMIN(min_var, var);
759
0
      max_var = AOMMAX(max_var, var);
760
0
    }
761
0
  }
762
763
0
  int min_energy = (int)round(log((double)min_var + 1.0));
764
0
  int max_energy = (int)round(log((double)max_var + 1.0));
765
0
  int energy_diff = AOMMAX(0, max_energy - min_energy);
766
767
0
  ((MACROBLOCK *)x)->sub_block_energy_diff = energy_diff;
768
0
  ((MACROBLOCK *)x)->sub_block_energy_bsize = bsize;
769
0
  return energy_diff;
770
0
}
771
#endif
772
773
static void adjust_rdcost(const AV1_COMP *cpi, const MACROBLOCK *x,
774
0
                          RD_STATS *rd_cost, bool is_inter_pred) {
775
0
  if ((cpi->oxcf.tune_cfg.tuning == AOM_TUNE_IQ ||
776
0
       cpi->oxcf.tune_cfg.tuning == AOM_TUNE_SSIMULACRA2) &&
777
0
      is_inter_pred) {
778
    // Tune IQ and SSIMULACRA2 can be used to encode layered images, where
779
    // keyframes could be encoded at a lower or similar quality (i.e. higher
780
    // QP) than inter-coded frames.
781
    // In this case, libaom tends to underestimate the true RD cost of inter
782
    // prediction candidates, causing encoded file size to increase without a
783
    // corresponding increase in quality.
784
    // When both intra and inter encoded block candidates are available (with
785
    // rdcosts close to each other), the intra-coded candidate was subjectively
786
    // observed to be a bit less blurry, with a corresponding increase in
787
    // SSIMULACRA 2 scores.
788
    // Apply a 1.125x inter block bias to increase overall perceptual
789
    // compression efficiency, while still allowing the encoder to pick inter
790
    // prediction when it's beneficial.
791
0
    rd_cost->dist += rd_cost->dist >> 3;
792
0
    rd_cost->rdcost += rd_cost->rdcost >> 3;
793
0
    return;
794
0
  }
795
796
0
#if CONFIG_AV1_HIGHBITDEPTH
797
0
  const MACROBLOCKD *xd = &x->e_mbd;
798
0
  if (xd->bd > 8 && cpi->oxcf.algo_cfg.sharpness == 3) {
799
0
    if (frame_is_intra_only(&cpi->common)) return;
800
801
0
    int64_t src_var, rec_var;
802
0
    av1_get_variance_stats(x, &src_var, &rec_var);
803
804
0
    int64_t var_offset = (src_var > rec_var) ? (src_var - rec_var) : 0;
805
806
0
    const MB_MODE_INFO *mbmi = xd->mi[0];
807
0
    const int is_smooth_intra_mode =
808
0
        (mbmi->mode == DC_PRED || mbmi->mode == SMOOTH_PRED ||
809
0
         mbmi->mode == SMOOTH_V_PRED || mbmi->mode == SMOOTH_H_PRED ||
810
0
         mbmi->mode == PAETH_PRED);
811
812
0
    const int is_skip_txfm = mbmi->skip_txfm || rd_cost->skip_txfm;
813
0
    const int num_pixels =
814
0
        block_size_wide[mbmi->bsize] * block_size_high[mbmi->bsize];
815
0
    const int64_t src_var_per_px = src_var / num_pixels;
816
817
0
    if (var_offset > 0 &&
818
0
        ((is_skip_txfm && src_var_per_px < 64) || is_smooth_intra_mode ||
819
0
         is_interintra_mode(mbmi) || has_second_ref(mbmi))) {
820
0
      var_offset *= 4;
821
0
    }
822
823
0
    if (is_inter_pred && !has_second_ref(mbmi)) {
824
0
      const int mv_mag =
825
0
          abs(mbmi->mv[0].as_mv.row) + abs(mbmi->mv[0].as_mv.col);
826
0
      if (mv_mag > 0 && src_var_per_px < 64) {
827
0
        var_offset += (int64_t)mv_mag * (64 - src_var_per_px);
828
0
      }
829
0
    }
830
831
0
    if (var_offset > 0) {
832
0
      rd_cost->dist += var_offset;
833
0
      rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
834
0
    }
835
836
    // Sub-block local variance energy disparity adjustment
837
0
    if (mbmi->bsize >= BLOCK_16X16) {
838
0
      const int energy_diff = get_sub_block_energy_diff(cpi, x, mbmi->bsize);
839
0
      if (energy_diff > 0) {
840
0
        int64_t extra_rd = 0;
841
0
        if (!is_inter_pred) {
842
0
          if (mbmi->mode == DC_PRED || is_smooth_intra_mode) {
843
0
            extra_rd = rd_cost->rdcost * energy_diff;
844
0
          } else {
845
0
            extra_rd = (rd_cost->rdcost * energy_diff) / 4;
846
0
          }
847
0
        } else if (has_second_ref(mbmi)) {
848
0
          extra_rd = rd_cost->rdcost / 4;
849
0
        }
850
0
        if (extra_rd > 0) {
851
0
          const int64_t extra_dist =
852
0
              (extra_rd + (1 << (RDDIV_BITS - 1))) >> RDDIV_BITS;
853
0
          rd_cost->dist += extra_dist;
854
0
          rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
855
0
        }
856
0
      }
857
0
    }
858
859
0
    return;
860
0
  }
861
0
#endif
862
863
0
  if (cpi->oxcf.algo_cfg.sharpness != 3) return;
864
865
0
  if (frame_is_kf_gf_arf(cpi)) return;
866
867
0
  int64_t src_var, rec_var;
868
0
  av1_get_variance_stats(x, &src_var, &rec_var);
869
870
0
  if (src_var <= rec_var) return;
871
872
0
  int64_t var_offset = src_var - rec_var;
873
874
0
  rd_cost->dist += var_offset;
875
876
0
  rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
877
0
}
878
879
static void adjust_cost(const AV1_COMP *cpi, const MACROBLOCK *x,
880
0
                        int64_t *rd_cost, bool is_inter_pred) {
881
0
  if ((cpi->oxcf.tune_cfg.tuning == AOM_TUNE_IQ ||
882
0
       cpi->oxcf.tune_cfg.tuning == AOM_TUNE_SSIMULACRA2) &&
883
0
      is_inter_pred) {
884
0
    *rd_cost += *rd_cost >> 3;
885
0
    return;
886
0
  }
887
888
0
#if CONFIG_AV1_HIGHBITDEPTH
889
0
  const MACROBLOCKD *xd = &x->e_mbd;
890
0
  if (xd->bd > 8 && cpi->oxcf.algo_cfg.sharpness == 3) {
891
0
    if (frame_is_intra_only(&cpi->common)) return;
892
893
0
    int64_t src_var, rec_var;
894
0
    av1_get_variance_stats(x, &src_var, &rec_var);
895
896
0
    int64_t var_offset = (src_var > rec_var) ? (src_var - rec_var) : 0;
897
898
0
    const MB_MODE_INFO *mbmi = xd->mi[0];
899
0
    const int is_smooth_intra_mode =
900
0
        (mbmi->mode == DC_PRED || mbmi->mode == SMOOTH_PRED ||
901
0
         mbmi->mode == SMOOTH_V_PRED || mbmi->mode == SMOOTH_H_PRED ||
902
0
         mbmi->mode == PAETH_PRED);
903
904
0
    const int is_skip_txfm = mbmi->skip_txfm;
905
0
    const int num_pixels =
906
0
        block_size_wide[mbmi->bsize] * block_size_high[mbmi->bsize];
907
0
    const int64_t src_var_per_px = src_var / num_pixels;
908
909
0
    if (var_offset > 0 &&
910
0
        ((is_skip_txfm && src_var_per_px < 64) || is_smooth_intra_mode ||
911
0
         is_interintra_mode(mbmi) || has_second_ref(mbmi))) {
912
0
      var_offset *= 4;
913
0
    }
914
915
0
    if (is_inter_pred && !has_second_ref(mbmi)) {
916
0
      const int mv_mag =
917
0
          abs(mbmi->mv[0].as_mv.row) + abs(mbmi->mv[0].as_mv.col);
918
0
      if (mv_mag > 0 && src_var_per_px < 64) {
919
0
        var_offset += (int64_t)mv_mag * (64 - src_var_per_px);
920
0
      }
921
0
    }
922
923
0
    if (var_offset > 0) {
924
0
      *rd_cost += RDCOST(x->rdmult, 0, var_offset);
925
0
    }
926
927
    // Sub-block local variance energy disparity adjustment
928
0
    if (mbmi->bsize >= BLOCK_16X16) {
929
0
      const int energy_diff = get_sub_block_energy_diff(cpi, x, mbmi->bsize);
930
0
      if (energy_diff > 0) {
931
0
        if (!is_inter_pred) {
932
0
          if (mbmi->mode == DC_PRED || is_smooth_intra_mode) {
933
0
            *rd_cost += *rd_cost * energy_diff;
934
0
          } else {
935
0
            *rd_cost += (*rd_cost * energy_diff) / 4;
936
0
          }
937
0
        } else if (has_second_ref(mbmi)) {
938
0
          *rd_cost += *rd_cost / 4;
939
0
        }
940
0
      }
941
0
    }
942
0
    return;
943
0
  }
944
0
#endif
945
946
0
  if (cpi->oxcf.algo_cfg.sharpness != 3) return;
947
948
0
  if (frame_is_kf_gf_arf(cpi)) return;
949
950
0
  int64_t src_var, rec_var;
951
0
  av1_get_variance_stats(x, &src_var, &rec_var);
952
953
0
  if (src_var <= rec_var) return;
954
955
0
  int64_t var_offset = src_var - rec_var;
956
957
0
  *rd_cost += RDCOST(x->rdmult, 0, var_offset);
958
0
}
959
960
static int64_t get_sse(const AV1_COMP *cpi, const MACROBLOCK *x,
961
0
                       int64_t *sse_y) {
962
0
  const AV1_COMMON *cm = &cpi->common;
963
0
  const int num_planes = av1_num_planes(cm);
964
0
  const MACROBLOCKD *xd = &x->e_mbd;
965
0
  const MB_MODE_INFO *mbmi = xd->mi[0];
966
0
  int64_t total_sse = 0;
967
0
  for (int plane = 0; plane < num_planes; ++plane) {
968
0
    if (plane && !xd->is_chroma_ref) break;
969
0
    const struct macroblock_plane *const p = &x->plane[plane];
970
0
    const struct macroblockd_plane *const pd = &xd->plane[plane];
971
0
    const BLOCK_SIZE bs =
972
0
        get_plane_block_size(mbmi->bsize, pd->subsampling_x, pd->subsampling_y);
973
0
    unsigned int sse;
974
0
    int bw, bh;
975
0
    const int block_width = block_size_wide[bs];
976
0
    const int block_height = block_size_high[bs];
977
978
0
    get_visible_dimensions(x, plane, bs, 0, 0, block_width, block_height,
979
0
                           cpi->do_border_pad, &bw, &bh);
980
981
0
    sse = pixel_dist_visible_only(cpi, x, p->src.buf, p->src.stride,
982
0
                                  pd->dst.buf, pd->dst.stride, bs, block_height,
983
0
                                  block_width, bh, bw);
984
0
    total_sse += sse;
985
0
    if (!plane && sse_y) *sse_y = sse;
986
0
  }
987
0
  total_sse <<= 4;
988
0
  return total_sse;
989
0
}
990
991
int64_t av1_block_error_c(const tran_low_t *coeff, const tran_low_t *dqcoeff,
992
0
                          intptr_t block_size, int64_t *ssz) {
993
0
  int i;
994
0
  int64_t error = 0, sqcoeff = 0;
995
996
0
  for (i = 0; i < block_size; i++) {
997
0
    const int diff = coeff[i] - dqcoeff[i];
998
0
    error += diff * diff;
999
0
    sqcoeff += coeff[i] * coeff[i];
1000
0
  }
1001
1002
0
  *ssz = sqcoeff;
1003
0
  return error;
1004
0
}
1005
1006
int64_t av1_block_error_lp_c(const int16_t *coeff, const int16_t *dqcoeff,
1007
0
                             intptr_t block_size) {
1008
0
  int64_t error = 0;
1009
1010
0
  for (int i = 0; i < block_size; i++) {
1011
0
    const int diff = coeff[i] - dqcoeff[i];
1012
0
    error += diff * diff;
1013
0
  }
1014
1015
0
  return error;
1016
0
}
1017
1018
#if CONFIG_AV1_HIGHBITDEPTH
1019
int64_t av1_highbd_block_error_c(const tran_low_t *coeff,
1020
                                 const tran_low_t *dqcoeff, intptr_t block_size,
1021
0
                                 int64_t *ssz, int bd) {
1022
0
  int i;
1023
0
  int64_t error = 0, sqcoeff = 0;
1024
0
  int shift = 2 * (bd - 8);
1025
0
  int rounding = (1 << shift) >> 1;
1026
1027
0
  for (i = 0; i < block_size; i++) {
1028
0
    const int64_t diff = coeff[i] - dqcoeff[i];
1029
0
    error += diff * diff;
1030
0
    sqcoeff += (int64_t)coeff[i] * (int64_t)coeff[i];
1031
0
  }
1032
0
  error = (error + rounding) >> shift;
1033
0
  sqcoeff = (sqcoeff + rounding) >> shift;
1034
1035
0
  *ssz = sqcoeff;
1036
0
  return error;
1037
0
}
1038
#endif
1039
1040
static int conditional_skipintra(PREDICTION_MODE mode,
1041
0
                                 PREDICTION_MODE best_intra_mode) {
1042
0
  if (mode == D113_PRED && best_intra_mode != V_PRED &&
1043
0
      best_intra_mode != D135_PRED)
1044
0
    return 1;
1045
0
  if (mode == D67_PRED && best_intra_mode != V_PRED &&
1046
0
      best_intra_mode != D45_PRED)
1047
0
    return 1;
1048
0
  if (mode == D203_PRED && best_intra_mode != H_PRED &&
1049
0
      best_intra_mode != D45_PRED)
1050
0
    return 1;
1051
0
  if (mode == D157_PRED && best_intra_mode != H_PRED &&
1052
0
      best_intra_mode != D135_PRED)
1053
0
    return 1;
1054
0
  return 0;
1055
0
}
1056
1057
static int cost_mv_ref(const ModeCosts *const mode_costs, PREDICTION_MODE mode,
1058
0
                       int16_t mode_context) {
1059
0
  if (is_inter_compound_mode(mode)) {
1060
0
    return mode_costs
1061
0
        ->inter_compound_mode_cost[mode_context][INTER_COMPOUND_OFFSET(mode)];
1062
0
  }
1063
1064
0
  int mode_cost = 0;
1065
0
  int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
1066
1067
0
  assert(is_inter_mode(mode));
1068
1069
0
  if (mode == NEWMV) {
1070
0
    mode_cost = mode_costs->newmv_mode_cost[mode_ctx][0];
1071
0
    return mode_cost;
1072
0
  } else {
1073
0
    mode_cost = mode_costs->newmv_mode_cost[mode_ctx][1];
1074
0
    mode_ctx = (mode_context >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
1075
1076
0
    if (mode == GLOBALMV) {
1077
0
      mode_cost += mode_costs->zeromv_mode_cost[mode_ctx][0];
1078
0
      return mode_cost;
1079
0
    } else {
1080
0
      mode_cost += mode_costs->zeromv_mode_cost[mode_ctx][1];
1081
0
      mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
1082
0
      mode_cost += mode_costs->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
1083
0
      return mode_cost;
1084
0
    }
1085
0
  }
1086
0
}
1087
1088
static inline PREDICTION_MODE get_single_mode(PREDICTION_MODE this_mode,
1089
0
                                              int ref_idx) {
1090
0
  return ref_idx ? compound_ref1_mode(this_mode)
1091
0
                 : compound_ref0_mode(this_mode);
1092
0
}
1093
1094
static inline void estimate_ref_frame_costs(
1095
    const AV1_COMMON *cm, const MACROBLOCKD *xd, const ModeCosts *mode_costs,
1096
    int segment_id, unsigned int *ref_costs_single,
1097
0
    unsigned int (*ref_costs_comp)[REF_FRAMES]) {
1098
0
  int seg_ref_active =
1099
0
      segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
1100
0
  if (seg_ref_active) {
1101
0
    memset(ref_costs_single, 0, REF_FRAMES * sizeof(*ref_costs_single));
1102
0
    int ref_frame;
1103
0
    for (ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame)
1104
0
      memset(ref_costs_comp[ref_frame], 0,
1105
0
             REF_FRAMES * sizeof((*ref_costs_comp)[0]));
1106
0
  } else {
1107
0
    int intra_inter_ctx = av1_get_intra_inter_context(xd);
1108
0
    ref_costs_single[INTRA_FRAME] =
1109
0
        mode_costs->intra_inter_cost[intra_inter_ctx][0];
1110
0
    unsigned int base_cost = mode_costs->intra_inter_cost[intra_inter_ctx][1];
1111
1112
0
    for (int i = LAST_FRAME; i <= ALTREF_FRAME; ++i)
1113
0
      ref_costs_single[i] = base_cost;
1114
1115
0
    const int ctx_p1 = av1_get_pred_context_single_ref_p1(xd);
1116
0
    const int ctx_p2 = av1_get_pred_context_single_ref_p2(xd);
1117
0
    const int ctx_p3 = av1_get_pred_context_single_ref_p3(xd);
1118
0
    const int ctx_p4 = av1_get_pred_context_single_ref_p4(xd);
1119
0
    const int ctx_p5 = av1_get_pred_context_single_ref_p5(xd);
1120
0
    const int ctx_p6 = av1_get_pred_context_single_ref_p6(xd);
1121
1122
    // Determine cost of a single ref frame, where frame types are represented
1123
    // by a tree:
1124
    // Level 0: add cost whether this ref is a forward or backward ref
1125
0
    ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
1126
0
    ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
1127
0
    ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
1128
0
    ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
1129
0
    ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][1];
1130
0
    ref_costs_single[ALTREF2_FRAME] +=
1131
0
        mode_costs->single_ref_cost[ctx_p1][0][1];
1132
0
    ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][1];
1133
1134
    // Level 1: if this ref is forward ref,
1135
    // add cost whether it is last/last2 or last3/golden
1136
0
    ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][0];
1137
0
    ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][0];
1138
0
    ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][1];
1139
0
    ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][1];
1140
1141
    // Level 1: if this ref is backward ref
1142
    // then add cost whether this ref is altref or backward ref
1143
0
    ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p2][1][0];
1144
0
    ref_costs_single[ALTREF2_FRAME] +=
1145
0
        mode_costs->single_ref_cost[ctx_p2][1][0];
1146
0
    ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[ctx_p2][1][1];
1147
1148
    // Level 2: further add cost whether this ref is last or last2
1149
0
    ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p4][3][0];
1150
0
    ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p4][3][1];
1151
1152
    // Level 2: last3 or golden
1153
0
    ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p5][4][0];
1154
0
    ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p5][4][1];
1155
1156
    // Level 2: bwdref or altref2
1157
0
    ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p6][5][0];
1158
0
    ref_costs_single[ALTREF2_FRAME] +=
1159
0
        mode_costs->single_ref_cost[ctx_p6][5][1];
1160
1161
0
    if (cm->current_frame.reference_mode != SINGLE_REFERENCE) {
1162
      // Similar to single ref, determine cost of compound ref frames.
1163
      // cost_compound_refs = cost_first_ref + cost_second_ref
1164
0
      const int bwdref_comp_ctx_p = av1_get_pred_context_comp_bwdref_p(xd);
1165
0
      const int bwdref_comp_ctx_p1 = av1_get_pred_context_comp_bwdref_p1(xd);
1166
0
      const int ref_comp_ctx_p = av1_get_pred_context_comp_ref_p(xd);
1167
0
      const int ref_comp_ctx_p1 = av1_get_pred_context_comp_ref_p1(xd);
1168
0
      const int ref_comp_ctx_p2 = av1_get_pred_context_comp_ref_p2(xd);
1169
1170
0
      const int comp_ref_type_ctx = av1_get_comp_reference_type_context(xd);
1171
0
      unsigned int ref_bicomp_costs[REF_FRAMES] = { 0 };
1172
1173
0
      ref_bicomp_costs[LAST_FRAME] = ref_bicomp_costs[LAST2_FRAME] =
1174
0
          ref_bicomp_costs[LAST3_FRAME] = ref_bicomp_costs[GOLDEN_FRAME] =
1175
0
              base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][1];
1176
0
      ref_bicomp_costs[BWDREF_FRAME] = ref_bicomp_costs[ALTREF2_FRAME] = 0;
1177
0
      ref_bicomp_costs[ALTREF_FRAME] = 0;
1178
1179
      // cost of first ref frame
1180
0
      ref_bicomp_costs[LAST_FRAME] +=
1181
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p][0][0];
1182
0
      ref_bicomp_costs[LAST2_FRAME] +=
1183
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p][0][0];
1184
0
      ref_bicomp_costs[LAST3_FRAME] +=
1185
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p][0][1];
1186
0
      ref_bicomp_costs[GOLDEN_FRAME] +=
1187
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p][0][1];
1188
1189
0
      ref_bicomp_costs[LAST_FRAME] +=
1190
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p1][1][0];
1191
0
      ref_bicomp_costs[LAST2_FRAME] +=
1192
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p1][1][1];
1193
1194
0
      ref_bicomp_costs[LAST3_FRAME] +=
1195
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p2][2][0];
1196
0
      ref_bicomp_costs[GOLDEN_FRAME] +=
1197
0
          mode_costs->comp_ref_cost[ref_comp_ctx_p2][2][1];
1198
1199
      // cost of second ref frame
1200
0
      ref_bicomp_costs[BWDREF_FRAME] +=
1201
0
          mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p][0][0];
1202
0
      ref_bicomp_costs[ALTREF2_FRAME] +=
1203
0
          mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p][0][0];
1204
0
      ref_bicomp_costs[ALTREF_FRAME] +=
1205
0
          mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p][0][1];
1206
1207
0
      ref_bicomp_costs[BWDREF_FRAME] +=
1208
0
          mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p1][1][0];
1209
0
      ref_bicomp_costs[ALTREF2_FRAME] +=
1210
0
          mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p1][1][1];
1211
1212
      // cost: if one ref frame is forward ref, the other ref is backward ref
1213
0
      int ref0, ref1;
1214
0
      for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
1215
0
        for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1) {
1216
0
          ref_costs_comp[ref0][ref1] =
1217
0
              ref_bicomp_costs[ref0] + ref_bicomp_costs[ref1];
1218
0
        }
1219
0
      }
1220
1221
      // cost: if both ref frames are the same side.
1222
0
      const int uni_comp_ref_ctx_p = av1_get_pred_context_uni_comp_ref_p(xd);
1223
0
      const int uni_comp_ref_ctx_p1 = av1_get_pred_context_uni_comp_ref_p1(xd);
1224
0
      const int uni_comp_ref_ctx_p2 = av1_get_pred_context_uni_comp_ref_p2(xd);
1225
0
      ref_costs_comp[LAST_FRAME][LAST2_FRAME] =
1226
0
          base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
1227
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
1228
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][0];
1229
0
      ref_costs_comp[LAST_FRAME][LAST3_FRAME] =
1230
0
          base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
1231
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
1232
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][1] +
1233
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p2][2][0];
1234
0
      ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] =
1235
0
          base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
1236
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
1237
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][1] +
1238
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p2][2][1];
1239
0
      ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] =
1240
0
          base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
1241
0
          mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][1];
1242
0
    } else {
1243
0
      int ref0, ref1;
1244
0
      for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
1245
0
        for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1)
1246
0
          ref_costs_comp[ref0][ref1] = 512;
1247
0
      }
1248
0
      ref_costs_comp[LAST_FRAME][LAST2_FRAME] = 512;
1249
0
      ref_costs_comp[LAST_FRAME][LAST3_FRAME] = 512;
1250
0
      ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] = 512;
1251
0
      ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] = 512;
1252
0
    }
1253
0
  }
1254
0
}
1255
1256
static inline void store_coding_context(
1257
#if CONFIG_INTERNAL_STATS
1258
    MACROBLOCK *x, PICK_MODE_CONTEXT *ctx, int mode_index,
1259
#else
1260
    MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
1261
#endif  // CONFIG_INTERNAL_STATS
1262
0
    int skippable) {
1263
0
  MACROBLOCKD *const xd = &x->e_mbd;
1264
1265
  // Take a snapshot of the coding context so it can be
1266
  // restored if we decide to encode this way
1267
0
  ctx->rd_stats.skip_txfm = x->txfm_search_info.skip_txfm;
1268
0
  ctx->skippable = skippable;
1269
#if CONFIG_INTERNAL_STATS
1270
  ctx->best_mode_index = mode_index;
1271
#endif  // CONFIG_INTERNAL_STATS
1272
0
  ctx->mic = *xd->mi[0];
1273
0
  av1_copy_mbmi_ext_to_mbmi_ext_frame(&ctx->mbmi_ext_best, &x->mbmi_ext,
1274
0
                                      av1_ref_frame_type(xd->mi[0]->ref_frame));
1275
0
}
1276
1277
static inline void setup_buffer_ref_mvs_inter(
1278
    const AV1_COMP *const cpi, MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame,
1279
0
    BLOCK_SIZE block_size, struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
1280
0
  const AV1_COMMON *cm = &cpi->common;
1281
0
  const int num_planes = av1_num_planes(cm);
1282
0
  const YV12_BUFFER_CONFIG *scaled_ref_frame =
1283
0
      av1_get_scaled_ref_frame(cpi, ref_frame);
1284
0
  MACROBLOCKD *const xd = &x->e_mbd;
1285
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
1286
0
  MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
1287
0
  const struct scale_factors *const sf =
1288
0
      get_ref_scale_factors_const(cm, ref_frame);
1289
0
  const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_yv12_buf(cm, ref_frame);
1290
0
  assert(yv12 != NULL);
1291
1292
0
  if (scaled_ref_frame) {
1293
    // Setup pred block based on scaled reference, because av1_mv_pred() doesn't
1294
    // support scaling.
1295
0
    av1_setup_pred_block(xd, yv12_mb[ref_frame], scaled_ref_frame, NULL, NULL,
1296
0
                         num_planes);
1297
0
  } else {
1298
0
    av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
1299
0
  }
1300
1301
  // Gets an initial list of candidate vectors from neighbours and orders them
1302
0
  av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
1303
0
                   xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
1304
0
                   mbmi_ext->mode_context);
1305
  // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
1306
  // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
1307
0
  av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
1308
  // Further refinement that is encode side only to test the top few candidates
1309
  // in full and choose the best as the center point for subsequent searches.
1310
  // The current implementation doesn't support scaling.
1311
0
  av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12_mb[ref_frame][0].stride,
1312
0
              ref_frame, block_size);
1313
1314
  // Go back to unscaled reference.
1315
0
  if (scaled_ref_frame) {
1316
    // We had temporarily setup pred block based on scaled reference above. Go
1317
    // back to unscaled reference now, for subsequent use.
1318
0
    av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
1319
0
  }
1320
0
}
1321
1322
0
#define LEFT_TOP_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
1323
0
#define RIGHT_BOTTOM_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
1324
1325
// TODO(jingning): this mv clamping function should be block size dependent.
1326
0
static inline void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
1327
0
  const SubpelMvLimits mv_limits = { xd->mb_to_left_edge - LEFT_TOP_MARGIN,
1328
0
                                     xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
1329
0
                                     xd->mb_to_top_edge - LEFT_TOP_MARGIN,
1330
0
                                     xd->mb_to_bottom_edge +
1331
0
                                         RIGHT_BOTTOM_MARGIN };
1332
0
  clamp_mv(mv, &mv_limits);
1333
0
}
1334
1335
/* If the current mode shares the same mv with other modes with higher cost,
1336
 * skip this mode. */
1337
static AOM_FORCE_INLINE int skip_repeated_mv(
1338
    const AV1_COMMON *const cm, const MACROBLOCK *const x,
1339
    PREDICTION_MODE this_mode, const MV_REFERENCE_FRAME ref_frames[2],
1340
0
    InterModeSearchState *search_state) {
1341
0
  const int is_comp_pred = ref_frames[1] > INTRA_FRAME;
1342
0
  const uint8_t ref_frame_type = av1_ref_frame_type(ref_frames);
1343
0
  const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
1344
0
  const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
1345
0
  PREDICTION_MODE compare_mode = MB_MODE_COUNT;
1346
0
  if (!is_comp_pred) {
1347
0
    if (this_mode == NEARMV) {
1348
0
      if (ref_mv_count == 0) {
1349
        // NEARMV has the same motion vector as NEARESTMV
1350
0
        compare_mode = NEARESTMV;
1351
0
      }
1352
0
      if (ref_mv_count == 1 &&
1353
0
          cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) {
1354
        // NEARMV has the same motion vector as GLOBALMV
1355
0
        compare_mode = GLOBALMV;
1356
0
      }
1357
0
    }
1358
0
    if (this_mode == GLOBALMV) {
1359
0
      if (ref_mv_count == 0 &&
1360
0
          cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) {
1361
        // GLOBALMV has the same motion vector as NEARESTMV
1362
0
        compare_mode = NEARESTMV;
1363
0
      }
1364
0
      if (ref_mv_count == 1) {
1365
        // GLOBALMV has the same motion vector as NEARMV
1366
0
        compare_mode = NEARMV;
1367
0
      }
1368
0
    }
1369
1370
0
    if (compare_mode != MB_MODE_COUNT) {
1371
      // Use modelled_rd to check whether compare mode was searched
1372
0
      if (search_state->modelled_rd[compare_mode][0][ref_frames[0]] !=
1373
0
          INT64_MAX) {
1374
0
        const int16_t mode_ctx =
1375
0
            av1_mode_context_analyzer(mbmi_ext->mode_context, ref_frames);
1376
0
        const int compare_cost =
1377
0
            cost_mv_ref(&x->mode_costs, compare_mode, mode_ctx);
1378
0
        const int this_cost = cost_mv_ref(&x->mode_costs, this_mode, mode_ctx);
1379
1380
        // Only skip if the mode cost is larger than compare mode cost
1381
0
        if (this_cost > compare_cost) {
1382
0
          search_state->modelled_rd[this_mode][0][ref_frames[0]] =
1383
0
              search_state->modelled_rd[compare_mode][0][ref_frames[0]];
1384
0
          return 1;
1385
0
        }
1386
0
      }
1387
0
    }
1388
0
  }
1389
0
  return 0;
1390
0
}
1391
1392
static inline int clamp_and_check_mv(int_mv *out_mv, int_mv in_mv,
1393
                                     const AV1_COMMON *cm,
1394
0
                                     const MACROBLOCK *x) {
1395
0
  const MACROBLOCKD *const xd = &x->e_mbd;
1396
0
  *out_mv = in_mv;
1397
0
  lower_mv_precision(&out_mv->as_mv, cm->features.allow_high_precision_mv,
1398
0
                     cm->features.cur_frame_force_integer_mv);
1399
0
  clamp_mv2(&out_mv->as_mv, xd);
1400
0
  return av1_is_fullmv_in_range(&x->mv_limits,
1401
0
                                get_fullmv_from_mv(&out_mv->as_mv));
1402
0
}
1403
1404
// To use single newmv directly for compound modes, need to clamp the mv to the
1405
// valid mv range. Without this, encoder would generate out of range mv, and
1406
// this is seen in 8k encoding.
1407
static inline void clamp_mv_in_range(MACROBLOCK *const x, int_mv *mv,
1408
0
                                     int ref_idx) {
1409
0
  const int_mv ref_mv = av1_get_ref_mv(x, ref_idx);
1410
0
  SubpelMvLimits mv_limits;
1411
1412
0
  av1_set_subpel_mv_search_range(&mv_limits, &x->mv_limits, &ref_mv.as_mv);
1413
0
  clamp_mv(&mv->as_mv, &mv_limits);
1414
0
}
1415
1416
static int64_t handle_newmv(const AV1_COMP *const cpi, MACROBLOCK *const x,
1417
                            const BLOCK_SIZE bsize, int_mv *cur_mv,
1418
                            int *const rate_mv, HandleInterModeArgs *const args,
1419
0
                            inter_mode_info *mode_info) {
1420
0
  MACROBLOCKD *const xd = &x->e_mbd;
1421
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
1422
0
  const int is_comp_pred = has_second_ref(mbmi);
1423
0
  const PREDICTION_MODE this_mode = mbmi->mode;
1424
0
  const int refs[2] = { mbmi->ref_frame[0],
1425
0
                        mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
1426
0
  const int ref_mv_idx = mbmi->ref_mv_idx;
1427
1428
0
  if (is_comp_pred) {
1429
0
    const int valid_mv0 = args->single_newmv_valid[ref_mv_idx][refs[0]];
1430
0
    const int valid_mv1 = args->single_newmv_valid[ref_mv_idx][refs[1]];
1431
0
    if (this_mode == NEW_NEWMV) {
1432
0
      if (valid_mv0) {
1433
0
        cur_mv[0].as_int = args->single_newmv[ref_mv_idx][refs[0]].as_int;
1434
0
        clamp_mv_in_range(x, &cur_mv[0], 0);
1435
0
      }
1436
0
      if (valid_mv1) {
1437
0
        cur_mv[1].as_int = args->single_newmv[ref_mv_idx][refs[1]].as_int;
1438
0
        clamp_mv_in_range(x, &cur_mv[1], 1);
1439
0
      }
1440
0
      *rate_mv = 0;
1441
0
      for (int i = 0; i < 2; ++i) {
1442
0
        const int_mv ref_mv = av1_get_ref_mv(x, i);
1443
0
        *rate_mv += av1_mv_bit_cost(&cur_mv[i].as_mv, &ref_mv.as_mv,
1444
0
                                    x->mv_costs->nmv_joint_cost,
1445
0
                                    x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1446
0
      }
1447
0
    } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
1448
0
      if (valid_mv1) {
1449
0
        cur_mv[1].as_int = args->single_newmv[ref_mv_idx][refs[1]].as_int;
1450
0
        clamp_mv_in_range(x, &cur_mv[1], 1);
1451
0
      }
1452
0
      const int_mv ref_mv = av1_get_ref_mv(x, 1);
1453
0
      *rate_mv = av1_mv_bit_cost(&cur_mv[1].as_mv, &ref_mv.as_mv,
1454
0
                                 x->mv_costs->nmv_joint_cost,
1455
0
                                 x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1456
0
    } else {
1457
0
      assert(this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV);
1458
0
      if (valid_mv0) {
1459
0
        cur_mv[0].as_int = args->single_newmv[ref_mv_idx][refs[0]].as_int;
1460
0
        clamp_mv_in_range(x, &cur_mv[0], 0);
1461
0
      }
1462
0
      const int_mv ref_mv = av1_get_ref_mv(x, 0);
1463
0
      *rate_mv = av1_mv_bit_cost(&cur_mv[0].as_mv, &ref_mv.as_mv,
1464
0
                                 x->mv_costs->nmv_joint_cost,
1465
0
                                 x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1466
0
    }
1467
0
  } else {
1468
    // Single ref case.
1469
0
    const int ref_idx = 0;
1470
0
    int search_range = INT_MAX;
1471
1472
0
    if (cpi->sf.mv_sf.reduce_search_range && mbmi->ref_mv_idx > 0) {
1473
0
      const MV ref_mv = av1_get_ref_mv(x, ref_idx).as_mv;
1474
0
      int min_mv_diff = INT_MAX;
1475
0
      int best_match = -1;
1476
0
      MV prev_ref_mv[2] = { { 0 } };
1477
0
      for (int idx = 0; idx < mbmi->ref_mv_idx; ++idx) {
1478
0
        prev_ref_mv[idx] = av1_get_ref_mv_from_stack(ref_idx, mbmi->ref_frame,
1479
0
                                                     idx, &x->mbmi_ext)
1480
0
                               .as_mv;
1481
0
        const int ref_mv_diff = AOMMAX(abs(ref_mv.row - prev_ref_mv[idx].row),
1482
0
                                       abs(ref_mv.col - prev_ref_mv[idx].col));
1483
1484
0
        if (min_mv_diff > ref_mv_diff) {
1485
0
          min_mv_diff = ref_mv_diff;
1486
0
          best_match = idx;
1487
0
        }
1488
0
      }
1489
1490
0
      if (min_mv_diff < (16 << 3)) {
1491
0
        if (args->single_newmv_valid[best_match][refs[0]]) {
1492
0
          search_range = min_mv_diff;
1493
0
          search_range +=
1494
0
              AOMMAX(abs(args->single_newmv[best_match][refs[0]].as_mv.row -
1495
0
                         prev_ref_mv[best_match].row),
1496
0
                     abs(args->single_newmv[best_match][refs[0]].as_mv.col -
1497
0
                         prev_ref_mv[best_match].col));
1498
          // Get full pixel search range.
1499
0
          search_range = (search_range + 4) >> 3;
1500
0
        }
1501
0
      }
1502
0
    }
1503
1504
0
    int_mv best_mv;
1505
0
    av1_single_motion_search(cpi, x, bsize, ref_idx, rate_mv, search_range,
1506
0
                             mode_info, &best_mv, args);
1507
0
    if (best_mv.as_int == INVALID_MV) return INT64_MAX;
1508
1509
0
    args->single_newmv[ref_mv_idx][refs[0]] = best_mv;
1510
0
    args->single_newmv_rate[ref_mv_idx][refs[0]] = *rate_mv;
1511
0
    args->single_newmv_valid[ref_mv_idx][refs[0]] = 1;
1512
0
    cur_mv[0].as_int = best_mv.as_int;
1513
1514
    // Return after single_newmv is set.
1515
0
    if (mode_info[mbmi->ref_mv_idx].skip) return INT64_MAX;
1516
0
  }
1517
1518
0
  return 0;
1519
0
}
1520
1521
static inline void update_mode_start_end_index(
1522
    const AV1_COMP *const cpi, const MB_MODE_INFO *const mbmi,
1523
    int *mode_index_start, int *mode_index_end, int last_motion_mode_allowed,
1524
0
    int interintra_allowed, int eval_motion_mode) {
1525
0
  *mode_index_start = (int)SIMPLE_TRANSLATION;
1526
0
  *mode_index_end = (int)last_motion_mode_allowed + interintra_allowed;
1527
0
  if (cpi->sf.winner_mode_sf.motion_mode_for_winner_cand) {
1528
0
    if (!eval_motion_mode) {
1529
0
      *mode_index_end = (int)SIMPLE_TRANSLATION;
1530
0
    } else {
1531
      // Set the start index appropriately to process motion modes other than
1532
      // simple translation
1533
0
      *mode_index_start = 1;
1534
0
    }
1535
0
  }
1536
0
  if (cpi->sf.inter_sf.extra_prune_warped && mbmi->bsize > BLOCK_16X16)
1537
0
    *mode_index_end = SIMPLE_TRANSLATION;
1538
0
}
1539
1540
// Scale rate, dist and sse of RD_STATS as per the given bias percentage
1541
0
static inline void scale_rdstats(RD_STATS *rd_stats, double rd_scale_pct) {
1542
0
  if (rd_stats == NULL) return;
1543
0
  rd_stats->rate += (int)(rd_scale_pct * rd_stats->rate + 0.5);
1544
0
  rd_stats->dist += (int64_t)(rd_scale_pct * rd_stats->dist + 0.5);
1545
0
  rd_stats->sse += (int64_t)(rd_scale_pct * rd_stats->sse + 0.5);
1546
0
  rd_stats->zero_rate += (int)(rd_scale_pct * rd_stats->zero_rate + 0.5);
1547
0
}
1548
1549
// Increase rate, distortion and SSE in RD_STATS structure of warp and obmc
1550
// motion modes for low complexity decoding.
1551
static inline void increase_motion_mode_rdstats(const AV1_COMP *cpi,
1552
                                                const MB_MODE_INFO *this_mbmi,
1553
                                                RD_STATS *rd_stats,
1554
                                                RD_STATS *rd_stats_y,
1555
0
                                                RD_STATS *rd_stats_uv) {
1556
0
  if (rd_stats->rate == INT_MAX ||
1557
0
      (rd_stats_y != NULL && rd_stats_y->rate == INT_MAX) ||
1558
0
      (rd_stats_uv != NULL && rd_stats_uv->rate == INT_MAX))
1559
0
    return;
1560
0
  const INTER_MODE_SPEED_FEATURES *const inter_sf = &cpi->sf.inter_sf;
1561
0
  double rd_bias_scale = 0.0;
1562
0
  if (this_mbmi->motion_mode == WARPED_CAUSAL) {
1563
0
    rd_bias_scale = inter_sf->bias_warp_mode_rd_scale_pct / 100.0;
1564
0
  } else if (this_mbmi->motion_mode == OBMC_CAUSAL) {
1565
0
    rd_bias_scale = inter_sf->bias_obmc_mode_rd_scale_pct / 100.0;
1566
0
  } else if (this_mbmi->mode == GLOBALMV ||
1567
0
             this_mbmi->mode == GLOBAL_GLOBALMV) {
1568
0
    rd_bias_scale = get_global_mv_mode_bias(cpi, this_mbmi);
1569
0
  }
1570
0
  if (rd_bias_scale <= 0.0) return;
1571
1572
0
  scale_rdstats(rd_stats, rd_bias_scale);
1573
0
  scale_rdstats(rd_stats_y, rd_bias_scale);
1574
0
  scale_rdstats(rd_stats_uv, rd_bias_scale);
1575
0
}
1576
1577
/*!\brief AV1 motion mode search
1578
 *
1579
 * \ingroup inter_mode_search
1580
 * Function to search over and determine the motion mode. It will update
1581
 * mbmi->motion_mode to one of SIMPLE_TRANSLATION, OBMC_CAUSAL, or
1582
 * WARPED_CAUSAL and determine any necessary side information for the selected
1583
 * motion mode. It will also perform the full transform search, unless the
1584
 * input parameter do_tx_search indicates to do an estimation of the RD rather
1585
 * than an RD corresponding to a full transform search. It will return the
1586
 * RD for the final motion_mode.
1587
 * Do the RD search for a given inter mode and compute all information relevant
1588
 * to the input mode. It will compute the best MV,
1589
 * compound parameters (if the mode is a compound mode) and interpolation filter
1590
 * parameters.
1591
 *
1592
 * \param[in]     cpi               Top-level encoder structure.
1593
 * \param[in]     tile_data         Pointer to struct holding adaptive
1594
 *                                  data/contexts/models for the tile during
1595
 *                                  encoding.
1596
 * \param[in]     x                 Pointer to struct holding all the data for
1597
 *                                  the current macroblock.
1598
 * \param[in]     bsize             Current block size.
1599
 * \param[in,out] rd_stats          Struct to keep track of the overall RD
1600
 *                                  information.
1601
 * \param[in,out] rd_stats_y        Struct to keep track of the RD information
1602
 *                                  for only the Y plane.
1603
 * \param[in,out] rd_stats_uv       Struct to keep track of the RD information
1604
 *                                  for only the UV planes.
1605
 * \param[in]     args              HandleInterModeArgs struct holding
1606
 *                                  miscellaneous arguments for inter mode
1607
 *                                  search. See the documentation for this
1608
 *                                  struct for a description of each member.
1609
 * \param[in]     ref_best_rd       Best RD found so far for this block.
1610
 *                                  It is used for early termination of this
1611
 *                                  search if the RD exceeds this value.
1612
 * \param[in,out] ref_skip_rd       A length 2 array, where skip_rd[0] is the
1613
 *                                  best total RD for a skip mode so far, and
1614
 *                                  skip_rd[1] is the best RD for a skip mode so
1615
 *                                  far in luma. This is used as a speed feature
1616
 *                                  to skip the transform search if the computed
1617
 *                                  skip RD for the current mode is not better
1618
 *                                  than the best skip_rd so far.
1619
 * \param[in,out] rate_mv           The rate associated with the motion vectors.
1620
 *                                  This will be modified if a motion search is
1621
 *                                  done in the motion mode search.
1622
 * \param[in,out] orig_dst          A prediction buffer to hold a computed
1623
 *                                  prediction. This will eventually hold the
1624
 *                                  final prediction, and the tmp_dst info will
1625
 *                                  be copied here.
1626
 * \param[in,out] best_est_rd       Estimated RD for motion mode search if
1627
 *                                  do_tx_search (see below) is 0.
1628
 * \param[in]     do_tx_search      Parameter to indicate whether or not to do
1629
 *                                  a full transform search. This will compute
1630
 *                                  an estimated RD for the modes without the
1631
 *                                  transform search and later perform the full
1632
 *                                  transform search on the best candidates.
1633
 * \param[in]     inter_modes_info  InterModesInfo struct to hold inter mode
1634
 *                                  information to perform a full transform
1635
 *                                  search only on winning candidates searched
1636
 *                                  with an estimate for transform coding RD.
1637
 * \param[in]     eval_motion_mode  Boolean whether or not to evaluate motion
1638
 *                                  motion modes other than SIMPLE_TRANSLATION.
1639
 * \param[out]    yrd               Stores the rdcost corresponding to encoding
1640
 *                                  the luma plane.
1641
 * \return Returns INT64_MAX if the determined motion mode is invalid and the
1642
 * current motion mode being tested should be skipped. It returns 0 if the
1643
 * motion mode search is a success.
1644
 */
1645
static int64_t motion_mode_rd(
1646
    const AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *const x,
1647
    BLOCK_SIZE bsize, RD_STATS *rd_stats, RD_STATS *rd_stats_y,
1648
    RD_STATS *rd_stats_uv, HandleInterModeArgs *const args, int64_t ref_best_rd,
1649
    int64_t *ref_skip_rd, int *rate_mv, const BUFFER_SET *orig_dst,
1650
    int64_t *best_est_rd, int do_tx_search, InterModesInfo *inter_modes_info,
1651
0
    int eval_motion_mode, int64_t *yrd) {
1652
0
  assert(rd_stats != NULL && rd_stats_y != NULL && rd_stats_uv != NULL);
1653
0
  const AV1_COMMON *const cm = &cpi->common;
1654
0
  const FeatureFlags *const features = &cm->features;
1655
0
  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
1656
0
  const int num_planes = av1_num_planes(cm);
1657
0
  MACROBLOCKD *xd = &x->e_mbd;
1658
0
  MB_MODE_INFO *mbmi = xd->mi[0];
1659
0
  const int is_comp_pred = has_second_ref(mbmi);
1660
0
  const PREDICTION_MODE this_mode = mbmi->mode;
1661
0
  const int rate2_nocoeff = rd_stats->rate;
1662
0
  int best_xskip_txfm = 0;
1663
0
  RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
1664
0
  uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
1665
0
  const int rate_mv0 = *rate_mv;
1666
0
  const int interintra_allowed = cm->seq_params->enable_interintra_compound &&
1667
0
                                 is_interintra_allowed(mbmi) &&
1668
0
                                 mbmi->compound_idx;
1669
0
  WARP_SAMPLE_INFO *const warp_sample_info =
1670
0
      &x->warp_sample_info[mbmi->ref_frame[0]];
1671
0
  int *pts0 = warp_sample_info->pts;
1672
0
  int *pts_inref0 = warp_sample_info->pts_inref;
1673
1674
0
  assert(mbmi->ref_frame[1] != INTRA_FRAME);
1675
0
  const MV_REFERENCE_FRAME ref_frame_1 = mbmi->ref_frame[1];
1676
0
  av1_invalid_rd_stats(&best_rd_stats);
1677
0
  mbmi->num_proj_ref = 1;  // assume num_proj_ref >=1
1678
0
  MOTION_MODE last_motion_mode_allowed = SIMPLE_TRANSLATION;
1679
0
  *yrd = INT64_MAX;
1680
0
  if (features->switchable_motion_mode) {
1681
    // Determine which motion modes to search if more than SIMPLE_TRANSLATION
1682
    // is allowed.
1683
0
    last_motion_mode_allowed = motion_mode_allowed(
1684
0
        xd->global_motion, xd, mbmi, features->allow_warped_motion);
1685
0
  }
1686
1687
0
  if (last_motion_mode_allowed == WARPED_CAUSAL) {
1688
    // Collect projection samples used in least squares approximation of
1689
    // the warped motion parameters if WARPED_CAUSAL is going to be searched.
1690
0
    if (warp_sample_info->num < 0) {
1691
0
      warp_sample_info->num = av1_findSamples(cm, xd, pts0, pts_inref0);
1692
0
    }
1693
0
    mbmi->num_proj_ref = warp_sample_info->num;
1694
0
  }
1695
0
  const int total_samples = mbmi->num_proj_ref;
1696
0
  if (total_samples == 0) {
1697
    // Do not search WARPED_CAUSAL if there are no samples to use to determine
1698
    // warped parameters.
1699
0
    last_motion_mode_allowed = OBMC_CAUSAL;
1700
0
  }
1701
1702
0
  const MB_MODE_INFO base_mbmi = *mbmi;
1703
0
  MB_MODE_INFO best_mbmi;
1704
0
  const int interp_filter = features->interp_filter;
1705
0
  const int switchable_rate =
1706
0
      av1_is_interp_needed(xd)
1707
0
          ? av1_get_switchable_rate(x, xd, interp_filter,
1708
0
                                    cm->seq_params->enable_dual_filter)
1709
0
          : 0;
1710
0
  int64_t best_rd = INT64_MAX;
1711
0
  int best_rate_mv = rate_mv0;
1712
0
  const int mi_row = xd->mi_row;
1713
0
  const int mi_col = xd->mi_col;
1714
0
  int mode_index_start, mode_index_end;
1715
0
  const int txfm_rd_gate_level =
1716
0
      get_txfm_rd_gate_level(cm->seq_params->enable_masked_compound,
1717
0
                             cpi->sf.inter_sf.txfm_rd_gate_level, bsize,
1718
0
                             TX_SEARCH_MOTION_MODE, eval_motion_mode);
1719
1720
  // Modify the start and end index according to speed features. For example,
1721
  // if SIMPLE_TRANSLATION has already been searched according to
1722
  // the motion_mode_for_winner_cand speed feature, update the mode_index_start
1723
  // to avoid searching it again.
1724
0
  update_mode_start_end_index(cpi, mbmi, &mode_index_start, &mode_index_end,
1725
0
                              last_motion_mode_allowed, interintra_allowed,
1726
0
                              eval_motion_mode);
1727
  // Main function loop. This loops over all of the possible motion modes and
1728
  // computes RD to determine the best one. This process includes computing
1729
  // any necessary side information for the motion mode and performing the
1730
  // transform search.
1731
0
  for (int mode_index = mode_index_start; mode_index <= mode_index_end;
1732
0
       mode_index++) {
1733
0
    if (args->skip_motion_mode && mode_index) continue;
1734
0
    int tmp_rate2 = rate2_nocoeff;
1735
0
    const int is_interintra_mode = mode_index > (int)last_motion_mode_allowed;
1736
0
    int tmp_rate_mv = rate_mv0;
1737
1738
0
    *mbmi = base_mbmi;
1739
0
    if (is_interintra_mode) {
1740
      // Only use SIMPLE_TRANSLATION for interintra
1741
0
      mbmi->motion_mode = SIMPLE_TRANSLATION;
1742
0
    } else {
1743
0
      mbmi->motion_mode = (MOTION_MODE)mode_index;
1744
0
      assert(mbmi->ref_frame[1] != INTRA_FRAME);
1745
0
    }
1746
1747
0
    if (cpi->oxcf.algo_cfg.sharpness == 3 &&
1748
0
        (mbmi->motion_mode == OBMC_CAUSAL ||
1749
0
         mbmi->motion_mode == WARPED_CAUSAL))
1750
0
      continue;
1751
1752
    // Do not search OBMC if the probability of selecting it is below a
1753
    // predetermined threshold for this update_type and block size.
1754
0
    const FRAME_UPDATE_TYPE update_type =
1755
0
        get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
1756
0
    int use_actual_frame_probs = 1;
1757
0
    int prune_obmc;
1758
#if CONFIG_FPMT_TEST
1759
    use_actual_frame_probs =
1760
        (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) ? 0 : 1;
1761
    if (!use_actual_frame_probs) {
1762
      prune_obmc = cpi->ppi->temp_frame_probs.obmc_probs[update_type][bsize] <
1763
                   cpi->sf.inter_sf.prune_obmc_prob_thresh;
1764
    }
1765
#endif
1766
0
    if (use_actual_frame_probs) {
1767
0
      prune_obmc = cpi->ppi->frame_probs.obmc_probs[update_type][bsize] <
1768
0
                   cpi->sf.inter_sf.prune_obmc_prob_thresh;
1769
0
    }
1770
0
    if ((!cpi->oxcf.motion_mode_cfg.enable_obmc || prune_obmc) &&
1771
0
        mbmi->motion_mode == OBMC_CAUSAL)
1772
0
      continue;
1773
1774
0
    if (mbmi->motion_mode == SIMPLE_TRANSLATION && !is_interintra_mode) {
1775
      // SIMPLE_TRANSLATION mode: no need to recalculate.
1776
      // The prediction is calculated before motion_mode_rd() is called in
1777
      // handle_inter_mode()
1778
0
    } else if (mbmi->motion_mode == OBMC_CAUSAL) {
1779
0
      const uint32_t cur_mv = mbmi->mv[0].as_int;
1780
      // OBMC_CAUSAL not allowed for compound prediction
1781
0
      assert(!is_comp_pred);
1782
0
      if (have_newmv_in_inter_mode(this_mode)) {
1783
0
        av1_single_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, INT_MAX, NULL,
1784
0
                                 &mbmi->mv[0], NULL);
1785
0
        tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
1786
0
      }
1787
0
      if ((mbmi->mv[0].as_int != cur_mv) || eval_motion_mode) {
1788
        // Build the predictor according to the current motion vector if it has
1789
        // not already been built
1790
0
        av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
1791
0
                                      0, av1_num_planes(cm) - 1);
1792
0
      }
1793
      // Build the inter predictor by blending the predictor corresponding to
1794
      // this MV, and the neighboring blocks using the OBMC model
1795
0
      av1_build_obmc_inter_prediction(
1796
0
          cm, xd, args->above_pred_buf, args->above_pred_stride,
1797
0
          args->left_pred_buf, args->left_pred_stride);
1798
0
#if !CONFIG_REALTIME_ONLY
1799
0
    } else if (mbmi->motion_mode == WARPED_CAUSAL) {
1800
0
      int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
1801
0
      mbmi->motion_mode = WARPED_CAUSAL;
1802
0
      mbmi->wm_params.wmtype = DEFAULT_WMTYPE;
1803
0
      mbmi->interp_filters =
1804
0
          av1_broadcast_interp_filter(av1_unswitchable_filter(interp_filter));
1805
1806
0
      memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
1807
0
      memcpy(pts_inref, pts_inref0, total_samples * 2 * sizeof(*pts_inref0));
1808
      // Select the samples according to motion vector difference
1809
0
      if (mbmi->num_proj_ref > 1) {
1810
0
        mbmi->num_proj_ref = av1_selectSamples(
1811
0
            &mbmi->mv[0].as_mv, pts, pts_inref, mbmi->num_proj_ref, bsize);
1812
0
      }
1813
1814
      // Compute the warped motion parameters with a least squares fit
1815
      //  using the collected samples
1816
0
      if (!av1_find_projection(mbmi->num_proj_ref, pts, pts_inref, bsize,
1817
0
                               mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
1818
0
                               &mbmi->wm_params, mi_row, mi_col)) {
1819
0
        assert(!is_comp_pred);
1820
0
        unsigned int dst_y_valid = 0;
1821
0
        if (have_newmv_in_inter_mode(this_mode)) {
1822
          // Refine MV for NEWMV mode
1823
0
          const int_mv mv0 = mbmi->mv[0];
1824
0
          const WarpedMotionParams wm_params0 = mbmi->wm_params;
1825
0
          const int num_proj_ref0 = mbmi->num_proj_ref;
1826
1827
0
          const int_mv ref_mv = av1_get_ref_mv(x, 0);
1828
0
          SUBPEL_MOTION_SEARCH_PARAMS ms_params;
1829
0
          av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize,
1830
0
                                            &ref_mv.as_mv, NULL);
1831
1832
          // Refine MV in a small range.
1833
0
          dst_y_valid = av1_refine_warped_mv(xd, cm, &ms_params, bsize, pts0,
1834
0
                                             pts_inref0, total_samples,
1835
0
                                             cpi->sf.mv_sf.warp_search_method,
1836
0
                                             cpi->sf.mv_sf.warp_search_iters);
1837
1838
0
          if (mv0.as_int != mbmi->mv[0].as_int) {
1839
            // Keep the refined MV and WM parameters.
1840
0
            tmp_rate_mv = av1_mv_bit_cost(
1841
0
                &mbmi->mv[0].as_mv, &ref_mv.as_mv, x->mv_costs->nmv_joint_cost,
1842
0
                x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1843
0
            tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
1844
0
          } else {
1845
            // Restore the old MV and WM parameters.
1846
0
            mbmi->mv[0] = mv0;
1847
0
            mbmi->wm_params = wm_params0;
1848
0
            mbmi->num_proj_ref = num_proj_ref0;
1849
0
          }
1850
0
        }
1851
1852
        // Build the warped predictor
1853
0
        av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
1854
0
                                      dst_y_valid ? AOM_PLANE_U : AOM_PLANE_Y,
1855
0
                                      av1_num_planes(cm) - 1);
1856
0
      } else {
1857
0
        continue;
1858
0
      }
1859
0
#endif  // !CONFIG_REALTIME_ONLY
1860
0
    } else if (is_interintra_mode) {
1861
0
      const int ret =
1862
0
          av1_handle_inter_intra_mode(cpi, x, bsize, mbmi, args, ref_best_rd,
1863
0
                                      &tmp_rate_mv, &tmp_rate2, orig_dst);
1864
0
      if (ret < 0) continue;
1865
0
    }
1866
1867
    // If we are searching newmv and the mv is the same as refmv, skip the
1868
    // current mode
1869
0
    if (!av1_check_newmv_joint_nonzero(cm, x)) continue;
1870
1871
    // Update rd_stats for the current motion mode
1872
0
    txfm_info->skip_txfm = 0;
1873
0
    rd_stats->dist = 0;
1874
0
    rd_stats->sse = 0;
1875
0
    rd_stats->skip_txfm = 1;
1876
0
    rd_stats->rate = tmp_rate2;
1877
0
    const ModeCosts *mode_costs = &x->mode_costs;
1878
0
    if (mbmi->motion_mode != WARPED_CAUSAL) rd_stats->rate += switchable_rate;
1879
0
    if (interintra_allowed) {
1880
0
      rd_stats->rate +=
1881
0
          mode_costs->interintra_cost[size_group_lookup[bsize]]
1882
0
                                     [mbmi->ref_frame[1] == INTRA_FRAME];
1883
0
    }
1884
0
    if ((last_motion_mode_allowed > SIMPLE_TRANSLATION) &&
1885
0
        (mbmi->ref_frame[1] != INTRA_FRAME)) {
1886
0
      if (last_motion_mode_allowed == WARPED_CAUSAL) {
1887
0
        rd_stats->rate +=
1888
0
            mode_costs->motion_mode_cost[bsize][mbmi->motion_mode];
1889
0
      } else {
1890
0
        rd_stats->rate +=
1891
0
            mode_costs->motion_mode_cost1[bsize][mbmi->motion_mode];
1892
0
      }
1893
0
    }
1894
1895
0
    int64_t this_yrd = INT64_MAX;
1896
1897
0
    if (!do_tx_search) {
1898
      // Avoid doing a transform search here to speed up the overall mode
1899
      // search. It will be done later in the mode search if the current
1900
      // motion mode seems promising.
1901
0
      int64_t curr_sse = -1;
1902
0
      int64_t sse_y = -1;
1903
0
      int est_residue_cost = 0;
1904
0
      int64_t est_dist = 0;
1905
0
      int64_t est_rd = 0;
1906
0
      if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
1907
0
        curr_sse = get_sse(cpi, x, &sse_y);
1908
0
        const int has_est_rd = get_est_rate_dist(tile_data, bsize, curr_sse,
1909
0
                                                 &est_residue_cost, &est_dist);
1910
0
        (void)has_est_rd;
1911
0
        assert(has_est_rd);
1912
0
      } else if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 2 ||
1913
0
                 cpi->sf.rt_sf.use_nonrd_pick_mode) {
1914
0
        model_rd_sb_fn[MODELRD_TYPE_MOTION_MODE_RD](
1915
0
            cpi, bsize, x, xd, 0, num_planes - 1, &est_residue_cost, &est_dist,
1916
0
            NULL, &curr_sse, NULL, NULL, NULL);
1917
0
        sse_y = x->pred_sse[xd->mi[0]->ref_frame[0]];
1918
0
      }
1919
0
      est_rd = RDCOST(x->rdmult, rd_stats->rate + est_residue_cost, est_dist);
1920
0
      if (est_rd * 0.80 > *best_est_rd) {
1921
0
        mbmi->ref_frame[1] = ref_frame_1;
1922
0
        continue;
1923
0
      }
1924
0
      const int mode_rate = rd_stats->rate;
1925
0
      rd_stats->rate += est_residue_cost;
1926
0
      rd_stats->dist = est_dist;
1927
0
      rd_stats->rdcost = est_rd;
1928
0
      if (rd_stats->rdcost < *best_est_rd) {
1929
0
        *best_est_rd = rd_stats->rdcost;
1930
0
        assert(sse_y >= 0);
1931
0
        ref_skip_rd[1] = txfm_rd_gate_level
1932
0
                             ? RDCOST(x->rdmult, mode_rate, (sse_y << 4))
1933
0
                             : INT64_MAX;
1934
0
      }
1935
0
      if (cm->current_frame.reference_mode == SINGLE_REFERENCE) {
1936
0
        if (!is_comp_pred) {
1937
0
          assert(curr_sse >= 0);
1938
0
          inter_modes_info_push(inter_modes_info, mode_rate, curr_sse,
1939
0
                                rd_stats->rdcost, rd_stats, rd_stats_y,
1940
0
                                rd_stats_uv, mbmi);
1941
0
        }
1942
0
      } else {
1943
0
        assert(curr_sse >= 0);
1944
0
        inter_modes_info_push(inter_modes_info, mode_rate, curr_sse,
1945
0
                              rd_stats->rdcost, rd_stats, rd_stats_y,
1946
0
                              rd_stats_uv, mbmi);
1947
0
      }
1948
0
      mbmi->skip_txfm = 0;
1949
0
      rd_stats->skip_txfm = 0;
1950
0
      rd_stats_y->skip_txfm = 0;
1951
0
      increase_motion_mode_rdstats(cpi, mbmi, rd_stats, NULL, NULL);
1952
1953
0
    } else {
1954
      // Perform full transform search
1955
0
      int64_t skip_rd = INT64_MAX;
1956
0
      int64_t skip_rdy = INT64_MAX;
1957
0
      if (txfm_rd_gate_level) {
1958
        // Check if the mode is good enough based on skip RD
1959
0
        int64_t sse_y = INT64_MAX;
1960
0
        int64_t curr_sse = get_sse(cpi, x, &sse_y);
1961
0
        skip_rd = RDCOST(x->rdmult, rd_stats->rate, curr_sse);
1962
0
        skip_rdy = RDCOST(x->rdmult, rd_stats->rate, (sse_y << 4));
1963
0
        int eval_txfm = check_txfm_eval(x, bsize, ref_skip_rd[0], skip_rd,
1964
0
                                        txfm_rd_gate_level, 0);
1965
0
        if (!eval_txfm) continue;
1966
0
      }
1967
1968
      // Do transform search
1969
0
      const int mode_rate = rd_stats->rate;
1970
0
      if (!av1_txfm_search(cpi, x, bsize, rd_stats, rd_stats_y, rd_stats_uv,
1971
0
                           rd_stats->rate, ref_best_rd)) {
1972
0
        if (rd_stats_y->rate == INT_MAX && mode_index == 0) {
1973
0
          return INT64_MAX;
1974
0
        }
1975
0
        continue;
1976
0
      }
1977
0
      const int skip_ctx = av1_get_skip_txfm_context(xd);
1978
0
      const int *skip_txfm_cost_ptr = mode_costs->skip_txfm_cost[skip_ctx];
1979
1980
0
      if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
1981
0
        inter_mode_data_push(tile_data, mbmi->bsize, rd_stats->sse,
1982
0
                             rd_stats->dist,
1983
0
                             rd_stats_y->rate + rd_stats_uv->rate +
1984
0
                                 skip_txfm_cost_ptr[mbmi->skip_txfm]);
1985
0
      }
1986
      // Scale RD_STATS after mode stats are collected. Thus unscaled metrics
1987
      // are used for model generation
1988
0
      increase_motion_mode_rdstats(cpi, mbmi, rd_stats, rd_stats_y,
1989
0
                                   rd_stats_uv);
1990
0
      const int skip_rate =
1991
0
          rd_stats->skip_txfm ? skip_txfm_cost_ptr[1] : skip_txfm_cost_ptr[0];
1992
1993
0
      const int32_t scaled_skip_rate =
1994
0
          increase_motion_mode_rate(cpi, mbmi, skip_rate);
1995
0
      const int y_rate =
1996
0
          scaled_skip_rate + (rd_stats->skip_txfm ? 0 : rd_stats_y->rate);
1997
0
      this_yrd = RDCOST(x->rdmult, y_rate + mode_rate, rd_stats_y->dist);
1998
1999
0
      const int64_t curr_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
2000
0
      if (curr_rd < ref_best_rd) {
2001
0
        ref_best_rd = curr_rd;
2002
0
        ref_skip_rd[0] = skip_rd;
2003
0
        ref_skip_rd[1] = skip_rdy;
2004
0
      }
2005
0
    }
2006
2007
0
    if (this_mode == GLOBALMV || this_mode == GLOBAL_GLOBALMV) {
2008
0
      if (is_nontrans_global_motion(xd, xd->mi[0])) {
2009
0
        mbmi->interp_filters =
2010
0
            av1_broadcast_interp_filter(av1_unswitchable_filter(interp_filter));
2011
0
      }
2012
0
    }
2013
2014
0
    if (this_yrd < INT64_MAX) {
2015
0
      adjust_cost(cpi, x, &this_yrd, /*is_inter_pred=*/true);
2016
0
    }
2017
0
    adjust_rdcost(cpi, x, rd_stats, /*is_inter_pred=*/true);
2018
    // Bug 494653438: If do_tx_search is 0, rd_stats_y is uninitialized, so
2019
    // valgrind will warn if we use rd_stats_y->rdcost in a conditional.
2020
0
    if (!do_tx_search || rd_stats_y->rdcost < INT64_MAX) {
2021
0
      adjust_rdcost(cpi, x, rd_stats_y, /*is_inter_pred=*/true);
2022
0
    }
2023
2024
0
    const int64_t tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
2025
0
    if (mode_index == 0) {
2026
0
      args->simple_rd[this_mode][mbmi->ref_mv_idx][mbmi->ref_frame[0]] = tmp_rd;
2027
0
    }
2028
0
    if (mode_index == 0 || tmp_rd < best_rd) {
2029
      // Update best_rd data if this is the best motion mode so far
2030
0
      best_mbmi = *mbmi;
2031
0
      best_rd = tmp_rd;
2032
0
      best_rd_stats = *rd_stats;
2033
0
      best_rd_stats_y = *rd_stats_y;
2034
0
      best_rate_mv = tmp_rate_mv;
2035
0
      *yrd = this_yrd;
2036
0
      if (num_planes > 1) best_rd_stats_uv = *rd_stats_uv;
2037
0
      av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->height * xd->width);
2038
0
      best_xskip_txfm = mbmi->skip_txfm;
2039
0
    }
2040
0
  }
2041
  // Update RD and mbmi stats for selected motion mode
2042
0
  mbmi->ref_frame[1] = ref_frame_1;
2043
0
  *rate_mv = best_rate_mv;
2044
0
  if (best_rd == INT64_MAX || !av1_check_newmv_joint_nonzero(cm, x)) {
2045
0
    av1_invalid_rd_stats(rd_stats);
2046
0
    restore_dst_buf(xd, *orig_dst, num_planes);
2047
0
    return INT64_MAX;
2048
0
  }
2049
0
  *mbmi = best_mbmi;
2050
0
  *rd_stats = best_rd_stats;
2051
0
  *rd_stats_y = best_rd_stats_y;
2052
0
  if (num_planes > 1) *rd_stats_uv = best_rd_stats_uv;
2053
0
  av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->height * xd->width);
2054
0
  txfm_info->skip_txfm = best_xskip_txfm;
2055
2056
0
  restore_dst_buf(xd, *orig_dst, num_planes);
2057
0
  return 0;
2058
0
}
2059
2060
static int64_t skip_mode_rd(RD_STATS *rd_stats, const AV1_COMP *const cpi,
2061
                            MACROBLOCK *const x, BLOCK_SIZE bsize,
2062
0
                            const BUFFER_SET *const orig_dst, int64_t best_rd) {
2063
0
  assert(bsize < BLOCK_SIZES_ALL);
2064
0
  const AV1_COMMON *cm = &cpi->common;
2065
0
  const int num_planes = av1_num_planes(cm);
2066
0
  MACROBLOCKD *const xd = &x->e_mbd;
2067
0
  const int mi_row = xd->mi_row;
2068
0
  const int mi_col = xd->mi_col;
2069
0
  int64_t total_sse = 0;
2070
0
  int64_t this_rd = INT64_MAX;
2071
0
  const int skip_mode_ctx = av1_get_skip_mode_context(xd);
2072
0
  rd_stats->rate = x->mode_costs.skip_mode_cost[skip_mode_ctx][1];
2073
2074
0
  for (int plane = 0; plane < num_planes; ++plane) {
2075
    // Call av1_enc_build_inter_predictor() for one plane at a time.
2076
0
    av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
2077
0
                                  plane, plane);
2078
0
    const struct macroblockd_plane *const pd = &xd->plane[plane];
2079
0
    const BLOCK_SIZE plane_bsize =
2080
0
        get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
2081
2082
0
    av1_subtract_plane(x, plane_bsize, plane, cpi->do_border_pad);
2083
2084
0
    int64_t sse =
2085
0
        av1_pixel_diff_dist(x, plane, 0, 0, plane_bsize, plane_bsize, NULL);
2086
0
    if (is_cur_buf_hbd(xd)) sse = ROUND_POWER_OF_TWO(sse, (xd->bd - 8) * 2);
2087
0
    sse <<= 4;
2088
0
    total_sse += sse;
2089
    // When current rd cost is more than the best rd, skip evaluation of
2090
    // remaining planes.
2091
0
    this_rd = RDCOST(x->rdmult, rd_stats->rate, total_sse);
2092
0
    if (this_rd > best_rd) break;
2093
0
  }
2094
2095
0
  rd_stats->dist = rd_stats->sse = total_sse;
2096
0
  rd_stats->rdcost = this_rd;
2097
2098
0
  restore_dst_buf(xd, *orig_dst, num_planes);
2099
0
  return 0;
2100
0
}
2101
2102
// Check NEARESTMV, NEARMV, GLOBALMV ref mvs for duplicate and skip the relevant
2103
// mode
2104
// Note(rachelbarker): This speed feature currently does not interact correctly
2105
// with global motion. The issue is that, when global motion is used, GLOBALMV
2106
// produces a different prediction to NEARESTMV/NEARMV even if the motion
2107
// vectors are the same. Thus GLOBALMV should not be pruned in this case.
2108
static inline int check_repeat_ref_mv(const MB_MODE_INFO_EXT *mbmi_ext,
2109
                                      int ref_idx,
2110
                                      const MV_REFERENCE_FRAME *ref_frame,
2111
0
                                      PREDICTION_MODE single_mode) {
2112
0
  const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
2113
0
  const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
2114
0
  assert(single_mode != NEWMV);
2115
0
  if (single_mode == NEARESTMV) {
2116
0
    return 0;
2117
0
  } else if (single_mode == NEARMV) {
2118
    // when ref_mv_count = 0, NEARESTMV and NEARMV are same as GLOBALMV
2119
    // when ref_mv_count = 1, NEARMV is same as GLOBALMV
2120
0
    if (ref_mv_count < 2) return 1;
2121
0
  } else if (single_mode == GLOBALMV) {
2122
    // when ref_mv_count == 0, GLOBALMV is same as NEARESTMV
2123
0
    if (ref_mv_count == 0) return 1;
2124
    // when ref_mv_count == 1, NEARMV is same as GLOBALMV
2125
0
    else if (ref_mv_count == 1)
2126
0
      return 0;
2127
2128
0
    int stack_size = AOMMIN(USABLE_REF_MV_STACK_SIZE, ref_mv_count);
2129
    // Check GLOBALMV is matching with any mv in ref_mv_stack
2130
0
    for (int ref_mv_idx = 0; ref_mv_idx < stack_size; ref_mv_idx++) {
2131
0
      int_mv this_mv;
2132
2133
0
      if (ref_idx == 0)
2134
0
        this_mv = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
2135
0
      else
2136
0
        this_mv = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
2137
2138
0
      if (this_mv.as_int == mbmi_ext->global_mvs[ref_frame[ref_idx]].as_int)
2139
0
        return 1;
2140
0
    }
2141
0
  }
2142
0
  return 0;
2143
0
}
2144
2145
static inline int get_this_mv(int_mv *this_mv, PREDICTION_MODE this_mode,
2146
                              int ref_idx, int ref_mv_idx,
2147
                              int skip_repeated_ref_mv,
2148
                              const MV_REFERENCE_FRAME *ref_frame,
2149
0
                              const MB_MODE_INFO_EXT *mbmi_ext) {
2150
0
  const PREDICTION_MODE single_mode = get_single_mode(this_mode, ref_idx);
2151
0
  assert(is_inter_singleref_mode(single_mode));
2152
0
  if (single_mode == NEWMV) {
2153
0
    this_mv->as_int = INVALID_MV;
2154
0
  } else if (single_mode == GLOBALMV) {
2155
0
    if (skip_repeated_ref_mv &&
2156
0
        check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
2157
0
      return 0;
2158
0
    *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
2159
0
  } else {
2160
0
    assert(single_mode == NEARMV || single_mode == NEARESTMV);
2161
0
    const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
2162
0
    const int ref_mv_offset = single_mode == NEARESTMV ? 0 : ref_mv_idx + 1;
2163
0
    if (ref_mv_offset < mbmi_ext->ref_mv_count[ref_frame_type]) {
2164
0
      assert(ref_mv_offset >= 0);
2165
0
      if (ref_idx == 0) {
2166
0
        *this_mv =
2167
0
            mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_offset].this_mv;
2168
0
      } else {
2169
0
        *this_mv =
2170
0
            mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_offset].comp_mv;
2171
0
      }
2172
0
    } else {
2173
0
      if (skip_repeated_ref_mv &&
2174
0
          check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
2175
0
        return 0;
2176
0
      *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
2177
0
    }
2178
0
  }
2179
0
  return 1;
2180
0
}
2181
2182
// Skip NEARESTMV and NEARMV modes based on refmv weight computed in ref mv list
2183
// population
2184
static inline int skip_nearest_near_mv_using_refmv_weight(
2185
    const MACROBLOCK *const x, const PREDICTION_MODE this_mode,
2186
0
    const int8_t ref_frame_type, PREDICTION_MODE best_mode) {
2187
0
  if (this_mode != NEARESTMV && this_mode != NEARMV) return 0;
2188
  // Do not skip the mode if the current block has not yet obtained a valid
2189
  // inter mode.
2190
0
  if (!is_inter_mode(best_mode)) return 0;
2191
2192
0
  const MACROBLOCKD *xd = &x->e_mbd;
2193
  // Do not skip the mode if both the top and left neighboring blocks are not
2194
  // available.
2195
0
  if (!xd->left_available || !xd->up_available) return 0;
2196
0
  const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
2197
0
  const uint16_t *const ref_mv_weight = mbmi_ext->weight[ref_frame_type];
2198
0
  const int ref_mv_count =
2199
0
      AOMMIN(MAX_REF_MV_SEARCH, mbmi_ext->ref_mv_count[ref_frame_type]);
2200
2201
0
  if (ref_mv_count == 0) return 0;
2202
  // If ref mv list has at least one nearest candidate do not prune NEARESTMV
2203
0
  if (this_mode == NEARESTMV && ref_mv_weight[0] >= REF_CAT_LEVEL) return 0;
2204
2205
  // Count number of ref mvs populated from nearest candidates
2206
0
  int nearest_refmv_count = 0;
2207
0
  for (int ref_mv_idx = 0; ref_mv_idx < ref_mv_count; ref_mv_idx++) {
2208
0
    if (ref_mv_weight[ref_mv_idx] >= REF_CAT_LEVEL) nearest_refmv_count++;
2209
0
  }
2210
2211
  // nearest_refmv_count indicates the closeness of block motion characteristics
2212
  // with respect to its spatial neighbor. Smaller value of nearest_refmv_count
2213
  // w.r.t to ref_mv_count means less correlation with its spatial neighbors.
2214
  // Hence less possibility for NEARESTMV and NEARMV modes becoming the best
2215
  // mode since these modes work well for blocks that shares similar motion
2216
  // characteristics with its neighbor. Thus, NEARMV mode is pruned when
2217
  // nearest_refmv_count is relatively smaller than ref_mv_count and NEARESTMV
2218
  // mode is pruned if none of the ref mvs are populated from nearest candidate.
2219
0
  const int prune_thresh = 1 + (ref_mv_count >= 2);
2220
0
  if (nearest_refmv_count < prune_thresh) return 1;
2221
0
  return 0;
2222
0
}
2223
2224
// This function update the non-new mv for the current prediction mode
2225
static inline int build_cur_mv(int_mv *cur_mv, PREDICTION_MODE this_mode,
2226
                               const AV1_COMMON *cm, const MACROBLOCK *x,
2227
0
                               int skip_repeated_ref_mv) {
2228
0
  const MACROBLOCKD *xd = &x->e_mbd;
2229
0
  const MB_MODE_INFO *mbmi = xd->mi[0];
2230
0
  const int is_comp_pred = has_second_ref(mbmi);
2231
2232
0
  int ret = 1;
2233
0
  for (int i = 0; i < is_comp_pred + 1; ++i) {
2234
0
    int_mv this_mv;
2235
0
    this_mv.as_int = INVALID_MV;
2236
0
    ret = get_this_mv(&this_mv, this_mode, i, mbmi->ref_mv_idx,
2237
0
                      skip_repeated_ref_mv, mbmi->ref_frame, &x->mbmi_ext);
2238
0
    if (!ret) return 0;
2239
0
    const PREDICTION_MODE single_mode = get_single_mode(this_mode, i);
2240
0
    if (single_mode == NEWMV) {
2241
0
      const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
2242
0
      cur_mv[i] =
2243
0
          (i == 0) ? x->mbmi_ext.ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
2244
0
                         .this_mv
2245
0
                   : x->mbmi_ext.ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
2246
0
                         .comp_mv;
2247
0
    } else {
2248
0
      ret &= clamp_and_check_mv(cur_mv + i, this_mv, cm, x);
2249
0
    }
2250
0
  }
2251
0
  return ret;
2252
0
}
2253
2254
static inline int get_drl_cost(const MB_MODE_INFO *mbmi,
2255
                               const MB_MODE_INFO_EXT *mbmi_ext,
2256
                               const int (*const drl_mode_cost0)[2],
2257
0
                               int8_t ref_frame_type) {
2258
0
  int cost = 0;
2259
0
  if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
2260
0
    for (int idx = 0; idx < 2; ++idx) {
2261
0
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
2262
0
        uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
2263
0
        cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != idx];
2264
0
        if (mbmi->ref_mv_idx == idx) return cost;
2265
0
      }
2266
0
    }
2267
0
    return cost;
2268
0
  }
2269
2270
0
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
2271
0
    for (int idx = 1; idx < 3; ++idx) {
2272
0
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
2273
0
        uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
2274
0
        cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != (idx - 1)];
2275
0
        if (mbmi->ref_mv_idx == (idx - 1)) return cost;
2276
0
      }
2277
0
    }
2278
0
    return cost;
2279
0
  }
2280
0
  return cost;
2281
0
}
2282
2283
static inline int is_single_newmv_valid(const HandleInterModeArgs *const args,
2284
                                        const MB_MODE_INFO *const mbmi,
2285
0
                                        PREDICTION_MODE this_mode) {
2286
0
  for (int ref_idx = 0; ref_idx < 2; ++ref_idx) {
2287
0
    const PREDICTION_MODE single_mode = get_single_mode(this_mode, ref_idx);
2288
0
    const MV_REFERENCE_FRAME ref = mbmi->ref_frame[ref_idx];
2289
0
    if (single_mode == NEWMV &&
2290
0
        args->single_newmv_valid[mbmi->ref_mv_idx][ref] == 0) {
2291
0
      return 0;
2292
0
    }
2293
0
  }
2294
0
  return 1;
2295
0
}
2296
2297
static int get_drl_refmv_count(const MACROBLOCK *const x,
2298
                               const MV_REFERENCE_FRAME *ref_frame,
2299
0
                               PREDICTION_MODE mode) {
2300
0
  const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
2301
0
  const int8_t ref_frame_type = av1_ref_frame_type(ref_frame);
2302
0
  const int has_nearmv = have_nearmv_in_inter_mode(mode) ? 1 : 0;
2303
0
  const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
2304
0
  const int only_newmv = (mode == NEWMV || mode == NEW_NEWMV);
2305
0
  const int has_drl =
2306
0
      (has_nearmv && ref_mv_count > 2) || (only_newmv && ref_mv_count > 1);
2307
0
  const int ref_set =
2308
0
      has_drl ? AOMMIN(MAX_REF_MV_SEARCH, ref_mv_count - has_nearmv) : 1;
2309
2310
0
  return ref_set;
2311
0
}
2312
2313
// Checks if particular ref_mv_idx should be pruned.
2314
static int prune_ref_mv_idx_using_qindex(const int reduce_inter_modes,
2315
                                         const int qindex,
2316
0
                                         const int ref_mv_idx) {
2317
0
  if (reduce_inter_modes >= 3) return 1;
2318
  // Q-index logic based pruning is enabled only for
2319
  // reduce_inter_modes = 2.
2320
0
  assert(reduce_inter_modes == 2);
2321
  // When reduce_inter_modes=2, pruning happens as below based on q index.
2322
  // For q index range between 0 and 85: prune if ref_mv_idx >= 1.
2323
  // For q index range between 86 and 170: prune if ref_mv_idx == 2.
2324
  // For q index range between 171 and 255: no pruning.
2325
0
  const int min_prune_ref_mv_idx = (qindex * 3 / QINDEX_RANGE) + 1;
2326
0
  return (ref_mv_idx >= min_prune_ref_mv_idx);
2327
0
}
2328
2329
// Whether this reference motion vector can be skipped, based on initial
2330
// heuristics.
2331
static bool ref_mv_idx_early_breakout(
2332
    const SPEED_FEATURES *const sf,
2333
    const RefFrameDistanceInfo *const ref_frame_dist_info, MACROBLOCK *x,
2334
    const HandleInterModeArgs *const args, int64_t ref_best_rd,
2335
0
    int ref_mv_idx) {
2336
0
  MACROBLOCKD *xd = &x->e_mbd;
2337
0
  MB_MODE_INFO *mbmi = xd->mi[0];
2338
0
  const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
2339
0
  const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
2340
0
  const int is_comp_pred = has_second_ref(mbmi);
2341
0
  if (sf->inter_sf.reduce_inter_modes && ref_mv_idx > 0) {
2342
0
    if (mbmi->ref_frame[0] == LAST2_FRAME ||
2343
0
        mbmi->ref_frame[0] == LAST3_FRAME ||
2344
0
        mbmi->ref_frame[1] == LAST2_FRAME ||
2345
0
        mbmi->ref_frame[1] == LAST3_FRAME) {
2346
0
      const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
2347
0
      if (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
2348
0
          REF_CAT_LEVEL) {
2349
0
        return true;
2350
0
      }
2351
0
    }
2352
    // TODO(any): Experiment with reduce_inter_modes for compound prediction
2353
0
    if (sf->inter_sf.reduce_inter_modes >= 2 && !is_comp_pred &&
2354
0
        have_newmv_in_inter_mode(mbmi->mode)) {
2355
0
      if (mbmi->ref_frame[0] != ref_frame_dist_info->nearest_past_ref &&
2356
0
          mbmi->ref_frame[0] != ref_frame_dist_info->nearest_future_ref) {
2357
0
        const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
2358
0
        const int do_prune = prune_ref_mv_idx_using_qindex(
2359
0
            sf->inter_sf.reduce_inter_modes, x->qindex, ref_mv_idx);
2360
0
        if (do_prune &&
2361
0
            (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
2362
0
             REF_CAT_LEVEL)) {
2363
0
          return true;
2364
0
        }
2365
0
      }
2366
0
    }
2367
0
  }
2368
2369
0
  mbmi->ref_mv_idx = ref_mv_idx;
2370
0
  if (is_comp_pred && (!is_single_newmv_valid(args, mbmi, mbmi->mode))) {
2371
0
    return true;
2372
0
  }
2373
0
  size_t est_rd_rate = args->ref_frame_cost + args->single_comp_cost;
2374
0
  const int drl_cost = get_drl_cost(
2375
0
      mbmi, mbmi_ext, x->mode_costs.drl_mode_cost0, ref_frame_type);
2376
0
  est_rd_rate += drl_cost;
2377
0
  if (RDCOST(x->rdmult, est_rd_rate, 0) > ref_best_rd &&
2378
0
      mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
2379
0
    return true;
2380
0
  }
2381
0
  return false;
2382
0
}
2383
2384
// Compute the estimated RD cost for the motion vector with simple translation.
2385
static int64_t simple_translation_pred_rd(AV1_COMP *const cpi, MACROBLOCK *x,
2386
                                          HandleInterModeArgs *args,
2387
                                          int ref_mv_idx, int64_t ref_best_rd,
2388
0
                                          BLOCK_SIZE bsize) {
2389
0
  MACROBLOCKD *xd = &x->e_mbd;
2390
0
  MB_MODE_INFO *mbmi = xd->mi[0];
2391
0
  MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
2392
0
  const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
2393
0
  const AV1_COMMON *cm = &cpi->common;
2394
0
  const int is_comp_pred = has_second_ref(mbmi);
2395
0
  const ModeCosts *mode_costs = &x->mode_costs;
2396
2397
0
  struct macroblockd_plane *p = xd->plane;
2398
0
  const BUFFER_SET orig_dst = {
2399
0
    { p[0].dst.buf, p[1].dst.buf, p[2].dst.buf },
2400
0
    { p[0].dst.stride, p[1].dst.stride, p[2].dst.stride },
2401
0
  };
2402
0
  RD_STATS rd_stats;
2403
0
  av1_init_rd_stats(&rd_stats);
2404
2405
0
  mbmi->interinter_comp.type = COMPOUND_AVERAGE;
2406
0
  mbmi->comp_group_idx = 0;
2407
0
  mbmi->compound_idx = 1;
2408
0
  if (mbmi->ref_frame[1] == INTRA_FRAME) {
2409
0
    mbmi->ref_frame[1] = NONE_FRAME;
2410
0
  }
2411
0
  int16_t mode_ctx =
2412
0
      av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame);
2413
2414
0
  mbmi->num_proj_ref = 0;
2415
0
  mbmi->motion_mode = SIMPLE_TRANSLATION;
2416
0
  mbmi->ref_mv_idx = ref_mv_idx;
2417
2418
0
  rd_stats.rate += args->ref_frame_cost + args->single_comp_cost;
2419
0
  const int drl_cost =
2420
0
      get_drl_cost(mbmi, mbmi_ext, mode_costs->drl_mode_cost0, ref_frame_type);
2421
0
  rd_stats.rate += drl_cost;
2422
2423
0
  int_mv cur_mv[2];
2424
0
  if (!build_cur_mv(cur_mv, mbmi->mode, cm, x, 0)) {
2425
0
    return INT64_MAX;
2426
0
  }
2427
0
  assert(have_nearmv_in_inter_mode(mbmi->mode));
2428
0
  for (int i = 0; i < is_comp_pred + 1; ++i) {
2429
0
    mbmi->mv[i].as_int = cur_mv[i].as_int;
2430
0
  }
2431
0
  const int ref_mv_cost = cost_mv_ref(mode_costs, mbmi->mode, mode_ctx);
2432
0
  rd_stats.rate += ref_mv_cost;
2433
2434
0
  if (RDCOST(x->rdmult, rd_stats.rate, 0) > ref_best_rd) {
2435
0
    return INT64_MAX;
2436
0
  }
2437
2438
0
  mbmi->motion_mode = SIMPLE_TRANSLATION;
2439
0
  mbmi->num_proj_ref = 0;
2440
0
  if (is_comp_pred) {
2441
    // Only compound_average
2442
0
    mbmi->interinter_comp.type = COMPOUND_AVERAGE;
2443
0
    mbmi->comp_group_idx = 0;
2444
0
    mbmi->compound_idx = 1;
2445
0
  }
2446
0
  set_default_interp_filters(mbmi, cm->features.interp_filter);
2447
2448
0
  const int mi_row = xd->mi_row;
2449
0
  const int mi_col = xd->mi_col;
2450
0
  av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize,
2451
0
                                AOM_PLANE_Y, AOM_PLANE_Y);
2452
0
  int est_rate;
2453
0
  int64_t est_dist;
2454
0
  model_rd_sb_fn[MODELRD_CURVFIT](cpi, bsize, x, xd, 0, 0, &est_rate, &est_dist,
2455
0
                                  NULL, NULL, NULL, NULL, NULL);
2456
0
  return RDCOST(x->rdmult, rd_stats.rate + est_rate, est_dist);
2457
0
}
2458
2459
// Represents a set of integers, from 0 to sizeof(int) * 8, as bits in
2460
// an integer. 0 for the i-th bit means that integer is excluded, 1 means
2461
// it is included.
2462
0
static inline void mask_set_bit(int *mask, int index) { *mask |= (1 << index); }
2463
2464
0
static inline bool mask_check_bit(int mask, int index) {
2465
0
  return (mask >> index) & 0x1;
2466
0
}
2467
2468
// Before performing the full MV search in handle_inter_mode, do a simple
2469
// translation search and see if we can eliminate any motion vectors.
2470
// Returns an integer where, if the i-th bit is set, it means that the i-th
2471
// motion vector should be searched. This is only set for NEAR_MV.
2472
static int ref_mv_idx_to_search(AV1_COMP *const cpi, MACROBLOCK *x,
2473
                                HandleInterModeArgs *const args,
2474
                                int64_t ref_best_rd, BLOCK_SIZE bsize,
2475
0
                                const int ref_set) {
2476
  // If the number of ref mv count is equal to 1, do not prune the same. It
2477
  // is better to evaluate the same than to prune it.
2478
0
  if (ref_set == 1) return 1;
2479
0
  AV1_COMMON *const cm = &cpi->common;
2480
0
  const MACROBLOCKD *const xd = &x->e_mbd;
2481
0
  const MB_MODE_INFO *const mbmi = xd->mi[0];
2482
0
  const PREDICTION_MODE this_mode = mbmi->mode;
2483
2484
  // Only search indices if they have some chance of being good.
2485
0
  int good_indices = 0;
2486
0
  for (int i = 0; i < ref_set; ++i) {
2487
0
    if (ref_mv_idx_early_breakout(&cpi->sf, &cpi->ref_frame_dist_info, x, args,
2488
0
                                  ref_best_rd, i)) {
2489
0
      continue;
2490
0
    }
2491
0
    mask_set_bit(&good_indices, i);
2492
0
  }
2493
2494
  // Only prune in NEARMV mode, if the speed feature is set, and the block size
2495
  // is large enough. If these conditions are not met, return all good indices
2496
  // found so far.
2497
0
  if (!cpi->sf.inter_sf.prune_mode_search_simple_translation)
2498
0
    return good_indices;
2499
0
  if (!have_nearmv_in_inter_mode(this_mode)) return good_indices;
2500
0
  if (num_pels_log2_lookup[bsize] <= 6) return good_indices;
2501
  // Do not prune when there is internal resizing. TODO(elliottk) fix this
2502
  // so b/2384 can be resolved.
2503
0
  if (av1_is_scaled(get_ref_scale_factors(cm, mbmi->ref_frame[0])) ||
2504
0
      (mbmi->ref_frame[1] > 0 &&
2505
0
       av1_is_scaled(get_ref_scale_factors(cm, mbmi->ref_frame[1])))) {
2506
0
    return good_indices;
2507
0
  }
2508
2509
  // Calculate the RD cost for the motion vectors using simple translation.
2510
0
  int64_t idx_rdcost[] = { INT64_MAX, INT64_MAX, INT64_MAX };
2511
0
  for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ++ref_mv_idx) {
2512
    // If this index is bad, ignore it.
2513
0
    if (!mask_check_bit(good_indices, ref_mv_idx)) {
2514
0
      continue;
2515
0
    }
2516
0
    idx_rdcost[ref_mv_idx] = simple_translation_pred_rd(
2517
0
        cpi, x, args, ref_mv_idx, ref_best_rd, bsize);
2518
0
  }
2519
  // Find the index with the best RD cost.
2520
0
  int best_idx = 0;
2521
0
  for (int i = 1; i < MAX_REF_MV_SEARCH; ++i) {
2522
0
    if (idx_rdcost[i] < idx_rdcost[best_idx]) {
2523
0
      best_idx = i;
2524
0
    }
2525
0
  }
2526
  // Only include indices that are good and within a % of the best.
2527
0
  const double dth = has_second_ref(mbmi) ? 1.05 : 1.001;
2528
  // If the simple translation cost is not within this multiple of the
2529
  // best RD, skip it. Note that the cutoff is derived experimentally.
2530
0
  const double ref_dth = 5;
2531
0
  int result = 0;
2532
0
  for (int i = 0; i < ref_set; ++i) {
2533
0
    if (mask_check_bit(good_indices, i) &&
2534
0
        (1.0 * idx_rdcost[i]) / idx_rdcost[best_idx] < dth &&
2535
0
        (1.0 * idx_rdcost[i]) / ref_best_rd < ref_dth) {
2536
0
      mask_set_bit(&result, i);
2537
0
    }
2538
0
  }
2539
0
  return result;
2540
0
}
2541
2542
/*!\brief Motion mode information for inter mode search speedup.
2543
 *
2544
 * Used in a speed feature to search motion modes other than
2545
 * SIMPLE_TRANSLATION only on winning candidates.
2546
 */
2547
typedef struct motion_mode_candidate {
2548
  /*!
2549
   * Mode info for the motion mode candidate.
2550
   */
2551
  MB_MODE_INFO mbmi;
2552
  /*!
2553
   * Rate describing the cost of the motion vectors for this candidate.
2554
   */
2555
  int rate_mv;
2556
  /*!
2557
   * Rate before motion mode search and transform coding is applied.
2558
   */
2559
  int rate2_nocoeff;
2560
  /*!
2561
   * An integer value 0 or 1 which indicates whether or not to skip the motion
2562
   * mode search and default to SIMPLE_TRANSLATION as a speed feature for this
2563
   * candidate.
2564
   */
2565
  int skip_motion_mode;
2566
  /*!
2567
   * Total RD cost for this candidate.
2568
   */
2569
  int64_t rd_cost;
2570
} motion_mode_candidate;
2571
2572
/*!\cond */
2573
typedef struct motion_mode_best_st_candidate {
2574
  motion_mode_candidate motion_mode_cand[MAX_WINNER_MOTION_MODES];
2575
  int num_motion_mode_cand;
2576
} motion_mode_best_st_candidate;
2577
2578
// Checks if the current reference frame matches with neighbouring block's
2579
// (top/left) reference frames
2580
static inline int ref_match_found_in_nb_blocks(MB_MODE_INFO *cur_mbmi,
2581
0
                                               MB_MODE_INFO *nb_mbmi) {
2582
0
  MV_REFERENCE_FRAME nb_ref_frames[2] = { nb_mbmi->ref_frame[0],
2583
0
                                          nb_mbmi->ref_frame[1] };
2584
0
  MV_REFERENCE_FRAME cur_ref_frames[2] = { cur_mbmi->ref_frame[0],
2585
0
                                           cur_mbmi->ref_frame[1] };
2586
0
  const int is_cur_comp_pred = has_second_ref(cur_mbmi);
2587
0
  int match_found = 0;
2588
2589
0
  for (int i = 0; i < (is_cur_comp_pred + 1); i++) {
2590
0
    if ((cur_ref_frames[i] == nb_ref_frames[0]) ||
2591
0
        (cur_ref_frames[i] == nb_ref_frames[1]))
2592
0
      match_found = 1;
2593
0
  }
2594
0
  return match_found;
2595
0
}
2596
2597
static inline int find_ref_match_in_above_nbs(const int total_mi_cols,
2598
0
                                              MACROBLOCKD *xd) {
2599
0
  if (!xd->up_available) return 1;
2600
0
  const int mi_col = xd->mi_col;
2601
0
  MB_MODE_INFO **cur_mbmi = xd->mi;
2602
  // prev_row_mi points into the mi array, starting at the beginning of the
2603
  // previous row.
2604
0
  MB_MODE_INFO **prev_row_mi = xd->mi - mi_col - 1 * xd->mi_stride;
2605
0
  const int end_col = AOMMIN(mi_col + xd->width, total_mi_cols);
2606
0
  uint8_t mi_step;
2607
0
  for (int above_mi_col = mi_col; above_mi_col < end_col;
2608
0
       above_mi_col += mi_step) {
2609
0
    MB_MODE_INFO **above_mi = prev_row_mi + above_mi_col;
2610
0
    mi_step = mi_size_wide[above_mi[0]->bsize];
2611
0
    int match_found = 0;
2612
0
    if (is_inter_block(*above_mi))
2613
0
      match_found = ref_match_found_in_nb_blocks(*cur_mbmi, *above_mi);
2614
0
    if (match_found) return 1;
2615
0
  }
2616
0
  return 0;
2617
0
}
2618
2619
static inline int find_ref_match_in_left_nbs(const int total_mi_rows,
2620
0
                                             MACROBLOCKD *xd) {
2621
0
  if (!xd->left_available) return 1;
2622
0
  const int mi_row = xd->mi_row;
2623
0
  MB_MODE_INFO **cur_mbmi = xd->mi;
2624
  // prev_col_mi points into the mi array, starting at the top of the
2625
  // previous column
2626
0
  MB_MODE_INFO **prev_col_mi = xd->mi - 1 - mi_row * xd->mi_stride;
2627
0
  const int end_row = AOMMIN(mi_row + xd->height, total_mi_rows);
2628
0
  uint8_t mi_step;
2629
0
  for (int left_mi_row = mi_row; left_mi_row < end_row;
2630
0
       left_mi_row += mi_step) {
2631
0
    MB_MODE_INFO **left_mi = prev_col_mi + left_mi_row * xd->mi_stride;
2632
0
    mi_step = mi_size_high[left_mi[0]->bsize];
2633
0
    int match_found = 0;
2634
0
    if (is_inter_block(*left_mi))
2635
0
      match_found = ref_match_found_in_nb_blocks(*cur_mbmi, *left_mi);
2636
0
    if (match_found) return 1;
2637
0
  }
2638
0
  return 0;
2639
0
}
2640
/*!\endcond */
2641
2642
/*! \brief Struct used to hold TPL data to
2643
 * narrow down parts of the inter mode search.
2644
 */
2645
typedef struct {
2646
  /*!
2647
   * The best inter cost out of all of the reference frames.
2648
   */
2649
  int64_t best_inter_cost;
2650
  /*!
2651
   * The inter cost for each reference frame.
2652
   */
2653
  int64_t ref_inter_cost[INTER_REFS_PER_FRAME];
2654
} PruneInfoFromTpl;
2655
2656
#if !CONFIG_REALTIME_ONLY
2657
// TODO(Remya): Check if get_tpl_stats_b() can be reused
2658
static inline void get_block_level_tpl_stats(
2659
    AV1_COMP *cpi, BLOCK_SIZE bsize, int mi_row, int mi_col, int *valid_refs,
2660
0
    PruneInfoFromTpl *inter_cost_info_from_tpl) {
2661
0
  AV1_COMMON *const cm = &cpi->common;
2662
2663
0
  assert(IMPLIES(cpi->ppi->gf_group.size > 0,
2664
0
                 cpi->gf_frame_index < cpi->ppi->gf_group.size));
2665
0
  const int tpl_idx = cpi->gf_frame_index;
2666
0
  TplParams *const tpl_data = &cpi->ppi->tpl_data;
2667
0
  if (!av1_tpl_stats_ready(tpl_data, tpl_idx)) return;
2668
0
  const TplDepFrame *tpl_frame = &tpl_data->tpl_frame[tpl_idx];
2669
0
  const TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
2670
0
  const int mi_wide = mi_size_wide[bsize];
2671
0
  const int mi_high = mi_size_high[bsize];
2672
0
  const int tpl_stride = tpl_frame->stride;
2673
0
  const int step = 1 << tpl_data->tpl_stats_block_mis_log2;
2674
0
  const int mi_col_sr =
2675
0
      coded_to_superres_mi(mi_col, cm->superres_scale_denominator);
2676
0
  const int mi_col_end_sr =
2677
0
      coded_to_superres_mi(mi_col + mi_wide, cm->superres_scale_denominator);
2678
0
  const int mi_cols_sr = av1_pixels_to_mi(cm->superres_upscaled_width);
2679
2680
0
  const int row_step = step;
2681
0
  const int col_step_sr =
2682
0
      coded_to_superres_mi(step, cm->superres_scale_denominator);
2683
0
  for (int row = mi_row; row < AOMMIN(mi_row + mi_high, cm->mi_params.mi_rows);
2684
0
       row += row_step) {
2685
0
    for (int col = mi_col_sr; col < AOMMIN(mi_col_end_sr, mi_cols_sr);
2686
0
         col += col_step_sr) {
2687
0
      const TplDepStats *this_stats = &tpl_stats[av1_tpl_ptr_pos(
2688
0
          row, col, tpl_stride, tpl_data->tpl_stats_block_mis_log2)];
2689
2690
      // Sums up the inter cost of corresponding ref frames
2691
0
      for (int ref_idx = 0; ref_idx < INTER_REFS_PER_FRAME; ref_idx++) {
2692
0
        inter_cost_info_from_tpl->ref_inter_cost[ref_idx] +=
2693
0
            this_stats->pred_error[ref_idx];
2694
0
      }
2695
0
    }
2696
0
  }
2697
2698
  // Computes the best inter cost (minimum inter_cost)
2699
0
  int64_t best_inter_cost = INT64_MAX;
2700
0
  for (int ref_idx = 0; ref_idx < INTER_REFS_PER_FRAME; ref_idx++) {
2701
0
    const int64_t cur_inter_cost =
2702
0
        inter_cost_info_from_tpl->ref_inter_cost[ref_idx];
2703
    // For invalid ref frames, cur_inter_cost = 0 and has to be handled while
2704
    // calculating the minimum inter_cost
2705
0
    if (cur_inter_cost != 0 && (cur_inter_cost < best_inter_cost) &&
2706
0
        valid_refs[ref_idx])
2707
0
      best_inter_cost = cur_inter_cost;
2708
0
  }
2709
0
  inter_cost_info_from_tpl->best_inter_cost = best_inter_cost;
2710
0
}
2711
#endif
2712
2713
static inline int prune_modes_based_on_tpl_stats(
2714
    PruneInfoFromTpl *inter_cost_info_from_tpl, const int *refs, int ref_mv_idx,
2715
0
    const PREDICTION_MODE this_mode, int prune_mode_level) {
2716
0
  const int is_ref_last2 = refs[0] == LAST2_FRAME || refs[1] == LAST2_FRAME;
2717
0
  if (prune_mode_level == 1 && !is_ref_last2) return 0;
2718
2719
0
  const int have_newmv = have_newmv_in_inter_mode(this_mode);
2720
0
  if ((prune_mode_level == 2) && have_newmv) return 0;
2721
2722
0
  const int64_t best_inter_cost = inter_cost_info_from_tpl->best_inter_cost;
2723
0
  if (best_inter_cost == INT64_MAX) return 0;
2724
2725
0
  int64_t cur_inter_cost;
2726
2727
0
  const int is_comp_pred = (refs[1] > INTRA_FRAME);
2728
0
  if (!is_comp_pred) {
2729
0
    cur_inter_cost = inter_cost_info_from_tpl->ref_inter_cost[refs[0] - 1];
2730
0
  } else {
2731
0
    const int64_t inter_cost_ref0 =
2732
0
        inter_cost_info_from_tpl->ref_inter_cost[refs[0] - 1];
2733
0
    const int64_t inter_cost_ref1 =
2734
0
        inter_cost_info_from_tpl->ref_inter_cost[refs[1] - 1];
2735
    // Choose maximum inter_cost among inter_cost_ref0 and inter_cost_ref1 for
2736
    // more aggressive pruning
2737
0
    cur_inter_cost = AOMMAX(inter_cost_ref0, inter_cost_ref1);
2738
0
  }
2739
2740
0
  if (is_ref_last2) return (cur_inter_cost > best_inter_cost);
2741
2742
0
  const int is_globalmv =
2743
0
      (this_mode == GLOBALMV) || (this_mode == GLOBAL_GLOBALMV);
2744
0
  const int prune_index = is_globalmv ? MAX_REF_MV_SEARCH : ref_mv_idx;
2745
0
  const int prune_level = prune_mode_level - 2;
2746
2747
  // Thresholds used for pruning:
2748
  // Lower value indicates aggressive pruning and higher value indicates
2749
  // conservative pruning which is set based on ref_mv_idx and speed feature.
2750
  // 'prune_index' 0, 1, 2 corresponds to ref_mv indices 0, 1 and 2.
2751
  // prune_index 3 corresponds to GLOBALMV/GLOBAL_GLOBALMV
2752
0
  static const int tpl_inter_mode_prune_mul_factor[3][MAX_REF_MV_SEARCH + 1] = {
2753
0
    { 6, 6, 6, 4 }, { 6, 4, 4, 4 }, { 5, 4, 4, 4 }
2754
0
  };
2755
2756
  // Prune the mode if cur_inter_cost is greater than threshold times
2757
  // best_inter_cost
2758
0
  if (cur_inter_cost >
2759
0
      ((tpl_inter_mode_prune_mul_factor[prune_level][prune_index] *
2760
0
        best_inter_cost) >>
2761
0
       2))
2762
0
    return 1;
2763
0
  return 0;
2764
0
}
2765
2766
/*!\brief High level function to select parameters for compound mode.
2767
 *
2768
 * \ingroup inter_mode_search
2769
 * The main search functionality is done in the call to av1_compound_type_rd().
2770
 *
2771
 * \param[in]     cpi               Top-level encoder structure.
2772
 * \param[in]     x                 Pointer to struct holding all the data for
2773
 *                                  the current macroblock.
2774
 * \param[in]     args              HandleInterModeArgs struct holding
2775
 *                                  miscellaneous arguments for inter mode
2776
 *                                  search. See the documentation for this
2777
 *                                  struct for a description of each member.
2778
 * \param[in]     ref_best_rd       Best RD found so far for this block.
2779
 *                                  It is used for early termination of this
2780
 *                                  search if the RD exceeds this value.
2781
 * \param[in,out] cur_mv            Current motion vector.
2782
 * \param[in]     bsize             Current block size.
2783
 * \param[in,out] compmode_interinter_cost  RD of the selected interinter
2784
                                    compound mode.
2785
 * \param[in,out] rd_buffers        CompoundTypeRdBuffers struct to hold all
2786
 *                                  allocated buffers for the compound
2787
 *                                  predictors and masks in the compound type
2788
 *                                  search.
2789
 * \param[in,out] orig_dst          A prediction buffer to hold a computed
2790
 *                                  prediction. This will eventually hold the
2791
 *                                  final prediction, and the tmp_dst info will
2792
 *                                  be copied here.
2793
 * \param[in]     tmp_dst           A temporary prediction buffer to hold a
2794
 *                                  computed prediction.
2795
 * \param[in,out] rate_mv           The rate associated with the motion vectors.
2796
 *                                  This will be modified if a motion search is
2797
 *                                  done in the motion mode search.
2798
 * \param[in,out] rd_stats          Struct to keep track of the overall RD
2799
 *                                  information.
2800
 * \param[in,out] skip_rd           An array of length 2 where skip_rd[0] is the
2801
 *                                  best total RD for a skip mode so far, and
2802
 *                                  skip_rd[1] is the best RD for a skip mode so
2803
 *                                  far in luma. This is used as a speed feature
2804
 *                                  to skip the transform search if the computed
2805
 *                                  skip RD for the current mode is not better
2806
 *                                  than the best skip_rd so far.
2807
 * \param[out] skip_build_pred      Indicates whether or not to build the inter
2808
 *                                  predictor during/after interpolation
2809
 *                                  filter search.
2810
 * \return Returns 1 if this mode is worse than one already seen and 0 if it is
2811
 * a viable candidate.
2812
 */
2813
static int process_compound_inter_mode(
2814
    AV1_COMP *const cpi, MACROBLOCK *x, HandleInterModeArgs *args,
2815
    int64_t ref_best_rd, int_mv *cur_mv, BLOCK_SIZE bsize,
2816
    int *compmode_interinter_cost, const CompoundTypeRdBuffers *rd_buffers,
2817
    const BUFFER_SET *orig_dst, const BUFFER_SET *tmp_dst, int *rate_mv,
2818
0
    RD_STATS *rd_stats, int64_t *skip_rd, int *skip_build_pred) {
2819
0
  MACROBLOCKD *xd = &x->e_mbd;
2820
0
  MB_MODE_INFO *mbmi = xd->mi[0];
2821
0
  const AV1_COMMON *cm = &cpi->common;
2822
0
  const int masked_compound_used = is_any_masked_compound_used(bsize) &&
2823
0
                                   cm->seq_params->enable_masked_compound;
2824
0
  int mode_search_mask = (1 << COMPOUND_AVERAGE) | (1 << COMPOUND_DISTWTD) |
2825
0
                         (1 << COMPOUND_WEDGE) | (1 << COMPOUND_DIFFWTD);
2826
2827
0
  const int num_planes = av1_num_planes(cm);
2828
0
  const int mi_row = xd->mi_row;
2829
0
  const int mi_col = xd->mi_col;
2830
0
  int is_luma_interp_done = 0;
2831
0
  set_default_interp_filters(mbmi, cm->features.interp_filter);
2832
2833
0
  int64_t best_rd_compound;
2834
0
  int64_t rd_thresh;
2835
0
  const int comp_type_rd_shift = COMP_TYPE_RD_THRESH_SHIFT;
2836
0
  const int comp_type_rd_scale = COMP_TYPE_RD_THRESH_SCALE;
2837
0
  rd_thresh = get_rd_thresh_from_best_rd(ref_best_rd, (1 << comp_type_rd_shift),
2838
0
                                         comp_type_rd_scale);
2839
  // Select compound type and any parameters related to that type
2840
  // (for example, the mask parameters if it is a masked mode) and compute
2841
  // the RD
2842
0
  *compmode_interinter_cost = av1_compound_type_rd(
2843
0
      cpi, x, args, bsize, cur_mv, mode_search_mask, masked_compound_used,
2844
0
      orig_dst, tmp_dst, rd_buffers, rate_mv, &best_rd_compound, rd_stats,
2845
0
      ref_best_rd, skip_rd[1], &is_luma_interp_done, rd_thresh);
2846
0
  if (ref_best_rd < INT64_MAX &&
2847
0
      (best_rd_compound >> comp_type_rd_shift) * comp_type_rd_scale >
2848
0
          ref_best_rd) {
2849
0
    restore_dst_buf(xd, *orig_dst, num_planes);
2850
0
    return 1;
2851
0
  }
2852
2853
  // Build only uv predictor for COMPOUND_AVERAGE.
2854
  // Note there is no need to call av1_enc_build_inter_predictor
2855
  // for luma if COMPOUND_AVERAGE is selected because it is the first
2856
  // candidate in av1_compound_type_rd, which means it used the dst_buf
2857
  // rather than the tmp_buf.
2858
0
  if (mbmi->interinter_comp.type == COMPOUND_AVERAGE && is_luma_interp_done) {
2859
0
    if (num_planes > 1) {
2860
0
      av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
2861
0
                                    AOM_PLANE_U, num_planes - 1);
2862
0
    }
2863
0
    *skip_build_pred = INTERP_SKIP_LUMA_SKIP_CHROMA;
2864
0
  }
2865
0
  return 0;
2866
0
}
2867
2868
// Speed feature to prune out MVs that are similar to previous MVs if they
2869
// don't achieve the best RD advantage.
2870
static int prune_ref_mv_idx_search(int ref_mv_idx, int best_ref_mv_idx,
2871
                                   int_mv save_mv[MAX_REF_MV_SEARCH - 1][2],
2872
0
                                   MB_MODE_INFO *mbmi, int pruning_factor) {
2873
0
  int i;
2874
0
  const int is_comp_pred = has_second_ref(mbmi);
2875
0
  const int thr = (1 + is_comp_pred) << (pruning_factor + 1);
2876
2877
  // Skip the evaluation if an MV match is found.
2878
0
  if (ref_mv_idx > 0) {
2879
0
    for (int idx = 0; idx < ref_mv_idx; ++idx) {
2880
0
      if (save_mv[idx][0].as_int == INVALID_MV) continue;
2881
2882
0
      int mv_diff = 0;
2883
0
      for (i = 0; i < 1 + is_comp_pred; ++i) {
2884
0
        mv_diff += abs(save_mv[idx][i].as_mv.row - mbmi->mv[i].as_mv.row) +
2885
0
                   abs(save_mv[idx][i].as_mv.col - mbmi->mv[i].as_mv.col);
2886
0
      }
2887
2888
      // If this mode is not the best one, and current MV is similar to
2889
      // previous stored MV, terminate this ref_mv_idx evaluation.
2890
0
      if (best_ref_mv_idx == -1 && mv_diff <= thr) return 1;
2891
0
    }
2892
0
  }
2893
2894
0
  if (ref_mv_idx < MAX_REF_MV_SEARCH - 1) {
2895
0
    for (i = 0; i < is_comp_pred + 1; ++i)
2896
0
      save_mv[ref_mv_idx][i].as_int = mbmi->mv[i].as_int;
2897
0
  }
2898
2899
0
  return 0;
2900
0
}
2901
2902
/*!\brief Prunes ZeroMV Search Using Best NEWMV's SSE
2903
 *
2904
 * \ingroup inter_mode_search
2905
 *
2906
 * Compares the sse of zero mv and the best sse found in single new_mv. If the
2907
 * sse of the zero_mv is higher, returns 1 to signal zero_mv can be skipped.
2908
 * Else returns 0.
2909
 *
2910
 * Note that the sse of here comes from single_motion_search. So it is
2911
 * interpolated with the filter in motion search, not the actual interpolation
2912
 * filter used in encoding.
2913
 *
2914
 * \param[in]     fn_ptr            A table of function pointers to compute SSE.
2915
 * \param[in]     x                 Pointer to struct holding all the data for
2916
 *                                  the current macroblock.
2917
 * \param[in]     bsize             The current block_size.
2918
 * \param[in]     args              The args to handle_inter_mode, used to track
2919
 *                                  the best SSE.
2920
 * \param[in]    prune_zero_mv_with_sse  The argument holds speed feature
2921
 *                                       prune_zero_mv_with_sse value
2922
 * \return Returns 1 if zero_mv is pruned, 0 otherwise.
2923
 */
2924
static inline int prune_zero_mv_with_sse(const aom_variance_fn_ptr_t *fn_ptr,
2925
                                         const MACROBLOCK *x, BLOCK_SIZE bsize,
2926
                                         const HandleInterModeArgs *args,
2927
0
                                         int prune_zero_mv_with_sse) {
2928
0
  const MACROBLOCKD *xd = &x->e_mbd;
2929
0
  const MB_MODE_INFO *mbmi = xd->mi[0];
2930
2931
0
  const int is_comp_pred = has_second_ref(mbmi);
2932
0
  const MV_REFERENCE_FRAME *refs = mbmi->ref_frame;
2933
2934
0
  for (int idx = 0; idx < 1 + is_comp_pred; idx++) {
2935
0
    if (xd->global_motion[refs[idx]].wmtype != IDENTITY) {
2936
      // Pruning logic only works for IDENTITY type models
2937
      // Note: In theory we could apply similar logic for TRANSLATION
2938
      // type models, but we do not code these due to a spec bug
2939
      // (see comments in gm_get_motion_vector() in av1/common/mv.h)
2940
0
      assert(xd->global_motion[refs[idx]].wmtype != TRANSLATION);
2941
0
      return 0;
2942
0
    }
2943
2944
    // Don't prune if we have invalid data
2945
0
    assert(mbmi->mv[idx].as_int == 0);
2946
0
    if (args->best_single_sse_in_refs[refs[idx]] == INT32_MAX) {
2947
0
      return 0;
2948
0
    }
2949
0
  }
2950
2951
  // Sum up the sse of ZEROMV and best NEWMV
2952
0
  unsigned int this_sse_sum = 0;
2953
0
  unsigned int best_sse_sum = 0;
2954
0
  for (int idx = 0; idx < 1 + is_comp_pred; idx++) {
2955
0
    const struct macroblock_plane *const p = &x->plane[AOM_PLANE_Y];
2956
0
    const struct macroblockd_plane *pd = xd->plane;
2957
0
    const struct buf_2d *src_buf = &p->src;
2958
0
    const struct buf_2d *ref_buf = &pd->pre[idx];
2959
0
    const uint8_t *src = src_buf->buf;
2960
0
    const uint8_t *ref = ref_buf->buf;
2961
0
    const int src_stride = src_buf->stride;
2962
0
    const int ref_stride = ref_buf->stride;
2963
2964
0
    unsigned int this_sse;
2965
0
    fn_ptr[bsize].vf(ref, ref_stride, src, src_stride, &this_sse);
2966
0
    this_sse_sum += this_sse;
2967
2968
0
    const unsigned int best_sse = args->best_single_sse_in_refs[refs[idx]];
2969
0
    best_sse_sum += best_sse;
2970
0
  }
2971
2972
0
  const double mul = prune_zero_mv_with_sse > 1 ? 1.00 : 1.25;
2973
0
  if ((double)this_sse_sum > (mul * (double)best_sse_sum)) {
2974
0
    return 1;
2975
0
  }
2976
2977
0
  return 0;
2978
0
}
2979
2980
/*!\brief Searches for interpolation filter in realtime mode during winner eval
2981
 *
2982
 * \ingroup inter_mode_search
2983
 *
2984
 * Does a simple interpolation filter search during winner mode evaluation. This
2985
 * is currently only used by realtime mode as \ref
2986
 * av1_interpolation_filter_search is not called during realtime encoding.
2987
 *
2988
 * This function only searches over two possible filters. EIGHTTAP_REGULAR is
2989
 * always search. For lowres clips (<= 240p), MULTITAP_SHARP is also search. For
2990
 * higher  res slips (>240p), EIGHTTAP_SMOOTH is also searched.
2991
 *  *
2992
 * \param[in]     cpi               Pointer to the compressor. Used for feature
2993
 *                                  flags.
2994
 * \param[in,out] x                 Pointer to macroblock. This is primarily
2995
 *                                  used to access the buffers.
2996
 * \param[in]     mi_row            The current row in mi unit (4X4 pixels).
2997
 * \param[in]     mi_col            The current col in mi unit (4X4 pixels).
2998
 * \param[in]     bsize             The current block_size.
2999
 * \return Returns true if a predictor is built in xd->dst, false otherwise.
3000
 */
3001
static inline bool fast_interp_search(const AV1_COMP *cpi, MACROBLOCK *x,
3002
                                      int mi_row, int mi_col,
3003
0
                                      BLOCK_SIZE bsize) {
3004
0
  static const InterpFilters filters_ref_set[3] = {
3005
0
    { EIGHTTAP_REGULAR, EIGHTTAP_REGULAR },
3006
0
    { EIGHTTAP_SMOOTH, EIGHTTAP_SMOOTH },
3007
0
    { MULTITAP_SHARP, MULTITAP_SHARP }
3008
0
  };
3009
3010
0
  const AV1_COMMON *const cm = &cpi->common;
3011
0
  MACROBLOCKD *const xd = &x->e_mbd;
3012
0
  MB_MODE_INFO *const mi = xd->mi[0];
3013
0
  int64_t best_cost = INT64_MAX;
3014
0
  int best_filter_index = -1;
3015
  // dst_bufs[0] sores the new predictor, and dist_bifs[1] stores the best
3016
0
  const int num_planes = av1_num_planes(cm);
3017
0
  const int is_240p_or_lesser = AOMMIN(cm->width, cm->height) <= 240;
3018
0
  assert(is_inter_mode(mi->mode));
3019
0
  assert(mi->motion_mode == SIMPLE_TRANSLATION);
3020
0
  assert(!is_inter_compound_mode(mi->mode));
3021
3022
0
  if (!av1_is_interp_needed(xd)) {
3023
0
    return false;
3024
0
  }
3025
3026
0
  struct macroblockd_plane *pd = xd->plane;
3027
0
  const BUFFER_SET orig_dst = {
3028
0
    { pd[0].dst.buf, pd[1].dst.buf, pd[2].dst.buf },
3029
0
    { pd[0].dst.stride, pd[1].dst.stride, pd[2].dst.stride },
3030
0
  };
3031
0
  uint8_t *const tmp_buf = get_buf_by_bd(xd, x->tmp_pred_bufs[0]);
3032
0
  const BUFFER_SET tmp_dst = { { tmp_buf, tmp_buf + 1 * MAX_SB_SQUARE,
3033
0
                                 tmp_buf + 2 * MAX_SB_SQUARE },
3034
0
                               { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE } };
3035
0
  const BUFFER_SET *dst_bufs[2] = { &orig_dst, &tmp_dst };
3036
3037
0
  for (int i = 0; i < 3; ++i) {
3038
0
    if (is_240p_or_lesser) {
3039
0
      if (filters_ref_set[i].x_filter == EIGHTTAP_SMOOTH) {
3040
0
        continue;
3041
0
      }
3042
0
    } else {
3043
0
      if (filters_ref_set[i].x_filter == MULTITAP_SHARP) {
3044
0
        continue;
3045
0
      }
3046
0
    }
3047
0
    int64_t cost;
3048
0
    RD_STATS tmp_rd = { 0 };
3049
3050
0
    mi->interp_filters.as_filters = filters_ref_set[i];
3051
0
    av1_enc_build_inter_predictor_y(xd, mi_row, mi_col);
3052
3053
0
    model_rd_sb_fn[cpi->sf.rt_sf.use_simple_rd_model
3054
0
                       ? MODELRD_LEGACY
3055
0
                       : MODELRD_TYPE_INTERP_FILTER](
3056
0
        cpi, bsize, x, xd, AOM_PLANE_Y, AOM_PLANE_Y, &tmp_rd.rate, &tmp_rd.dist,
3057
0
        &tmp_rd.skip_txfm, &tmp_rd.sse, NULL, NULL, NULL);
3058
3059
0
    tmp_rd.rate += av1_get_switchable_rate(x, xd, cm->features.interp_filter,
3060
0
                                           cm->seq_params->enable_dual_filter);
3061
0
    cost = RDCOST(x->rdmult, tmp_rd.rate, tmp_rd.dist);
3062
0
    if (cost < best_cost) {
3063
0
      best_filter_index = i;
3064
0
      best_cost = cost;
3065
0
      swap_dst_buf(xd, dst_bufs, num_planes);
3066
0
    }
3067
0
  }
3068
0
  assert(best_filter_index >= 0);
3069
3070
0
  mi->interp_filters.as_filters = filters_ref_set[best_filter_index];
3071
3072
0
  const bool is_best_pred_in_orig = &orig_dst == dst_bufs[1];
3073
3074
0
  if (is_best_pred_in_orig) {
3075
0
    swap_dst_buf(xd, dst_bufs, num_planes);
3076
0
  } else {
3077
    // Note that xd->pd's bufers are kept in sync with dst_bufs[0]. So if
3078
    // is_best_pred_in_orig is false, that means the current buffer is the
3079
    // original one.
3080
0
    assert(&orig_dst == dst_bufs[0]);
3081
0
    assert(xd->plane[AOM_PLANE_Y].dst.buf == orig_dst.plane[AOM_PLANE_Y]);
3082
0
    const int width = block_size_wide[bsize];
3083
0
    const int height = block_size_high[bsize];
3084
0
#if CONFIG_AV1_HIGHBITDEPTH
3085
0
    const bool is_hbd = is_cur_buf_hbd(xd);
3086
0
    if (is_hbd) {
3087
0
      aom_highbd_convolve_copy(CONVERT_TO_SHORTPTR(tmp_dst.plane[AOM_PLANE_Y]),
3088
0
                               tmp_dst.stride[AOM_PLANE_Y],
3089
0
                               CONVERT_TO_SHORTPTR(orig_dst.plane[AOM_PLANE_Y]),
3090
0
                               orig_dst.stride[AOM_PLANE_Y], width, height);
3091
0
    } else {
3092
0
      aom_convolve_copy(tmp_dst.plane[AOM_PLANE_Y], tmp_dst.stride[AOM_PLANE_Y],
3093
0
                        orig_dst.plane[AOM_PLANE_Y],
3094
0
                        orig_dst.stride[AOM_PLANE_Y], width, height);
3095
0
    }
3096
#else
3097
    aom_convolve_copy(tmp_dst.plane[AOM_PLANE_Y], tmp_dst.stride[AOM_PLANE_Y],
3098
                      orig_dst.plane[AOM_PLANE_Y], orig_dst.stride[AOM_PLANE_Y],
3099
                      width, height);
3100
#endif
3101
0
  }
3102
3103
  // Build the YUV predictor.
3104
0
  if (num_planes > 1) {
3105
0
    av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
3106
0
                                  AOM_PLANE_U, AOM_PLANE_V);
3107
0
  }
3108
3109
0
  return true;
3110
0
}
3111
3112
/*!\brief AV1 inter mode RD computation
3113
 *
3114
 * \ingroup inter_mode_search
3115
 * Do the RD search for a given inter mode and compute all information relevant
3116
 * to the input mode. It will compute the best MV,
3117
 * compound parameters (if the mode is a compound mode) and interpolation filter
3118
 * parameters.
3119
 *
3120
 * \param[in]     cpi               Top-level encoder structure.
3121
 * \param[in]     tile_data         Pointer to struct holding adaptive
3122
 *                                  data/contexts/models for the tile during
3123
 *                                  encoding.
3124
 * \param[in]     x                 Pointer to structure holding all the data
3125
 *                                  for the current macroblock.
3126
 * \param[in]     bsize             Current block size.
3127
 * \param[in,out] rd_stats          Struct to keep track of the overall RD
3128
 *                                  information.
3129
 * \param[out]    rd_stats_y        Struct to keep track of the RD information
3130
 *                                  for only the Y plane.
3131
 * \param[out]    rd_stats_uv       Struct to keep track of the RD information
3132
 *                                  for only the UV planes.
3133
 * \param[in]     args              HandleInterModeArgs struct holding
3134
 *                                  miscellaneous arguments for inter mode
3135
 *                                  search. See the documentation for this
3136
 *                                  struct for a description of each member.
3137
 * \param[in]     ref_best_rd       Best RD found so far for this block.
3138
 *                                  It is used for early termination of this
3139
 *                                  search if the RD exceeds this value.
3140
 * \param[in]     tmp_buf           Temporary buffer used to hold predictors
3141
 *                                  built in this search.
3142
 * \param[in,out] rd_buffers        CompoundTypeRdBuffers struct to hold all
3143
 *                                  allocated buffers for the compound
3144
 *                                  predictors and masks in the compound type
3145
 *                                  search.
3146
 * \param[in,out] best_est_rd       Estimated RD for motion mode search if
3147
 *                                  do_tx_search (see below) is 0.
3148
 * \param[in]     do_tx_search      Parameter to indicate whether or not to do
3149
 *                                  a full transform search. This will compute
3150
 *                                  an estimated RD for the modes without the
3151
 *                                  transform search and later perform the full
3152
 *                                  transform search on the best candidates.
3153
 * \param[in,out] inter_modes_info  InterModesInfo struct to hold inter mode
3154
 *                                  information to perform a full transform
3155
 *                                  search only on winning candidates searched
3156
 *                                  with an estimate for transform coding RD.
3157
 * \param[in,out] motion_mode_cand  A motion_mode_candidate struct to store
3158
 *                                  motion mode information used in a speed
3159
 *                                  feature to search motion modes other than
3160
 *                                  SIMPLE_TRANSLATION only on winning
3161
 *                                  candidates.
3162
 * \param[in,out] skip_rd           A length 2 array, where skip_rd[0] is the
3163
 *                                  best total RD for a skip mode so far, and
3164
 *                                  skip_rd[1] is the best RD for a skip mode so
3165
 *                                  far in luma. This is used as a speed feature
3166
 *                                  to skip the transform search if the computed
3167
 *                                  skip RD for the current mode is not better
3168
 *                                  than the best skip_rd so far.
3169
 * \param[in]     inter_cost_info_from_tpl A PruneInfoFromTpl struct used to
3170
 *                                         narrow down the search based on data
3171
 *                                         collected in the TPL model.
3172
 * \param[out]    yrd               Stores the rdcost corresponding to encoding
3173
 *                                  the luma plane.
3174
 *
3175
 * \return The RD cost for the mode being searched. If the return value is
3176
 *         INT64_MAX, the output parameters are not set; do not use them.
3177
 */
3178
static int64_t handle_inter_mode(
3179
    AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *x,
3180
    BLOCK_SIZE bsize, RD_STATS *rd_stats, RD_STATS *rd_stats_y,
3181
    RD_STATS *rd_stats_uv, HandleInterModeArgs *args, int64_t ref_best_rd,
3182
    uint8_t *const tmp_buf, const CompoundTypeRdBuffers *rd_buffers,
3183
    int64_t *best_est_rd, const int do_tx_search,
3184
    InterModesInfo *inter_modes_info, motion_mode_candidate *motion_mode_cand,
3185
    int64_t *skip_rd, PruneInfoFromTpl *inter_cost_info_from_tpl,
3186
0
    int64_t *yrd) {
3187
0
  assert(rd_stats != NULL && rd_stats_y != NULL && rd_stats_uv != NULL);
3188
0
  const AV1_COMMON *cm = &cpi->common;
3189
0
  const int num_planes = av1_num_planes(cm);
3190
0
  MACROBLOCKD *xd = &x->e_mbd;
3191
0
  MB_MODE_INFO *mbmi = xd->mi[0];
3192
0
  MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
3193
0
  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
3194
0
  const int is_comp_pred = has_second_ref(mbmi);
3195
0
  const PREDICTION_MODE this_mode = mbmi->mode;
3196
3197
#if CONFIG_REALTIME_ONLY
3198
  const int prune_modes_based_on_tpl = 0;
3199
#else   // CONFIG_REALTIME_ONLY
3200
0
  const TplParams *const tpl_data = &cpi->ppi->tpl_data;
3201
0
  const int prune_modes_based_on_tpl =
3202
0
      cpi->sf.inter_sf.prune_inter_modes_based_on_tpl &&
3203
0
      av1_tpl_stats_ready(tpl_data, cpi->gf_frame_index);
3204
0
#endif  // CONFIG_REALTIME_ONLY
3205
0
  int i;
3206
  // Reference frames for this mode
3207
0
  const int refs[2] = { mbmi->ref_frame[0],
3208
0
                        (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
3209
0
  int rate_mv = 0;
3210
0
  int64_t rd = INT64_MAX;
3211
  // Do first prediction into the destination buffer. Do the next
3212
  // prediction into a temporary buffer. Then keep track of which one
3213
  // of these currently holds the best predictor, and use the other
3214
  // one for future predictions. In the end, copy from tmp_buf to
3215
  // dst if necessary.
3216
0
  struct macroblockd_plane *pd = xd->plane;
3217
0
  const BUFFER_SET orig_dst = {
3218
0
    { pd[0].dst.buf, pd[1].dst.buf, pd[2].dst.buf },
3219
0
    { pd[0].dst.stride, pd[1].dst.stride, pd[2].dst.stride },
3220
0
  };
3221
0
  const BUFFER_SET tmp_dst = { { tmp_buf, tmp_buf + 1 * MAX_SB_SQUARE,
3222
0
                                 tmp_buf + 2 * MAX_SB_SQUARE },
3223
0
                               { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE } };
3224
3225
0
  int64_t ret_val = INT64_MAX;
3226
0
  const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
3227
0
  RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
3228
0
  int64_t best_rd = INT64_MAX;
3229
0
  uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
3230
0
  int64_t best_yrd = INT64_MAX;
3231
0
  MB_MODE_INFO best_mbmi = *mbmi;
3232
0
  int best_xskip_txfm = 0;
3233
0
  int64_t newmv_ret_val = INT64_MAX;
3234
0
  inter_mode_info mode_info[MAX_REF_MV_SEARCH];
3235
3236
  // Do not prune the mode based on inter cost from tpl if the current ref frame
3237
  // is the winner ref in neighbouring blocks.
3238
0
  int ref_match_found_in_above_nb = 0;
3239
0
  int ref_match_found_in_left_nb = 0;
3240
0
  if (prune_modes_based_on_tpl) {
3241
0
    ref_match_found_in_above_nb =
3242
0
        find_ref_match_in_above_nbs(cm->mi_params.mi_cols, xd);
3243
0
    ref_match_found_in_left_nb =
3244
0
        find_ref_match_in_left_nbs(cm->mi_params.mi_rows, xd);
3245
0
  }
3246
3247
  // First, perform a simple translation search for each of the indices. If
3248
  // an index performs well, it will be fully searched in the main loop
3249
  // of this function.
3250
0
  const int ref_set = get_drl_refmv_count(x, mbmi->ref_frame, this_mode);
3251
  // Save MV results from first 2 ref_mv_idx.
3252
0
  int_mv save_mv[MAX_REF_MV_SEARCH - 1][2];
3253
0
  int best_ref_mv_idx = -1;
3254
0
  const int idx_mask =
3255
0
      ref_mv_idx_to_search(cpi, x, args, ref_best_rd, bsize, ref_set);
3256
0
  const int16_t mode_ctx =
3257
0
      av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame);
3258
0
  const ModeCosts *mode_costs = &x->mode_costs;
3259
0
  const int ref_mv_cost = cost_mv_ref(mode_costs, this_mode, mode_ctx);
3260
0
  const int base_rate =
3261
0
      args->ref_frame_cost + args->single_comp_cost + ref_mv_cost;
3262
3263
0
  for (i = 0; i < MAX_REF_MV_SEARCH - 1; ++i) {
3264
0
    save_mv[i][0].as_int = INVALID_MV;
3265
0
    save_mv[i][1].as_int = INVALID_MV;
3266
0
  }
3267
0
  args->start_mv_cnt = 0;
3268
3269
  // Main loop of this function. This will  iterate over all of the ref mvs
3270
  // in the dynamic reference list and do the following:
3271
  //    1.) Get the current MV. Create newmv MV if necessary
3272
  //    2.) Search compound type and parameters if applicable
3273
  //    3.) Do interpolation filter search
3274
  //    4.) Build the inter predictor
3275
  //    5.) Pick the motion mode (SIMPLE_TRANSLATION, OBMC_CAUSAL,
3276
  //        WARPED_CAUSAL)
3277
  //    6.) Update stats if best so far
3278
0
  for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ++ref_mv_idx) {
3279
0
    mbmi->ref_mv_idx = ref_mv_idx;
3280
3281
0
    mode_info[ref_mv_idx].full_search_mv.as_int = INVALID_MV;
3282
0
    mode_info[ref_mv_idx].full_mv_bestsme = INT_MAX;
3283
0
    mode_info[ref_mv_idx].pred_sse = UINT_MAX;
3284
0
    mode_info[ref_mv_idx].model_rd = INT64_MAX;
3285
0
    const int drl_cost = get_drl_cost(
3286
0
        mbmi, mbmi_ext, mode_costs->drl_mode_cost0, ref_frame_type);
3287
0
    mode_info[ref_mv_idx].drl_cost = drl_cost;
3288
0
    mode_info[ref_mv_idx].skip = 0;
3289
3290
0
    if (!mask_check_bit(idx_mask, ref_mv_idx)) {
3291
      // MV did not perform well in simple translation search. Skip it.
3292
0
      continue;
3293
0
    }
3294
0
    if (prune_modes_based_on_tpl && !ref_match_found_in_above_nb &&
3295
0
        !ref_match_found_in_left_nb && (ref_best_rd != INT64_MAX)) {
3296
      // Skip mode if TPL model indicates it will not be beneficial.
3297
0
      if (prune_modes_based_on_tpl_stats(
3298
0
              inter_cost_info_from_tpl, refs, ref_mv_idx, this_mode,
3299
0
              cpi->sf.inter_sf.prune_inter_modes_based_on_tpl))
3300
0
        continue;
3301
0
    }
3302
0
    av1_init_rd_stats(rd_stats);
3303
3304
    // Initialize compound mode data
3305
0
    mbmi->interinter_comp.type = COMPOUND_AVERAGE;
3306
0
    mbmi->comp_group_idx = 0;
3307
0
    mbmi->compound_idx = 1;
3308
0
    if (mbmi->ref_frame[1] == INTRA_FRAME) mbmi->ref_frame[1] = NONE_FRAME;
3309
3310
0
    mbmi->num_proj_ref = 0;
3311
0
    mbmi->motion_mode = SIMPLE_TRANSLATION;
3312
3313
    // Compute cost for signalling this DRL index
3314
0
    rd_stats->rate = base_rate;
3315
0
    rd_stats->rate += drl_cost;
3316
3317
0
    int rs = 0;
3318
0
    int compmode_interinter_cost = 0;
3319
3320
0
    int_mv cur_mv[2];
3321
3322
    // TODO(Cherma): Extend this speed feature to support compound mode
3323
0
    int skip_repeated_ref_mv =
3324
0
        is_comp_pred ? 0 : cpi->sf.inter_sf.skip_repeated_ref_mv;
3325
    // Generate the current mv according to the prediction mode
3326
0
    if (!build_cur_mv(cur_mv, this_mode, cm, x, skip_repeated_ref_mv)) {
3327
0
      continue;
3328
0
    }
3329
3330
    // The above call to build_cur_mv does not handle NEWMV modes. Build
3331
    // the mv here if we have NEWMV for any predictors.
3332
0
    if (have_newmv_in_inter_mode(this_mode)) {
3333
#if CONFIG_COLLECT_COMPONENT_TIMING
3334
      start_timing(cpi, handle_newmv_time);
3335
#endif
3336
0
      newmv_ret_val =
3337
0
          handle_newmv(cpi, x, bsize, cur_mv, &rate_mv, args, mode_info);
3338
#if CONFIG_COLLECT_COMPONENT_TIMING
3339
      end_timing(cpi, handle_newmv_time);
3340
#endif
3341
3342
0
      if (newmv_ret_val != 0) continue;
3343
3344
0
      if (is_inter_singleref_mode(this_mode) &&
3345
0
          cur_mv[0].as_int != INVALID_MV) {
3346
0
        const MV_REFERENCE_FRAME ref = refs[0];
3347
0
        const unsigned int this_sse = x->pred_sse[ref];
3348
0
        if (this_sse < args->best_single_sse_in_refs[ref]) {
3349
0
          args->best_single_sse_in_refs[ref] = this_sse;
3350
0
        }
3351
3352
0
        if (cpi->sf.rt_sf.skip_newmv_mode_based_on_sse) {
3353
0
          const int th_idx = cpi->sf.rt_sf.skip_newmv_mode_based_on_sse - 1;
3354
0
          const int pix_idx = num_pels_log2_lookup[bsize] - 4;
3355
0
          const double scale_factor[3][11] = {
3356
0
            { 0.7, 0.7, 0.7, 0.7, 0.7, 0.8, 0.8, 0.9, 0.9, 0.9, 0.9 },
3357
0
            { 0.7, 0.7, 0.7, 0.7, 0.8, 0.8, 1, 1, 1, 1, 1 },
3358
0
            { 0.7, 0.7, 0.7, 0.7, 1, 1, 1, 1, 1, 1, 1 }
3359
0
          };
3360
0
          assert(pix_idx >= 0);
3361
0
          assert(th_idx <= 2);
3362
0
          if (args->best_pred_sse < scale_factor[th_idx][pix_idx] * this_sse)
3363
0
            continue;
3364
0
        }
3365
0
      }
3366
3367
0
      rd_stats->rate += rate_mv;
3368
0
    }
3369
    // Copy the motion vector for this mode into mbmi struct
3370
0
    for (i = 0; i < is_comp_pred + 1; ++i) {
3371
0
      mbmi->mv[i].as_int = cur_mv[i].as_int;
3372
0
    }
3373
3374
0
    if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd &&
3375
0
        mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
3376
0
      continue;
3377
0
    }
3378
3379
    // Skip the rest of the search if prune_ref_mv_idx_search speed feature
3380
    // is enabled, and the current MV is similar to a previous one.
3381
0
    if (cpi->sf.inter_sf.prune_ref_mv_idx_search && is_comp_pred &&
3382
0
        prune_ref_mv_idx_search(ref_mv_idx, best_ref_mv_idx, save_mv, mbmi,
3383
0
                                cpi->sf.inter_sf.prune_ref_mv_idx_search))
3384
0
      continue;
3385
3386
0
    if (cpi->sf.gm_sf.prune_zero_mv_with_sse &&
3387
0
        (this_mode == GLOBALMV || this_mode == GLOBAL_GLOBALMV)) {
3388
0
      if (prune_zero_mv_with_sse(cpi->ppi->fn_ptr, x, bsize, args,
3389
0
                                 cpi->sf.gm_sf.prune_zero_mv_with_sse)) {
3390
0
        continue;
3391
0
      }
3392
0
    }
3393
3394
    // Flag to indicate whether to skip av1_enc_build_inter_predictor() after
3395
    // interpolation filter search
3396
0
    int skip_build_pred = INTERP_EVAL_LUMA_EVAL_CHROMA;
3397
0
    const int mi_row = xd->mi_row;
3398
0
    const int mi_col = xd->mi_col;
3399
3400
    // Handle a compound predictor, continue if it is determined this
3401
    // cannot be the best compound mode
3402
0
    if (is_comp_pred) {
3403
#if CONFIG_COLLECT_COMPONENT_TIMING
3404
      start_timing(cpi, compound_type_rd_time);
3405
#endif
3406
0
      const int not_best_mode = process_compound_inter_mode(
3407
0
          cpi, x, args, ref_best_rd, cur_mv, bsize, &compmode_interinter_cost,
3408
0
          rd_buffers, &orig_dst, &tmp_dst, &rate_mv, rd_stats, skip_rd,
3409
0
          &skip_build_pred);
3410
#if CONFIG_COLLECT_COMPONENT_TIMING
3411
      end_timing(cpi, compound_type_rd_time);
3412
#endif
3413
0
      if (not_best_mode) continue;
3414
0
    }
3415
3416
0
    if (!args->skip_ifs) {
3417
#if CONFIG_COLLECT_COMPONENT_TIMING
3418
      start_timing(cpi, interpolation_filter_search_time);
3419
#endif
3420
      // Determine the interpolation filter for this mode
3421
0
      ret_val = av1_interpolation_filter_search(
3422
0
          x, cpi, tile_data, bsize, &tmp_dst, &orig_dst, &rd, &rs,
3423
0
          &skip_build_pred, args, ref_best_rd);
3424
#if CONFIG_COLLECT_COMPONENT_TIMING
3425
      end_timing(cpi, interpolation_filter_search_time);
3426
#endif
3427
0
      if (args->modelled_rd != NULL && !is_comp_pred) {
3428
0
        args->modelled_rd[this_mode][ref_mv_idx][refs[0]] = rd;
3429
0
      }
3430
0
      if (ret_val != 0) {
3431
0
        restore_dst_buf(xd, orig_dst, num_planes);
3432
0
        continue;
3433
0
      } else if (cpi->sf.inter_sf.model_based_post_interp_filter_breakout &&
3434
0
                 ref_best_rd != INT64_MAX && (rd >> 3) * 3 > ref_best_rd) {
3435
0
        restore_dst_buf(xd, orig_dst, num_planes);
3436
0
        continue;
3437
0
      }
3438
3439
      // Compute modelled RD if enabled
3440
0
      if (args->modelled_rd != NULL) {
3441
0
        if (is_comp_pred) {
3442
0
          const int mode0 = compound_ref0_mode(this_mode);
3443
0
          const int mode1 = compound_ref1_mode(this_mode);
3444
0
          const int64_t mrd =
3445
0
              AOMMIN(args->modelled_rd[mode0][ref_mv_idx][refs[0]],
3446
0
                     args->modelled_rd[mode1][ref_mv_idx][refs[1]]);
3447
0
          if ((rd >> 3) * 6 > mrd && ref_best_rd < INT64_MAX) {
3448
0
            restore_dst_buf(xd, orig_dst, num_planes);
3449
0
            continue;
3450
0
          }
3451
0
        }
3452
0
      }
3453
0
    }
3454
3455
0
    rd_stats->rate += compmode_interinter_cost;
3456
0
    if (skip_build_pred != INTERP_SKIP_LUMA_SKIP_CHROMA) {
3457
      // Chroma plane of COMPOUND_DIFFWTD mode shares the segment mask of luma
3458
      // which is stored in xd->seg_mask. Hence, the predictor is populated for
3459
      // all planes. This should avoid usage of incorrect segment mask when the
3460
      // call is made only for chroma.
3461
0
      const int skip_luma_plane =
3462
0
          skip_build_pred == INTERP_SKIP_LUMA_EVAL_CHROMA &&
3463
0
          mbmi->interinter_comp.type != COMPOUND_DIFFWTD;
3464
0
      const int start_plane = skip_luma_plane ? AOM_PLANE_U : AOM_PLANE_Y;
3465
      // Build this inter predictor if it has not been previously built
3466
0
      av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize,
3467
0
                                    start_plane, num_planes - 1);
3468
0
    }
3469
#if CONFIG_COLLECT_COMPONENT_TIMING
3470
    start_timing(cpi, motion_mode_rd_time);
3471
#endif
3472
0
    int rate2_nocoeff = rd_stats->rate;
3473
    // Determine the motion mode. This will be one of SIMPLE_TRANSLATION,
3474
    // OBMC_CAUSAL or WARPED_CAUSAL
3475
0
    int64_t this_yrd;
3476
0
    ret_val = motion_mode_rd(cpi, tile_data, x, bsize, rd_stats, rd_stats_y,
3477
0
                             rd_stats_uv, args, ref_best_rd, skip_rd, &rate_mv,
3478
0
                             &orig_dst, best_est_rd, do_tx_search,
3479
0
                             inter_modes_info, 0, &this_yrd);
3480
#if CONFIG_COLLECT_COMPONENT_TIMING
3481
    end_timing(cpi, motion_mode_rd_time);
3482
#endif
3483
0
    assert(
3484
0
        IMPLIES(!av1_check_newmv_joint_nonzero(cm, x), ret_val == INT64_MAX));
3485
3486
0
    if (ret_val != INT64_MAX) {
3487
0
      int64_t tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
3488
0
      const THR_MODES mode_enum = get_prediction_mode_idx(
3489
0
          mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
3490
      // Collect mode stats for multiwinner mode processing
3491
0
      store_winner_mode_stats(cpi, x, mbmi, rd_stats, rd_stats_y, rd_stats_uv,
3492
0
                              mode_enum, NULL, bsize, tmp_rd,
3493
0
                              cpi->sf.winner_mode_sf.multi_winner_mode_type,
3494
0
                              do_tx_search);
3495
0
      if (tmp_rd < best_rd) {
3496
0
        best_yrd = this_yrd;
3497
        // Update the best rd stats if we found the best mode so far
3498
0
        best_rd_stats = *rd_stats;
3499
0
        best_rd_stats_y = *rd_stats_y;
3500
0
        best_rd_stats_uv = *rd_stats_uv;
3501
0
        best_rd = tmp_rd;
3502
0
        best_mbmi = *mbmi;
3503
0
        best_xskip_txfm = txfm_info->skip_txfm;
3504
0
        av1_copy_array(best_tx_type_map, xd->tx_type_map,
3505
0
                       xd->height * xd->width);
3506
0
        motion_mode_cand->rate_mv = rate_mv;
3507
0
        motion_mode_cand->rate2_nocoeff = rate2_nocoeff;
3508
0
      }
3509
3510
0
      if (tmp_rd < ref_best_rd) {
3511
0
        ref_best_rd = tmp_rd;
3512
0
        best_ref_mv_idx = ref_mv_idx;
3513
0
      }
3514
0
    }
3515
0
    restore_dst_buf(xd, orig_dst, num_planes);
3516
0
  }
3517
3518
0
  if (best_rd == INT64_MAX) return INT64_MAX;
3519
3520
  // re-instate status of the best choice
3521
0
  *rd_stats = best_rd_stats;
3522
0
  *rd_stats_y = best_rd_stats_y;
3523
0
  *rd_stats_uv = best_rd_stats_uv;
3524
0
  *yrd = best_yrd;
3525
0
  *mbmi = best_mbmi;
3526
0
  txfm_info->skip_txfm = best_xskip_txfm;
3527
0
  assert(IMPLIES(mbmi->comp_group_idx == 1,
3528
0
                 mbmi->interinter_comp.type != COMPOUND_AVERAGE));
3529
0
  av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->height * xd->width);
3530
3531
0
  rd_stats->rdcost = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
3532
3533
0
  return rd_stats->rdcost;
3534
0
}
3535
3536
/*!\brief Search for the best intrabc predictor
3537
 *
3538
 * \ingroup intra_mode_search
3539
 * \callergraph
3540
 * This function performs a motion search to find the best intrabc predictor.
3541
 *
3542
 * \returns Returns the best overall rdcost (including the non-intrabc modes
3543
 * search before this function).
3544
 */
3545
static int64_t rd_pick_intrabc_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
3546
                                       PICK_MODE_CONTEXT *ctx,
3547
                                       RD_STATS *rd_stats, BLOCK_SIZE bsize,
3548
0
                                       int64_t best_rd) {
3549
0
  const AV1_COMMON *const cm = &cpi->common;
3550
0
  if (!av1_allow_intrabc(cm) || !cpi->oxcf.kf_cfg.enable_intrabc ||
3551
0
      !cpi->sf.mv_sf.use_intrabc ||
3552
0
      (cpi->sf.rt_sf.use_nonrd_pick_mode && !cpi->sf.rt_sf.rt_use_intrabc))
3553
0
    return INT64_MAX;
3554
0
  if (cpi->sf.mv_sf.intrabc_search_level >= 1 && bsize != BLOCK_4X4 &&
3555
0
      bsize != BLOCK_8X8 && bsize != BLOCK_16X16) {
3556
0
    return INT64_MAX;
3557
0
  }
3558
0
  const int num_planes = av1_num_planes(cm);
3559
3560
0
  MACROBLOCKD *const xd = &x->e_mbd;
3561
0
  const TileInfo *tile = &xd->tile;
3562
0
  MB_MODE_INFO *mbmi = xd->mi[0];
3563
3564
0
  const int mi_row = xd->mi_row;
3565
0
  const int mi_col = xd->mi_col;
3566
0
  const int w = block_size_wide[bsize];
3567
0
  const int h = block_size_high[bsize];
3568
0
  const int sb_row = mi_row >> cm->seq_params->mib_size_log2;
3569
0
  const int sb_col = mi_col >> cm->seq_params->mib_size_log2;
3570
3571
0
  MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
3572
0
  const MV_REFERENCE_FRAME ref_frame = INTRA_FRAME;
3573
0
  av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
3574
0
                   xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
3575
0
                   mbmi_ext->mode_context);
3576
  // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
3577
  // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
3578
0
  av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
3579
0
  int_mv nearestmv, nearmv;
3580
0
  av1_find_best_ref_mvs_from_stack(0, mbmi_ext, ref_frame, &nearestmv, &nearmv,
3581
0
                                   0);
3582
3583
0
  if (nearestmv.as_int == INVALID_MV) {
3584
0
    nearestmv.as_int = 0;
3585
0
  }
3586
0
  if (nearmv.as_int == INVALID_MV) {
3587
0
    nearmv.as_int = 0;
3588
0
  }
3589
3590
0
  int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
3591
0
  if (dv_ref.as_int == 0) {
3592
0
    av1_find_ref_dv(&dv_ref, tile, cm->seq_params->mib_size, mi_row);
3593
0
  }
3594
  // Ref DV should not have sub-pel.
3595
0
  assert((dv_ref.as_mv.col & 7) == 0);
3596
0
  assert((dv_ref.as_mv.row & 7) == 0);
3597
0
  mbmi_ext->ref_mv_stack[INTRA_FRAME][0].this_mv = dv_ref;
3598
3599
0
  struct buf_2d yv12_mb[MAX_MB_PLANE];
3600
0
  av1_setup_pred_block(xd, yv12_mb, xd->cur_buf, NULL, NULL, num_planes);
3601
0
  for (int i = 0; i < num_planes; ++i) {
3602
0
    xd->plane[i].pre[0] = yv12_mb[i];
3603
0
  }
3604
3605
0
  enum IntrabcMotionDirection {
3606
0
    IBC_MOTION_ABOVE,
3607
0
    IBC_MOTION_LEFT,
3608
0
    IBC_MOTION_DIRECTIONS
3609
0
  };
3610
3611
0
  MB_MODE_INFO best_mbmi = *mbmi;
3612
0
  RD_STATS best_rdstats = *rd_stats;
3613
0
  uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
3614
0
  av1_copy_array(best_tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
3615
3616
0
  FULLPEL_MOTION_SEARCH_PARAMS fullms_params;
3617
0
  const SEARCH_METHODS search_method =
3618
0
      av1_get_default_mv_search_method(x, &cpi->sf.mv_sf, bsize);
3619
0
  const search_site_config *src_search_sites =
3620
0
      av1_get_search_site_config(cpi, x, search_method);
3621
0
  const FULLPEL_MV start_mv = get_fullmv_from_mv(&dv_ref.as_mv);
3622
0
  av1_make_default_fullpel_ms_params(&fullms_params, cpi, x, bsize,
3623
0
                                     &dv_ref.as_mv, start_mv, src_search_sites,
3624
0
                                     search_method,
3625
0
                                     /*fine_search_interval=*/0);
3626
0
  const IntraBCMVCosts *const dv_costs = x->dv_costs;
3627
0
  av1_set_ms_to_intra_mode(&fullms_params, dv_costs);
3628
3629
0
  const enum IntrabcMotionDirection max_dir = cpi->sf.mv_sf.intrabc_search_level
3630
0
                                                  ? IBC_MOTION_LEFT
3631
0
                                                  : IBC_MOTION_DIRECTIONS;
3632
3633
0
  for (enum IntrabcMotionDirection dir = IBC_MOTION_ABOVE; dir < max_dir;
3634
0
       ++dir) {
3635
0
    switch (dir) {
3636
0
      case IBC_MOTION_ABOVE:
3637
0
        fullms_params.mv_limits.col_min =
3638
0
            (tile->mi_col_start - mi_col) * MI_SIZE;
3639
0
        fullms_params.mv_limits.col_max =
3640
0
            (tile->mi_col_end - mi_col) * MI_SIZE - w;
3641
0
        fullms_params.mv_limits.row_min =
3642
0
            (tile->mi_row_start - mi_row) * MI_SIZE;
3643
0
        fullms_params.mv_limits.row_max =
3644
0
            (sb_row * cm->seq_params->mib_size - mi_row) * MI_SIZE - h;
3645
0
        break;
3646
0
      case IBC_MOTION_LEFT:
3647
0
        fullms_params.mv_limits.col_min =
3648
0
            (tile->mi_col_start - mi_col) * MI_SIZE;
3649
0
        fullms_params.mv_limits.col_max =
3650
0
            (sb_col * cm->seq_params->mib_size - mi_col) * MI_SIZE - w;
3651
        // TODO(aconverse@google.com): Minimize the overlap between above and
3652
        // left areas.
3653
0
        fullms_params.mv_limits.row_min =
3654
0
            (tile->mi_row_start - mi_row) * MI_SIZE;
3655
0
        int bottom_coded_mi_edge =
3656
0
            AOMMIN((sb_row + 1) * cm->seq_params->mib_size, tile->mi_row_end);
3657
0
        fullms_params.mv_limits.row_max =
3658
0
            (bottom_coded_mi_edge - mi_row) * MI_SIZE - h;
3659
0
        break;
3660
0
      default: assert(0);
3661
0
    }
3662
0
    assert(fullms_params.mv_limits.col_min >= fullms_params.mv_limits.col_min);
3663
0
    assert(fullms_params.mv_limits.col_max <= fullms_params.mv_limits.col_max);
3664
0
    assert(fullms_params.mv_limits.row_min >= fullms_params.mv_limits.row_min);
3665
0
    assert(fullms_params.mv_limits.row_max <= fullms_params.mv_limits.row_max);
3666
3667
0
    av1_set_mv_search_range(&fullms_params.mv_limits, &dv_ref.as_mv);
3668
3669
0
    if (fullms_params.mv_limits.col_max < fullms_params.mv_limits.col_min ||
3670
0
        fullms_params.mv_limits.row_max < fullms_params.mv_limits.row_min) {
3671
0
      continue;
3672
0
    }
3673
3674
0
    const int step_param = cpi->mv_search_params.mv_step_param;
3675
0
    IntraBCHashInfo *intrabc_hash_info = &x->intrabc_hash_info;
3676
0
    int_mv best_mv;
3677
0
    FULLPEL_MV_STATS best_mv_stats;
3678
0
    int bestsme = INT_MAX;
3679
3680
    // Perform a hash search first, and see if we get any matches.
3681
0
    if (!cpi->sf.mv_sf.hash_max_8x8_intrabc_blocks || bsize <= BLOCK_8X8) {
3682
0
      bestsme = av1_intrabc_hash_search(cpi, xd, &fullms_params,
3683
0
                                        intrabc_hash_info, &best_mv.as_fullmv);
3684
0
    }
3685
3686
    // If intrabc_search_level is not 0 and we found a hash search match, do
3687
    // not proceed with pixel search as the hash match is very likely to be the
3688
    // best intrabc candidate anyway.
3689
0
    if (bestsme == INT_MAX || cpi->sf.mv_sf.intrabc_search_level == 0) {
3690
0
      int_mv best_pixel_mv;
3691
0
      const int pixelsme =
3692
0
          av1_full_pixel_search(start_mv, &fullms_params, step_param, NULL,
3693
0
                                &best_pixel_mv.as_fullmv, &best_mv_stats, NULL);
3694
0
      if (pixelsme < bestsme) {
3695
0
        bestsme = pixelsme;
3696
0
        best_mv = best_pixel_mv;
3697
0
      }
3698
0
    }
3699
0
    if (bestsme == INT_MAX) continue;
3700
0
    const MV dv = get_mv_from_fullmv(&best_mv.as_fullmv);
3701
0
    if (!av1_is_fullmv_in_range(&fullms_params.mv_limits,
3702
0
                                get_fullmv_from_mv(&dv)))
3703
0
      continue;
3704
0
    if (!av1_is_dv_valid(dv, cm, xd, mi_row, mi_col, bsize,
3705
0
                         cm->seq_params->mib_size_log2))
3706
0
      continue;
3707
3708
    // DV should not have sub-pel.
3709
0
    assert((dv.col & 7) == 0);
3710
0
    assert((dv.row & 7) == 0);
3711
0
    memset(&mbmi->palette_mode_info, 0, sizeof(mbmi->palette_mode_info));
3712
0
    mbmi->filter_intra_mode_info.use_filter_intra = 0;
3713
0
    mbmi->use_intrabc = 1;
3714
0
    mbmi->mode = DC_PRED;
3715
0
    mbmi->uv_mode = UV_DC_PRED;
3716
0
    mbmi->motion_mode = SIMPLE_TRANSLATION;
3717
0
    mbmi->mv[0].as_mv = dv;
3718
0
    mbmi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
3719
0
    mbmi->skip_txfm = 0;
3720
0
    av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
3721
0
                                  av1_num_planes(cm) - 1);
3722
3723
    // TODO(aconverse@google.com): The full motion field defining discount
3724
    // in MV_COST_WEIGHT is too large. Explore other values.
3725
0
    const int rate_mv = av1_mv_bit_cost(&dv, &dv_ref.as_mv, dv_costs->joint_mv,
3726
0
                                        dv_costs->dv_costs, MV_COST_WEIGHT_SUB);
3727
0
    const int rate_mode = x->mode_costs.intrabc_cost[1];
3728
0
    RD_STATS rd_stats_yuv, rd_stats_y, rd_stats_uv;
3729
0
    if (!av1_txfm_search(cpi, x, bsize, &rd_stats_yuv, &rd_stats_y,
3730
0
                         &rd_stats_uv, rate_mode + rate_mv, INT64_MAX))
3731
0
      continue;
3732
0
    rd_stats_yuv.rdcost =
3733
0
        RDCOST(x->rdmult, rd_stats_yuv.rate, rd_stats_yuv.dist);
3734
0
    if (rd_stats_yuv.rdcost < best_rd) {
3735
0
      best_rd = rd_stats_yuv.rdcost;
3736
0
      best_mbmi = *mbmi;
3737
0
      best_rdstats = rd_stats_yuv;
3738
0
      av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->height * xd->width);
3739
0
    }
3740
0
  }
3741
0
  *mbmi = best_mbmi;
3742
0
  *rd_stats = best_rdstats;
3743
0
  av1_copy_array(xd->tx_type_map, best_tx_type_map, ctx->num_4x4_blk);
3744
#if CONFIG_RD_DEBUG
3745
  mbmi->rd_stats = *rd_stats;
3746
#endif
3747
0
  return best_rd;
3748
0
}
3749
3750
// TODO(chiyotsai@google.com): We are using struct $struct_name instead of their
3751
// typedef here because Doxygen doesn't know about the typedefs yet. So using
3752
// the typedef will prevent doxygen from finding this function and generating
3753
// the callgraph. Once documents for AV1_COMP and MACROBLOCK are added to
3754
// doxygen, we can revert back to using the typedefs.
3755
void av1_rd_pick_intra_mode_sb(const struct AV1_COMP *cpi, struct macroblock *x,
3756
                               struct RD_STATS *rd_cost, BLOCK_SIZE bsize,
3757
0
                               PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
3758
0
  const AV1_COMMON *const cm = &cpi->common;
3759
0
  MACROBLOCKD *const xd = &x->e_mbd;
3760
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
3761
0
  const int num_planes = av1_num_planes(cm);
3762
0
  int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
3763
0
  uint8_t y_skip_txfm = 0, uv_skip_txfm = 0;
3764
0
  int64_t dist_y = 0, dist_uv = 0;
3765
3766
0
  ctx->rd_stats.skip_txfm = 0;
3767
0
  mbmi->ref_frame[0] = INTRA_FRAME;
3768
0
  mbmi->ref_frame[1] = NONE_FRAME;
3769
0
  mbmi->use_intrabc = 0;
3770
0
  mbmi->mv[0].as_int = 0;
3771
0
  mbmi->skip_mode = 0;
3772
3773
0
  const int64_t intra_yrd =
3774
0
      av1_rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly, &dist_y,
3775
0
                                 &y_skip_txfm, bsize, best_rd, ctx);
3776
3777
  // Initialize default mode evaluation params
3778
0
  set_mode_eval_params(cpi, x, DEFAULT_EVAL);
3779
3780
0
  if (intra_yrd < best_rd) {
3781
    // Search intra modes for uv planes if needed
3782
0
    if (num_planes > 1) {
3783
      // Set up the tx variables for reproducing the y predictions in case we
3784
      // need it for chroma-from-luma.
3785
0
      if (xd->is_chroma_ref && store_cfl_required_rdo(cm, x)) {
3786
0
        av1_copy_array(xd->tx_type_map, ctx->tx_type_map, ctx->num_4x4_blk);
3787
0
      }
3788
0
      const TX_SIZE max_uv_tx_size = av1_get_tx_size(AOM_PLANE_U, xd);
3789
0
      av1_rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
3790
0
                                  &dist_uv, &uv_skip_txfm, bsize,
3791
0
                                  max_uv_tx_size);
3792
0
    }
3793
3794
    // Intra block is always coded as non-skip
3795
0
    rd_cost->rate =
3796
0
        rate_y + rate_uv +
3797
0
        x->mode_costs.skip_txfm_cost[av1_get_skip_txfm_context(xd)][0];
3798
0
    rd_cost->dist = dist_y + dist_uv;
3799
0
    rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
3800
0
    rd_cost->skip_txfm = 0;
3801
0
  } else {
3802
0
    rd_cost->rate = INT_MAX;
3803
0
  }
3804
3805
0
  if (rd_cost->rate != INT_MAX && rd_cost->rdcost < best_rd)
3806
0
    best_rd = rd_cost->rdcost;
3807
0
  if (rd_pick_intrabc_mode_sb(cpi, x, ctx, rd_cost, bsize, best_rd) < best_rd) {
3808
0
    ctx->rd_stats.skip_txfm = mbmi->skip_txfm;
3809
0
    assert(rd_cost->rate != INT_MAX);
3810
0
  }
3811
0
  if (rd_cost->rate == INT_MAX) return;
3812
3813
0
  ctx->mic = *mbmi;
3814
0
  av1_copy_mbmi_ext_to_mbmi_ext_frame(&ctx->mbmi_ext_best, &x->mbmi_ext,
3815
0
                                      av1_ref_frame_type(xd->mi[0]->ref_frame));
3816
0
  av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
3817
0
}
3818
3819
static inline void calc_target_weighted_pred(
3820
    const AV1_COMMON *cm, const MACROBLOCK *x, const MACROBLOCKD *xd,
3821
    const uint8_t *above, int above_stride, const uint8_t *left,
3822
    int left_stride);
3823
3824
static inline void rd_pick_skip_mode(
3825
    RD_STATS *rd_cost, InterModeSearchState *search_state,
3826
    const AV1_COMP *const cpi, MACROBLOCK *const x, BLOCK_SIZE bsize,
3827
0
    struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
3828
0
  const AV1_COMMON *const cm = &cpi->common;
3829
0
  const SkipModeInfo *const skip_mode_info = &cm->current_frame.skip_mode_info;
3830
0
  const int num_planes = av1_num_planes(cm);
3831
0
  MACROBLOCKD *const xd = &x->e_mbd;
3832
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
3833
3834
0
  x->compound_idx = 1;  // COMPOUND_AVERAGE
3835
0
  RD_STATS skip_mode_rd_stats;
3836
0
  av1_invalid_rd_stats(&skip_mode_rd_stats);
3837
3838
0
  if (skip_mode_info->ref_frame_idx_0 == INVALID_IDX ||
3839
0
      skip_mode_info->ref_frame_idx_1 == INVALID_IDX) {
3840
0
    return;
3841
0
  }
3842
3843
0
  const MV_REFERENCE_FRAME ref_frame =
3844
0
      LAST_FRAME + skip_mode_info->ref_frame_idx_0;
3845
0
  const MV_REFERENCE_FRAME second_ref_frame =
3846
0
      LAST_FRAME + skip_mode_info->ref_frame_idx_1;
3847
0
  const PREDICTION_MODE this_mode = NEAREST_NEARESTMV;
3848
0
  const THR_MODES mode_index =
3849
0
      get_prediction_mode_idx(this_mode, ref_frame, second_ref_frame);
3850
3851
0
  if (mode_index == THR_INVALID) {
3852
0
    return;
3853
0
  }
3854
3855
0
  if ((!cpi->oxcf.ref_frm_cfg.enable_onesided_comp ||
3856
0
       cpi->sf.inter_sf.disable_onesided_comp) &&
3857
0
      cpi->all_one_sided_refs) {
3858
0
    return;
3859
0
  }
3860
3861
0
  mbmi->mode = this_mode;
3862
0
  mbmi->uv_mode = UV_DC_PRED;
3863
0
  mbmi->ref_frame[0] = ref_frame;
3864
0
  mbmi->ref_frame[1] = second_ref_frame;
3865
0
  const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
3866
0
  if (x->mbmi_ext.ref_mv_count[ref_frame_type] == UINT8_MAX) {
3867
0
    MB_MODE_INFO_EXT *mbmi_ext = &x->mbmi_ext;
3868
0
    if (mbmi_ext->ref_mv_count[ref_frame] == UINT8_MAX ||
3869
0
        mbmi_ext->ref_mv_count[second_ref_frame] == UINT8_MAX) {
3870
0
      return;
3871
0
    }
3872
0
    av1_find_mv_refs(cm, xd, mbmi, ref_frame_type, mbmi_ext->ref_mv_count,
3873
0
                     xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
3874
0
                     mbmi_ext->mode_context);
3875
    // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
3876
    // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
3877
0
    av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame_type);
3878
0
  }
3879
3880
0
  assert(this_mode == NEAREST_NEARESTMV);
3881
0
  if (!build_cur_mv(mbmi->mv, this_mode, cm, x, 0)) {
3882
0
    return;
3883
0
  }
3884
3885
0
  mbmi->filter_intra_mode_info.use_filter_intra = 0;
3886
0
  mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
3887
0
  mbmi->comp_group_idx = 0;
3888
0
  mbmi->compound_idx = x->compound_idx;
3889
0
  mbmi->interinter_comp.type = COMPOUND_AVERAGE;
3890
0
  mbmi->motion_mode = SIMPLE_TRANSLATION;
3891
0
  mbmi->ref_mv_idx = 0;
3892
0
  mbmi->skip_mode = mbmi->skip_txfm = 1;
3893
0
  mbmi->palette_mode_info.palette_size[0] = 0;
3894
0
  mbmi->palette_mode_info.palette_size[1] = 0;
3895
3896
0
  set_default_interp_filters(mbmi, cm->features.interp_filter);
3897
3898
0
  set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
3899
0
  for (int i = 0; i < num_planes; i++) {
3900
0
    xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
3901
0
    xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
3902
0
  }
3903
3904
0
  BUFFER_SET orig_dst;
3905
0
  for (int i = 0; i < num_planes; i++) {
3906
0
    orig_dst.plane[i] = xd->plane[i].dst.buf;
3907
0
    orig_dst.stride[i] = xd->plane[i].dst.stride;
3908
0
  }
3909
3910
  // Compare the use of skip_mode with the best intra/inter mode obtained.
3911
0
  const int skip_mode_ctx = av1_get_skip_mode_context(xd);
3912
0
  int64_t best_intra_inter_mode_cost = INT64_MAX;
3913
0
  if (rd_cost->dist < INT64_MAX && rd_cost->rate < INT32_MAX) {
3914
0
    const ModeCosts *mode_costs = &x->mode_costs;
3915
0
    best_intra_inter_mode_cost = RDCOST(
3916
0
        x->rdmult, rd_cost->rate + mode_costs->skip_mode_cost[skip_mode_ctx][0],
3917
0
        rd_cost->dist);
3918
    // Account for non-skip mode rate in total rd stats
3919
0
    rd_cost->rate += mode_costs->skip_mode_cost[skip_mode_ctx][0];
3920
0
    av1_rd_cost_update(x->rdmult, rd_cost);
3921
0
  }
3922
3923
  // Obtain the rdcost for skip_mode.
3924
0
  skip_mode_rd(&skip_mode_rd_stats, cpi, x, bsize, &orig_dst,
3925
0
               best_intra_inter_mode_cost);
3926
3927
0
  if (skip_mode_rd_stats.rdcost <= best_intra_inter_mode_cost &&
3928
0
      (!xd->lossless[mbmi->segment_id] || skip_mode_rd_stats.dist == 0)) {
3929
0
    assert(mode_index != THR_INVALID);
3930
0
    search_state->best_mbmode.skip_mode = 1;
3931
0
    search_state->best_mbmode = *mbmi;
3932
0
    memset(search_state->best_mbmode.inter_tx_size,
3933
0
           search_state->best_mbmode.tx_size,
3934
0
           sizeof(search_state->best_mbmode.inter_tx_size));
3935
0
    set_txfm_ctxs(search_state->best_mbmode.tx_size, xd->width, xd->height,
3936
0
                  search_state->best_mbmode.skip_txfm && is_inter_block(mbmi),
3937
0
                  xd);
3938
0
    search_state->best_mode_index = mode_index;
3939
3940
    // Update rd_cost
3941
0
    rd_cost->rate = skip_mode_rd_stats.rate;
3942
0
    rd_cost->dist = rd_cost->sse = skip_mode_rd_stats.dist;
3943
0
    rd_cost->rdcost = skip_mode_rd_stats.rdcost;
3944
3945
0
    search_state->best_rd = rd_cost->rdcost;
3946
0
    search_state->best_skip2 = 1;
3947
0
    search_state->best_mode_skippable = 1;
3948
3949
0
    x->txfm_search_info.skip_txfm = 1;
3950
0
  }
3951
0
}
3952
3953
// Get winner mode stats of given mode index
3954
static inline MB_MODE_INFO *get_winner_mode_stats(
3955
    MACROBLOCK *x, MB_MODE_INFO *best_mbmode, RD_STATS *best_rd_cost,
3956
    int best_rate_y, int best_rate_uv, THR_MODES *best_mode_index,
3957
    RD_STATS **winner_rd_cost, int *winner_rate_y, int *winner_rate_uv,
3958
    THR_MODES *winner_mode_index, MULTI_WINNER_MODE_TYPE multi_winner_mode_type,
3959
0
    int mode_idx) {
3960
0
  MB_MODE_INFO *winner_mbmi;
3961
0
  if (multi_winner_mode_type) {
3962
0
    assert(mode_idx >= 0 && mode_idx < x->winner_mode_count);
3963
0
    WinnerModeStats *winner_mode_stat = &x->winner_mode_stats[mode_idx];
3964
0
    winner_mbmi = &winner_mode_stat->mbmi;
3965
3966
0
    *winner_rd_cost = &winner_mode_stat->rd_cost;
3967
0
    *winner_rate_y = winner_mode_stat->rate_y;
3968
0
    *winner_rate_uv = winner_mode_stat->rate_uv;
3969
0
    *winner_mode_index = winner_mode_stat->mode_index;
3970
0
  } else {
3971
0
    winner_mbmi = best_mbmode;
3972
0
    *winner_rd_cost = best_rd_cost;
3973
0
    *winner_rate_y = best_rate_y;
3974
0
    *winner_rate_uv = best_rate_uv;
3975
0
    *winner_mode_index = *best_mode_index;
3976
0
  }
3977
0
  return winner_mbmi;
3978
0
}
3979
3980
// speed feature: fast intra/inter transform type search
3981
// Used for speed >= 2
3982
// When this speed feature is on, in rd mode search, only DCT is used.
3983
// After the mode is determined, this function is called, to select
3984
// transform types and get accurate rdcost.
3985
static inline void refine_winner_mode_tx(
3986
    const AV1_COMP *cpi, MACROBLOCK *x, RD_STATS *rd_cost, BLOCK_SIZE bsize,
3987
    PICK_MODE_CONTEXT *ctx, THR_MODES *best_mode_index,
3988
    MB_MODE_INFO *best_mbmode, struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],
3989
0
    int best_rate_y, int best_rate_uv, int *best_skip2, int winner_mode_count) {
3990
0
  const AV1_COMMON *const cm = &cpi->common;
3991
0
  MACROBLOCKD *const xd = &x->e_mbd;
3992
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
3993
0
  TxfmSearchParams *txfm_params = &x->txfm_search_params;
3994
0
  int64_t best_rd;
3995
0
  const int num_planes = av1_num_planes(cm);
3996
3997
0
  if (!is_winner_mode_processing_enabled(cpi, x, best_mbmode,
3998
0
                                         rd_cost->skip_txfm))
3999
0
    return;
4000
4001
  // Set params for winner mode evaluation
4002
0
  set_mode_eval_params(cpi, x, WINNER_MODE_EVAL);
4003
4004
  // No best mode identified so far
4005
0
  if (*best_mode_index == THR_INVALID) return;
4006
4007
0
  best_rd = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
4008
0
  for (int mode_idx = 0; mode_idx < winner_mode_count; mode_idx++) {
4009
0
    RD_STATS *winner_rd_stats = NULL;
4010
0
    int winner_rate_y = 0, winner_rate_uv = 0;
4011
0
    THR_MODES winner_mode_index = 0;
4012
4013
    // TODO(any): Combine best mode and multi-winner mode processing paths
4014
    // Get winner mode stats for current mode index
4015
0
    MB_MODE_INFO *winner_mbmi = get_winner_mode_stats(
4016
0
        x, best_mbmode, rd_cost, best_rate_y, best_rate_uv, best_mode_index,
4017
0
        &winner_rd_stats, &winner_rate_y, &winner_rate_uv, &winner_mode_index,
4018
0
        cpi->sf.winner_mode_sf.multi_winner_mode_type, mode_idx);
4019
4020
0
    if (xd->lossless[winner_mbmi->segment_id] == 0 &&
4021
0
        winner_mode_index != THR_INVALID &&
4022
0
        is_winner_mode_processing_enabled(cpi, x, winner_mbmi,
4023
0
                                          rd_cost->skip_txfm)) {
4024
0
      RD_STATS rd_stats = *winner_rd_stats;
4025
0
      int skip_blk = 0;
4026
0
      RD_STATS rd_stats_y, rd_stats_uv;
4027
0
      const int skip_ctx = av1_get_skip_txfm_context(xd);
4028
4029
0
      *mbmi = *winner_mbmi;
4030
4031
0
      set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4032
4033
      // Select prediction reference frames.
4034
0
      for (int i = 0; i < num_planes; i++) {
4035
0
        xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
4036
0
        if (has_second_ref(mbmi))
4037
0
          xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
4038
0
      }
4039
4040
0
      if (is_inter_mode(mbmi->mode)) {
4041
0
        const int mi_row = xd->mi_row;
4042
0
        const int mi_col = xd->mi_col;
4043
0
        bool is_predictor_built = false;
4044
0
        const PREDICTION_MODE prediction_mode = mbmi->mode;
4045
        // Do interpolation filter search for realtime mode if applicable.
4046
0
        if (cpi->sf.winner_mode_sf.winner_mode_ifs &&
4047
0
            cpi->oxcf.mode == REALTIME &&
4048
0
            cm->current_frame.reference_mode == SINGLE_REFERENCE &&
4049
0
            is_inter_mode(prediction_mode) &&
4050
0
            mbmi->motion_mode == SIMPLE_TRANSLATION &&
4051
0
            !is_inter_compound_mode(prediction_mode)) {
4052
0
          is_predictor_built =
4053
0
              fast_interp_search(cpi, x, mi_row, mi_col, bsize);
4054
0
        }
4055
0
        if (!is_predictor_built) {
4056
0
          av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
4057
0
                                        av1_num_planes(cm) - 1);
4058
0
        }
4059
0
        if (mbmi->motion_mode == OBMC_CAUSAL)
4060
0
          av1_build_obmc_inter_predictors_sb(cm, xd);
4061
4062
0
        av1_subtract_plane(x, bsize, PLANE_TYPE_Y, cpi->do_border_pad);
4063
0
        if (txfm_params->tx_mode_search_type == TX_MODE_SELECT &&
4064
0
            !xd->lossless[mbmi->segment_id]) {
4065
0
          av1_pick_recursive_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize,
4066
0
                                              INT64_MAX);
4067
0
          assert(rd_stats_y.rate != INT_MAX);
4068
0
        } else {
4069
0
          av1_pick_uniform_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize,
4070
0
                                            INT64_MAX);
4071
0
          memset(mbmi->inter_tx_size, mbmi->tx_size,
4072
0
                 sizeof(mbmi->inter_tx_size));
4073
0
        }
4074
0
      } else {
4075
0
        av1_pick_uniform_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize,
4076
0
                                          INT64_MAX);
4077
0
      }
4078
4079
0
      if (num_planes > 1) {
4080
0
        av1_txfm_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
4081
0
      } else {
4082
0
        av1_init_rd_stats(&rd_stats_uv);
4083
0
      }
4084
4085
0
      const int comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
4086
4087
0
      const ModeCosts *mode_costs = &x->mode_costs;
4088
0
      int64_t this_dist = rd_stats_y.dist + rd_stats_uv.dist;
4089
0
      int64_t this_sse = rd_stats_y.sse + rd_stats_uv.sse;
4090
0
      if (cpi->sf.hl_sf.weighted_chroma_distortion) {
4091
0
        this_dist = rd_stats_y.dist + rd_stats_uv.dist * 15 / 16;
4092
0
        this_sse = rd_stats_y.sse + rd_stats_uv.sse * 15 / 16;
4093
0
      }
4094
4095
0
      int64_t no_skip_dist, skip_sse;
4096
0
      av1_get_tx_skip_dist(cpi, x, mbmi->bsize, this_dist, this_sse,
4097
0
                           &no_skip_dist, &skip_sse);
4098
4099
0
      if (is_inter_mode(mbmi->mode) &&
4100
0
          (!cpi->oxcf.algo_cfg.sharpness || !comp_pred) &&
4101
0
          RDCOST(x->rdmult,
4102
0
                 mode_costs->skip_txfm_cost[skip_ctx][0] + rd_stats_y.rate +
4103
0
                     rd_stats_uv.rate,
4104
0
                 no_skip_dist) > RDCOST(x->rdmult,
4105
0
                                        mode_costs->skip_txfm_cost[skip_ctx][1],
4106
0
                                        skip_sse)) {
4107
0
        skip_blk = 1;
4108
0
        rd_stats_y.rate = mode_costs->skip_txfm_cost[skip_ctx][1];
4109
0
        rd_stats_uv.rate = 0;
4110
0
        rd_stats_y.dist = rd_stats_y.sse;
4111
0
        rd_stats_uv.dist = rd_stats_uv.sse;
4112
0
        this_dist = this_sse;
4113
0
      } else {
4114
0
        skip_blk = 0;
4115
0
        rd_stats_y.rate += mode_costs->skip_txfm_cost[skip_ctx][0];
4116
0
      }
4117
0
      increase_motion_mode_rdstats(cpi, mbmi, &rd_stats, &rd_stats_y,
4118
0
                                   &rd_stats_uv);
4119
0
      int this_rate = rd_stats.rate + rd_stats_y.rate + rd_stats_uv.rate -
4120
0
                      winner_rate_y - winner_rate_uv;
4121
0
      int64_t this_rd;
4122
0
#if CONFIG_AV1_HIGHBITDEPTH
4123
0
      if (xd->bd > 8 && cpi->oxcf.algo_cfg.sharpness == 3) {
4124
0
        RD_STATS tmp_rd_stats;
4125
0
        av1_init_rd_stats(&tmp_rd_stats);
4126
0
        tmp_rd_stats.rate = this_rate;
4127
0
        tmp_rd_stats.dist = this_dist;
4128
0
        tmp_rd_stats.sse = this_sse;
4129
0
        tmp_rd_stats.skip_txfm = skip_blk;
4130
0
        adjust_rdcost(cpi, x, &tmp_rd_stats, is_inter_mode(mbmi->mode));
4131
0
        this_rd = tmp_rd_stats.rdcost;
4132
0
        this_dist = tmp_rd_stats.dist;
4133
0
      } else
4134
0
#endif
4135
0
      {
4136
0
        this_rd = RDCOST(x->rdmult, this_rate, this_dist);
4137
0
      }
4138
0
      if (best_rd > this_rd) {
4139
0
        *best_mbmode = *mbmi;
4140
0
        *best_mode_index = winner_mode_index;
4141
0
        av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
4142
0
        rd_cost->rate = this_rate;
4143
0
        rd_cost->dist = this_dist;
4144
0
        rd_cost->sse = this_sse;
4145
0
        rd_cost->rdcost = this_rd;
4146
0
        best_rd = this_rd;
4147
0
        *best_skip2 = skip_blk;
4148
0
      }
4149
0
    }
4150
0
  }
4151
0
}
4152
4153
/*!\cond */
4154
typedef struct {
4155
  // Mask for each reference frame, specifying which prediction modes to NOT try
4156
  // during search.
4157
  uint32_t pred_modes[REF_FRAMES];
4158
  // If ref_combo[i][j + 1] is true, do NOT try prediction using combination of
4159
  // reference frames (i, j).
4160
  // Note: indexing with 'j + 1' is due to the fact that 2nd reference can be -1
4161
  // (NONE_FRAME).
4162
  bool ref_combo[REF_FRAMES][REF_FRAMES + 1];
4163
} mode_skip_mask_t;
4164
/*!\endcond */
4165
4166
// Update 'ref_combo' mask to disable given 'ref' in single and compound modes.
4167
static inline void disable_reference(
4168
0
    MV_REFERENCE_FRAME ref, bool ref_combo[REF_FRAMES][REF_FRAMES + 1]) {
4169
0
  for (MV_REFERENCE_FRAME ref2 = NONE_FRAME; ref2 < REF_FRAMES; ++ref2) {
4170
0
    ref_combo[ref][ref2 + 1] = true;
4171
0
  }
4172
0
}
4173
4174
// Update 'ref_combo' mask to disable all inter references except ALTREF.
4175
static inline void disable_inter_references_except_altref(
4176
0
    bool ref_combo[REF_FRAMES][REF_FRAMES + 1]) {
4177
0
  disable_reference(LAST_FRAME, ref_combo);
4178
0
  disable_reference(LAST2_FRAME, ref_combo);
4179
0
  disable_reference(LAST3_FRAME, ref_combo);
4180
0
  disable_reference(GOLDEN_FRAME, ref_combo);
4181
0
  disable_reference(BWDREF_FRAME, ref_combo);
4182
0
  disable_reference(ALTREF2_FRAME, ref_combo);
4183
0
}
4184
4185
static const MV_REFERENCE_FRAME reduced_ref_combos[][2] = {
4186
  { LAST_FRAME, NONE_FRAME },     { ALTREF_FRAME, NONE_FRAME },
4187
  { LAST_FRAME, ALTREF_FRAME },   { GOLDEN_FRAME, NONE_FRAME },
4188
  { INTRA_FRAME, NONE_FRAME },    { GOLDEN_FRAME, ALTREF_FRAME },
4189
  { LAST_FRAME, GOLDEN_FRAME },   { LAST_FRAME, INTRA_FRAME },
4190
  { LAST_FRAME, BWDREF_FRAME },   { LAST_FRAME, LAST3_FRAME },
4191
  { GOLDEN_FRAME, BWDREF_FRAME }, { GOLDEN_FRAME, INTRA_FRAME },
4192
  { BWDREF_FRAME, NONE_FRAME },   { BWDREF_FRAME, ALTREF_FRAME },
4193
  { ALTREF_FRAME, INTRA_FRAME },  { BWDREF_FRAME, INTRA_FRAME },
4194
};
4195
4196
typedef enum { REF_SET_FULL, REF_SET_REDUCED, REF_SET_REALTIME } REF_SET;
4197
4198
0
static inline void default_skip_mask(mode_skip_mask_t *mask, REF_SET ref_set) {
4199
0
  if (ref_set == REF_SET_FULL) {
4200
    // Everything available by default.
4201
0
    memset(mask, 0, sizeof(*mask));
4202
0
  } else {
4203
    // All modes available by default.
4204
0
    memset(mask->pred_modes, 0, sizeof(mask->pred_modes));
4205
    // All references disabled first.
4206
0
    for (MV_REFERENCE_FRAME ref1 = INTRA_FRAME; ref1 < REF_FRAMES; ++ref1) {
4207
0
      for (MV_REFERENCE_FRAME ref2 = NONE_FRAME; ref2 < REF_FRAMES; ++ref2) {
4208
0
        mask->ref_combo[ref1][ref2 + 1] = true;
4209
0
      }
4210
0
    }
4211
0
    const MV_REFERENCE_FRAME(*ref_set_combos)[2];
4212
0
    int num_ref_combos;
4213
4214
    // Then enable reduced set of references explicitly.
4215
0
    switch (ref_set) {
4216
0
      case REF_SET_REDUCED:
4217
0
        ref_set_combos = reduced_ref_combos;
4218
0
        num_ref_combos =
4219
0
            (int)sizeof(reduced_ref_combos) / sizeof(reduced_ref_combos[0]);
4220
0
        break;
4221
0
      case REF_SET_REALTIME:
4222
0
        ref_set_combos = real_time_ref_combos;
4223
0
        num_ref_combos =
4224
0
            (int)sizeof(real_time_ref_combos) / sizeof(real_time_ref_combos[0]);
4225
0
        break;
4226
0
      default: assert(0); num_ref_combos = 0;
4227
0
    }
4228
4229
0
    for (int i = 0; i < num_ref_combos; ++i) {
4230
0
      const MV_REFERENCE_FRAME *const this_combo = ref_set_combos[i];
4231
0
      mask->ref_combo[this_combo[0]][this_combo[1] + 1] = false;
4232
0
    }
4233
0
  }
4234
0
}
4235
4236
static inline void init_mode_skip_mask(mode_skip_mask_t *mask,
4237
                                       const AV1_COMP *cpi, MACROBLOCK *x,
4238
0
                                       BLOCK_SIZE bsize) {
4239
0
  const AV1_COMMON *const cm = &cpi->common;
4240
0
  const struct segmentation *const seg = &cm->seg;
4241
0
  MACROBLOCKD *const xd = &x->e_mbd;
4242
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
4243
0
  unsigned char segment_id = mbmi->segment_id;
4244
0
  const SPEED_FEATURES *const sf = &cpi->sf;
4245
0
  const INTER_MODE_SPEED_FEATURES *const inter_sf = &sf->inter_sf;
4246
0
  REF_SET ref_set = REF_SET_FULL;
4247
4248
0
  if (sf->rt_sf.use_real_time_ref_set)
4249
0
    ref_set = REF_SET_REALTIME;
4250
0
  else if (cpi->oxcf.ref_frm_cfg.enable_reduced_reference_set)
4251
0
    ref_set = REF_SET_REDUCED;
4252
4253
0
  default_skip_mask(mask, ref_set);
4254
4255
0
  int min_pred_mv_sad = INT_MAX;
4256
0
  MV_REFERENCE_FRAME ref_frame;
4257
0
  if (ref_set == REF_SET_REALTIME) {
4258
    // For real-time encoding, we only look at a subset of ref frames. So the
4259
    // threshold for pruning should be computed from this subset as well.
4260
0
    const int num_rt_refs =
4261
0
        sizeof(real_time_ref_combos) / sizeof(*real_time_ref_combos);
4262
0
    for (int r_idx = 0; r_idx < num_rt_refs; r_idx++) {
4263
0
      const MV_REFERENCE_FRAME ref = real_time_ref_combos[r_idx][0];
4264
0
      if (ref != INTRA_FRAME) {
4265
0
        const MV_REFERENCE_FRAME ref_frames[2] = { ref, NONE_FRAME };
4266
0
        const int_mv ref_mv =
4267
0
            av1_get_ref_mv_from_stack(0, ref_frames, 0, &x->mbmi_ext);
4268
0
        const FULLPEL_MV full_mv = get_fullmv_from_mv(&ref_mv.as_mv);
4269
0
        if (av1_is_fullmv_in_range(&x->mv_limits, full_mv)) {
4270
0
          min_pred_mv_sad = AOMMIN(min_pred_mv_sad, x->pred_mv_sad[ref]);
4271
0
        }
4272
0
      }
4273
0
    }
4274
0
  } else {
4275
0
    for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame)
4276
0
      min_pred_mv_sad = AOMMIN(min_pred_mv_sad, x->pred_mv_sad[ref_frame]);
4277
0
  }
4278
4279
0
  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
4280
0
    if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame])) {
4281
      // Skip checking missing reference in both single and compound reference
4282
      // modes.
4283
0
      disable_reference(ref_frame, mask->ref_combo);
4284
0
    } else {
4285
      // Skip fixed mv modes for poor references
4286
0
      if ((x->pred_mv_sad[ref_frame] >> 2) > min_pred_mv_sad) {
4287
0
        mask->pred_modes[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
4288
0
      }
4289
0
    }
4290
0
    if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
4291
0
        get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
4292
      // Reference not used for the segment.
4293
0
      disable_reference(ref_frame, mask->ref_combo);
4294
0
    }
4295
0
  }
4296
  // Note: We use the following drop-out only if the SEG_LVL_REF_FRAME feature
4297
  // is disabled for this segment. This is to prevent the possibility that we
4298
  // end up unable to pick any mode.
4299
0
  if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
4300
    // Only consider GLOBALMV/ALTREF_FRAME for alt ref frame,
4301
    // unless ARNR filtering is enabled in which case we want
4302
    // an unfiltered alternative. We allow near/nearest as well
4303
    // because they may result in zero-zero MVs but be cheaper.
4304
0
    if (cpi->rc.is_src_frame_alt_ref &&
4305
0
        (cpi->oxcf.algo_cfg.arnr_max_frames == 0)) {
4306
0
      disable_inter_references_except_altref(mask->ref_combo);
4307
4308
0
      mask->pred_modes[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
4309
0
      const MV_REFERENCE_FRAME tmp_ref_frames[2] = { ALTREF_FRAME, NONE_FRAME };
4310
0
      int_mv near_mv, nearest_mv, global_mv;
4311
0
      get_this_mv(&nearest_mv, NEARESTMV, 0, 0, 0, tmp_ref_frames,
4312
0
                  &x->mbmi_ext);
4313
0
      get_this_mv(&near_mv, NEARMV, 0, 0, 0, tmp_ref_frames, &x->mbmi_ext);
4314
0
      get_this_mv(&global_mv, GLOBALMV, 0, 0, 0, tmp_ref_frames, &x->mbmi_ext);
4315
4316
0
      if (near_mv.as_int != global_mv.as_int)
4317
0
        mask->pred_modes[ALTREF_FRAME] |= (1 << NEARMV);
4318
0
      if (nearest_mv.as_int != global_mv.as_int)
4319
0
        mask->pred_modes[ALTREF_FRAME] |= (1 << NEARESTMV);
4320
0
    }
4321
0
  }
4322
4323
0
  if (cpi->rc.is_src_frame_alt_ref) {
4324
0
    if (inter_sf->alt_ref_search_fp &&
4325
0
        (cpi->ref_frame_flags & av1_ref_frame_flag_list[ALTREF_FRAME])) {
4326
0
      mask->pred_modes[ALTREF_FRAME] = 0;
4327
0
      disable_inter_references_except_altref(mask->ref_combo);
4328
0
      disable_reference(INTRA_FRAME, mask->ref_combo);
4329
0
    }
4330
0
  }
4331
4332
0
  if (inter_sf->alt_ref_search_fp) {
4333
0
    if (!cm->show_frame && x->best_pred_mv_sad[0] < INT_MAX) {
4334
0
      int sad_thresh = x->best_pred_mv_sad[0] + (x->best_pred_mv_sad[0] >> 3);
4335
      // Conservatively skip the modes w.r.t. BWDREF, ALTREF2 and ALTREF, if
4336
      // those are past frames
4337
0
      MV_REFERENCE_FRAME start_frame =
4338
0
          inter_sf->alt_ref_search_fp == 1 ? ALTREF2_FRAME : BWDREF_FRAME;
4339
0
      for (ref_frame = start_frame; ref_frame <= ALTREF_FRAME; ref_frame++) {
4340
0
        if (cpi->ref_frame_dist_info.ref_relative_dist[ref_frame - LAST_FRAME] <
4341
0
            0) {
4342
          // Prune inter modes when relative dist of ALTREF2 and ALTREF is close
4343
          // to the relative dist of LAST_FRAME.
4344
0
          if (abs(cpi->ref_frame_dist_info
4345
0
                      .ref_relative_dist[ref_frame - LAST_FRAME] -
4346
0
                  cpi->ref_frame_dist_info
4347
0
                      .ref_relative_dist[LAST_FRAME - LAST_FRAME]) > 4) {
4348
0
            continue;
4349
0
          }
4350
0
          if (x->pred_mv_sad[ref_frame] > sad_thresh)
4351
0
            mask->pred_modes[ref_frame] |= INTER_ALL;
4352
0
        }
4353
0
      }
4354
0
    }
4355
0
  }
4356
4357
0
  if (sf->rt_sf.prune_inter_modes_wrt_gf_arf_based_on_sad) {
4358
0
    if (x->best_pred_mv_sad[0] < INT_MAX) {
4359
0
      int sad_thresh = x->best_pred_mv_sad[0] + (x->best_pred_mv_sad[0] >> 1);
4360
0
      const int prune_ref_list[2] = { GOLDEN_FRAME, ALTREF_FRAME };
4361
4362
      // Conservatively skip the modes w.r.t. GOLDEN and ALTREF references
4363
0
      for (int ref_idx = 0; ref_idx < 2; ref_idx++) {
4364
0
        ref_frame = prune_ref_list[ref_idx];
4365
0
        if (x->pred_mv_sad[ref_frame] > sad_thresh)
4366
0
          mask->pred_modes[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
4367
0
      }
4368
0
    }
4369
0
  }
4370
4371
0
  if (bsize > sf->part_sf.max_intra_bsize) {
4372
0
    disable_reference(INTRA_FRAME, mask->ref_combo);
4373
0
  }
4374
4375
0
  if (!cpi->oxcf.tool_cfg.enable_global_motion) {
4376
0
    for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
4377
0
      mask->pred_modes[ref_frame] |= (1 << GLOBALMV);
4378
0
      mask->pred_modes[ref_frame] |= (1 << GLOBAL_GLOBALMV);
4379
0
    }
4380
0
  }
4381
4382
0
  mask->pred_modes[INTRA_FRAME] |=
4383
0
      ~(uint32_t)sf->intra_sf.intra_y_mode_mask[max_txsize_lookup[bsize]];
4384
4385
  // Prune reference frames which are not the closest to the current
4386
  // frame and with large pred_mv_sad.
4387
0
  if (inter_sf->prune_single_ref) {
4388
0
    assert(inter_sf->prune_single_ref > 0 && inter_sf->prune_single_ref < 5);
4389
0
    const double prune_thresh = (inter_sf->prune_single_ref <= 3) ? 1.20 : 1.05;
4390
4391
0
    for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
4392
0
      const RefFrameDistanceInfo *const ref_frame_dist_info =
4393
0
          &cpi->ref_frame_dist_info;
4394
0
      const int is_closest_ref =
4395
0
          (ref_frame == ref_frame_dist_info->nearest_past_ref) ||
4396
0
          (ref_frame == ref_frame_dist_info->nearest_future_ref);
4397
0
      const int ref_idx = ref_frame - LAST_FRAME;
4398
4399
0
      if (!(cpi->keep_single_ref_frame_mask & (1 << ref_idx) ||
4400
0
            is_closest_ref)) {
4401
0
        const int dir =
4402
0
            (ref_frame_dist_info->ref_relative_dist[ref_frame - LAST_FRAME] < 0)
4403
0
                ? 0
4404
0
                : 1;
4405
0
        if (x->best_pred_mv_sad[dir] < INT_MAX &&
4406
0
            x->pred_mv_sad[ref_frame] > prune_thresh * x->best_pred_mv_sad[dir])
4407
0
          mask->pred_modes[ref_frame] |= INTER_SINGLE_ALL;
4408
0
      }
4409
0
    }
4410
0
  }
4411
0
}
4412
4413
static inline void init_neighbor_pred_buf(const OBMCBuffer *const obmc_buffer,
4414
                                          HandleInterModeArgs *const args,
4415
0
                                          int is_hbd) {
4416
0
  if (is_hbd) {
4417
0
    const int len = sizeof(uint16_t);
4418
0
    args->above_pred_buf[0] = CONVERT_TO_BYTEPTR(obmc_buffer->above_pred);
4419
0
    args->above_pred_buf[1] = CONVERT_TO_BYTEPTR(obmc_buffer->above_pred +
4420
0
                                                 (MAX_SB_SQUARE >> 1) * len);
4421
0
    args->above_pred_buf[2] =
4422
0
        CONVERT_TO_BYTEPTR(obmc_buffer->above_pred + MAX_SB_SQUARE * len);
4423
0
    args->left_pred_buf[0] = CONVERT_TO_BYTEPTR(obmc_buffer->left_pred);
4424
0
    args->left_pred_buf[1] =
4425
0
        CONVERT_TO_BYTEPTR(obmc_buffer->left_pred + (MAX_SB_SQUARE >> 1) * len);
4426
0
    args->left_pred_buf[2] =
4427
0
        CONVERT_TO_BYTEPTR(obmc_buffer->left_pred + MAX_SB_SQUARE * len);
4428
0
  } else {
4429
0
    args->above_pred_buf[0] = obmc_buffer->above_pred;
4430
0
    args->above_pred_buf[1] = obmc_buffer->above_pred + (MAX_SB_SQUARE >> 1);
4431
0
    args->above_pred_buf[2] = obmc_buffer->above_pred + MAX_SB_SQUARE;
4432
0
    args->left_pred_buf[0] = obmc_buffer->left_pred;
4433
0
    args->left_pred_buf[1] = obmc_buffer->left_pred + (MAX_SB_SQUARE >> 1);
4434
0
    args->left_pred_buf[2] = obmc_buffer->left_pred + MAX_SB_SQUARE;
4435
0
  }
4436
0
}
4437
4438
static inline int prune_ref_frame(const AV1_COMP *cpi, const MACROBLOCK *x,
4439
0
                                  MV_REFERENCE_FRAME ref_frame) {
4440
0
  const AV1_COMMON *const cm = &cpi->common;
4441
0
  MV_REFERENCE_FRAME rf[2];
4442
0
  av1_set_ref_frame(rf, ref_frame);
4443
4444
0
  if ((cpi->prune_ref_frame_mask >> ref_frame) & 1) return 1;
4445
4446
0
  if (prune_ref_by_selective_ref_frame(cpi, x, rf,
4447
0
                                       cm->cur_frame->ref_display_order_hint)) {
4448
0
    return 1;
4449
0
  }
4450
4451
0
  return 0;
4452
0
}
4453
4454
static inline int is_ref_frame_used_by_compound_ref(int ref_frame,
4455
0
                                                    int skip_ref_frame_mask) {
4456
0
  for (int r = ALTREF_FRAME + 1; r < MODE_CTX_REF_FRAMES; ++r) {
4457
0
    if (!(skip_ref_frame_mask & (1 << r))) {
4458
0
      const MV_REFERENCE_FRAME *rf = ref_frame_map[r - REF_FRAMES];
4459
0
      if (rf[0] == ref_frame || rf[1] == ref_frame) {
4460
0
        return 1;
4461
0
      }
4462
0
    }
4463
0
  }
4464
0
  return 0;
4465
0
}
4466
4467
static inline int is_ref_frame_used_in_cache(MV_REFERENCE_FRAME ref_frame,
4468
0
                                             const MB_MODE_INFO *mi_cache) {
4469
0
  if (!mi_cache) {
4470
0
    return 0;
4471
0
  }
4472
4473
0
  if (ref_frame < REF_FRAMES) {
4474
0
    return (ref_frame == mi_cache->ref_frame[0] ||
4475
0
            ref_frame == mi_cache->ref_frame[1]);
4476
0
  }
4477
4478
  // if we are here, then the current mode is compound.
4479
0
  MV_REFERENCE_FRAME cached_ref_type = av1_ref_frame_type(mi_cache->ref_frame);
4480
0
  return ref_frame == cached_ref_type;
4481
0
}
4482
4483
// Please add/modify parameter setting in this function, making it consistent
4484
// and easy to read and maintain.
4485
static inline void set_params_rd_pick_inter_mode(
4486
    const AV1_COMP *cpi, MACROBLOCK *x, HandleInterModeArgs *args,
4487
    BLOCK_SIZE bsize, mode_skip_mask_t *mode_skip_mask, int skip_ref_frame_mask,
4488
    unsigned int *ref_costs_single, unsigned int (*ref_costs_comp)[REF_FRAMES],
4489
0
    struct buf_2d (*yv12_mb)[MAX_MB_PLANE]) {
4490
0
  const AV1_COMMON *const cm = &cpi->common;
4491
0
  MACROBLOCKD *const xd = &x->e_mbd;
4492
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
4493
0
  MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
4494
0
  unsigned char segment_id = mbmi->segment_id;
4495
4496
0
  init_neighbor_pred_buf(&x->obmc_buffer, args, is_cur_buf_hbd(&x->e_mbd));
4497
0
  av1_collect_neighbors_ref_counts(xd);
4498
0
  estimate_ref_frame_costs(cm, xd, &x->mode_costs, segment_id, ref_costs_single,
4499
0
                           ref_costs_comp);
4500
4501
0
  const int mi_row = xd->mi_row;
4502
0
  const int mi_col = xd->mi_col;
4503
0
  x->best_pred_mv_sad[0] = INT_MAX;
4504
0
  x->best_pred_mv_sad[1] = INT_MAX;
4505
4506
0
  for (MV_REFERENCE_FRAME ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME;
4507
0
       ++ref_frame) {
4508
0
    x->pred_mv_sad[ref_frame] = INT_MAX;
4509
0
    mbmi_ext->mode_context[ref_frame] = 0;
4510
0
    mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
4511
0
    if (cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
4512
      // Skip the ref frame if the mask says skip and the ref is not used by
4513
      // compound ref.
4514
0
      if (skip_ref_frame_mask & (1 << ref_frame) &&
4515
0
          !is_ref_frame_used_by_compound_ref(ref_frame, skip_ref_frame_mask) &&
4516
0
          !is_ref_frame_used_in_cache(ref_frame, x->mb_mode_cache)) {
4517
0
        continue;
4518
0
      }
4519
0
      assert(get_ref_frame_yv12_buf(cm, ref_frame) != NULL);
4520
0
      setup_buffer_ref_mvs_inter(cpi, x, ref_frame, bsize, yv12_mb);
4521
0
    }
4522
0
    if (cpi->sf.inter_sf.alt_ref_search_fp ||
4523
0
        cpi->sf.inter_sf.prune_single_ref ||
4524
0
        cpi->sf.rt_sf.prune_inter_modes_wrt_gf_arf_based_on_sad) {
4525
      // Store the best pred_mv_sad across all past frames
4526
0
      if (cpi->ref_frame_dist_info.ref_relative_dist[ref_frame - LAST_FRAME] <
4527
0
          0)
4528
0
        x->best_pred_mv_sad[0] =
4529
0
            AOMMIN(x->best_pred_mv_sad[0], x->pred_mv_sad[ref_frame]);
4530
0
      else
4531
        // Store the best pred_mv_sad across all future frames
4532
0
        x->best_pred_mv_sad[1] =
4533
0
            AOMMIN(x->best_pred_mv_sad[1], x->pred_mv_sad[ref_frame]);
4534
0
    }
4535
0
  }
4536
4537
0
  if (!cpi->sf.rt_sf.use_real_time_ref_set && is_comp_ref_allowed(bsize)) {
4538
    // No second reference on RT ref set, so no need to initialize
4539
0
    for (MV_REFERENCE_FRAME ref_frame = EXTREF_FRAME;
4540
0
         ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {
4541
0
      mbmi_ext->mode_context[ref_frame] = 0;
4542
0
      mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
4543
0
      const MV_REFERENCE_FRAME *rf = ref_frame_map[ref_frame - REF_FRAMES];
4544
0
      if (!((cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[0]]) &&
4545
0
            (cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[1]]))) {
4546
0
        continue;
4547
0
      }
4548
4549
0
      if (skip_ref_frame_mask & (1 << ref_frame) &&
4550
0
          !is_ref_frame_used_in_cache(ref_frame, x->mb_mode_cache)) {
4551
0
        continue;
4552
0
      }
4553
      // Ref mv list population is not required, when compound references are
4554
      // pruned.
4555
0
      if (prune_ref_frame(cpi, x, ref_frame)) continue;
4556
4557
0
      av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
4558
0
                       xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
4559
0
                       mbmi_ext->mode_context);
4560
      // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
4561
      // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
4562
0
      av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
4563
0
    }
4564
0
  }
4565
4566
0
  av1_count_overlappable_neighbors(cm, xd);
4567
0
  const FRAME_UPDATE_TYPE update_type =
4568
0
      get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
4569
0
  int use_actual_frame_probs = 1;
4570
0
  int prune_obmc;
4571
#if CONFIG_FPMT_TEST
4572
  use_actual_frame_probs =
4573
      (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) ? 0 : 1;
4574
  if (!use_actual_frame_probs) {
4575
    prune_obmc = cpi->ppi->temp_frame_probs.obmc_probs[update_type][bsize] <
4576
                 cpi->sf.inter_sf.prune_obmc_prob_thresh;
4577
  }
4578
#endif
4579
0
  if (use_actual_frame_probs) {
4580
0
    prune_obmc = cpi->ppi->frame_probs.obmc_probs[update_type][bsize] <
4581
0
                 cpi->sf.inter_sf.prune_obmc_prob_thresh;
4582
0
  }
4583
0
  if (cpi->oxcf.motion_mode_cfg.enable_obmc && !prune_obmc) {
4584
0
    if (check_num_overlappable_neighbors(mbmi) &&
4585
0
        is_motion_variation_allowed_bsize(bsize)) {
4586
0
      int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
4587
0
      int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
4588
0
                                       MAX_SB_SIZE >> 1 };
4589
0
      int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
4590
0
                                        MAX_SB_SIZE >> 1 };
4591
0
      int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
4592
0
      av1_build_prediction_by_above_preds(cm, xd, args->above_pred_buf,
4593
0
                                          dst_width1, dst_height1,
4594
0
                                          args->above_pred_stride);
4595
0
      av1_build_prediction_by_left_preds(cm, xd, args->left_pred_buf,
4596
0
                                         dst_width2, dst_height2,
4597
0
                                         args->left_pred_stride);
4598
0
      const int num_planes = av1_num_planes(cm);
4599
0
      av1_setup_dst_planes(xd->plane, bsize, &cm->cur_frame->buf, mi_row,
4600
0
                           mi_col, 0, num_planes);
4601
0
      calc_target_weighted_pred(
4602
0
          cm, x, xd, args->above_pred_buf[0], args->above_pred_stride[0],
4603
0
          args->left_pred_buf[0], args->left_pred_stride[0]);
4604
0
    }
4605
0
  }
4606
4607
0
  init_mode_skip_mask(mode_skip_mask, cpi, x, bsize);
4608
4609
  // Set params for mode evaluation
4610
0
  set_mode_eval_params(cpi, x, MODE_EVAL);
4611
4612
0
  x->comp_rd_stats_idx = 0;
4613
4614
0
  for (int idx = 0; idx < REF_FRAMES; idx++) {
4615
0
    args->best_single_sse_in_refs[idx] = INT32_MAX;
4616
0
  }
4617
0
}
4618
4619
static inline void init_single_inter_mode_search_state(
4620
0
    InterModeSearchState *search_state) {
4621
0
  for (int dir = 0; dir < 2; ++dir) {
4622
0
    for (int mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
4623
0
      for (int ref_frame = 0; ref_frame < FWD_REFS; ++ref_frame) {
4624
0
        SingleInterModeState *state;
4625
4626
0
        state = &search_state->single_state[dir][mode][ref_frame];
4627
0
        state->ref_frame = NONE_FRAME;
4628
0
        state->rd = INT64_MAX;
4629
4630
0
        state = &search_state->single_state_modelled[dir][mode][ref_frame];
4631
0
        state->ref_frame = NONE_FRAME;
4632
0
        state->rd = INT64_MAX;
4633
4634
0
        search_state->single_rd_order[dir][mode][ref_frame] = NONE_FRAME;
4635
0
      }
4636
0
    }
4637
0
  }
4638
4639
0
  for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
4640
0
    search_state->best_single_rd[ref_frame] = INT64_MAX;
4641
0
    search_state->best_single_mode[ref_frame] = PRED_MODE_INVALID;
4642
0
  }
4643
0
  av1_zero(search_state->single_state_cnt);
4644
0
  av1_zero(search_state->single_state_modelled_cnt);
4645
0
}
4646
4647
static inline void init_inter_mode_search_state(
4648
    InterModeSearchState *search_state, const AV1_COMP *cpi,
4649
0
    const MACROBLOCK *x, BLOCK_SIZE bsize, int64_t best_rd_so_far) {
4650
0
  init_intra_mode_search_state(&search_state->intra_search_state);
4651
0
  av1_invalid_rd_stats(&search_state->best_y_rdcost);
4652
4653
0
  search_state->best_rd = best_rd_so_far;
4654
0
  search_state->best_skip_rd[0] = INT64_MAX;
4655
0
  search_state->best_skip_rd[1] = INT64_MAX;
4656
4657
0
  av1_zero(search_state->best_mbmode);
4658
4659
0
  search_state->best_rate_y = INT_MAX;
4660
4661
0
  search_state->best_rate_uv = INT_MAX;
4662
4663
0
  search_state->best_mode_skippable = 0;
4664
4665
0
  search_state->best_skip2 = 0;
4666
4667
0
  search_state->best_mode_index = THR_INVALID;
4668
4669
0
  const MACROBLOCKD *const xd = &x->e_mbd;
4670
0
  const MB_MODE_INFO *const mbmi = xd->mi[0];
4671
0
  const unsigned char segment_id = mbmi->segment_id;
4672
4673
0
  search_state->num_available_refs = 0;
4674
0
  memset(search_state->dist_refs, -1, sizeof(search_state->dist_refs));
4675
0
  memset(search_state->dist_order_refs, -1,
4676
0
         sizeof(search_state->dist_order_refs));
4677
4678
0
  for (int i = 0; i <= LAST_NEW_MV_INDEX; ++i)
4679
0
    search_state->mode_threshold[i] = 0;
4680
0
  const int *const rd_threshes = cpi->rd.threshes[segment_id][bsize];
4681
0
  for (int i = LAST_NEW_MV_INDEX + 1; i < SINGLE_REF_MODE_END; ++i)
4682
0
    search_state->mode_threshold[i] =
4683
0
        ((int64_t)rd_threshes[i] * x->thresh_freq_fact[bsize][i]) >>
4684
0
        RD_THRESH_FAC_FRAC_BITS;
4685
4686
0
  search_state->best_intra_rd = INT64_MAX;
4687
4688
0
  search_state->best_pred_sse = UINT_MAX;
4689
4690
0
  av1_zero(search_state->single_newmv);
4691
0
  av1_zero(search_state->single_newmv_rate);
4692
0
  av1_zero(search_state->single_newmv_valid);
4693
0
  for (int i = SINGLE_INTER_MODE_START; i < SINGLE_INTER_MODE_END; ++i) {
4694
0
    for (int j = 0; j < MAX_REF_MV_SEARCH; ++j) {
4695
0
      for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
4696
0
        search_state->modelled_rd[i][j][ref_frame] = INT64_MAX;
4697
0
        search_state->simple_rd[i][j][ref_frame] = INT64_MAX;
4698
0
      }
4699
0
    }
4700
0
  }
4701
4702
0
  for (int i = 0; i < REFERENCE_MODES; ++i) {
4703
0
    search_state->best_pred_rd[i] = INT64_MAX;
4704
0
  }
4705
4706
0
  if (cpi->common.current_frame.reference_mode != SINGLE_REFERENCE) {
4707
0
    for (int i = SINGLE_REF_MODE_END; i < THR_INTER_MODE_END; ++i)
4708
0
      search_state->mode_threshold[i] =
4709
0
          ((int64_t)rd_threshes[i] * x->thresh_freq_fact[bsize][i]) >>
4710
0
          RD_THRESH_FAC_FRAC_BITS;
4711
4712
0
    for (int i = COMP_INTER_MODE_START; i < COMP_INTER_MODE_END; ++i) {
4713
0
      for (int j = 0; j < MAX_REF_MV_SEARCH; ++j) {
4714
0
        for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
4715
0
          search_state->modelled_rd[i][j][ref_frame] = INT64_MAX;
4716
0
          search_state->simple_rd[i][j][ref_frame] = INT64_MAX;
4717
0
        }
4718
0
      }
4719
0
    }
4720
4721
0
    init_single_inter_mode_search_state(search_state);
4722
0
  }
4723
0
}
4724
4725
static bool mask_says_skip(const mode_skip_mask_t *mode_skip_mask,
4726
                           const MV_REFERENCE_FRAME *ref_frame,
4727
0
                           const PREDICTION_MODE this_mode) {
4728
0
  if (mode_skip_mask->pred_modes[ref_frame[0]] & (1 << this_mode)) {
4729
0
    return true;
4730
0
  }
4731
4732
0
  return mode_skip_mask->ref_combo[ref_frame[0]][ref_frame[1] + 1];
4733
0
}
4734
4735
static AOM_FORCE_INLINE int inter_mode_compatible_skip(
4736
    const AV1_COMP *cpi, const MACROBLOCK *x, BLOCK_SIZE bsize,
4737
0
    PREDICTION_MODE curr_mode, const MV_REFERENCE_FRAME *ref_frames) {
4738
0
  const int comp_pred = ref_frames[1] > INTRA_FRAME;
4739
0
  if (comp_pred) {
4740
0
    if (!is_comp_ref_allowed(bsize)) return 1;
4741
0
    if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frames[1]])) {
4742
0
      return 1;
4743
0
    }
4744
4745
0
    const AV1_COMMON *const cm = &cpi->common;
4746
0
    if (frame_is_intra_only(cm)) return 1;
4747
4748
0
    const CurrentFrame *const current_frame = &cm->current_frame;
4749
0
    if (current_frame->reference_mode == SINGLE_REFERENCE) return 1;
4750
4751
0
    const struct segmentation *const seg = &cm->seg;
4752
0
    const unsigned char segment_id = x->e_mbd.mi[0]->segment_id;
4753
    // Do not allow compound prediction if the segment level reference frame
4754
    // feature is in use as in this case there can only be one reference.
4755
0
    if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) return 1;
4756
0
  }
4757
4758
0
  if (ref_frames[0] > INTRA_FRAME && ref_frames[1] == INTRA_FRAME) {
4759
    // Mode must be compatible
4760
0
    if (!is_interintra_allowed_bsize(bsize)) return 1;
4761
0
    if (!is_interintra_allowed_mode(curr_mode)) return 1;
4762
0
  }
4763
4764
0
  return 0;
4765
0
}
4766
4767
static int fetch_picked_ref_frames_mask(const MACROBLOCK *const x,
4768
0
                                        BLOCK_SIZE bsize, int mib_size) {
4769
0
  const int sb_size_mask = mib_size - 1;
4770
0
  const MACROBLOCKD *const xd = &x->e_mbd;
4771
0
  const int mi_row = xd->mi_row;
4772
0
  const int mi_col = xd->mi_col;
4773
0
  const int mi_row_in_sb = mi_row & sb_size_mask;
4774
0
  const int mi_col_in_sb = mi_col & sb_size_mask;
4775
0
  const int mi_w = mi_size_wide[bsize];
4776
0
  const int mi_h = mi_size_high[bsize];
4777
0
  int picked_ref_frames_mask = 0;
4778
0
  for (int i = mi_row_in_sb; i < mi_row_in_sb + mi_h; ++i) {
4779
0
    for (int j = mi_col_in_sb; j < mi_col_in_sb + mi_w; ++j) {
4780
0
      picked_ref_frames_mask |= x->picked_ref_frames_mask[i * 32 + j];
4781
0
    }
4782
0
  }
4783
0
  return picked_ref_frames_mask;
4784
0
}
4785
4786
// Check if reference frame pair of the current block matches with the given
4787
// block.
4788
static inline int match_ref_frame_pair(const MB_MODE_INFO *mbmi,
4789
0
                                       const MV_REFERENCE_FRAME *ref_frames) {
4790
0
  return ((ref_frames[0] == mbmi->ref_frame[0]) &&
4791
0
          (ref_frames[1] == mbmi->ref_frame[1]));
4792
0
}
4793
4794
// Case 1: return 0, means don't skip this mode
4795
// Case 2: return 1, means skip this mode completely
4796
// Case 3: return 2, means skip compound only, but still try single motion modes
4797
static AOM_FORCE_INLINE int inter_mode_search_order_independent_skip(
4798
    const AV1_COMP *cpi, const MACROBLOCK *x, mode_skip_mask_t *mode_skip_mask,
4799
    InterModeSearchState *search_state, int skip_ref_frame_mask,
4800
0
    PREDICTION_MODE mode, const MV_REFERENCE_FRAME *ref_frame) {
4801
0
  if (mask_says_skip(mode_skip_mask, ref_frame, mode)) {
4802
0
    return 1;
4803
0
  }
4804
4805
0
  const int ref_type = av1_ref_frame_type(ref_frame);
4806
0
  if (!cpi->sf.rt_sf.use_real_time_ref_set)
4807
0
    if (prune_ref_frame(cpi, x, ref_type)) return 1;
4808
4809
  // This is only used in motion vector unit test.
4810
0
  if (cpi->oxcf.unit_test_cfg.motion_vector_unit_test &&
4811
0
      ref_frame[0] == INTRA_FRAME)
4812
0
    return 1;
4813
4814
0
  const AV1_COMMON *const cm = &cpi->common;
4815
0
  if (skip_repeated_mv(cm, x, mode, ref_frame, search_state)) {
4816
0
    return 1;
4817
0
  }
4818
4819
  // Reuse the prediction mode in cache
4820
0
  if (x->use_mb_mode_cache) {
4821
0
    const MB_MODE_INFO *cached_mi = x->mb_mode_cache;
4822
0
    const PREDICTION_MODE cached_mode = cached_mi->mode;
4823
0
    const MV_REFERENCE_FRAME *cached_frame = cached_mi->ref_frame;
4824
0
    const int cached_mode_is_single = cached_frame[1] <= INTRA_FRAME;
4825
4826
    // If the cached mode is intra, then we just need to match the mode.
4827
0
    if (is_mode_intra(cached_mode) && mode != cached_mode) {
4828
0
      return 1;
4829
0
    }
4830
4831
    // If the cached mode is single inter mode, then we match the mode and
4832
    // reference frame.
4833
0
    if (cached_mode_is_single) {
4834
0
      if (mode != cached_mode || ref_frame[0] != cached_frame[0]) {
4835
0
        return 1;
4836
0
      }
4837
0
    } else {
4838
      // If the cached mode is compound, then we need to consider several cases.
4839
0
      const int mode_is_single = ref_frame[1] <= INTRA_FRAME;
4840
0
      if (mode_is_single) {
4841
        // If the mode is single, we know the modes can't match. But we might
4842
        // still want to search it if compound mode depends on the current mode.
4843
0
        int skip_motion_mode_only = 0;
4844
0
        if (cached_mode == NEW_NEARMV || cached_mode == NEW_NEARESTMV) {
4845
0
          skip_motion_mode_only = (ref_frame[0] == cached_frame[0]);
4846
0
        } else if (cached_mode == NEAR_NEWMV || cached_mode == NEAREST_NEWMV) {
4847
0
          skip_motion_mode_only = (ref_frame[0] == cached_frame[1]);
4848
0
        } else if (cached_mode == NEW_NEWMV) {
4849
0
          skip_motion_mode_only = (ref_frame[0] == cached_frame[0] ||
4850
0
                                   ref_frame[0] == cached_frame[1]);
4851
0
        }
4852
4853
0
        return 1 + skip_motion_mode_only;
4854
0
      } else {
4855
        // If both modes are compound, then everything must match.
4856
0
        if (mode != cached_mode || ref_frame[0] != cached_frame[0] ||
4857
0
            ref_frame[1] != cached_frame[1]) {
4858
0
          return 1;
4859
0
        }
4860
0
      }
4861
0
    }
4862
0
  }
4863
4864
0
  const MB_MODE_INFO *const mbmi = x->e_mbd.mi[0];
4865
  // If no valid mode has been found so far in PARTITION_NONE when finding a
4866
  // valid partition is required, do not skip mode.
4867
0
  if (search_state->best_rd == INT64_MAX && mbmi->partition == PARTITION_NONE &&
4868
0
      x->must_find_valid_partition)
4869
0
    return 0;
4870
4871
0
  const SPEED_FEATURES *const sf = &cpi->sf;
4872
  // Prune NEARMV and NEAR_NEARMV based on q index and neighbor's reference
4873
  // frames
4874
0
  if (sf->inter_sf.prune_nearmv_using_neighbors &&
4875
0
      (mode == NEAR_NEARMV || mode == NEARMV)) {
4876
0
    const MACROBLOCKD *const xd = &x->e_mbd;
4877
0
    if (search_state->best_rd != INT64_MAX && xd->left_available &&
4878
0
        xd->up_available) {
4879
0
      const int thresholds[PRUNE_NEARMV_MAX][3] = { { 1, 0, 0 },
4880
0
                                                    { 1, 1, 0 },
4881
0
                                                    { 2, 1, 0 } };
4882
0
      const int qindex_sub_range = x->qindex * 3 / QINDEX_RANGE;
4883
4884
0
      assert(sf->inter_sf.prune_nearmv_using_neighbors <= PRUNE_NEARMV_MAX &&
4885
0
             qindex_sub_range < 3);
4886
0
      const int num_ref_frame_pair_match_thresh =
4887
0
          thresholds[sf->inter_sf.prune_nearmv_using_neighbors - 1]
4888
0
                    [qindex_sub_range];
4889
4890
0
      assert(num_ref_frame_pair_match_thresh <= 2 &&
4891
0
             num_ref_frame_pair_match_thresh >= 0);
4892
0
      int num_ref_frame_pair_match = 0;
4893
4894
0
      num_ref_frame_pair_match = match_ref_frame_pair(xd->left_mbmi, ref_frame);
4895
0
      num_ref_frame_pair_match +=
4896
0
          match_ref_frame_pair(xd->above_mbmi, ref_frame);
4897
4898
      // Pruning based on ref frame pair match with neighbors.
4899
0
      if (num_ref_frame_pair_match < num_ref_frame_pair_match_thresh) return 1;
4900
0
    }
4901
0
  }
4902
4903
0
  int skip_motion_mode = 0;
4904
0
  if (mbmi->partition != PARTITION_NONE) {
4905
0
    assert(ref_type > NONE_FRAME);
4906
0
    int skip_ref = skip_ref_frame_mask & (1 << ref_type);
4907
0
    if (ref_type <= ALTREF_FRAME && skip_ref) {
4908
      // Since the compound ref modes depends on the motion estimation result of
4909
      // two single ref modes (best mv of single ref modes as the start point),
4910
      // if current single ref mode is marked skip, we need to check if it will
4911
      // be used in compound ref modes.
4912
0
      if (is_ref_frame_used_by_compound_ref(ref_type, skip_ref_frame_mask)) {
4913
        // Found a not skipped compound ref mode which contains current
4914
        // single ref. So this single ref can't be skipped completely
4915
        // Just skip its motion mode search, still try its simple
4916
        // transition mode.
4917
0
        skip_motion_mode = 1;
4918
0
        skip_ref = 0;
4919
0
      }
4920
0
    }
4921
    // If we are reusing the prediction from cache, and the current frame is
4922
    // required by the cache, then we cannot prune it.
4923
0
    if (is_ref_frame_used_in_cache(ref_type, x->mb_mode_cache)) {
4924
0
      skip_ref = 0;
4925
      // If the cache only needs the current reference type for compound
4926
      // prediction, then we can skip motion mode search.
4927
0
      skip_motion_mode = (ref_type <= ALTREF_FRAME &&
4928
0
                          x->mb_mode_cache->ref_frame[1] > INTRA_FRAME);
4929
0
    }
4930
0
    if (skip_ref) return 1;
4931
0
  }
4932
4933
0
  if (ref_frame[0] == INTRA_FRAME) {
4934
0
    if (mode != DC_PRED) {
4935
      // Disable intra modes other than DC_PRED for blocks with low variance
4936
      // Threshold for intra skipping based on source variance
4937
      // TODO(debargha): Specialize the threshold for super block sizes
4938
0
      const unsigned int skip_intra_var_thresh = 64;
4939
0
      if ((sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
4940
0
          x->source_variance < skip_intra_var_thresh)
4941
0
        return 1;
4942
0
    }
4943
0
  }
4944
4945
0
  if (skip_motion_mode) return 2;
4946
4947
0
  return 0;
4948
0
}
4949
4950
static inline void init_mbmi(MB_MODE_INFO *mbmi, PREDICTION_MODE curr_mode,
4951
                             const MV_REFERENCE_FRAME *ref_frames,
4952
0
                             const AV1_COMMON *cm) {
4953
0
  PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
4954
0
  mbmi->ref_mv_idx = 0;
4955
0
  mbmi->mode = curr_mode;
4956
0
  mbmi->uv_mode = UV_DC_PRED;
4957
0
  mbmi->ref_frame[0] = ref_frames[0];
4958
0
  mbmi->ref_frame[1] = ref_frames[1];
4959
0
  pmi->palette_size[0] = 0;
4960
0
  pmi->palette_size[1] = 0;
4961
0
  mbmi->filter_intra_mode_info.use_filter_intra = 0;
4962
0
  mbmi->mv[0].as_int = mbmi->mv[1].as_int = 0;
4963
0
  mbmi->motion_mode = SIMPLE_TRANSLATION;
4964
0
  mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
4965
0
  set_default_interp_filters(mbmi, cm->features.interp_filter);
4966
0
  mbmi->skip_txfm = 0;
4967
0
}
4968
4969
static inline void collect_single_states(MACROBLOCK *x,
4970
                                         InterModeSearchState *search_state,
4971
0
                                         const MB_MODE_INFO *const mbmi) {
4972
0
  int i, j;
4973
0
  const MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame[0];
4974
0
  const PREDICTION_MODE this_mode = mbmi->mode;
4975
0
  const int dir = ref_frame <= GOLDEN_FRAME ? 0 : 1;
4976
0
  const int mode_offset = INTER_OFFSET(this_mode);
4977
0
  const int ref_set = get_drl_refmv_count(x, mbmi->ref_frame, this_mode);
4978
4979
  // Simple rd
4980
0
  int64_t simple_rd = search_state->simple_rd[this_mode][0][ref_frame];
4981
0
  for (int ref_mv_idx = 1; ref_mv_idx < ref_set; ++ref_mv_idx) {
4982
0
    const int64_t rd =
4983
0
        search_state->simple_rd[this_mode][ref_mv_idx][ref_frame];
4984
0
    if (rd < simple_rd) simple_rd = rd;
4985
0
  }
4986
4987
  // Insertion sort of single_state
4988
0
  const SingleInterModeState this_state_s = { simple_rd, ref_frame, 1 };
4989
0
  SingleInterModeState *state_s = search_state->single_state[dir][mode_offset];
4990
0
  i = search_state->single_state_cnt[dir][mode_offset];
4991
0
  for (j = i; j > 0 && state_s[j - 1].rd > this_state_s.rd; --j)
4992
0
    state_s[j] = state_s[j - 1];
4993
0
  state_s[j] = this_state_s;
4994
0
  search_state->single_state_cnt[dir][mode_offset]++;
4995
4996
  // Modelled rd
4997
0
  int64_t modelled_rd = search_state->modelled_rd[this_mode][0][ref_frame];
4998
0
  for (int ref_mv_idx = 1; ref_mv_idx < ref_set; ++ref_mv_idx) {
4999
0
    const int64_t rd =
5000
0
        search_state->modelled_rd[this_mode][ref_mv_idx][ref_frame];
5001
0
    if (rd < modelled_rd) modelled_rd = rd;
5002
0
  }
5003
5004
  // Insertion sort of single_state_modelled
5005
0
  const SingleInterModeState this_state_m = { modelled_rd, ref_frame, 1 };
5006
0
  SingleInterModeState *state_m =
5007
0
      search_state->single_state_modelled[dir][mode_offset];
5008
0
  i = search_state->single_state_modelled_cnt[dir][mode_offset];
5009
0
  for (j = i; j > 0 && state_m[j - 1].rd > this_state_m.rd; --j)
5010
0
    state_m[j] = state_m[j - 1];
5011
0
  state_m[j] = this_state_m;
5012
0
  search_state->single_state_modelled_cnt[dir][mode_offset]++;
5013
0
}
5014
5015
static inline void analyze_single_states(const AV1_COMP *cpi,
5016
0
                                         InterModeSearchState *search_state) {
5017
0
  const int prune_level = cpi->sf.inter_sf.prune_comp_search_by_single_result;
5018
0
  assert(prune_level >= 1);
5019
0
  int i, j, dir, mode;
5020
5021
0
  for (dir = 0; dir < 2; ++dir) {
5022
0
    int64_t best_rd;
5023
0
    SingleInterModeState(*state)[FWD_REFS];
5024
0
    const int prune_factor = prune_level >= 2 ? 6 : 5;
5025
5026
    // Use the best rd of GLOBALMV or NEWMV to prune the unlikely
5027
    // reference frames for all the modes (NEARESTMV and NEARMV may not
5028
    // have same motion vectors). Always keep the best of each mode
5029
    // because it might form the best possible combination with other mode.
5030
0
    state = search_state->single_state[dir];
5031
0
    best_rd = AOMMIN(state[INTER_OFFSET(NEWMV)][0].rd,
5032
0
                     state[INTER_OFFSET(GLOBALMV)][0].rd);
5033
0
    for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
5034
0
      for (i = 1; i < search_state->single_state_cnt[dir][mode]; ++i) {
5035
0
        if (state[mode][i].rd != INT64_MAX &&
5036
0
            (state[mode][i].rd >> 3) * prune_factor > best_rd) {
5037
0
          state[mode][i].valid = 0;
5038
0
        }
5039
0
      }
5040
0
    }
5041
5042
0
    state = search_state->single_state_modelled[dir];
5043
0
    best_rd = AOMMIN(state[INTER_OFFSET(NEWMV)][0].rd,
5044
0
                     state[INTER_OFFSET(GLOBALMV)][0].rd);
5045
0
    for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
5046
0
      for (i = 1; i < search_state->single_state_modelled_cnt[dir][mode]; ++i) {
5047
0
        if (state[mode][i].rd != INT64_MAX &&
5048
0
            (state[mode][i].rd >> 3) * prune_factor > best_rd) {
5049
0
          state[mode][i].valid = 0;
5050
0
        }
5051
0
      }
5052
0
    }
5053
0
  }
5054
5055
  // Ordering by simple rd first, then by modelled rd
5056
0
  for (dir = 0; dir < 2; ++dir) {
5057
0
    for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
5058
0
      const int state_cnt_s = search_state->single_state_cnt[dir][mode];
5059
0
      const int state_cnt_m =
5060
0
          search_state->single_state_modelled_cnt[dir][mode];
5061
0
      SingleInterModeState *state_s = search_state->single_state[dir][mode];
5062
0
      SingleInterModeState *state_m =
5063
0
          search_state->single_state_modelled[dir][mode];
5064
0
      int count = 0;
5065
0
      const int max_candidates = AOMMAX(state_cnt_s, state_cnt_m);
5066
0
      for (i = 0; i < state_cnt_s; ++i) {
5067
0
        if (state_s[i].rd == INT64_MAX) break;
5068
0
        if (state_s[i].valid) {
5069
0
          search_state->single_rd_order[dir][mode][count++] =
5070
0
              state_s[i].ref_frame;
5071
0
        }
5072
0
      }
5073
0
      if (count >= max_candidates) continue;
5074
5075
0
      for (i = 0; i < state_cnt_m && count < max_candidates; ++i) {
5076
0
        if (state_m[i].rd == INT64_MAX) break;
5077
0
        if (!state_m[i].valid) continue;
5078
0
        const int ref_frame = state_m[i].ref_frame;
5079
0
        int match = 0;
5080
        // Check if existing already
5081
0
        for (j = 0; j < count; ++j) {
5082
0
          if (search_state->single_rd_order[dir][mode][j] == ref_frame) {
5083
0
            match = 1;
5084
0
            break;
5085
0
          }
5086
0
        }
5087
0
        if (match) continue;
5088
        // Check if this ref_frame is removed in simple rd
5089
0
        int valid = 1;
5090
0
        for (j = 0; j < state_cnt_s; ++j) {
5091
0
          if (ref_frame == state_s[j].ref_frame) {
5092
0
            valid = state_s[j].valid;
5093
0
            break;
5094
0
          }
5095
0
        }
5096
0
        if (valid) {
5097
0
          search_state->single_rd_order[dir][mode][count++] = ref_frame;
5098
0
        }
5099
0
      }
5100
0
    }
5101
0
  }
5102
0
}
5103
5104
static int compound_skip_get_candidates(
5105
    const AV1_COMP *cpi, const InterModeSearchState *search_state,
5106
0
    const int dir, const PREDICTION_MODE mode) {
5107
0
  const int mode_offset = INTER_OFFSET(mode);
5108
0
  const SingleInterModeState *state =
5109
0
      search_state->single_state[dir][mode_offset];
5110
0
  const SingleInterModeState *state_modelled =
5111
0
      search_state->single_state_modelled[dir][mode_offset];
5112
5113
0
  int max_candidates = 0;
5114
0
  for (int i = 0; i < FWD_REFS; ++i) {
5115
0
    if (search_state->single_rd_order[dir][mode_offset][i] == NONE_FRAME) break;
5116
0
    max_candidates++;
5117
0
  }
5118
5119
0
  int candidates = max_candidates;
5120
0
  if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 2) {
5121
0
    candidates = AOMMIN(2, max_candidates);
5122
0
  }
5123
0
  if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 3) {
5124
0
    if (state[0].rd != INT64_MAX && state_modelled[0].rd != INT64_MAX &&
5125
0
        state[0].ref_frame == state_modelled[0].ref_frame)
5126
0
      candidates = 1;
5127
0
    if (mode == NEARMV || mode == GLOBALMV) candidates = 1;
5128
0
  }
5129
5130
0
  if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 4) {
5131
    // Limit the number of candidates to 1 in each direction for compound
5132
    // prediction
5133
0
    candidates = AOMMIN(1, candidates);
5134
0
  }
5135
0
  return candidates;
5136
0
}
5137
5138
static AOM_FORCE_INLINE int compound_skip_by_single_states(
5139
    const AV1_COMP *cpi, const InterModeSearchState *search_state,
5140
    const PREDICTION_MODE this_mode, const MV_REFERENCE_FRAME ref_frame,
5141
0
    const MV_REFERENCE_FRAME second_ref_frame, const MACROBLOCK *x) {
5142
0
  const MV_REFERENCE_FRAME refs[2] = { ref_frame, second_ref_frame };
5143
0
  const int mode[2] = { compound_ref0_mode(this_mode),
5144
0
                        compound_ref1_mode(this_mode) };
5145
0
  const int mode_offset[2] = { INTER_OFFSET(mode[0]), INTER_OFFSET(mode[1]) };
5146
0
  const int mode_dir[2] = { refs[0] <= GOLDEN_FRAME ? 0 : 1,
5147
0
                            refs[1] <= GOLDEN_FRAME ? 0 : 1 };
5148
0
  int ref_searched[2] = { 0, 0 };
5149
0
  int ref_mv_match[2] = { 1, 1 };
5150
0
  int i, j;
5151
5152
0
  for (i = 0; i < 2; ++i) {
5153
0
    const SingleInterModeState *state =
5154
0
        search_state->single_state[mode_dir[i]][mode_offset[i]];
5155
0
    const int state_cnt =
5156
0
        search_state->single_state_cnt[mode_dir[i]][mode_offset[i]];
5157
0
    for (j = 0; j < state_cnt; ++j) {
5158
0
      if (state[j].ref_frame == refs[i]) {
5159
0
        ref_searched[i] = 1;
5160
0
        break;
5161
0
      }
5162
0
    }
5163
0
  }
5164
5165
0
  const int ref_set = get_drl_refmv_count(x, refs, this_mode);
5166
0
  for (i = 0; i < 2; ++i) {
5167
0
    if (!ref_searched[i] || (mode[i] != NEARESTMV && mode[i] != NEARMV)) {
5168
0
      continue;
5169
0
    }
5170
0
    const MV_REFERENCE_FRAME single_refs[2] = { refs[i], NONE_FRAME };
5171
0
    for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ref_mv_idx++) {
5172
0
      int_mv single_mv;
5173
0
      int_mv comp_mv;
5174
0
      get_this_mv(&single_mv, mode[i], 0, ref_mv_idx, 0, single_refs,
5175
0
                  &x->mbmi_ext);
5176
0
      get_this_mv(&comp_mv, this_mode, i, ref_mv_idx, 0, refs, &x->mbmi_ext);
5177
0
      if (single_mv.as_int != comp_mv.as_int) {
5178
0
        ref_mv_match[i] = 0;
5179
0
        break;
5180
0
      }
5181
0
    }
5182
0
  }
5183
5184
0
  for (i = 0; i < 2; ++i) {
5185
0
    if (!ref_searched[i] || !ref_mv_match[i]) continue;
5186
0
    const int candidates =
5187
0
        compound_skip_get_candidates(cpi, search_state, mode_dir[i], mode[i]);
5188
0
    const MV_REFERENCE_FRAME *ref_order =
5189
0
        search_state->single_rd_order[mode_dir[i]][mode_offset[i]];
5190
0
    int match = 0;
5191
0
    for (j = 0; j < candidates; ++j) {
5192
0
      if (refs[i] == ref_order[j]) {
5193
0
        match = 1;
5194
0
        break;
5195
0
      }
5196
0
    }
5197
0
    if (!match) return 1;
5198
0
  }
5199
5200
0
  return 0;
5201
0
}
5202
5203
// Check if ref frames of current block matches with given block.
5204
static inline void match_ref_frame(const MB_MODE_INFO *const mbmi,
5205
                                   const MV_REFERENCE_FRAME *ref_frames,
5206
0
                                   int *const is_ref_match) {
5207
0
  if (is_inter_block(mbmi)) {
5208
0
    is_ref_match[0] |= ref_frames[0] == mbmi->ref_frame[0];
5209
0
    is_ref_match[1] |= ref_frames[1] == mbmi->ref_frame[0];
5210
0
    if (has_second_ref(mbmi)) {
5211
0
      is_ref_match[0] |= ref_frames[0] == mbmi->ref_frame[1];
5212
0
      is_ref_match[1] |= ref_frames[1] == mbmi->ref_frame[1];
5213
0
    }
5214
0
  }
5215
0
}
5216
5217
// Prune compound mode using ref frames of neighbor blocks.
5218
static inline int compound_skip_using_neighbor_refs(
5219
    MACROBLOCKD *const xd, const PREDICTION_MODE this_mode,
5220
0
    const MV_REFERENCE_FRAME *ref_frames, int prune_ext_comp_using_neighbors) {
5221
  // Exclude non-extended compound modes from pruning
5222
0
  if (this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
5223
0
      this_mode == NEW_NEWMV || this_mode == GLOBAL_GLOBALMV)
5224
0
    return 0;
5225
5226
0
  if (prune_ext_comp_using_neighbors >= 3) return 1;
5227
5228
0
  int is_ref_match[2] = { 0 };  // 0 - match for forward refs
5229
                                // 1 - match for backward refs
5230
  // Check if ref frames of this block matches with left neighbor.
5231
0
  if (xd->left_available)
5232
0
    match_ref_frame(xd->left_mbmi, ref_frames, is_ref_match);
5233
5234
  // Check if ref frames of this block matches with above neighbor.
5235
0
  if (xd->up_available)
5236
0
    match_ref_frame(xd->above_mbmi, ref_frames, is_ref_match);
5237
5238
  // Combine ref frame match with neighbors in forward and backward refs.
5239
0
  const int track_ref_match = is_ref_match[0] + is_ref_match[1];
5240
5241
  // Pruning based on ref frame match with neighbors.
5242
0
  if (track_ref_match >= prune_ext_comp_using_neighbors) return 0;
5243
0
  return 1;
5244
0
}
5245
5246
// Update best single mode for the given reference frame based on simple rd.
5247
static inline void update_best_single_mode(InterModeSearchState *search_state,
5248
                                           const PREDICTION_MODE this_mode,
5249
                                           const MV_REFERENCE_FRAME ref_frame,
5250
0
                                           int64_t this_rd) {
5251
0
  if (this_rd < search_state->best_single_rd[ref_frame]) {
5252
0
    search_state->best_single_rd[ref_frame] = this_rd;
5253
0
    search_state->best_single_mode[ref_frame] = this_mode;
5254
0
  }
5255
0
}
5256
5257
// Prune compound mode using best single mode for the same reference.
5258
static inline int skip_compound_using_best_single_mode_ref(
5259
    const PREDICTION_MODE this_mode, const MV_REFERENCE_FRAME *ref_frames,
5260
    const PREDICTION_MODE *best_single_mode,
5261
0
    int prune_comp_using_best_single_mode_ref) {
5262
  // Exclude non-extended compound modes from pruning
5263
0
  if (this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
5264
0
      this_mode == NEW_NEWMV || this_mode == GLOBAL_GLOBALMV)
5265
0
    return 0;
5266
5267
0
  assert(this_mode >= NEAREST_NEWMV && this_mode <= NEW_NEARMV);
5268
0
  const PREDICTION_MODE comp_mode_ref0 = compound_ref0_mode(this_mode);
5269
  // Get ref frame direction corresponding to NEWMV
5270
  // 0 - NEWMV corresponding to forward direction
5271
  // 1 - NEWMV corresponding to backward direction
5272
0
  const int newmv_dir = comp_mode_ref0 != NEWMV;
5273
5274
  // Avoid pruning the compound mode when ref frame corresponding to NEWMV
5275
  // have NEWMV as single mode winner.
5276
  // Example: For an extended-compound mode,
5277
  // {mode, {fwd_frame, bwd_frame}} = {NEAR_NEWMV, {LAST_FRAME, ALTREF_FRAME}}
5278
  // - Ref frame corresponding to NEWMV is ALTREF_FRAME
5279
  // - Avoid pruning this mode, if best single mode corresponding to ref frame
5280
  //   ALTREF_FRAME is NEWMV
5281
0
  const PREDICTION_MODE single_mode = best_single_mode[ref_frames[newmv_dir]];
5282
0
  if (single_mode == NEWMV) return 0;
5283
5284
  // Avoid pruning the compound mode when best single mode is not available
5285
0
  if (prune_comp_using_best_single_mode_ref == 1)
5286
0
    if (single_mode == MB_MODE_COUNT) return 0;
5287
0
  return 1;
5288
0
}
5289
5290
0
static int compare_int64(const void *a, const void *b) {
5291
0
  int64_t a64 = *((int64_t *)a);
5292
0
  int64_t b64 = *((int64_t *)b);
5293
0
  if (a64 < b64) {
5294
0
    return -1;
5295
0
  } else if (a64 == b64) {
5296
0
    return 0;
5297
0
  } else {
5298
0
    return 1;
5299
0
  }
5300
0
}
5301
5302
static inline void update_search_state(
5303
    const AV1_COMP *cpi, InterModeSearchState *search_state,
5304
    RD_STATS *best_rd_stats_dst, PICK_MODE_CONTEXT *ctx,
5305
    const RD_STATS *new_best_rd_stats, const RD_STATS *new_best_rd_stats_y,
5306
    const RD_STATS *new_best_rd_stats_uv, THR_MODES new_best_mode,
5307
0
    const MACROBLOCK *x, int txfm_search_done) {
5308
0
  const MACROBLOCKD *xd = &x->e_mbd;
5309
0
  const MB_MODE_INFO *mbmi = xd->mi[0];
5310
0
  const int skip_ctx = av1_get_skip_txfm_context(xd);
5311
0
  const int skip_txfm =
5312
0
      mbmi->skip_txfm && !is_mode_intra(av1_mode_defs[new_best_mode].mode);
5313
5314
0
  search_state->best_rd = new_best_rd_stats->rdcost;
5315
0
  search_state->best_mode_index = new_best_mode;
5316
0
  *best_rd_stats_dst = *new_best_rd_stats;
5317
0
  search_state->best_mbmode = *mbmi;
5318
0
  search_state->best_skip2 = skip_txfm;
5319
0
  search_state->best_mode_skippable = new_best_rd_stats->skip_txfm;
5320
  // When !txfm_search_done, new_best_rd_stats won't provide correct rate_y and
5321
  // rate_uv because av1_txfm_search process is replaced by rd estimation.
5322
  // Therefore, we should avoid updating best_rate_y and best_rate_uv here.
5323
  // These two values will be updated when av1_txfm_search is called.
5324
0
  if (txfm_search_done) {
5325
0
    const int32_t skip_rate =
5326
0
        x->mode_costs.skip_txfm_cost[skip_ctx]
5327
0
                                    [new_best_rd_stats->skip_txfm || skip_txfm];
5328
0
    const int32_t scaled_skip_rate =
5329
0
        increase_motion_mode_rate(cpi, mbmi, skip_rate);
5330
0
    search_state->best_rate_y = new_best_rd_stats_y->rate + scaled_skip_rate;
5331
0
    search_state->best_rate_uv = new_best_rd_stats_uv->rate;
5332
0
  }
5333
0
  search_state->best_y_rdcost = *new_best_rd_stats_y;
5334
0
  av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
5335
0
}
5336
5337
// Find the best RD for a reference frame (among single reference modes)
5338
// and store +10% of it in the 0-th element in ref_frame_rd.
5339
0
static inline void find_top_ref(int64_t ref_frame_rd[REF_FRAMES]) {
5340
0
  assert(ref_frame_rd[0] == INT64_MAX);
5341
0
  int64_t ref_copy[REF_FRAMES - 1];
5342
0
  memcpy(ref_copy, ref_frame_rd + 1,
5343
0
         sizeof(ref_frame_rd[0]) * (REF_FRAMES - 1));
5344
0
  qsort(ref_copy, REF_FRAMES - 1, sizeof(int64_t), compare_int64);
5345
5346
0
  int64_t cutoff = ref_copy[0];
5347
  // The cut-off is within 10% of the best.
5348
0
  if (cutoff != INT64_MAX) {
5349
0
    assert(cutoff < INT64_MAX / 200);
5350
0
    cutoff = (110 * cutoff) / 100;
5351
0
  }
5352
0
  ref_frame_rd[0] = cutoff;
5353
0
}
5354
5355
// Check if either frame is within the cutoff.
5356
static inline bool in_single_ref_cutoff(int64_t ref_frame_rd[REF_FRAMES],
5357
                                        MV_REFERENCE_FRAME frame1,
5358
0
                                        MV_REFERENCE_FRAME frame2) {
5359
0
  assert(frame2 > 0);
5360
0
  return ref_frame_rd[frame1] <= ref_frame_rd[0] ||
5361
0
         ref_frame_rd[frame2] <= ref_frame_rd[0];
5362
0
}
5363
5364
static inline void evaluate_motion_mode_for_winner_candidates(
5365
    const AV1_COMP *const cpi, MACROBLOCK *const x, RD_STATS *const rd_cost,
5366
    HandleInterModeArgs *const args, TileDataEnc *const tile_data,
5367
    PICK_MODE_CONTEXT *const ctx,
5368
    struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],
5369
    const motion_mode_best_st_candidate *const best_motion_mode_cands,
5370
    int do_tx_search, const BLOCK_SIZE bsize, int64_t *const best_est_rd,
5371
0
    InterModeSearchState *const search_state, int64_t *yrd) {
5372
0
  const AV1_COMMON *const cm = &cpi->common;
5373
0
  const int num_planes = av1_num_planes(cm);
5374
0
  MACROBLOCKD *const xd = &x->e_mbd;
5375
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
5376
0
  InterModesInfo *const inter_modes_info = x->inter_modes_info;
5377
0
  const int num_best_cand = best_motion_mode_cands->num_motion_mode_cand;
5378
5379
0
  for (int cand = 0; cand < num_best_cand; cand++) {
5380
0
    RD_STATS rd_stats;
5381
0
    RD_STATS rd_stats_y;
5382
0
    RD_STATS rd_stats_uv;
5383
0
    av1_init_rd_stats(&rd_stats);
5384
0
    av1_init_rd_stats(&rd_stats_y);
5385
0
    av1_init_rd_stats(&rd_stats_uv);
5386
0
    int rate_mv;
5387
5388
0
    rate_mv = best_motion_mode_cands->motion_mode_cand[cand].rate_mv;
5389
0
    args->skip_motion_mode =
5390
0
        best_motion_mode_cands->motion_mode_cand[cand].skip_motion_mode;
5391
0
    *mbmi = best_motion_mode_cands->motion_mode_cand[cand].mbmi;
5392
0
    rd_stats.rate =
5393
0
        best_motion_mode_cands->motion_mode_cand[cand].rate2_nocoeff;
5394
5395
    // Continue if the best candidate is compound.
5396
0
    if (!is_inter_singleref_mode(mbmi->mode)) continue;
5397
5398
0
    x->txfm_search_info.skip_txfm = 0;
5399
0
    struct macroblockd_plane *pd = xd->plane;
5400
0
    const BUFFER_SET orig_dst = {
5401
0
      { pd[0].dst.buf, pd[1].dst.buf, pd[2].dst.buf },
5402
0
      { pd[0].dst.stride, pd[1].dst.stride, pd[2].dst.stride },
5403
0
    };
5404
5405
0
    set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
5406
    // Initialize motion mode to simple translation
5407
    // Calculation of switchable rate depends on it.
5408
0
    mbmi->motion_mode = 0;
5409
0
    const int is_comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
5410
0
    for (int i = 0; i < num_planes; i++) {
5411
0
      xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
5412
0
      if (is_comp_pred) xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
5413
0
    }
5414
5415
0
    int64_t skip_rd[2] = { search_state->best_skip_rd[0],
5416
0
                           search_state->best_skip_rd[1] };
5417
0
    int64_t this_yrd = INT64_MAX;
5418
0
    int64_t ret_value = motion_mode_rd(
5419
0
        cpi, tile_data, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv, args,
5420
0
        search_state->best_rd, skip_rd, &rate_mv, &orig_dst, best_est_rd,
5421
0
        do_tx_search, inter_modes_info, 1, &this_yrd);
5422
5423
0
    if (ret_value != INT64_MAX) {
5424
0
      rd_stats.rdcost = RDCOST(x->rdmult, rd_stats.rate, rd_stats.dist);
5425
0
      const THR_MODES mode_enum = get_prediction_mode_idx(
5426
0
          mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
5427
      // Collect mode stats for multiwinner mode processing
5428
0
      store_winner_mode_stats(
5429
0
          cpi, x, mbmi, &rd_stats, &rd_stats_y, &rd_stats_uv, mode_enum, NULL,
5430
0
          bsize, rd_stats.rdcost, cpi->sf.winner_mode_sf.multi_winner_mode_type,
5431
0
          do_tx_search);
5432
5433
0
      if (rd_stats.rdcost < search_state->best_rd) {
5434
0
        *yrd = this_yrd;
5435
0
        update_search_state(cpi, search_state, rd_cost, ctx, &rd_stats,
5436
0
                            &rd_stats_y, &rd_stats_uv, mode_enum, x,
5437
0
                            do_tx_search);
5438
0
        if (do_tx_search) search_state->best_skip_rd[0] = skip_rd[0];
5439
0
      }
5440
0
    }
5441
0
  }
5442
0
}
5443
5444
/*!\cond */
5445
// Arguments for speed feature pruning of inter mode search
5446
typedef struct {
5447
  int *skip_motion_mode;
5448
  mode_skip_mask_t *mode_skip_mask;
5449
  InterModeSearchState *search_state;
5450
  int skip_ref_frame_mask;
5451
  int reach_first_comp_mode;
5452
  int mode_thresh_mul_fact;
5453
  int num_single_modes_processed;
5454
  int prune_cpd_using_sr_stats_ready;
5455
} InterModeSFArgs;
5456
/*!\endcond */
5457
5458
static AOM_FORCE_INLINE int skip_inter_mode(AV1_COMP *cpi, MACROBLOCK *x,
5459
                                            const BLOCK_SIZE bsize,
5460
                                            int64_t *ref_frame_rd, int midx,
5461
                                            InterModeSFArgs *args,
5462
0
                                            int is_low_temp_var) {
5463
0
  const SPEED_FEATURES *const sf = &cpi->sf;
5464
0
  MACROBLOCKD *const xd = &x->e_mbd;
5465
  // Get the actual prediction mode we are trying in this iteration
5466
0
  const THR_MODES mode_enum = av1_default_mode_order[midx];
5467
0
  const MODE_DEFINITION *mode_def = &av1_mode_defs[mode_enum];
5468
0
  const PREDICTION_MODE this_mode = mode_def->mode;
5469
0
  const MV_REFERENCE_FRAME *ref_frames = mode_def->ref_frame;
5470
0
  const MV_REFERENCE_FRAME ref_frame = ref_frames[0];
5471
0
  const MV_REFERENCE_FRAME second_ref_frame = ref_frames[1];
5472
0
  const int comp_pred = second_ref_frame > INTRA_FRAME;
5473
5474
0
  if (ref_frame == INTRA_FRAME) return 1;
5475
5476
0
  const FRAME_UPDATE_TYPE update_type =
5477
0
      get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
5478
0
  if (sf->inter_sf.skip_arf_compound && update_type == ARF_UPDATE &&
5479
0
      comp_pred) {
5480
0
    return 1;
5481
0
  }
5482
5483
  // This is for real time encoding.
5484
0
  if (is_low_temp_var && !comp_pred && ref_frame != LAST_FRAME &&
5485
0
      this_mode != NEARESTMV)
5486
0
    return 1;
5487
5488
  // Check if this mode should be skipped because it is incompatible with the
5489
  // current frame
5490
0
  if (inter_mode_compatible_skip(cpi, x, bsize, this_mode, ref_frames))
5491
0
    return 1;
5492
0
  const int ret = inter_mode_search_order_independent_skip(
5493
0
      cpi, x, args->mode_skip_mask, args->search_state,
5494
0
      args->skip_ref_frame_mask, this_mode, mode_def->ref_frame);
5495
0
  if (ret == 1) return 1;
5496
0
  *(args->skip_motion_mode) = (ret == 2);
5497
5498
  // We've reached the first compound prediction mode, get stats from the
5499
  // single reference predictors to help with pruning.
5500
  // Disable this pruning logic if interpolation filter search was skipped for
5501
  // single prediction modes as it can result in aggressive pruning of compound
5502
  // prediction modes due to the absence of modelled_rd populated by
5503
  // av1_interpolation_filter_search().
5504
  // TODO(Remya): Check the impact of the sf
5505
  // 'prune_comp_search_by_single_result' if compound prediction modes are
5506
  // enabled in future for REALTIME encode.
5507
0
  if (!sf->interp_sf.skip_interp_filter_search &&
5508
0
      sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred &&
5509
0
      args->reach_first_comp_mode == 0) {
5510
0
    analyze_single_states(cpi, args->search_state);
5511
0
    args->reach_first_comp_mode = 1;
5512
0
  }
5513
5514
  // Prune aggressively when best mode is skippable.
5515
0
  int mul_fact = args->search_state->best_mode_skippable
5516
0
                     ? args->mode_thresh_mul_fact
5517
0
                     : (1 << MODE_THRESH_QBITS);
5518
0
  int64_t mode_threshold =
5519
0
      (args->search_state->mode_threshold[mode_enum] * mul_fact) >>
5520
0
      MODE_THRESH_QBITS;
5521
5522
0
  if (args->search_state->best_rd < mode_threshold) return 1;
5523
5524
  // Skip this compound mode based on the RD results from the single prediction
5525
  // modes
5526
0
  if (!sf->interp_sf.skip_interp_filter_search &&
5527
0
      sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred) {
5528
0
    if (compound_skip_by_single_states(cpi, args->search_state, this_mode,
5529
0
                                       ref_frame, second_ref_frame, x))
5530
0
      return 1;
5531
0
  }
5532
5533
0
  if (sf->inter_sf.prune_compound_using_single_ref && comp_pred) {
5534
    // After we done with single reference modes, find the 2nd best RD
5535
    // for a reference frame. Only search compound modes that have a reference
5536
    // frame at least as good as the 2nd best.
5537
0
    if (!args->prune_cpd_using_sr_stats_ready &&
5538
0
        args->num_single_modes_processed == NUM_SINGLE_REF_MODES) {
5539
0
      find_top_ref(ref_frame_rd);
5540
0
      args->prune_cpd_using_sr_stats_ready = 1;
5541
0
    }
5542
0
    if (args->prune_cpd_using_sr_stats_ready &&
5543
0
        !in_single_ref_cutoff(ref_frame_rd, ref_frame, second_ref_frame))
5544
0
      return 1;
5545
0
  }
5546
5547
  // Skip NEW_NEARMV and NEAR_NEWMV extended compound modes
5548
0
  if (sf->inter_sf.skip_ext_comp_nearmv_mode &&
5549
0
      (this_mode == NEW_NEARMV || this_mode == NEAR_NEWMV)) {
5550
0
    return 1;
5551
0
  }
5552
5553
0
  if (sf->inter_sf.prune_ext_comp_using_neighbors && comp_pred) {
5554
0
    if (compound_skip_using_neighbor_refs(
5555
0
            xd, this_mode, ref_frames,
5556
0
            sf->inter_sf.prune_ext_comp_using_neighbors))
5557
0
      return 1;
5558
0
  }
5559
5560
0
  if (sf->inter_sf.prune_comp_using_best_single_mode_ref && comp_pred) {
5561
0
    if (skip_compound_using_best_single_mode_ref(
5562
0
            this_mode, ref_frames, args->search_state->best_single_mode,
5563
0
            sf->inter_sf.prune_comp_using_best_single_mode_ref))
5564
0
      return 1;
5565
0
  }
5566
5567
0
  if (sf->inter_sf.prune_nearest_near_mv_using_refmv_weight && !comp_pred) {
5568
0
    const int8_t ref_frame_type = av1_ref_frame_type(ref_frames);
5569
0
    if (skip_nearest_near_mv_using_refmv_weight(
5570
0
            x, this_mode, ref_frame_type,
5571
0
            args->search_state->best_mbmode.mode)) {
5572
      // Ensure the mode is pruned only when the current block has obtained a
5573
      // valid inter mode.
5574
0
      assert(is_inter_mode(args->search_state->best_mbmode.mode));
5575
0
      return 1;
5576
0
    }
5577
0
  }
5578
5579
0
  if (sf->rt_sf.prune_inter_modes_with_golden_ref &&
5580
0
      ref_frame == GOLDEN_FRAME && !comp_pred) {
5581
0
    const int subgop_size = AOMMIN(cpi->ppi->gf_group.size, FIXED_GF_INTERVAL);
5582
0
    if (cpi->rc.frames_since_golden > (subgop_size >> 2) &&
5583
0
        args->search_state->best_mbmode.ref_frame[0] != GOLDEN_FRAME) {
5584
0
      if ((bsize > BLOCK_16X16 && this_mode == NEWMV) || this_mode == NEARMV)
5585
0
        return 1;
5586
0
    }
5587
0
  }
5588
5589
0
  return 0;
5590
0
}
5591
5592
static void record_best_compound(REFERENCE_MODE reference_mode,
5593
                                 RD_STATS *rd_stats, int comp_pred, int rdmult,
5594
                                 InterModeSearchState *search_state,
5595
0
                                 int compmode_cost) {
5596
0
  int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
5597
5598
0
  if (reference_mode == REFERENCE_MODE_SELECT) {
5599
0
    single_rate = rd_stats->rate - compmode_cost;
5600
0
    hybrid_rate = rd_stats->rate;
5601
0
  } else {
5602
0
    single_rate = rd_stats->rate;
5603
0
    hybrid_rate = rd_stats->rate + compmode_cost;
5604
0
  }
5605
5606
0
  single_rd = RDCOST(rdmult, single_rate, rd_stats->dist);
5607
0
  hybrid_rd = RDCOST(rdmult, hybrid_rate, rd_stats->dist);
5608
5609
0
  if (!comp_pred) {
5610
0
    if (single_rd < search_state->best_pred_rd[SINGLE_REFERENCE])
5611
0
      search_state->best_pred_rd[SINGLE_REFERENCE] = single_rd;
5612
0
  } else {
5613
0
    if (single_rd < search_state->best_pred_rd[COMPOUND_REFERENCE])
5614
0
      search_state->best_pred_rd[COMPOUND_REFERENCE] = single_rd;
5615
0
  }
5616
0
  if (hybrid_rd < search_state->best_pred_rd[REFERENCE_MODE_SELECT])
5617
0
    search_state->best_pred_rd[REFERENCE_MODE_SELECT] = hybrid_rd;
5618
0
}
5619
5620
// Does a transform search over a list of the best inter mode candidates.
5621
// This is called if the original mode search computed an RD estimate
5622
// for the transform search rather than doing a full search.
5623
static void tx_search_best_inter_candidates(
5624
    AV1_COMP *cpi, TileDataEnc *tile_data, MACROBLOCK *x,
5625
    int64_t best_rd_so_far, BLOCK_SIZE bsize,
5626
    struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE], int mi_row, int mi_col,
5627
    InterModeSearchState *search_state, RD_STATS *rd_cost,
5628
0
    PICK_MODE_CONTEXT *ctx, int64_t *yrd) {
5629
0
  AV1_COMMON *const cm = &cpi->common;
5630
0
  MACROBLOCKD *const xd = &x->e_mbd;
5631
0
  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
5632
0
  const ModeCosts *mode_costs = &x->mode_costs;
5633
0
  const int num_planes = av1_num_planes(cm);
5634
0
  const int skip_ctx = av1_get_skip_txfm_context(xd);
5635
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
5636
0
  InterModesInfo *inter_modes_info = x->inter_modes_info;
5637
0
  inter_modes_info_sort(inter_modes_info, inter_modes_info->rd_idx_pair_arr);
5638
0
  search_state->best_rd = best_rd_so_far;
5639
0
  search_state->best_mode_index = THR_INVALID;
5640
  // Initialize best mode stats for winner mode processing
5641
0
  x->winner_mode_count = 0;
5642
0
  store_winner_mode_stats(cpi, x, mbmi, NULL, NULL, NULL, THR_INVALID, NULL,
5643
0
                          bsize, best_rd_so_far,
5644
0
                          cpi->sf.winner_mode_sf.multi_winner_mode_type, 0);
5645
0
  inter_modes_info->num =
5646
0
      inter_modes_info->num < cpi->sf.rt_sf.num_inter_modes_for_tx_search
5647
0
          ? inter_modes_info->num
5648
0
          : cpi->sf.rt_sf.num_inter_modes_for_tx_search;
5649
0
  const int64_t top_est_rd =
5650
0
      inter_modes_info->num > 0
5651
0
          ? inter_modes_info
5652
0
                ->est_rd_arr[inter_modes_info->rd_idx_pair_arr[0].idx]
5653
0
          : INT64_MAX;
5654
0
  *yrd = INT64_MAX;
5655
0
  int64_t best_rd_in_this_partition = INT64_MAX;
5656
0
  int num_inter_mode_cands = inter_modes_info->num;
5657
0
  int newmv_mode_evaled = 0;
5658
0
  int max_allowed_cands = INT_MAX;
5659
0
  if (cpi->sf.inter_sf.limit_inter_mode_cands) {
5660
    // The bound on the no. of inter mode candidates, beyond which the
5661
    // candidates are limited if a newmv mode got evaluated, is set as
5662
    // max_allowed_cands + 1.
5663
0
    const int num_allowed_cands[5] = { INT_MAX, 10, 9, 6, 2 };
5664
0
    assert(cpi->sf.inter_sf.limit_inter_mode_cands <= 4);
5665
0
    max_allowed_cands =
5666
0
        num_allowed_cands[cpi->sf.inter_sf.limit_inter_mode_cands];
5667
0
  }
5668
5669
0
  int num_mode_thresh = INT_MAX;
5670
0
  if (cpi->sf.inter_sf.limit_txfm_eval_per_mode) {
5671
    // Bound the no. of transform searches per prediction mode beyond a
5672
    // threshold.
5673
0
    const int num_mode_thresh_ary[4] = { INT_MAX, 4, 3, 0 };
5674
0
    assert(cpi->sf.inter_sf.limit_txfm_eval_per_mode <= 3);
5675
0
    num_mode_thresh =
5676
0
        num_mode_thresh_ary[cpi->sf.inter_sf.limit_txfm_eval_per_mode];
5677
0
  }
5678
5679
0
  int num_tx_cands = 0;
5680
0
  int num_tx_search_modes[INTER_MODE_END - INTER_MODE_START] = { 0 };
5681
  // Iterate over best inter mode candidates and perform tx search
5682
0
  for (int j = 0; j < num_inter_mode_cands; ++j) {
5683
0
    const int data_idx = inter_modes_info->rd_idx_pair_arr[j].idx;
5684
0
    *mbmi = inter_modes_info->mbmi_arr[data_idx];
5685
0
    const PREDICTION_MODE prediction_mode = mbmi->mode;
5686
0
    int64_t curr_est_rd = inter_modes_info->est_rd_arr[data_idx];
5687
0
    if (curr_est_rd * 0.80 > top_est_rd) break;
5688
5689
0
    if (num_tx_cands > num_mode_thresh) {
5690
0
      if ((prediction_mode != NEARESTMV &&
5691
0
           num_tx_search_modes[prediction_mode - INTER_MODE_START] >= 1) ||
5692
0
          (prediction_mode == NEARESTMV &&
5693
0
           num_tx_search_modes[prediction_mode - INTER_MODE_START] >= 2))
5694
0
        continue;
5695
0
    }
5696
5697
0
    txfm_info->skip_txfm = 0;
5698
0
    set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
5699
5700
    // Select prediction reference frames.
5701
0
    const int is_comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
5702
0
    for (int i = 0; i < num_planes; i++) {
5703
0
      xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
5704
0
      if (is_comp_pred) xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
5705
0
    }
5706
5707
0
    bool is_predictor_built = false;
5708
5709
    // Initialize RD stats
5710
0
    RD_STATS rd_stats;
5711
0
    RD_STATS rd_stats_y;
5712
0
    RD_STATS rd_stats_uv;
5713
0
    const int mode_rate = inter_modes_info->mode_rate_arr[data_idx];
5714
0
    int64_t skip_rd = INT64_MAX;
5715
0
    const int txfm_rd_gate_level = get_txfm_rd_gate_level(
5716
0
        cm->seq_params->enable_masked_compound,
5717
0
        cpi->sf.inter_sf.txfm_rd_gate_level, bsize, TX_SEARCH_DEFAULT,
5718
0
        /*eval_motion_mode=*/0);
5719
0
    if (txfm_rd_gate_level) {
5720
      // Check if the mode is good enough based on skip RD
5721
0
      int64_t curr_sse = inter_modes_info->sse_arr[data_idx];
5722
0
      skip_rd = RDCOST(x->rdmult, mode_rate, curr_sse);
5723
0
      int eval_txfm = check_txfm_eval(x, bsize, search_state->best_skip_rd[0],
5724
0
                                      skip_rd, txfm_rd_gate_level, 0);
5725
0
      if (!eval_txfm) continue;
5726
0
    }
5727
5728
    // Build the prediction for this mode
5729
0
    if (!is_predictor_built) {
5730
0
      av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
5731
0
                                    av1_num_planes(cm) - 1);
5732
0
    }
5733
0
    if (mbmi->motion_mode == OBMC_CAUSAL) {
5734
0
      av1_build_obmc_inter_predictors_sb(cm, xd);
5735
0
    }
5736
5737
0
    num_tx_cands++;
5738
0
    if (have_newmv_in_inter_mode(prediction_mode)) newmv_mode_evaled = 1;
5739
0
    num_tx_search_modes[prediction_mode - INTER_MODE_START]++;
5740
0
    int64_t this_yrd = INT64_MAX;
5741
    // Do the transform search
5742
0
    if (!av1_txfm_search(cpi, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv,
5743
0
                         mode_rate, search_state->best_rd)) {
5744
0
      continue;
5745
0
    } else {
5746
0
      if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
5747
0
        inter_mode_data_push(
5748
0
            tile_data, mbmi->bsize, rd_stats.sse, rd_stats.dist,
5749
0
            rd_stats_y.rate + rd_stats_uv.rate +
5750
0
                mode_costs->skip_txfm_cost[skip_ctx][mbmi->skip_txfm]);
5751
0
      }
5752
0
      increase_motion_mode_rdstats(cpi, mbmi, &rd_stats, &rd_stats_y,
5753
0
                                   &rd_stats_uv);
5754
0
      const int *skip_txfm_cost_ptr = mode_costs->skip_txfm_cost[skip_ctx];
5755
0
      const int skip_rate =
5756
0
          rd_stats.skip_txfm ? skip_txfm_cost_ptr[1] : skip_txfm_cost_ptr[0];
5757
0
      const int32_t scaled_skip_rate =
5758
0
          increase_motion_mode_rate(cpi, mbmi, skip_rate);
5759
0
      const int y_rate =
5760
0
          scaled_skip_rate + (rd_stats.skip_txfm ? 0 : rd_stats_y.rate);
5761
0
      this_yrd = RDCOST(x->rdmult, y_rate + mode_rate, rd_stats_y.dist);
5762
0
    }
5763
5764
0
    rd_stats.rdcost = RDCOST(x->rdmult, rd_stats.rate, rd_stats.dist);
5765
5766
0
    const THR_MODES mode_enum = get_prediction_mode_idx(
5767
0
        prediction_mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
5768
5769
    // Collect mode stats for multiwinner mode processing
5770
0
    const int txfm_search_done = 1;
5771
0
    store_winner_mode_stats(cpi, x, mbmi, &rd_stats, &rd_stats_y, &rd_stats_uv,
5772
0
                            mode_enum, NULL, bsize, rd_stats.rdcost,
5773
0
                            cpi->sf.winner_mode_sf.multi_winner_mode_type,
5774
0
                            txfm_search_done);
5775
5776
0
    if (rd_stats.rdcost < best_rd_in_this_partition) {
5777
0
      best_rd_in_this_partition = rd_stats.rdcost;
5778
0
      *yrd = this_yrd;
5779
0
    }
5780
5781
0
    if (rd_stats.rdcost < search_state->best_rd) {
5782
0
      update_search_state(cpi, search_state, rd_cost, ctx, &rd_stats,
5783
0
                          &rd_stats_y, &rd_stats_uv, mode_enum, x,
5784
0
                          txfm_search_done);
5785
0
      search_state->best_skip_rd[0] = skip_rd;
5786
      // Limit the total number of modes to be evaluated if the first is valid
5787
      // and transform skip or compound
5788
0
      if (cpi->sf.inter_sf.inter_mode_txfm_breakout) {
5789
0
        if (!j && (search_state->best_mbmode.skip_txfm || rd_stats.skip_txfm)) {
5790
          // Evaluate more candidates at high quantizers where occurrence of
5791
          // transform skip is high.
5792
0
          const int max_cands_cap[5] = { 2, 3, 5, 7, 9 };
5793
0
          const int qindex_band = (5 * x->qindex) >> QINDEX_BITS;
5794
0
          num_inter_mode_cands =
5795
0
              AOMMIN(max_cands_cap[qindex_band], inter_modes_info->num);
5796
0
        } else if (!j && has_second_ref(&search_state->best_mbmode)) {
5797
0
          const int aggr = cpi->sf.inter_sf.inter_mode_txfm_breakout - 1;
5798
          // Evaluate more candidates at low quantizers where occurrence of
5799
          // single reference mode is high.
5800
0
          const int max_cands_cap_cmp[2][4] = { { 10, 7, 5, 4 },
5801
0
                                                { 10, 7, 5, 3 } };
5802
0
          const int qindex_band_cmp = (4 * x->qindex) >> QINDEX_BITS;
5803
0
          num_inter_mode_cands = AOMMIN(
5804
0
              max_cands_cap_cmp[aggr][qindex_band_cmp], inter_modes_info->num);
5805
0
        }
5806
0
      }
5807
0
    }
5808
    // If the number of candidates evaluated exceeds max_allowed_cands, break if
5809
    // a newmv mode was evaluated already.
5810
0
    if ((num_tx_cands > max_allowed_cands) && newmv_mode_evaled) break;
5811
0
  }
5812
0
}
5813
5814
// Indicates number of winner simple translation modes to be used
5815
static const unsigned int num_winner_motion_modes[3] = { 0, 10, 3 };
5816
5817
// Adds a motion mode to the candidate list for motion_mode_for_winner_cand
5818
// speed feature. This list consists of modes that have only searched
5819
// SIMPLE_TRANSLATION. The final list will be used to search other motion
5820
// modes after the initial RD search.
5821
static void handle_winner_cand(
5822
    MB_MODE_INFO *const mbmi,
5823
    motion_mode_best_st_candidate *best_motion_mode_cands,
5824
    int max_winner_motion_mode_cand, int64_t this_rd,
5825
0
    motion_mode_candidate *motion_mode_cand, int skip_motion_mode) {
5826
  // Number of current motion mode candidates in list
5827
0
  const int num_motion_mode_cand = best_motion_mode_cands->num_motion_mode_cand;
5828
0
  int valid_motion_mode_cand_loc = num_motion_mode_cand;
5829
5830
  // find the best location to insert new motion mode candidate
5831
0
  for (int j = 0; j < num_motion_mode_cand; j++) {
5832
0
    if (this_rd < best_motion_mode_cands->motion_mode_cand[j].rd_cost) {
5833
0
      valid_motion_mode_cand_loc = j;
5834
0
      break;
5835
0
    }
5836
0
  }
5837
5838
  // Insert motion mode if location is found
5839
0
  if (valid_motion_mode_cand_loc < max_winner_motion_mode_cand) {
5840
0
    if (num_motion_mode_cand > 0 &&
5841
0
        valid_motion_mode_cand_loc < max_winner_motion_mode_cand - 1)
5842
0
      memmove(
5843
0
          &best_motion_mode_cands
5844
0
               ->motion_mode_cand[valid_motion_mode_cand_loc + 1],
5845
0
          &best_motion_mode_cands->motion_mode_cand[valid_motion_mode_cand_loc],
5846
0
          (AOMMIN(num_motion_mode_cand, max_winner_motion_mode_cand - 1) -
5847
0
           valid_motion_mode_cand_loc) *
5848
0
              sizeof(best_motion_mode_cands->motion_mode_cand[0]));
5849
0
    motion_mode_cand->mbmi = *mbmi;
5850
0
    motion_mode_cand->rd_cost = this_rd;
5851
0
    motion_mode_cand->skip_motion_mode = skip_motion_mode;
5852
0
    best_motion_mode_cands->motion_mode_cand[valid_motion_mode_cand_loc] =
5853
0
        *motion_mode_cand;
5854
0
    best_motion_mode_cands->num_motion_mode_cand =
5855
0
        AOMMIN(max_winner_motion_mode_cand,
5856
0
               best_motion_mode_cands->num_motion_mode_cand + 1);
5857
0
  }
5858
0
}
5859
5860
/*!\brief Search intra modes in interframes
5861
 *
5862
 * \ingroup intra_mode_search
5863
 *
5864
 * This function searches for the best intra mode when the current frame is an
5865
 * interframe. This function however does *not* handle luma palette mode.
5866
 * Palette mode is currently handled by \ref av1_search_palette_mode.
5867
 *
5868
 * This function will first iterate through the luma mode candidates to find the
5869
 * best luma intra mode. Once the best luma mode it's found, it will then search
5870
 * for the best chroma mode. Because palette mode is currently not handled by
5871
 * here, a cache of uv mode is stored in
5872
 * InterModeSearchState::intra_search_state so it can be reused later by \ref
5873
 * av1_search_palette_mode.
5874
 *
5875
 * \param[in,out] search_state      Struct keep track of the prediction mode
5876
 *                                  search state in interframe.
5877
 *
5878
 * \param[in]     cpi               Top-level encoder structure.
5879
 * \param[in,out] x                 Pointer to struct holding all the data for
5880
 *                                  the current prediction block.
5881
 * \param[out]    rd_cost           Stores the best rd_cost among all the
5882
 *                                  prediction modes searched.
5883
 * \param[in]     bsize             Current block size.
5884
 * \param[in,out] ctx               Structure to hold the number of 4x4 blks to
5885
 *                                  copy the tx_type and txfm_skip arrays.
5886
 *                                  for only the Y plane.
5887
 * \param[in]     sf_args           Stores the list of intra mode candidates
5888
 *                                  to be searched.
5889
 * \param[in]     intra_ref_frame_cost  The entropy cost for signaling that the
5890
 *                                      current ref frame is an intra frame.
5891
 * \param[in]     yrd_threshold     The rdcost threshold for luma intra mode to
5892
 *                                  terminate chroma intra mode search.
5893
 *
5894
 * \remark If a new best mode is found, search_state and rd_costs are updated
5895
 * correspondingly. While x is also modified, it is only used as a temporary
5896
 * buffer, and the final decisions are stored in search_state.
5897
 */
5898
static inline void search_intra_modes_in_interframe(
5899
    InterModeSearchState *search_state, const AV1_COMP *cpi, MACROBLOCK *x,
5900
    RD_STATS *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
5901
    const InterModeSFArgs *sf_args, unsigned int intra_ref_frame_cost,
5902
0
    int64_t yrd_threshold) {
5903
0
  const AV1_COMMON *const cm = &cpi->common;
5904
0
  const SPEED_FEATURES *const sf = &cpi->sf;
5905
0
  const IntraModeCfg *const intra_mode_cfg = &cpi->oxcf.intra_mode_cfg;
5906
0
  MACROBLOCKD *const xd = &x->e_mbd;
5907
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
5908
0
  IntraModeSearchState *intra_search_state = &search_state->intra_search_state;
5909
5910
0
  int is_best_y_mode_intra = 0;
5911
0
  RD_STATS best_intra_rd_stats_y;
5912
0
  int64_t best_rd_y = INT64_MAX;
5913
0
  int best_mode_cost_y = -1;
5914
0
  MB_MODE_INFO best_mbmi = *xd->mi[0];
5915
0
  THR_MODES best_mode_enum = THR_INVALID;
5916
0
  uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
5917
0
  const int num_4x4 = bsize_to_num_blk(bsize);
5918
5919
  // Performs luma search
5920
0
  int64_t best_model_rd = INT64_MAX;
5921
0
  int64_t top_intra_model_rd[TOP_INTRA_MODEL_COUNT];
5922
0
  for (int i = 0; i < TOP_INTRA_MODEL_COUNT; i++) {
5923
0
    top_intra_model_rd[i] = INT64_MAX;
5924
0
  }
5925
5926
0
#if CONFIG_AV1_HIGHBITDEPTH
5927
0
  const int allow_larger_intra =
5928
0
      xd->bd > 8 && cpi->oxcf.algo_cfg.sharpness == 3;
5929
#else
5930
  const int allow_larger_intra = 0;
5931
#endif
5932
0
  if (cpi->oxcf.algo_cfg.sharpness && !allow_larger_intra) {
5933
0
    int bh = mi_size_high[bsize];
5934
0
    int bw = mi_size_wide[bsize];
5935
0
    if (bh > 4 || bw > 4) return;
5936
0
  }
5937
5938
0
  mbmi->skip_txfm = 0;
5939
5940
0
  for (int mode_idx = 0; mode_idx < LUMA_MODE_COUNT; ++mode_idx) {
5941
0
    if (sf->intra_sf.skip_intra_in_interframe &&
5942
0
        search_state->intra_search_state.skip_intra_modes)
5943
0
      break;
5944
0
    set_y_mode_and_delta_angle(
5945
0
        mode_idx, mbmi, sf->intra_sf.prune_luma_odd_delta_angles_in_intra);
5946
0
    assert(mbmi->mode < INTRA_MODE_END);
5947
5948
    // Use intra_y_mode_mask speed feature to skip intra mode evaluation.
5949
0
    if (sf_args->mode_skip_mask->pred_modes[INTRA_FRAME] & (1 << mbmi->mode))
5950
0
      continue;
5951
5952
0
    const THR_MODES mode_enum =
5953
0
        get_prediction_mode_idx(mbmi->mode, INTRA_FRAME, NONE_FRAME);
5954
0
    if ((!intra_mode_cfg->enable_smooth_intra ||
5955
0
         cpi->sf.intra_sf.disable_smooth_intra) &&
5956
0
        (mbmi->mode == SMOOTH_PRED || mbmi->mode == SMOOTH_H_PRED ||
5957
0
         mbmi->mode == SMOOTH_V_PRED))
5958
0
      continue;
5959
0
    if (!intra_mode_cfg->enable_paeth_intra && mbmi->mode == PAETH_PRED)
5960
0
      continue;
5961
0
    if (av1_is_directional_mode(mbmi->mode) &&
5962
0
        !(av1_use_angle_delta(bsize) && intra_mode_cfg->enable_angle_delta) &&
5963
0
        mbmi->angle_delta[PLANE_TYPE_Y] != 0)
5964
0
      continue;
5965
0
    const PREDICTION_MODE this_mode = mbmi->mode;
5966
5967
0
    assert(av1_mode_defs[mode_enum].ref_frame[0] == INTRA_FRAME);
5968
0
    assert(av1_mode_defs[mode_enum].ref_frame[1] == NONE_FRAME);
5969
0
    init_mbmi(mbmi, this_mode, av1_mode_defs[mode_enum].ref_frame, cm);
5970
0
    x->txfm_search_info.skip_txfm = 0;
5971
5972
0
    if (this_mode != DC_PRED) {
5973
      // Only search the oblique modes if the best so far is
5974
      // one of the neighboring directional modes
5975
0
      if ((sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
5976
0
          (this_mode >= D45_PRED && this_mode <= PAETH_PRED)) {
5977
0
        if (search_state->best_mode_index != THR_INVALID &&
5978
0
            search_state->best_mbmode.ref_frame[0] > INTRA_FRAME)
5979
0
          continue;
5980
0
      }
5981
0
      if (sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
5982
0
        if (conditional_skipintra(
5983
0
                this_mode, search_state->intra_search_state.best_intra_mode))
5984
0
          continue;
5985
0
      }
5986
0
    }
5987
5988
0
    RD_STATS intra_rd_stats_y;
5989
0
    int mode_cost_y;
5990
0
    int64_t intra_rd_y = INT64_MAX;
5991
0
    const int is_luma_result_valid = av1_handle_intra_y_mode(
5992
0
        intra_search_state, cpi, x, bsize, intra_ref_frame_cost, ctx,
5993
0
        &intra_rd_stats_y, search_state->best_rd, &mode_cost_y, &intra_rd_y,
5994
0
        &best_model_rd, top_intra_model_rd);
5995
5996
0
    if (intra_rd_y < INT64_MAX) {
5997
0
      adjust_cost(cpi, x, &intra_rd_y, /*is_inter_pred=*/false);
5998
0
    }
5999
6000
0
    if (is_luma_result_valid && intra_rd_y < yrd_threshold) {
6001
0
      is_best_y_mode_intra = 1;
6002
0
      if (intra_rd_y < best_rd_y) {
6003
0
        best_intra_rd_stats_y = intra_rd_stats_y;
6004
0
        best_mode_cost_y = mode_cost_y;
6005
0
        best_rd_y = intra_rd_y;
6006
0
        best_mbmi = *mbmi;
6007
0
        best_mode_enum = mode_enum;
6008
0
        av1_copy_array(best_tx_type_map, xd->tx_type_map, num_4x4);
6009
0
      }
6010
0
    }
6011
0
  }
6012
6013
0
  if (!is_best_y_mode_intra) {
6014
0
    return;
6015
0
  }
6016
6017
0
  assert(best_rd_y < INT64_MAX);
6018
6019
  // Restores the best luma mode
6020
0
  *mbmi = best_mbmi;
6021
0
  av1_copy_array(xd->tx_type_map, best_tx_type_map, num_4x4);
6022
6023
  // Performs chroma search
6024
0
  RD_STATS intra_rd_stats, intra_rd_stats_uv;
6025
0
  av1_init_rd_stats(&intra_rd_stats);
6026
0
  av1_init_rd_stats(&intra_rd_stats_uv);
6027
0
  const int num_planes = av1_num_planes(cm);
6028
0
  if (num_planes > 1) {
6029
0
    const int intra_uv_mode_valid = av1_search_intra_uv_modes_in_interframe(
6030
0
        intra_search_state, cpi, x, bsize, &intra_rd_stats,
6031
0
        &best_intra_rd_stats_y, &intra_rd_stats_uv, search_state->best_rd);
6032
6033
0
    if (!intra_uv_mode_valid) {
6034
0
      return;
6035
0
    }
6036
0
  }
6037
6038
  // Merge the luma and chroma rd stats
6039
0
  assert(best_mode_cost_y >= 0);
6040
0
  intra_rd_stats.rate = best_intra_rd_stats_y.rate + best_mode_cost_y;
6041
0
  if (!xd->lossless[mbmi->segment_id] && block_signals_txsize(bsize)) {
6042
    // av1_pick_uniform_tx_size_type_yrd above includes the cost of the tx_size
6043
    // in the tokenonly rate, but for intra blocks, tx_size is always coded
6044
    // (prediction granularity), so we account for it in the full rate,
6045
    // not the tokenonly rate.
6046
0
    best_intra_rd_stats_y.rate -= tx_size_cost(x, bsize, mbmi->tx_size);
6047
0
  }
6048
6049
0
  const ModeCosts *mode_costs = &x->mode_costs;
6050
0
  const PREDICTION_MODE mode = mbmi->mode;
6051
0
  if (num_planes > 1 && xd->is_chroma_ref) {
6052
0
    const int uv_mode_cost =
6053
0
        mode_costs->intra_uv_mode_cost[is_cfl_allowed(xd)][mode][mbmi->uv_mode];
6054
0
    intra_rd_stats.rate +=
6055
0
        intra_rd_stats_uv.rate +
6056
0
        intra_mode_info_cost_uv(cpi, x, mbmi, bsize, uv_mode_cost);
6057
0
  }
6058
6059
  // Intra block is always coded as non-skip
6060
0
  intra_rd_stats.skip_txfm = 0;
6061
0
  intra_rd_stats.dist = best_intra_rd_stats_y.dist + intra_rd_stats_uv.dist;
6062
  // Add in the cost of the no skip flag.
6063
0
  const int skip_ctx = av1_get_skip_txfm_context(xd);
6064
0
  intra_rd_stats.rate += mode_costs->skip_txfm_cost[skip_ctx][0];
6065
  // Calculate the final RD estimate for this mode.
6066
0
  const int64_t this_rd =
6067
0
      RDCOST(x->rdmult, intra_rd_stats.rate, intra_rd_stats.dist);
6068
  // Keep record of best intra rd
6069
0
  if (this_rd < search_state->best_intra_rd) {
6070
0
    search_state->best_intra_rd = this_rd;
6071
0
    intra_search_state->best_intra_mode = mode;
6072
0
  }
6073
6074
0
  for (int i = 0; i < REFERENCE_MODES; ++i) {
6075
0
    search_state->best_pred_rd[i] =
6076
0
        AOMMIN(search_state->best_pred_rd[i], this_rd);
6077
0
  }
6078
6079
0
  intra_rd_stats.rdcost = this_rd;
6080
6081
0
  adjust_rdcost(cpi, x, &intra_rd_stats, /*is_inter_pred=*/false);
6082
6083
  // Collect mode stats for multiwinner mode processing
6084
0
  const int txfm_search_done = 1;
6085
0
  store_winner_mode_stats(
6086
0
      cpi, x, mbmi, &intra_rd_stats, &best_intra_rd_stats_y, &intra_rd_stats_uv,
6087
0
      best_mode_enum, NULL, bsize, intra_rd_stats.rdcost,
6088
0
      cpi->sf.winner_mode_sf.multi_winner_mode_type, txfm_search_done);
6089
0
  if (intra_rd_stats.rdcost < search_state->best_rd) {
6090
0
    update_search_state(cpi, search_state, rd_cost, ctx, &intra_rd_stats,
6091
0
                        &best_intra_rd_stats_y, &intra_rd_stats_uv,
6092
0
                        best_mode_enum, x, txfm_search_done);
6093
0
  }
6094
0
}
6095
6096
// Initialize the table that stores best RD Costs of transform no-split.
6097
static inline void init_top_tx_no_split_rd_for_inter_modes(
6098
0
    MACROBLOCK *x, int prune_inter_tx_split_rd_eval_lvl) {
6099
0
  if (!prune_inter_tx_split_rd_eval_lvl) return;
6100
6101
0
  for (int i = 0; i < MAX_TX_BLOCKS_IN_MAX_SB; i++) {
6102
0
    for (int j = 0; j < TOP_INTER_TX_NO_SPLIT_COUNT; j++) {
6103
0
      x->top_inter_tx_no_split_rd[i][j] = INT64_MAX;
6104
0
    }
6105
0
  }
6106
0
}
6107
6108
#if !CONFIG_REALTIME_ONLY
6109
// Prepare inter_cost and intra_cost from TPL stats, which are used as ML
6110
// features in intra mode pruning.
6111
static inline void calculate_cost_from_tpl_data(const AV1_COMP *cpi,
6112
                                                MACROBLOCK *x, BLOCK_SIZE bsize,
6113
                                                int mi_row, int mi_col,
6114
                                                int64_t *inter_cost,
6115
0
                                                int64_t *intra_cost) {
6116
0
  const AV1_COMMON *const cm = &cpi->common;
6117
  // Only consider full SB.
6118
0
  const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
6119
0
  const int tpl_bsize_1d = cpi->ppi->tpl_data.tpl_bsize_1d;
6120
0
  const int len = (block_size_wide[sb_size] / tpl_bsize_1d) *
6121
0
                  (block_size_high[sb_size] / tpl_bsize_1d);
6122
0
  SuperBlockEnc *sb_enc = &x->sb_enc;
6123
0
  if (sb_enc->tpl_data_count == len) {
6124
0
    const BLOCK_SIZE tpl_bsize = convert_length_to_bsize(tpl_bsize_1d);
6125
0
    const int tpl_stride = sb_enc->tpl_stride;
6126
0
    const int tplw = mi_size_wide[tpl_bsize];
6127
0
    const int tplh = mi_size_high[tpl_bsize];
6128
0
    const int nw = mi_size_wide[bsize] / tplw;
6129
0
    const int nh = mi_size_high[bsize] / tplh;
6130
0
    if (nw >= 1 && nh >= 1) {
6131
0
      const int of_h = mi_row % mi_size_high[sb_size];
6132
0
      const int of_w = mi_col % mi_size_wide[sb_size];
6133
0
      const int start = of_h / tplh * tpl_stride + of_w / tplw;
6134
6135
0
      for (int k = 0; k < nh; k++) {
6136
0
        for (int l = 0; l < nw; l++) {
6137
0
          *inter_cost += sb_enc->tpl_inter_cost[start + k * tpl_stride + l];
6138
0
          *intra_cost += sb_enc->tpl_intra_cost[start + k * tpl_stride + l];
6139
0
        }
6140
0
      }
6141
0
      *inter_cost /= nw * nh;
6142
0
      *intra_cost /= nw * nh;
6143
0
    }
6144
0
  }
6145
0
}
6146
#endif  // !CONFIG_REALTIME_ONLY
6147
6148
// When the speed feature skip_intra_in_interframe > 0, enable ML model to prune
6149
// intra mode search.
6150
static inline void skip_intra_modes_in_interframe(
6151
    AV1_COMMON *const cm, struct macroblock *x, BLOCK_SIZE bsize,
6152
    InterModeSearchState *search_state, const SPEED_FEATURES *const sf,
6153
0
    int64_t inter_cost, int64_t intra_cost) {
6154
0
  MACROBLOCKD *const xd = &x->e_mbd;
6155
0
  const int comp_pred = search_state->best_mbmode.ref_frame[1] > INTRA_FRAME;
6156
0
  if (sf->rt_sf.prune_intra_mode_based_on_mv_range &&
6157
0
      bsize > sf->part_sf.max_intra_bsize && !comp_pred) {
6158
0
    const MV best_mv = search_state->best_mbmode.mv[0].as_mv;
6159
0
    const int mv_thresh = 16 << sf->rt_sf.prune_intra_mode_based_on_mv_range;
6160
0
    if (abs(best_mv.row) < mv_thresh && abs(best_mv.col) < mv_thresh &&
6161
0
        x->source_variance > 128) {
6162
0
      search_state->intra_search_state.skip_intra_modes = 1;
6163
0
      return;
6164
0
    }
6165
0
  }
6166
6167
0
  const unsigned int src_var_thresh_intra_skip = 1;
6168
0
  const int skip_intra_in_interframe = sf->intra_sf.skip_intra_in_interframe;
6169
0
  if (!(skip_intra_in_interframe &&
6170
0
        (x->source_variance > src_var_thresh_intra_skip)))
6171
0
    return;
6172
6173
  // Prune intra search based on best inter mode being transfrom skip.
6174
0
  if ((skip_intra_in_interframe >= 2) && search_state->best_mbmode.skip_txfm) {
6175
0
    const int qindex_thresh[2] = { 200, MAXQ };
6176
0
    const int ind = (skip_intra_in_interframe >= 3) ? 1 : 0;
6177
0
    if (!have_newmv_in_inter_mode(search_state->best_mbmode.mode) &&
6178
0
        (x->qindex <= qindex_thresh[ind])) {
6179
0
      search_state->intra_search_state.skip_intra_modes = 1;
6180
0
      return;
6181
0
    } else if ((skip_intra_in_interframe >= 4) &&
6182
0
               (inter_cost < 0 || intra_cost < 0)) {
6183
0
      search_state->intra_search_state.skip_intra_modes = 1;
6184
0
      return;
6185
0
    }
6186
0
  }
6187
  // Use ML model to prune intra search.
6188
0
  if (inter_cost >= 0 && intra_cost >= 0) {
6189
0
    const NN_CONFIG *nn_config = (AOMMIN(cm->width, cm->height) <= 480)
6190
0
                                     ? &av1_intrap_nn_config
6191
0
                                     : &av1_intrap_hd_nn_config;
6192
0
    float nn_features[6];
6193
0
    float scores[2] = { 0.0f };
6194
6195
0
    nn_features[0] = (float)search_state->best_mbmode.skip_txfm;
6196
0
    nn_features[1] = (float)mi_size_wide_log2[bsize];
6197
0
    nn_features[2] = (float)mi_size_high_log2[bsize];
6198
0
    nn_features[3] = (float)intra_cost;
6199
0
    nn_features[4] = (float)inter_cost;
6200
0
    const int ac_q = av1_ac_quant_QTX(x->qindex, 0, xd->bd);
6201
0
    const int ac_q_max = av1_ac_quant_QTX(255, 0, xd->bd);
6202
0
    nn_features[5] = (float)(ac_q_max / ac_q);
6203
6204
0
    av1_nn_predict(nn_features, nn_config, 1, scores);
6205
6206
    // For two parameters, the max prob returned from av1_nn_softmax equals
6207
    // 1.0 / (1.0 + e^(-|diff_score|)). Here use scores directly to avoid the
6208
    // calling of av1_nn_softmax.
6209
0
    const float thresh[5] = { 1.4f, 1.4f, 1.4f, 1.4f, 1.4f };
6210
0
    assert(skip_intra_in_interframe <= 5);
6211
0
    if (scores[1] > scores[0] + thresh[skip_intra_in_interframe - 1]) {
6212
0
      search_state->intra_search_state.skip_intra_modes = 1;
6213
0
    }
6214
0
  }
6215
0
}
6216
6217
static inline bool skip_interp_filter_search(const AV1_COMP *cpi,
6218
0
                                             int is_single_pred) {
6219
0
  const MODE encoding_mode = cpi->oxcf.mode;
6220
0
  if (encoding_mode == REALTIME) {
6221
0
    return (cpi->common.current_frame.reference_mode == SINGLE_REFERENCE &&
6222
0
            (cpi->sf.interp_sf.skip_interp_filter_search ||
6223
0
             cpi->sf.winner_mode_sf.winner_mode_ifs));
6224
0
  } else if (encoding_mode == GOOD) {
6225
    // Skip interpolation filter search for single prediction modes.
6226
0
    return (cpi->sf.interp_sf.skip_interp_filter_search && is_single_pred);
6227
0
  }
6228
0
  return false;
6229
0
}
6230
6231
static inline int get_block_temp_var(const AV1_COMP *cpi, const MACROBLOCK *x,
6232
0
                                     BLOCK_SIZE bsize) {
6233
0
  const AV1_COMMON *const cm = &cpi->common;
6234
0
  const SPEED_FEATURES *const sf = &cpi->sf;
6235
6236
0
  if (sf->part_sf.partition_search_type != VAR_BASED_PARTITION ||
6237
0
      !sf->rt_sf.short_circuit_low_temp_var ||
6238
0
      !sf->rt_sf.prune_inter_modes_using_temp_var) {
6239
0
    return 0;
6240
0
  }
6241
6242
0
  const int mi_row = x->e_mbd.mi_row;
6243
0
  const int mi_col = x->e_mbd.mi_col;
6244
0
  int is_low_temp_var = 0;
6245
6246
0
  if (cm->seq_params->sb_size == BLOCK_64X64)
6247
0
    is_low_temp_var = av1_get_force_skip_low_temp_var_small_sb(
6248
0
        &x->part_search_info.variance_low[0], mi_row, mi_col, bsize);
6249
0
  else
6250
0
    is_low_temp_var = av1_get_force_skip_low_temp_var(
6251
0
        &x->part_search_info.variance_low[0], mi_row, mi_col, bsize);
6252
6253
0
  return is_low_temp_var;
6254
0
}
6255
6256
// TODO(chiyotsai@google.com): See the todo for av1_rd_pick_intra_mode_sb.
6257
void av1_rd_pick_inter_mode(struct AV1_COMP *cpi, struct TileDataEnc *tile_data,
6258
                            struct macroblock *x, struct RD_STATS *rd_cost,
6259
                            BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
6260
0
                            int64_t best_rd_so_far) {
6261
0
  AV1_COMMON *const cm = &cpi->common;
6262
0
  const FeatureFlags *const features = &cm->features;
6263
0
  const int num_planes = av1_num_planes(cm);
6264
0
  const SPEED_FEATURES *const sf = &cpi->sf;
6265
0
  MACROBLOCKD *const xd = &x->e_mbd;
6266
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
6267
0
  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
6268
0
  int i;
6269
0
  const ModeCosts *mode_costs = &x->mode_costs;
6270
0
  const int *comp_inter_cost =
6271
0
      mode_costs->comp_inter_cost[av1_get_reference_mode_context(xd)];
6272
6273
0
  InterModeSearchState search_state;
6274
0
  init_inter_mode_search_state(&search_state, cpi, x, bsize, best_rd_so_far);
6275
0
  INTERINTRA_MODE interintra_modes[REF_FRAMES] = {
6276
0
    INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES,
6277
0
    INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES
6278
0
  };
6279
6280
0
  init_top_tx_no_split_rd_for_inter_modes(
6281
0
      x, sf->tx_sf.prune_inter_tx_split_rd_eval_lvl);
6282
6283
0
  HandleInterModeArgs args = { { NULL },
6284
0
                               { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
6285
0
                               { NULL },
6286
0
                               { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
6287
0
                                 MAX_SB_SIZE >> 1 },
6288
0
                               NULL,
6289
0
                               NULL,
6290
0
                               NULL,
6291
0
                               search_state.modelled_rd,
6292
0
                               INT_MAX,
6293
0
                               INT_MAX,
6294
0
                               search_state.simple_rd,
6295
0
                               0,
6296
0
                               false,
6297
0
                               interintra_modes,
6298
0
                               { { { 0 }, { { 0 } }, { 0 }, 0, 0, 0, 0 } },
6299
0
                               { { 0, 0 } },
6300
0
                               { 0 },
6301
0
                               0,
6302
0
                               0,
6303
0
                               -1,
6304
0
                               -1,
6305
0
                               -1,
6306
0
                               { 0 },
6307
0
                               { 0 },
6308
0
                               UINT_MAX };
6309
  // Currently, is_low_temp_var is used in real time encoding.
6310
0
  const int is_low_temp_var = get_block_temp_var(cpi, x, bsize);
6311
6312
0
  for (i = 0; i < MODE_CTX_REF_FRAMES; ++i) args.cmp_mode[i] = -1;
6313
  // Indicates the appropriate number of simple translation winner modes for
6314
  // exhaustive motion mode evaluation
6315
0
  const int max_winner_motion_mode_cand =
6316
0
      num_winner_motion_modes[sf->winner_mode_sf.motion_mode_for_winner_cand];
6317
0
  assert(max_winner_motion_mode_cand <= MAX_WINNER_MOTION_MODES);
6318
0
  motion_mode_candidate motion_mode_cand;
6319
0
  motion_mode_best_st_candidate best_motion_mode_cands;
6320
  // Initializing the number of motion mode candidates to zero.
6321
0
  best_motion_mode_cands.num_motion_mode_cand = 0;
6322
0
  for (i = 0; i < MAX_WINNER_MOTION_MODES; ++i)
6323
0
    best_motion_mode_cands.motion_mode_cand[i].rd_cost = INT64_MAX;
6324
6325
0
  for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;
6326
6327
0
  av1_invalid_rd_stats(rd_cost);
6328
6329
0
  for (i = 0; i < REF_FRAMES; ++i) {
6330
0
    x->warp_sample_info[i].num = -1;
6331
0
  }
6332
6333
  // Ref frames that are selected by square partition blocks.
6334
0
  int picked_ref_frames_mask = 0;
6335
0
  if (sf->inter_sf.prune_ref_frame_for_rect_partitions &&
6336
0
      mbmi->partition != PARTITION_NONE) {
6337
    // prune_ref_frame_for_rect_partitions = 1 implies prune only extended
6338
    // partition blocks. prune_ref_frame_for_rect_partitions >=2
6339
    // implies prune for vert, horiz and extended partition blocks.
6340
0
    if ((mbmi->partition != PARTITION_VERT &&
6341
0
         mbmi->partition != PARTITION_HORZ) ||
6342
0
        sf->inter_sf.prune_ref_frame_for_rect_partitions >= 2) {
6343
0
      picked_ref_frames_mask =
6344
0
          fetch_picked_ref_frames_mask(x, bsize, cm->seq_params->mib_size);
6345
0
    }
6346
0
  }
6347
6348
#if CONFIG_COLLECT_COMPONENT_TIMING
6349
  start_timing(cpi, set_params_rd_pick_inter_mode_time);
6350
#endif
6351
  // Skip ref frames that never selected by square blocks.
6352
0
  const int skip_ref_frame_mask =
6353
0
      picked_ref_frames_mask ? ~picked_ref_frames_mask : 0;
6354
0
  mode_skip_mask_t mode_skip_mask;
6355
0
  unsigned int ref_costs_single[REF_FRAMES];
6356
0
  unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES];
6357
0
  struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE];
6358
  // init params, set frame modes, speed features
6359
0
  set_params_rd_pick_inter_mode(cpi, x, &args, bsize, &mode_skip_mask,
6360
0
                                skip_ref_frame_mask, ref_costs_single,
6361
0
                                ref_costs_comp, yv12_mb);
6362
#if CONFIG_COLLECT_COMPONENT_TIMING
6363
  end_timing(cpi, set_params_rd_pick_inter_mode_time);
6364
#endif
6365
6366
0
  int64_t best_est_rd = INT64_MAX;
6367
0
  const InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
6368
  // If do_tx_search is 0, only estimated RD should be computed.
6369
  // If do_tx_search is 1, all modes have TX search performed.
6370
0
  const int do_tx_search =
6371
0
      !((sf->inter_sf.inter_mode_rd_model_estimation == 1 && md->ready) ||
6372
0
        (sf->inter_sf.inter_mode_rd_model_estimation == 2 &&
6373
0
         num_pels_log2_lookup[bsize] > 8));
6374
0
  InterModesInfo *inter_modes_info = x->inter_modes_info;
6375
0
  inter_modes_info->num = 0;
6376
6377
  // Temporary buffers used by handle_inter_mode().
6378
0
  uint8_t *const tmp_buf = get_buf_by_bd(xd, x->tmp_pred_bufs[0]);
6379
6380
  // The best RD found for the reference frame, among single reference modes.
6381
  // Note that the 0-th element will contain a cut-off that is later used
6382
  // to determine if we should skip a compound mode.
6383
0
  int64_t ref_frame_rd[REF_FRAMES] = { INT64_MAX, INT64_MAX, INT64_MAX,
6384
0
                                       INT64_MAX, INT64_MAX, INT64_MAX,
6385
0
                                       INT64_MAX, INT64_MAX };
6386
6387
  // Prepared stats used later to check if we could skip intra mode eval.
6388
0
  int64_t inter_cost = -1;
6389
0
  int64_t intra_cost = -1;
6390
  // Need to tweak the threshold for hdres speed 0 & 1.
6391
0
  const int mi_row = xd->mi_row;
6392
0
  const int mi_col = xd->mi_col;
6393
6394
  // Obtain the relevant tpl stats for pruning inter modes
6395
0
  PruneInfoFromTpl inter_cost_info_from_tpl;
6396
0
#if !CONFIG_REALTIME_ONLY
6397
0
  if (sf->inter_sf.prune_inter_modes_based_on_tpl) {
6398
    // x->tpl_keep_ref_frame[id] = 1 => no pruning in
6399
    // prune_ref_by_selective_ref_frame()
6400
    // x->tpl_keep_ref_frame[id] = 0  => ref frame can be pruned in
6401
    // prune_ref_by_selective_ref_frame()
6402
    // Populating valid_refs[idx] = 1 ensures that
6403
    // 'inter_cost_info_from_tpl.best_inter_cost' does not correspond to a
6404
    // pruned ref frame.
6405
0
    int valid_refs[INTER_REFS_PER_FRAME];
6406
0
    for (MV_REFERENCE_FRAME frame = LAST_FRAME; frame < REF_FRAMES; frame++) {
6407
0
      const MV_REFERENCE_FRAME refs[2] = { frame, NONE_FRAME };
6408
0
      valid_refs[frame - 1] =
6409
0
          x->tpl_keep_ref_frame[frame] ||
6410
0
          !prune_ref_by_selective_ref_frame(
6411
0
              cpi, x, refs, cm->cur_frame->ref_display_order_hint);
6412
0
    }
6413
0
    av1_zero(inter_cost_info_from_tpl);
6414
0
    get_block_level_tpl_stats(cpi, bsize, mi_row, mi_col, valid_refs,
6415
0
                              &inter_cost_info_from_tpl);
6416
0
  }
6417
6418
0
  const int do_pruning =
6419
0
      (AOMMIN(cm->width, cm->height) > 480 && cpi->speed <= 1) ? 0 : 1;
6420
0
  if (do_pruning && sf->intra_sf.skip_intra_in_interframe &&
6421
0
      cpi->oxcf.algo_cfg.enable_tpl_model)
6422
0
    calculate_cost_from_tpl_data(cpi, x, bsize, mi_row, mi_col, &inter_cost,
6423
0
                                 &intra_cost);
6424
0
#endif  // !CONFIG_REALTIME_ONLY
6425
6426
  // Initialize best mode stats for winner mode processing.
6427
0
  const int max_winner_mode_count =
6428
0
      winner_mode_count_allowed[sf->winner_mode_sf.multi_winner_mode_type];
6429
0
  zero_winner_mode_stats(bsize, max_winner_mode_count, x->winner_mode_stats);
6430
0
  x->winner_mode_count = 0;
6431
0
  store_winner_mode_stats(cpi, x, mbmi, NULL, NULL, NULL, THR_INVALID, NULL,
6432
0
                          bsize, best_rd_so_far,
6433
0
                          sf->winner_mode_sf.multi_winner_mode_type, 0);
6434
6435
0
  int mode_thresh_mul_fact = (1 << MODE_THRESH_QBITS);
6436
0
  if (sf->inter_sf.prune_inter_modes_if_skippable) {
6437
    // Higher multiplication factor values for lower quantizers.
6438
0
    mode_thresh_mul_fact = mode_threshold_mul_factor[x->qindex];
6439
0
  }
6440
6441
  // Initialize arguments for mode loop speed features
6442
0
  InterModeSFArgs sf_args = { &args.skip_motion_mode,
6443
0
                              &mode_skip_mask,
6444
0
                              &search_state,
6445
0
                              skip_ref_frame_mask,
6446
0
                              0,
6447
0
                              mode_thresh_mul_fact,
6448
0
                              0,
6449
0
                              0 };
6450
0
  int64_t best_inter_yrd = INT64_MAX;
6451
6452
  // This is the main loop of this function. It loops over all possible inter
6453
  // modes and calls handle_inter_mode() to compute the RD for each.
6454
  // Here midx is just an iterator index that should not be used by itself
6455
  // except to keep track of the number of modes searched. It should be used
6456
  // with av1_default_mode_order to get the enum that defines the mode, which
6457
  // can be used with av1_mode_defs to get the prediction mode and the ref
6458
  // frames.
6459
  // TODO(yunqing, any): Setting mode_start and mode_end outside for-loop brings
6460
  // good speedup for real time case. If we decide to use compound mode in real
6461
  // time, maybe we can modify av1_default_mode_order table.
6462
0
  THR_MODES mode_start = THR_INTER_MODE_START;
6463
0
  THR_MODES mode_end = THR_INTER_MODE_END;
6464
0
  const CurrentFrame *const current_frame = &cm->current_frame;
6465
0
  if (current_frame->reference_mode == SINGLE_REFERENCE) {
6466
0
    mode_start = SINGLE_REF_MODE_START;
6467
0
    mode_end = SINGLE_REF_MODE_END;
6468
0
  }
6469
0
  init_comp_avg_est_rd(x, sf->inter_sf.skip_cmp_using_top_cmp_avg_est_rd_lvl);
6470
0
  init_smooth_interintra_est_rd(
6471
0
      x, sf->inter_sf.skip_interintra_using_top_smooth_rd_lvl);
6472
0
  for (THR_MODES midx = mode_start; midx < mode_end; ++midx) {
6473
    // Get the actual prediction mode we are trying in this iteration
6474
0
    const THR_MODES mode_enum = av1_default_mode_order[midx];
6475
0
    const MODE_DEFINITION *mode_def = &av1_mode_defs[mode_enum];
6476
0
    const PREDICTION_MODE this_mode = mode_def->mode;
6477
0
    const MV_REFERENCE_FRAME *ref_frames = mode_def->ref_frame;
6478
6479
0
    const MV_REFERENCE_FRAME ref_frame = ref_frames[0];
6480
0
    const MV_REFERENCE_FRAME second_ref_frame = ref_frames[1];
6481
0
    const int is_single_pred =
6482
0
        ref_frame > INTRA_FRAME && second_ref_frame == NONE_FRAME;
6483
0
    const int comp_pred = second_ref_frame > INTRA_FRAME;
6484
6485
0
    txfm_info->skip_txfm = 0;
6486
0
    mbmi->skip_txfm = 0;
6487
0
    sf_args.num_single_modes_processed += is_single_pred;
6488
#if CONFIG_COLLECT_COMPONENT_TIMING
6489
    start_timing(cpi, skip_inter_mode_time);
6490
#endif
6491
    // Apply speed features to decide if this inter mode can be skipped
6492
0
    const int is_skip_inter_mode = skip_inter_mode(
6493
0
        cpi, x, bsize, ref_frame_rd, midx, &sf_args, is_low_temp_var);
6494
#if CONFIG_COLLECT_COMPONENT_TIMING
6495
    end_timing(cpi, skip_inter_mode_time);
6496
#endif
6497
0
    if (is_skip_inter_mode) continue;
6498
6499
0
    init_mbmi(mbmi, this_mode, ref_frames, cm);
6500
0
    set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
6501
6502
    // Select prediction reference frames.
6503
0
    for (i = 0; i < num_planes; i++) {
6504
0
      xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
6505
0
      if (comp_pred) xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
6506
0
    }
6507
6508
0
    mbmi->angle_delta[PLANE_TYPE_Y] = 0;
6509
0
    mbmi->angle_delta[PLANE_TYPE_UV] = 0;
6510
0
    mbmi->filter_intra_mode_info.use_filter_intra = 0;
6511
0
    mbmi->ref_mv_idx = 0;
6512
6513
0
    const int64_t ref_best_rd = search_state.best_rd;
6514
0
    RD_STATS rd_stats, rd_stats_y, rd_stats_uv;
6515
0
    av1_init_rd_stats(&rd_stats);
6516
6517
0
    const int ref_frame_cost = comp_pred
6518
0
                                   ? ref_costs_comp[ref_frame][second_ref_frame]
6519
0
                                   : ref_costs_single[ref_frame];
6520
0
    const int compmode_cost =
6521
0
        is_comp_ref_allowed(mbmi->bsize) ? comp_inter_cost[comp_pred] : 0;
6522
0
    const int real_compmode_cost =
6523
0
        cm->current_frame.reference_mode == REFERENCE_MODE_SELECT
6524
0
            ? compmode_cost
6525
0
            : 0;
6526
    // Point to variables that are maintained between loop iterations
6527
0
    args.single_newmv = search_state.single_newmv;
6528
0
    args.single_newmv_rate = search_state.single_newmv_rate;
6529
0
    args.single_newmv_valid = search_state.single_newmv_valid;
6530
0
    args.single_comp_cost = real_compmode_cost;
6531
0
    args.ref_frame_cost = ref_frame_cost;
6532
0
    args.best_pred_sse = search_state.best_pred_sse;
6533
0
    args.skip_ifs = skip_interp_filter_search(cpi, is_single_pred);
6534
0
    int64_t skip_rd[2] = { search_state.best_skip_rd[0],
6535
0
                           search_state.best_skip_rd[1] };
6536
0
    int64_t this_yrd = INT64_MAX;
6537
#if CONFIG_COLLECT_COMPONENT_TIMING
6538
    start_timing(cpi, handle_inter_mode_time);
6539
#endif
6540
0
    int64_t this_rd = handle_inter_mode(
6541
0
        cpi, tile_data, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv, &args,
6542
0
        ref_best_rd, tmp_buf, &x->comp_rd_buffer, &best_est_rd, do_tx_search,
6543
0
        inter_modes_info, &motion_mode_cand, skip_rd, &inter_cost_info_from_tpl,
6544
0
        &this_yrd);
6545
#if CONFIG_COLLECT_COMPONENT_TIMING
6546
    end_timing(cpi, handle_inter_mode_time);
6547
#endif
6548
0
    if (current_frame->reference_mode != SINGLE_REFERENCE) {
6549
0
      if (!args.skip_ifs &&
6550
0
          sf->inter_sf.prune_comp_search_by_single_result > 0 &&
6551
0
          is_inter_singleref_mode(this_mode)) {
6552
0
        collect_single_states(x, &search_state, mbmi);
6553
0
      }
6554
6555
0
      if (sf->inter_sf.prune_comp_using_best_single_mode_ref > 0 &&
6556
0
          is_inter_singleref_mode(this_mode))
6557
0
        update_best_single_mode(&search_state, this_mode, ref_frame, this_rd);
6558
0
    }
6559
6560
0
    if (this_rd == INT64_MAX) continue;
6561
6562
0
    if (mbmi->skip_txfm) {
6563
0
      rd_stats_y.rate = 0;
6564
0
      rd_stats_uv.rate = 0;
6565
0
    }
6566
6567
0
    if (sf->inter_sf.prune_compound_using_single_ref && is_single_pred &&
6568
0
        this_rd < ref_frame_rd[ref_frame]) {
6569
0
      ref_frame_rd[ref_frame] = this_rd;
6570
0
    }
6571
6572
    // Did this mode help, i.e., is it the new best mode
6573
0
    if (this_rd < search_state.best_rd) {
6574
0
      assert(IMPLIES(comp_pred,
6575
0
                     cm->current_frame.reference_mode != SINGLE_REFERENCE));
6576
0
      search_state.best_pred_sse = x->pred_sse[ref_frame];
6577
0
      best_inter_yrd = this_yrd;
6578
0
      update_search_state(cpi, &search_state, rd_cost, ctx, &rd_stats,
6579
0
                          &rd_stats_y, &rd_stats_uv, mode_enum, x,
6580
0
                          do_tx_search);
6581
0
      if (do_tx_search) search_state.best_skip_rd[0] = skip_rd[0];
6582
      // skip_rd[0] is the best total rd for a skip mode so far.
6583
      // skip_rd[1] is the best total rd for a skip mode so far in luma.
6584
      // When do_tx_search = 1, both skip_rd[0] and skip_rd[1] are updated.
6585
      // When do_tx_search = 0, skip_rd[1] is updated.
6586
0
      search_state.best_skip_rd[1] = skip_rd[1];
6587
0
    }
6588
0
    if (sf->winner_mode_sf.motion_mode_for_winner_cand) {
6589
      // Add this mode to motion mode candidate list for motion mode search
6590
      // if using motion_mode_for_winner_cand speed feature
6591
0
      handle_winner_cand(mbmi, &best_motion_mode_cands,
6592
0
                         max_winner_motion_mode_cand, this_rd,
6593
0
                         &motion_mode_cand, args.skip_motion_mode);
6594
0
    }
6595
6596
    /* keep record of best compound/single-only prediction */
6597
0
    record_best_compound(cm->current_frame.reference_mode, &rd_stats, comp_pred,
6598
0
                         x->rdmult, &search_state, compmode_cost);
6599
0
  }
6600
6601
#if CONFIG_COLLECT_COMPONENT_TIMING
6602
  start_timing(cpi, evaluate_motion_mode_for_winner_candidates_time);
6603
#endif
6604
0
  if (sf->winner_mode_sf.motion_mode_for_winner_cand) {
6605
    // For the single ref winner candidates, evaluate other motion modes (non
6606
    // simple translation).
6607
0
    evaluate_motion_mode_for_winner_candidates(
6608
0
        cpi, x, rd_cost, &args, tile_data, ctx, yv12_mb,
6609
0
        &best_motion_mode_cands, do_tx_search, bsize, &best_est_rd,
6610
0
        &search_state, &best_inter_yrd);
6611
0
  }
6612
#if CONFIG_COLLECT_COMPONENT_TIMING
6613
  end_timing(cpi, evaluate_motion_mode_for_winner_candidates_time);
6614
#endif
6615
6616
#if CONFIG_COLLECT_COMPONENT_TIMING
6617
  start_timing(cpi, do_tx_search_time);
6618
#endif
6619
0
  if (do_tx_search != 1) {
6620
    // A full tx search has not yet been done, do tx search for
6621
    // top mode candidates
6622
0
    tx_search_best_inter_candidates(cpi, tile_data, x, best_rd_so_far, bsize,
6623
0
                                    yv12_mb, mi_row, mi_col, &search_state,
6624
0
                                    rd_cost, ctx, &best_inter_yrd);
6625
0
  }
6626
#if CONFIG_COLLECT_COMPONENT_TIMING
6627
  end_timing(cpi, do_tx_search_time);
6628
#endif
6629
6630
#if CONFIG_COLLECT_COMPONENT_TIMING
6631
  start_timing(cpi, handle_intra_mode_time);
6632
#endif
6633
  // Gate intra mode evaluation if best of inter is skip except when source
6634
  // variance is extremely low and also based on max intra bsize.
6635
0
  skip_intra_modes_in_interframe(cm, x, bsize, &search_state, sf, inter_cost,
6636
0
                                 intra_cost);
6637
6638
0
  const unsigned int intra_ref_frame_cost = ref_costs_single[INTRA_FRAME];
6639
0
  search_intra_modes_in_interframe(&search_state, cpi, x, rd_cost, bsize, ctx,
6640
0
                                   &sf_args, intra_ref_frame_cost,
6641
0
                                   best_inter_yrd);
6642
#if CONFIG_COLLECT_COMPONENT_TIMING
6643
  end_timing(cpi, handle_intra_mode_time);
6644
#endif
6645
6646
#if CONFIG_COLLECT_COMPONENT_TIMING
6647
  start_timing(cpi, refine_winner_mode_tx_time);
6648
#endif
6649
0
  int winner_mode_count =
6650
0
      sf->winner_mode_sf.multi_winner_mode_type ? x->winner_mode_count : 1;
6651
  // In effect only when fast tx search speed features are enabled.
6652
0
  refine_winner_mode_tx(
6653
0
      cpi, x, rd_cost, bsize, ctx, &search_state.best_mode_index,
6654
0
      &search_state.best_mbmode, yv12_mb, search_state.best_rate_y,
6655
0
      search_state.best_rate_uv, &search_state.best_skip2, winner_mode_count);
6656
#if CONFIG_COLLECT_COMPONENT_TIMING
6657
  end_timing(cpi, refine_winner_mode_tx_time);
6658
#endif
6659
6660
  // Initialize default mode evaluation params
6661
0
  set_mode_eval_params(cpi, x, DEFAULT_EVAL);
6662
6663
  // Only try palette mode when the best mode so far is an intra mode.
6664
0
  const int try_palette =
6665
0
      cpi->oxcf.tool_cfg.enable_palette &&
6666
0
      av1_allow_palette(features->allow_screen_content_tools, mbmi->bsize) &&
6667
0
      !is_inter_mode(search_state.best_mbmode.mode) && rd_cost->rate != INT_MAX;
6668
0
  RD_STATS this_rd_cost;
6669
0
  int this_skippable = 0;
6670
0
  if (try_palette) {
6671
#if CONFIG_COLLECT_COMPONENT_TIMING
6672
    start_timing(cpi, av1_search_palette_mode_time);
6673
#endif
6674
0
    this_skippable = av1_search_palette_mode(
6675
0
        &search_state.intra_search_state, cpi, x, bsize, intra_ref_frame_cost,
6676
0
        ctx, &this_rd_cost, search_state.best_rd);
6677
#if CONFIG_COLLECT_COMPONENT_TIMING
6678
    end_timing(cpi, av1_search_palette_mode_time);
6679
#endif
6680
0
    if (this_rd_cost.rdcost < search_state.best_rd) {
6681
0
      search_state.best_mode_index = THR_DC;
6682
0
      mbmi->mv[0].as_int = 0;
6683
0
      rd_cost->rate = this_rd_cost.rate;
6684
0
      rd_cost->dist = this_rd_cost.dist;
6685
0
      rd_cost->rdcost = this_rd_cost.rdcost;
6686
0
      search_state.best_rd = rd_cost->rdcost;
6687
0
      search_state.best_mbmode = *mbmi;
6688
0
      search_state.best_skip2 = 0;
6689
0
      search_state.best_mode_skippable = this_skippable;
6690
0
      av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
6691
0
    }
6692
0
  }
6693
6694
0
  search_state.best_mbmode.skip_mode = 0;
6695
0
  if (cm->current_frame.skip_mode_info.skip_mode_flag &&
6696
0
      cpi->oxcf.algo_cfg.sharpness != 3 && is_comp_ref_allowed(bsize)) {
6697
0
    const struct segmentation *const seg = &cm->seg;
6698
0
    unsigned char segment_id = mbmi->segment_id;
6699
0
    if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
6700
0
      rd_pick_skip_mode(rd_cost, &search_state, cpi, x, bsize, yv12_mb);
6701
0
    }
6702
0
  }
6703
6704
  // Make sure that the ref_mv_idx is only nonzero when we're
6705
  // using a mode which can support ref_mv_idx
6706
0
  if (search_state.best_mbmode.ref_mv_idx != 0 &&
6707
0
      !(search_state.best_mbmode.mode == NEWMV ||
6708
0
        search_state.best_mbmode.mode == NEW_NEWMV ||
6709
0
        have_nearmv_in_inter_mode(search_state.best_mbmode.mode))) {
6710
0
    search_state.best_mbmode.ref_mv_idx = 0;
6711
0
  }
6712
6713
0
  if (search_state.best_mode_index == THR_INVALID ||
6714
0
      search_state.best_rd >= best_rd_so_far) {
6715
0
    rd_cost->rate = INT_MAX;
6716
0
    rd_cost->rdcost = INT64_MAX;
6717
0
    return;
6718
0
  }
6719
6720
0
  const InterpFilter interp_filter = features->interp_filter;
6721
0
  assert((interp_filter == SWITCHABLE) ||
6722
0
         (interp_filter ==
6723
0
          search_state.best_mbmode.interp_filters.as_filters.y_filter) ||
6724
0
         !is_inter_block(&search_state.best_mbmode));
6725
0
  assert((interp_filter == SWITCHABLE) ||
6726
0
         (interp_filter ==
6727
0
          search_state.best_mbmode.interp_filters.as_filters.x_filter) ||
6728
0
         !is_inter_block(&search_state.best_mbmode));
6729
6730
0
  if (!cpi->rc.is_src_frame_alt_ref && sf->inter_sf.adaptive_rd_thresh) {
6731
0
    av1_update_rd_thresh_fact(
6732
0
        cm, x->thresh_freq_fact, sf->inter_sf.adaptive_rd_thresh, bsize,
6733
0
        search_state.best_mode_index, mode_start, mode_end, THR_DC, MAX_MODES);
6734
0
  }
6735
6736
  // macroblock modes
6737
0
  *mbmi = search_state.best_mbmode;
6738
0
  txfm_info->skip_txfm |= search_state.best_skip2;
6739
6740
  // Note: this section is needed since the mode may have been forced to
6741
  // GLOBALMV by the all-zero mode handling of ref-mv.
6742
0
  if (mbmi->mode == GLOBALMV || mbmi->mode == GLOBAL_GLOBALMV) {
6743
    // Correct the interp filters for GLOBALMV
6744
0
    if (is_nontrans_global_motion(xd, xd->mi[0])) {
6745
0
      int_interpfilters filters =
6746
0
          av1_broadcast_interp_filter(av1_unswitchable_filter(interp_filter));
6747
0
      assert(mbmi->interp_filters.as_int == filters.as_int);
6748
0
      (void)filters;
6749
0
    }
6750
0
  }
6751
6752
0
  txfm_info->skip_txfm |= search_state.best_mode_skippable;
6753
6754
0
  assert(search_state.best_mode_index != THR_INVALID);
6755
6756
#if CONFIG_INTERNAL_STATS
6757
  store_coding_context(x, ctx, search_state.best_mode_index,
6758
                       search_state.best_mode_skippable);
6759
#else
6760
0
  store_coding_context(x, ctx, search_state.best_mode_skippable);
6761
0
#endif  // CONFIG_INTERNAL_STATS
6762
6763
0
  if (mbmi->palette_mode_info.palette_size[1] > 0) {
6764
0
    assert(try_palette);
6765
0
    av1_restore_uv_color_map(cpi, x);
6766
0
  }
6767
0
}
6768
6769
void av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP *cpi,
6770
                                        TileDataEnc *tile_data, MACROBLOCK *x,
6771
                                        int mi_row, int mi_col,
6772
                                        RD_STATS *rd_cost, BLOCK_SIZE bsize,
6773
                                        PICK_MODE_CONTEXT *ctx,
6774
0
                                        int64_t best_rd_so_far) {
6775
0
  const AV1_COMMON *const cm = &cpi->common;
6776
0
  const FeatureFlags *const features = &cm->features;
6777
0
  MACROBLOCKD *const xd = &x->e_mbd;
6778
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
6779
0
  unsigned char segment_id = mbmi->segment_id;
6780
0
  const int comp_pred = 0;
6781
0
  int i;
6782
0
  unsigned int ref_costs_single[REF_FRAMES];
6783
0
  unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES];
6784
0
  const ModeCosts *mode_costs = &x->mode_costs;
6785
0
  const int *comp_inter_cost =
6786
0
      mode_costs->comp_inter_cost[av1_get_reference_mode_context(xd)];
6787
0
  InterpFilter best_filter = SWITCHABLE;
6788
0
  int64_t this_rd = INT64_MAX;
6789
0
  int rate2 = 0;
6790
0
  const int64_t distortion2 = 0;
6791
0
  (void)mi_row;
6792
0
  (void)mi_col;
6793
0
  (void)tile_data;
6794
6795
0
  av1_collect_neighbors_ref_counts(xd);
6796
6797
0
  estimate_ref_frame_costs(cm, xd, mode_costs, segment_id, ref_costs_single,
6798
0
                           ref_costs_comp);
6799
6800
0
  for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;
6801
0
  for (i = LAST_FRAME; i < REF_FRAMES; ++i) x->pred_mv_sad[i] = INT_MAX;
6802
6803
0
  rd_cost->rate = INT_MAX;
6804
6805
0
  assert(segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP));
6806
6807
0
  mbmi->palette_mode_info.palette_size[0] = 0;
6808
0
  mbmi->palette_mode_info.palette_size[1] = 0;
6809
0
  mbmi->filter_intra_mode_info.use_filter_intra = 0;
6810
0
  mbmi->mode = GLOBALMV;
6811
0
  mbmi->motion_mode = SIMPLE_TRANSLATION;
6812
0
  mbmi->uv_mode = UV_DC_PRED;
6813
0
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME))
6814
0
    mbmi->ref_frame[0] = get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
6815
0
  else
6816
0
    mbmi->ref_frame[0] = LAST_FRAME;
6817
0
  mbmi->ref_frame[1] = NONE_FRAME;
6818
0
  mbmi->mv[0].as_int =
6819
0
      gm_get_motion_vector(&cm->global_motion[mbmi->ref_frame[0]],
6820
0
                           features->allow_high_precision_mv, bsize, mi_col,
6821
0
                           mi_row, features->cur_frame_force_integer_mv)
6822
0
          .as_int;
6823
0
  mbmi->tx_size = max_txsize_lookup[bsize];
6824
0
  x->txfm_search_info.skip_txfm = 1;
6825
6826
0
  mbmi->ref_mv_idx = 0;
6827
6828
0
  mbmi->motion_mode = SIMPLE_TRANSLATION;
6829
0
  av1_count_overlappable_neighbors(cm, xd);
6830
0
  if (is_motion_variation_allowed_bsize(bsize) && !has_second_ref(mbmi)) {
6831
0
    int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
6832
0
    mbmi->num_proj_ref = av1_findSamples(cm, xd, pts, pts_inref);
6833
    // Select the samples according to motion vector difference
6834
0
    if (mbmi->num_proj_ref > 1) {
6835
0
      mbmi->num_proj_ref = av1_selectSamples(&mbmi->mv[0].as_mv, pts, pts_inref,
6836
0
                                             mbmi->num_proj_ref, bsize);
6837
0
    }
6838
0
  }
6839
6840
0
  const InterpFilter interp_filter = features->interp_filter;
6841
0
  set_default_interp_filters(mbmi, interp_filter);
6842
6843
0
  if (interp_filter != SWITCHABLE) {
6844
0
    best_filter = interp_filter;
6845
0
  } else {
6846
0
    best_filter = EIGHTTAP_REGULAR;
6847
0
    if (av1_is_interp_needed(xd)) {
6848
0
      int rs;
6849
0
      int best_rs = INT_MAX;
6850
0
      for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
6851
0
        mbmi->interp_filters = av1_broadcast_interp_filter(i);
6852
0
        rs = av1_get_switchable_rate(x, xd, interp_filter,
6853
0
                                     cm->seq_params->enable_dual_filter);
6854
0
        if (rs < best_rs) {
6855
0
          best_rs = rs;
6856
0
          best_filter = mbmi->interp_filters.as_filters.y_filter;
6857
0
        }
6858
0
      }
6859
0
    }
6860
0
  }
6861
  // Set the appropriate filter
6862
0
  mbmi->interp_filters = av1_broadcast_interp_filter(best_filter);
6863
0
  rate2 += av1_get_switchable_rate(x, xd, interp_filter,
6864
0
                                   cm->seq_params->enable_dual_filter);
6865
6866
0
  if (cm->current_frame.reference_mode == REFERENCE_MODE_SELECT)
6867
0
    rate2 += comp_inter_cost[comp_pred];
6868
6869
  // Estimate the reference frame signaling cost and add it
6870
  // to the rolling cost variable.
6871
0
  rate2 += ref_costs_single[LAST_FRAME];
6872
0
  this_rd = RDCOST(x->rdmult, rate2, distortion2);
6873
6874
0
  rd_cost->rate = rate2;
6875
0
  rd_cost->dist = distortion2;
6876
0
  rd_cost->rdcost = this_rd;
6877
6878
0
  if (this_rd >= best_rd_so_far) {
6879
0
    rd_cost->rate = INT_MAX;
6880
0
    rd_cost->rdcost = INT64_MAX;
6881
0
    return;
6882
0
  }
6883
6884
0
  assert((interp_filter == SWITCHABLE) ||
6885
0
         (interp_filter == mbmi->interp_filters.as_filters.y_filter));
6886
6887
0
  if (cpi->sf.inter_sf.adaptive_rd_thresh) {
6888
0
    av1_update_rd_thresh_fact(cm, x->thresh_freq_fact,
6889
0
                              cpi->sf.inter_sf.adaptive_rd_thresh, bsize,
6890
0
                              THR_GLOBALMV, THR_INTER_MODE_START,
6891
0
                              THR_INTER_MODE_END, THR_DC, MAX_MODES);
6892
0
  }
6893
6894
#if CONFIG_INTERNAL_STATS
6895
  store_coding_context(x, ctx, THR_GLOBALMV, 0);
6896
#else
6897
0
  store_coding_context(x, ctx, 0);
6898
0
#endif  // CONFIG_INTERNAL_STATS
6899
0
}
6900
6901
/*!\cond */
6902
struct calc_target_weighted_pred_ctxt {
6903
  const OBMCBuffer *obmc_buffer;
6904
  const uint8_t *tmp;
6905
  int tmp_stride;
6906
  int overlap;
6907
};
6908
/*!\endcond */
6909
6910
static inline void calc_target_weighted_pred_above(
6911
    MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
6912
0
    int dir, MB_MODE_INFO *nb_mi, void *fun_ctxt, const int num_planes) {
6913
0
  (void)nb_mi;
6914
0
  (void)num_planes;
6915
0
  (void)rel_mi_row;
6916
0
  (void)dir;
6917
6918
0
  struct calc_target_weighted_pred_ctxt *ctxt =
6919
0
      (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
6920
6921
0
  const int bw = xd->width << MI_SIZE_LOG2;
6922
0
  const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
6923
6924
0
  int32_t *wsrc = ctxt->obmc_buffer->wsrc + (rel_mi_col * MI_SIZE);
6925
0
  int32_t *mask = ctxt->obmc_buffer->mask + (rel_mi_col * MI_SIZE);
6926
0
  const uint8_t *tmp = ctxt->tmp + rel_mi_col * MI_SIZE;
6927
0
  const int is_hbd = is_cur_buf_hbd(xd);
6928
6929
0
  if (!is_hbd) {
6930
0
    for (int row = 0; row < ctxt->overlap; ++row) {
6931
0
      const uint8_t m0 = mask1d[row];
6932
0
      const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6933
0
      for (int col = 0; col < op_mi_size * MI_SIZE; ++col) {
6934
0
        wsrc[col] = m1 * tmp[col];
6935
0
        mask[col] = m0;
6936
0
      }
6937
0
      wsrc += bw;
6938
0
      mask += bw;
6939
0
      tmp += ctxt->tmp_stride;
6940
0
    }
6941
0
  } else {
6942
0
    const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
6943
6944
0
    for (int row = 0; row < ctxt->overlap; ++row) {
6945
0
      const uint8_t m0 = mask1d[row];
6946
0
      const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6947
0
      for (int col = 0; col < op_mi_size * MI_SIZE; ++col) {
6948
0
        wsrc[col] = m1 * tmp16[col];
6949
0
        mask[col] = m0;
6950
0
      }
6951
0
      wsrc += bw;
6952
0
      mask += bw;
6953
0
      tmp16 += ctxt->tmp_stride;
6954
0
    }
6955
0
  }
6956
0
}
6957
6958
static inline void calc_target_weighted_pred_left(
6959
    MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
6960
0
    int dir, MB_MODE_INFO *nb_mi, void *fun_ctxt, const int num_planes) {
6961
0
  (void)nb_mi;
6962
0
  (void)num_planes;
6963
0
  (void)rel_mi_col;
6964
0
  (void)dir;
6965
6966
0
  struct calc_target_weighted_pred_ctxt *ctxt =
6967
0
      (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
6968
6969
0
  const int bw = xd->width << MI_SIZE_LOG2;
6970
0
  const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
6971
6972
0
  int32_t *wsrc = ctxt->obmc_buffer->wsrc + (rel_mi_row * MI_SIZE * bw);
6973
0
  int32_t *mask = ctxt->obmc_buffer->mask + (rel_mi_row * MI_SIZE * bw);
6974
0
  const uint8_t *tmp = ctxt->tmp + (rel_mi_row * MI_SIZE * ctxt->tmp_stride);
6975
0
  const int is_hbd = is_cur_buf_hbd(xd);
6976
6977
0
  if (!is_hbd) {
6978
0
    for (int row = 0; row < op_mi_size * MI_SIZE; ++row) {
6979
0
      for (int col = 0; col < ctxt->overlap; ++col) {
6980
0
        const uint8_t m0 = mask1d[col];
6981
0
        const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6982
0
        wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
6983
0
                    (tmp[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
6984
0
        mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
6985
0
      }
6986
0
      wsrc += bw;
6987
0
      mask += bw;
6988
0
      tmp += ctxt->tmp_stride;
6989
0
    }
6990
0
  } else {
6991
0
    const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
6992
6993
0
    for (int row = 0; row < op_mi_size * MI_SIZE; ++row) {
6994
0
      for (int col = 0; col < ctxt->overlap; ++col) {
6995
0
        const uint8_t m0 = mask1d[col];
6996
0
        const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6997
0
        wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
6998
0
                    (tmp16[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
6999
0
        mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
7000
0
      }
7001
0
      wsrc += bw;
7002
0
      mask += bw;
7003
0
      tmp16 += ctxt->tmp_stride;
7004
0
    }
7005
0
  }
7006
0
}
7007
7008
// This function has a structure similar to av1_build_obmc_inter_prediction
7009
//
7010
// The OBMC predictor is computed as:
7011
//
7012
//  PObmc(x,y) =
7013
//    AOM_BLEND_A64(Mh(x),
7014
//                  AOM_BLEND_A64(Mv(y), P(x,y), PAbove(x,y)),
7015
//                  PLeft(x, y))
7016
//
7017
// Scaling up by AOM_BLEND_A64_MAX_ALPHA ** 2 and omitting the intermediate
7018
// rounding, this can be written as:
7019
//
7020
//  AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * Pobmc(x,y) =
7021
//    Mh(x) * Mv(y) * P(x,y) +
7022
//      Mh(x) * Cv(y) * Pabove(x,y) +
7023
//      AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
7024
//
7025
// Where :
7026
//
7027
//  Cv(y) = AOM_BLEND_A64_MAX_ALPHA - Mv(y)
7028
//  Ch(y) = AOM_BLEND_A64_MAX_ALPHA - Mh(y)
7029
//
7030
// This function computes 'wsrc' and 'mask' as:
7031
//
7032
//  wsrc(x, y) =
7033
//    AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * src(x, y) -
7034
//      Mh(x) * Cv(y) * Pabove(x,y) +
7035
//      AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
7036
//
7037
//  mask(x, y) = Mh(x) * Mv(y)
7038
//
7039
// These can then be used to efficiently approximate the error for any
7040
// predictor P in the context of the provided neighbouring predictors by
7041
// computing:
7042
//
7043
//  error(x, y) =
7044
//    wsrc(x, y) - mask(x, y) * P(x, y) / (AOM_BLEND_A64_MAX_ALPHA ** 2)
7045
//
7046
static inline void calc_target_weighted_pred(
7047
    const AV1_COMMON *cm, const MACROBLOCK *x, const MACROBLOCKD *xd,
7048
    const uint8_t *above, int above_stride, const uint8_t *left,
7049
0
    int left_stride) {
7050
0
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
7051
0
  const int bw = xd->width << MI_SIZE_LOG2;
7052
0
  const int bh = xd->height << MI_SIZE_LOG2;
7053
0
  const OBMCBuffer *obmc_buffer = &x->obmc_buffer;
7054
0
  int32_t *mask_buf = obmc_buffer->mask;
7055
0
  int32_t *wsrc_buf = obmc_buffer->wsrc;
7056
7057
0
  const int is_hbd = is_cur_buf_hbd(xd);
7058
0
  const int src_scale = AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA;
7059
7060
  // plane 0 should not be sub-sampled
7061
0
  assert(xd->plane[0].subsampling_x == 0);
7062
0
  assert(xd->plane[0].subsampling_y == 0);
7063
7064
0
  av1_zero_array(wsrc_buf, bw * bh);
7065
0
  for (int i = 0; i < bw * bh; ++i) mask_buf[i] = AOM_BLEND_A64_MAX_ALPHA;
7066
7067
  // handle above row
7068
0
  if (xd->up_available) {
7069
0
    const int overlap =
7070
0
        AOMMIN(block_size_high[bsize], block_size_high[BLOCK_64X64]) >> 1;
7071
0
    struct calc_target_weighted_pred_ctxt ctxt = { obmc_buffer, above,
7072
0
                                                   above_stride, overlap };
7073
0
    foreach_overlappable_nb_above(cm, (MACROBLOCKD *)xd,
7074
0
                                  max_neighbor_obmc[mi_size_wide_log2[bsize]],
7075
0
                                  calc_target_weighted_pred_above, &ctxt);
7076
0
  }
7077
7078
0
  for (int i = 0; i < bw * bh; ++i) {
7079
0
    wsrc_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
7080
0
    mask_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
7081
0
  }
7082
7083
  // handle left column
7084
0
  if (xd->left_available) {
7085
0
    const int overlap =
7086
0
        AOMMIN(block_size_wide[bsize], block_size_wide[BLOCK_64X64]) >> 1;
7087
0
    struct calc_target_weighted_pred_ctxt ctxt = { obmc_buffer, left,
7088
0
                                                   left_stride, overlap };
7089
0
    foreach_overlappable_nb_left(cm, (MACROBLOCKD *)xd,
7090
0
                                 max_neighbor_obmc[mi_size_high_log2[bsize]],
7091
0
                                 calc_target_weighted_pred_left, &ctxt);
7092
0
  }
7093
7094
0
  if (!is_hbd) {
7095
0
    const uint8_t *src = x->plane[0].src.buf;
7096
7097
0
    for (int row = 0; row < bh; ++row) {
7098
0
      for (int col = 0; col < bw; ++col) {
7099
0
        wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
7100
0
      }
7101
0
      wsrc_buf += bw;
7102
0
      src += x->plane[0].src.stride;
7103
0
    }
7104
0
  } else {
7105
0
    const uint16_t *src = CONVERT_TO_SHORTPTR(x->plane[0].src.buf);
7106
7107
0
    for (int row = 0; row < bh; ++row) {
7108
0
      for (int col = 0; col < bw; ++col) {
7109
0
        wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
7110
0
      }
7111
0
      wsrc_buf += bw;
7112
0
      src += x->plane[0].src.stride;
7113
0
    }
7114
0
  }
7115
0
}