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