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