xref: /aosp_15_r20/external/libaom/av1/encoder/rdopt.h (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #ifndef AOM_AV1_ENCODER_RDOPT_H_
13*77c1e3ccSAndroid Build Coastguard Worker #define AOM_AV1_ENCODER_RDOPT_H_
14*77c1e3ccSAndroid Build Coastguard Worker 
15*77c1e3ccSAndroid Build Coastguard Worker #include <stdbool.h>
16*77c1e3ccSAndroid Build Coastguard Worker 
17*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/blockd.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/txb_common.h"
19*77c1e3ccSAndroid Build Coastguard Worker 
20*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/block.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/context_tree.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encodetxb.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rdopt_utils.h"
25*77c1e3ccSAndroid Build Coastguard Worker 
26*77c1e3ccSAndroid Build Coastguard Worker #ifdef __cplusplus
27*77c1e3ccSAndroid Build Coastguard Worker extern "C" {
28*77c1e3ccSAndroid Build Coastguard Worker #endif
29*77c1e3ccSAndroid Build Coastguard Worker 
30*77c1e3ccSAndroid Build Coastguard Worker #define COMP_TYPE_RD_THRESH_SCALE 11
31*77c1e3ccSAndroid Build Coastguard Worker #define COMP_TYPE_RD_THRESH_SHIFT 4
32*77c1e3ccSAndroid Build Coastguard Worker #define MAX_WINNER_MOTION_MODES 10
33*77c1e3ccSAndroid Build Coastguard Worker 
34*77c1e3ccSAndroid Build Coastguard Worker struct TileInfo;
35*77c1e3ccSAndroid Build Coastguard Worker struct macroblock;
36*77c1e3ccSAndroid Build Coastguard Worker struct RD_STATS;
37*77c1e3ccSAndroid Build Coastguard Worker 
38*77c1e3ccSAndroid Build Coastguard Worker /*!\brief AV1 intra mode selection for intra frames.
39*77c1e3ccSAndroid Build Coastguard Worker  *
40*77c1e3ccSAndroid Build Coastguard Worker  * \ingroup intra_mode_search
41*77c1e3ccSAndroid Build Coastguard Worker  * \callgraph
42*77c1e3ccSAndroid Build Coastguard Worker  * Top level function for rd-based intra mode selection during intra frame
43*77c1e3ccSAndroid Build Coastguard Worker  * encoding. This function will first search for the best luma prediction by
44*77c1e3ccSAndroid Build Coastguard Worker  * calling av1_rd_pick_intra_sby_mode, then it searches for chroma prediction
45*77c1e3ccSAndroid Build Coastguard Worker  * with av1_rd_pick_intra_sbuv_mode. If applicable, this function ends the
46*77c1e3ccSAndroid Build Coastguard Worker  * search with an evaluation for intrabc.
47*77c1e3ccSAndroid Build Coastguard Worker  *
48*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    cpi            Top-level encoder structure.
49*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    x              Pointer to structure holding all the data for
50*77c1e3ccSAndroid Build Coastguard Worker                                 the current macroblock.
51*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    rd_cost        Struct to keep track of the RD information.
52*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    bsize          Current block size.
53*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    ctx            Structure to hold snapshot of coding context
54*77c1e3ccSAndroid Build Coastguard Worker                                 during the mode picking process.
55*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    best_rd Best   RD seen for this block so far.
56*77c1e3ccSAndroid Build Coastguard Worker  *
57*77c1e3ccSAndroid Build Coastguard Worker  * \remark Nothing is returned. Instead, the MB_MODE_INFO struct inside x
58*77c1e3ccSAndroid Build Coastguard Worker  * is modified to store information about the best mode computed
59*77c1e3ccSAndroid Build Coastguard Worker  * in this function. The rd_cost struct is also updated with the RD stats
60*77c1e3ccSAndroid Build Coastguard Worker  * corresponding to the best mode found.
61*77c1e3ccSAndroid Build Coastguard Worker  */
62*77c1e3ccSAndroid Build Coastguard Worker void av1_rd_pick_intra_mode_sb(const struct AV1_COMP *cpi, struct macroblock *x,
63*77c1e3ccSAndroid Build Coastguard Worker                                struct RD_STATS *rd_cost, BLOCK_SIZE bsize,
64*77c1e3ccSAndroid Build Coastguard Worker                                PICK_MODE_CONTEXT *ctx, int64_t best_rd);
65*77c1e3ccSAndroid Build Coastguard Worker 
66*77c1e3ccSAndroid Build Coastguard Worker /*!\brief AV1 inter mode selection.
67*77c1e3ccSAndroid Build Coastguard Worker  *
68*77c1e3ccSAndroid Build Coastguard Worker  * \ingroup inter_mode_search
69*77c1e3ccSAndroid Build Coastguard Worker  * \callgraph
70*77c1e3ccSAndroid Build Coastguard Worker  * Top level function for inter mode selection. This function will loop over
71*77c1e3ccSAndroid Build Coastguard Worker  * all possible inter modes and select the best one for the current block by
72*77c1e3ccSAndroid Build Coastguard Worker  * computing the RD cost. The mode search and RD are computed in
73*77c1e3ccSAndroid Build Coastguard Worker  * handle_inter_mode(), which is called from this function within the main
74*77c1e3ccSAndroid Build Coastguard Worker  * loop.
75*77c1e3ccSAndroid Build Coastguard Worker  *
76*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    cpi            Top-level encoder structure
77*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    tile_data      Pointer to struct holding adaptive
78*77c1e3ccSAndroid Build Coastguard Worker                                 data/contexts/models for the tile during
79*77c1e3ccSAndroid Build Coastguard Worker                                 encoding
80*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    x              Pointer to structure holding all the data for
81*77c1e3ccSAndroid Build Coastguard Worker                                 the current macroblock
82*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    rd_cost        Struct to keep track of the RD information
83*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    bsize          Current block size
84*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    ctx            Structure to hold snapshot of coding context
85*77c1e3ccSAndroid Build Coastguard Worker                                 during the mode picking process
86*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    best_rd_so_far Best RD seen for this block so far
87*77c1e3ccSAndroid Build Coastguard Worker  *
88*77c1e3ccSAndroid Build Coastguard Worker  * \remark Nothing is returned. Instead, the MB_MODE_INFO struct inside x
89*77c1e3ccSAndroid Build Coastguard Worker  * is modified to store information about the best mode computed
90*77c1e3ccSAndroid Build Coastguard Worker  * in this function. The rd_cost struct is also updated with the RD stats
91*77c1e3ccSAndroid Build Coastguard Worker  * corresponding to the best mode found.
92*77c1e3ccSAndroid Build Coastguard Worker  */
93*77c1e3ccSAndroid Build Coastguard Worker void av1_rd_pick_inter_mode(struct AV1_COMP *cpi, struct TileDataEnc *tile_data,
94*77c1e3ccSAndroid Build Coastguard Worker                             struct macroblock *x, struct RD_STATS *rd_cost,
95*77c1e3ccSAndroid Build Coastguard Worker                             BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
96*77c1e3ccSAndroid Build Coastguard Worker                             int64_t best_rd_so_far);
97*77c1e3ccSAndroid Build Coastguard Worker 
98*77c1e3ccSAndroid Build Coastguard Worker /*!\brief AV1 intra mode selection based on Non-RD optimized model.
99*77c1e3ccSAndroid Build Coastguard Worker  *
100*77c1e3ccSAndroid Build Coastguard Worker  * \ingroup nonrd_mode_search
101*77c1e3ccSAndroid Build Coastguard Worker  * \callgraph
102*77c1e3ccSAndroid Build Coastguard Worker  * \callergraph
103*77c1e3ccSAndroid Build Coastguard Worker  * Top level function for Non-RD optimized intra mode selection.
104*77c1e3ccSAndroid Build Coastguard Worker  * This finction will loop over subset of intra modes and select the best one
105*77c1e3ccSAndroid Build Coastguard Worker  * based on calculated modelled RD cost. Only 4 intra modes are checked as
106*77c1e3ccSAndroid Build Coastguard Worker  * specified in \c intra_mode_list. When calculating RD cost Hadamard transform
107*77c1e3ccSAndroid Build Coastguard Worker  * of residual is used to calculate rate. Estmation of RD cost is performed
108*77c1e3ccSAndroid Build Coastguard Worker  * in \c av1_estimate_block_intra which is called from this function
109*77c1e3ccSAndroid Build Coastguard Worker  *
110*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    cpi            Top-level encoder structure
111*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    x              Pointer to structure holding all the data for
112*77c1e3ccSAndroid Build Coastguard Worker                                 the current macroblock
113*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    rd_cost        Struct to keep track of the RD information
114*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    bsize          Current block size
115*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    ctx            Structure to hold snapshot of coding context
116*77c1e3ccSAndroid Build Coastguard Worker                                 during the mode picking process
117*77c1e3ccSAndroid Build Coastguard Worker  *
118*77c1e3ccSAndroid Build Coastguard Worker  * \remark Nothing is returned. Instead, the MB_MODE_INFO struct inside x
119*77c1e3ccSAndroid Build Coastguard Worker  * is modified to store information about the best mode computed
120*77c1e3ccSAndroid Build Coastguard Worker  * in this function. The rd_cost struct is also updated with the RD stats
121*77c1e3ccSAndroid Build Coastguard Worker  * corresponding to the best mode found.
122*77c1e3ccSAndroid Build Coastguard Worker  */
123*77c1e3ccSAndroid Build Coastguard Worker void av1_nonrd_pick_intra_mode(AV1_COMP *cpi, MACROBLOCK *x, RD_STATS *rd_cost,
124*77c1e3ccSAndroid Build Coastguard Worker                                BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx);
125*77c1e3ccSAndroid Build Coastguard Worker 
126*77c1e3ccSAndroid Build Coastguard Worker /*!\brief AV1 inter mode selection based on Non-RD optimized model.
127*77c1e3ccSAndroid Build Coastguard Worker  *
128*77c1e3ccSAndroid Build Coastguard Worker  * \ingroup nonrd_mode_search
129*77c1e3ccSAndroid Build Coastguard Worker  * \callgraph
130*77c1e3ccSAndroid Build Coastguard Worker  * Top level function for Non-RD optimized inter mode selection.
131*77c1e3ccSAndroid Build Coastguard Worker  * This finction will loop over subset of inter modes and select the best one
132*77c1e3ccSAndroid Build Coastguard Worker  * based on calculated modelled RD cost. While making decisions which modes to
133*77c1e3ccSAndroid Build Coastguard Worker  * check, this function applies heuristics based on previously checked modes,
134*77c1e3ccSAndroid Build Coastguard Worker  * block residual variance, block size, and other factors to prune certain
135*77c1e3ccSAndroid Build Coastguard Worker  * modes and reference frames. Currently only single reference frame modes
136*77c1e3ccSAndroid Build Coastguard Worker  * are checked. Additional heuristics are applied to decide if intra modes
137*77c1e3ccSAndroid Build Coastguard Worker  *  need to be checked.
138*77c1e3ccSAndroid Build Coastguard Worker  *  *
139*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    cpi            Top-level encoder structure
140*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    tile_data      Pointer to struct holding adaptive
141*77c1e3ccSAndroid Build Coastguard Worker                                 data/contexts/models for the tile during
142*77c1e3ccSAndroid Build Coastguard Worker                                 encoding
143*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    x              Pointer to structure holding all the data for
144*77c1e3ccSAndroid Build Coastguard Worker                                 the current macroblock
145*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    rd_cost        Struct to keep track of the RD information
146*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    bsize          Current block size
147*77c1e3ccSAndroid Build Coastguard Worker  * \param[in]    ctx            Structure to hold snapshot of coding context
148*77c1e3ccSAndroid Build Coastguard Worker                                 during the mode picking process
149*77c1e3ccSAndroid Build Coastguard Worker  *
150*77c1e3ccSAndroid Build Coastguard Worker  * \remark Nothing is returned. Instead, the MB_MODE_INFO struct inside x
151*77c1e3ccSAndroid Build Coastguard Worker  * is modified to store information about the best mode computed
152*77c1e3ccSAndroid Build Coastguard Worker  * in this function. The rd_cost struct is also updated with the RD stats
153*77c1e3ccSAndroid Build Coastguard Worker  * corresponding to the best mode found.
154*77c1e3ccSAndroid Build Coastguard Worker  */
155*77c1e3ccSAndroid Build Coastguard Worker void av1_nonrd_pick_inter_mode_sb(struct AV1_COMP *cpi,
156*77c1e3ccSAndroid Build Coastguard Worker                                   struct TileDataEnc *tile_data,
157*77c1e3ccSAndroid Build Coastguard Worker                                   struct macroblock *x,
158*77c1e3ccSAndroid Build Coastguard Worker                                   struct RD_STATS *rd_cost, BLOCK_SIZE bsize,
159*77c1e3ccSAndroid Build Coastguard Worker                                   PICK_MODE_CONTEXT *ctx);
160*77c1e3ccSAndroid Build Coastguard Worker 
161*77c1e3ccSAndroid Build Coastguard Worker void av1_rd_pick_inter_mode_sb_seg_skip(
162*77c1e3ccSAndroid Build Coastguard Worker     const struct AV1_COMP *cpi, struct TileDataEnc *tile_data,
163*77c1e3ccSAndroid Build Coastguard Worker     struct macroblock *x, int mi_row, int mi_col, struct RD_STATS *rd_cost,
164*77c1e3ccSAndroid Build Coastguard Worker     BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far);
165*77c1e3ccSAndroid Build Coastguard Worker 
166*77c1e3ccSAndroid Build Coastguard Worker void av1_inter_mode_data_init(struct TileDataEnc *tile_data);
167*77c1e3ccSAndroid Build Coastguard Worker void av1_inter_mode_data_fit(TileDataEnc *tile_data, int rdmult);
168*77c1e3ccSAndroid Build Coastguard Worker 
coded_to_superres_mi(int mi_col,int denom)169*77c1e3ccSAndroid Build Coastguard Worker static inline int coded_to_superres_mi(int mi_col, int denom) {
170*77c1e3ccSAndroid Build Coastguard Worker   return (mi_col * denom + SCALE_NUMERATOR / 2) / SCALE_NUMERATOR;
171*77c1e3ccSAndroid Build Coastguard Worker }
172*77c1e3ccSAndroid Build Coastguard Worker 
av1_encoder_get_relative_dist(int a,int b)173*77c1e3ccSAndroid Build Coastguard Worker static inline int av1_encoder_get_relative_dist(int a, int b) {
174*77c1e3ccSAndroid Build Coastguard Worker   assert(a >= 0 && b >= 0);
175*77c1e3ccSAndroid Build Coastguard Worker   return (a - b);
176*77c1e3ccSAndroid Build Coastguard Worker }
177*77c1e3ccSAndroid Build Coastguard Worker 
178*77c1e3ccSAndroid Build Coastguard Worker // This function will return number of mi's in a superblock.
av1_get_sb_mi_size(const AV1_COMMON * const cm)179*77c1e3ccSAndroid Build Coastguard Worker static inline int av1_get_sb_mi_size(const AV1_COMMON *const cm) {
180*77c1e3ccSAndroid Build Coastguard Worker   const int mi_alloc_size_1d = mi_size_wide[cm->mi_params.mi_alloc_bsize];
181*77c1e3ccSAndroid Build Coastguard Worker   int sb_mi_rows =
182*77c1e3ccSAndroid Build Coastguard Worker       (mi_size_wide[cm->seq_params->sb_size] + mi_alloc_size_1d - 1) /
183*77c1e3ccSAndroid Build Coastguard Worker       mi_alloc_size_1d;
184*77c1e3ccSAndroid Build Coastguard Worker   assert(mi_size_wide[cm->seq_params->sb_size] ==
185*77c1e3ccSAndroid Build Coastguard Worker          mi_size_high[cm->seq_params->sb_size]);
186*77c1e3ccSAndroid Build Coastguard Worker   int sb_mi_size = sb_mi_rows * sb_mi_rows;
187*77c1e3ccSAndroid Build Coastguard Worker 
188*77c1e3ccSAndroid Build Coastguard Worker   return sb_mi_size;
189*77c1e3ccSAndroid Build Coastguard Worker }
190*77c1e3ccSAndroid Build Coastguard Worker 
191*77c1e3ccSAndroid Build Coastguard Worker // This function prunes the mode if either of the reference frame falls in the
192*77c1e3ccSAndroid Build Coastguard Worker // pruning list
prune_ref(const MV_REFERENCE_FRAME * const ref_frame,const unsigned int * const ref_display_order_hint,const unsigned int frame_display_order_hint,const int * ref_frame_list)193*77c1e3ccSAndroid Build Coastguard Worker static inline int prune_ref(const MV_REFERENCE_FRAME *const ref_frame,
194*77c1e3ccSAndroid Build Coastguard Worker                             const unsigned int *const ref_display_order_hint,
195*77c1e3ccSAndroid Build Coastguard Worker                             const unsigned int frame_display_order_hint,
196*77c1e3ccSAndroid Build Coastguard Worker                             const int *ref_frame_list) {
197*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < 2; i++) {
198*77c1e3ccSAndroid Build Coastguard Worker     if (ref_frame_list[i] == NONE_FRAME) continue;
199*77c1e3ccSAndroid Build Coastguard Worker 
200*77c1e3ccSAndroid Build Coastguard Worker     if (ref_frame[0] == ref_frame_list[i] ||
201*77c1e3ccSAndroid Build Coastguard Worker         ref_frame[1] == ref_frame_list[i]) {
202*77c1e3ccSAndroid Build Coastguard Worker       if (av1_encoder_get_relative_dist(
203*77c1e3ccSAndroid Build Coastguard Worker               ref_display_order_hint[ref_frame_list[i] - LAST_FRAME],
204*77c1e3ccSAndroid Build Coastguard Worker               frame_display_order_hint) < 0)
205*77c1e3ccSAndroid Build Coastguard Worker         return 1;
206*77c1e3ccSAndroid Build Coastguard Worker     }
207*77c1e3ccSAndroid Build Coastguard Worker   }
208*77c1e3ccSAndroid Build Coastguard Worker   return 0;
209*77c1e3ccSAndroid Build Coastguard Worker }
210*77c1e3ccSAndroid Build Coastguard Worker 
has_closest_ref_frames(const MV_REFERENCE_FRAME * ref_frame,int8_t closest_past_ref,int8_t closest_future_ref)211*77c1e3ccSAndroid Build Coastguard Worker static inline int has_closest_ref_frames(const MV_REFERENCE_FRAME *ref_frame,
212*77c1e3ccSAndroid Build Coastguard Worker                                          int8_t closest_past_ref,
213*77c1e3ccSAndroid Build Coastguard Worker                                          int8_t closest_future_ref) {
214*77c1e3ccSAndroid Build Coastguard Worker   int has_closest_past_ref =
215*77c1e3ccSAndroid Build Coastguard Worker       (ref_frame[0] == closest_past_ref) || (ref_frame[1] == closest_past_ref);
216*77c1e3ccSAndroid Build Coastguard Worker   int has_closest_future_ref = (ref_frame[0] == closest_future_ref) ||
217*77c1e3ccSAndroid Build Coastguard Worker                                (ref_frame[1] == closest_future_ref);
218*77c1e3ccSAndroid Build Coastguard Worker   return (has_closest_past_ref && has_closest_future_ref);
219*77c1e3ccSAndroid Build Coastguard Worker }
220*77c1e3ccSAndroid Build Coastguard Worker 
has_best_pred_mv_sad(const MV_REFERENCE_FRAME * ref_frame,const MACROBLOCK * const x)221*77c1e3ccSAndroid Build Coastguard Worker static inline int has_best_pred_mv_sad(const MV_REFERENCE_FRAME *ref_frame,
222*77c1e3ccSAndroid Build Coastguard Worker                                        const MACROBLOCK *const x) {
223*77c1e3ccSAndroid Build Coastguard Worker   int has_best_past_pred_mv_sad = 0;
224*77c1e3ccSAndroid Build Coastguard Worker   int has_best_future_pred_mv_sad = 0;
225*77c1e3ccSAndroid Build Coastguard Worker   if (x->best_pred_mv_sad[0] < INT_MAX && x->best_pred_mv_sad[1] < INT_MAX) {
226*77c1e3ccSAndroid Build Coastguard Worker     has_best_past_pred_mv_sad =
227*77c1e3ccSAndroid Build Coastguard Worker         (x->pred_mv_sad[ref_frame[0]] == x->best_pred_mv_sad[0]) ||
228*77c1e3ccSAndroid Build Coastguard Worker         (x->pred_mv_sad[ref_frame[1]] == x->best_pred_mv_sad[0]);
229*77c1e3ccSAndroid Build Coastguard Worker     has_best_future_pred_mv_sad =
230*77c1e3ccSAndroid Build Coastguard Worker         (x->pred_mv_sad[ref_frame[0]] == x->best_pred_mv_sad[1]) ||
231*77c1e3ccSAndroid Build Coastguard Worker         (x->pred_mv_sad[ref_frame[1]] == x->best_pred_mv_sad[1]);
232*77c1e3ccSAndroid Build Coastguard Worker   }
233*77c1e3ccSAndroid Build Coastguard Worker   return (has_best_past_pred_mv_sad && has_best_future_pred_mv_sad);
234*77c1e3ccSAndroid Build Coastguard Worker }
235*77c1e3ccSAndroid Build Coastguard Worker 
prune_ref_by_selective_ref_frame(const AV1_COMP * const cpi,const MACROBLOCK * const x,const MV_REFERENCE_FRAME * const ref_frame,const unsigned int * const ref_display_order_hint)236*77c1e3ccSAndroid Build Coastguard Worker static inline int prune_ref_by_selective_ref_frame(
237*77c1e3ccSAndroid Build Coastguard Worker     const AV1_COMP *const cpi, const MACROBLOCK *const x,
238*77c1e3ccSAndroid Build Coastguard Worker     const MV_REFERENCE_FRAME *const ref_frame,
239*77c1e3ccSAndroid Build Coastguard Worker     const unsigned int *const ref_display_order_hint) {
240*77c1e3ccSAndroid Build Coastguard Worker   const SPEED_FEATURES *const sf = &cpi->sf;
241*77c1e3ccSAndroid Build Coastguard Worker   if (!sf->inter_sf.selective_ref_frame) return 0;
242*77c1e3ccSAndroid Build Coastguard Worker 
243*77c1e3ccSAndroid Build Coastguard Worker   const int comp_pred = ref_frame[1] > INTRA_FRAME;
244*77c1e3ccSAndroid Build Coastguard Worker 
245*77c1e3ccSAndroid Build Coastguard Worker   if (sf->inter_sf.selective_ref_frame >= 2 ||
246*77c1e3ccSAndroid Build Coastguard Worker       (sf->inter_sf.selective_ref_frame == 1 && comp_pred)) {
247*77c1e3ccSAndroid Build Coastguard Worker     int ref_frame_list[2] = { LAST3_FRAME, LAST2_FRAME };
248*77c1e3ccSAndroid Build Coastguard Worker 
249*77c1e3ccSAndroid Build Coastguard Worker     if (x != NULL) {
250*77c1e3ccSAndroid Build Coastguard Worker       // Disable pruning if either tpl suggests that we keep the frame or
251*77c1e3ccSAndroid Build Coastguard Worker       // the pred_mv gives us the best sad
252*77c1e3ccSAndroid Build Coastguard Worker       if (x->tpl_keep_ref_frame[LAST3_FRAME] ||
253*77c1e3ccSAndroid Build Coastguard Worker           x->pred_mv_sad[LAST3_FRAME] == x->best_pred_mv_sad[0]) {
254*77c1e3ccSAndroid Build Coastguard Worker         ref_frame_list[0] = NONE_FRAME;
255*77c1e3ccSAndroid Build Coastguard Worker       }
256*77c1e3ccSAndroid Build Coastguard Worker       if (x->tpl_keep_ref_frame[LAST2_FRAME] ||
257*77c1e3ccSAndroid Build Coastguard Worker           x->pred_mv_sad[LAST2_FRAME] == x->best_pred_mv_sad[0]) {
258*77c1e3ccSAndroid Build Coastguard Worker         ref_frame_list[1] = NONE_FRAME;
259*77c1e3ccSAndroid Build Coastguard Worker       }
260*77c1e3ccSAndroid Build Coastguard Worker     }
261*77c1e3ccSAndroid Build Coastguard Worker 
262*77c1e3ccSAndroid Build Coastguard Worker     if (prune_ref(ref_frame, ref_display_order_hint,
263*77c1e3ccSAndroid Build Coastguard Worker                   ref_display_order_hint[GOLDEN_FRAME - LAST_FRAME],
264*77c1e3ccSAndroid Build Coastguard Worker                   ref_frame_list))
265*77c1e3ccSAndroid Build Coastguard Worker       return 1;
266*77c1e3ccSAndroid Build Coastguard Worker   }
267*77c1e3ccSAndroid Build Coastguard Worker 
268*77c1e3ccSAndroid Build Coastguard Worker   if (sf->inter_sf.selective_ref_frame >= 3) {
269*77c1e3ccSAndroid Build Coastguard Worker     int ref_frame_list[2] = { ALTREF2_FRAME, BWDREF_FRAME };
270*77c1e3ccSAndroid Build Coastguard Worker 
271*77c1e3ccSAndroid Build Coastguard Worker     if (x != NULL) {
272*77c1e3ccSAndroid Build Coastguard Worker       // Disable pruning if either tpl suggests that we keep the frame or
273*77c1e3ccSAndroid Build Coastguard Worker       // the pred_mv gives us the best sad
274*77c1e3ccSAndroid Build Coastguard Worker       if (x->tpl_keep_ref_frame[ALTREF2_FRAME] ||
275*77c1e3ccSAndroid Build Coastguard Worker           x->pred_mv_sad[ALTREF2_FRAME] == x->best_pred_mv_sad[0]) {
276*77c1e3ccSAndroid Build Coastguard Worker         ref_frame_list[0] = NONE_FRAME;
277*77c1e3ccSAndroid Build Coastguard Worker       }
278*77c1e3ccSAndroid Build Coastguard Worker       if (x->tpl_keep_ref_frame[BWDREF_FRAME] ||
279*77c1e3ccSAndroid Build Coastguard Worker           x->pred_mv_sad[BWDREF_FRAME] == x->best_pred_mv_sad[0]) {
280*77c1e3ccSAndroid Build Coastguard Worker         ref_frame_list[1] = NONE_FRAME;
281*77c1e3ccSAndroid Build Coastguard Worker       }
282*77c1e3ccSAndroid Build Coastguard Worker     }
283*77c1e3ccSAndroid Build Coastguard Worker 
284*77c1e3ccSAndroid Build Coastguard Worker     if (prune_ref(ref_frame, ref_display_order_hint,
285*77c1e3ccSAndroid Build Coastguard Worker                   ref_display_order_hint[LAST_FRAME - LAST_FRAME],
286*77c1e3ccSAndroid Build Coastguard Worker                   ref_frame_list))
287*77c1e3ccSAndroid Build Coastguard Worker       return 1;
288*77c1e3ccSAndroid Build Coastguard Worker   }
289*77c1e3ccSAndroid Build Coastguard Worker 
290*77c1e3ccSAndroid Build Coastguard Worker   if (x != NULL && sf->inter_sf.prune_comp_ref_frames && comp_pred) {
291*77c1e3ccSAndroid Build Coastguard Worker     int closest_ref_frames = has_closest_ref_frames(
292*77c1e3ccSAndroid Build Coastguard Worker         ref_frame, cpi->ref_frame_dist_info.nearest_past_ref,
293*77c1e3ccSAndroid Build Coastguard Worker         cpi->ref_frame_dist_info.nearest_future_ref);
294*77c1e3ccSAndroid Build Coastguard Worker     if (closest_ref_frames == 0) {
295*77c1e3ccSAndroid Build Coastguard Worker       // Prune reference frames which are not the closest to the current frame.
296*77c1e3ccSAndroid Build Coastguard Worker       if (sf->inter_sf.prune_comp_ref_frames >= 2) {
297*77c1e3ccSAndroid Build Coastguard Worker         return 1;
298*77c1e3ccSAndroid Build Coastguard Worker       } else if (sf->inter_sf.prune_comp_ref_frames == 1) {
299*77c1e3ccSAndroid Build Coastguard Worker         // Prune reference frames with non minimum pred_mv_sad.
300*77c1e3ccSAndroid Build Coastguard Worker         if (has_best_pred_mv_sad(ref_frame, x) == 0) return 1;
301*77c1e3ccSAndroid Build Coastguard Worker       }
302*77c1e3ccSAndroid Build Coastguard Worker     }
303*77c1e3ccSAndroid Build Coastguard Worker   }
304*77c1e3ccSAndroid Build Coastguard Worker 
305*77c1e3ccSAndroid Build Coastguard Worker   return 0;
306*77c1e3ccSAndroid Build Coastguard Worker }
307*77c1e3ccSAndroid Build Coastguard Worker 
308*77c1e3ccSAndroid Build Coastguard Worker // This function will copy the best reference mode information from
309*77c1e3ccSAndroid Build Coastguard Worker // MB_MODE_INFO_EXT to MB_MODE_INFO_EXT_FRAME.
av1_copy_mbmi_ext_to_mbmi_ext_frame(MB_MODE_INFO_EXT_FRAME * mbmi_ext_best,const MB_MODE_INFO_EXT * const mbmi_ext,uint8_t ref_frame_type)310*77c1e3ccSAndroid Build Coastguard Worker static inline void av1_copy_mbmi_ext_to_mbmi_ext_frame(
311*77c1e3ccSAndroid Build Coastguard Worker     MB_MODE_INFO_EXT_FRAME *mbmi_ext_best,
312*77c1e3ccSAndroid Build Coastguard Worker     const MB_MODE_INFO_EXT *const mbmi_ext, uint8_t ref_frame_type) {
313*77c1e3ccSAndroid Build Coastguard Worker   memcpy(mbmi_ext_best->ref_mv_stack, mbmi_ext->ref_mv_stack[ref_frame_type],
314*77c1e3ccSAndroid Build Coastguard Worker          sizeof(mbmi_ext->ref_mv_stack[USABLE_REF_MV_STACK_SIZE]));
315*77c1e3ccSAndroid Build Coastguard Worker   memcpy(mbmi_ext_best->weight, mbmi_ext->weight[ref_frame_type],
316*77c1e3ccSAndroid Build Coastguard Worker          sizeof(mbmi_ext->weight[USABLE_REF_MV_STACK_SIZE]));
317*77c1e3ccSAndroid Build Coastguard Worker   mbmi_ext_best->mode_context = mbmi_ext->mode_context[ref_frame_type];
318*77c1e3ccSAndroid Build Coastguard Worker   mbmi_ext_best->ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
319*77c1e3ccSAndroid Build Coastguard Worker   memcpy(mbmi_ext_best->global_mvs, mbmi_ext->global_mvs,
320*77c1e3ccSAndroid Build Coastguard Worker          sizeof(mbmi_ext->global_mvs));
321*77c1e3ccSAndroid Build Coastguard Worker }
322*77c1e3ccSAndroid Build Coastguard Worker 
323*77c1e3ccSAndroid Build Coastguard Worker #ifdef __cplusplus
324*77c1e3ccSAndroid Build Coastguard Worker }  // extern "C"
325*77c1e3ccSAndroid Build Coastguard Worker #endif
326*77c1e3ccSAndroid Build Coastguard Worker 
327*77c1e3ccSAndroid Build Coastguard Worker #endif  // AOM_AV1_ENCODER_RDOPT_H_
328