encodeframe_utils.h (21558B)
1 /* 2 * Copyright (c) 2020, 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_ENCODEFRAME_UTILS_H_ 13 #define AOM_AV1_ENCODER_ENCODEFRAME_UTILS_H_ 14 15 #include "aom_ports/aom_timer.h" 16 17 #include "av1/common/reconinter.h" 18 19 #include "av1/encoder/encoder.h" 20 #include "av1/encoder/rdopt.h" 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 #define WRITE_FEATURE_TO_FILE 0 27 28 #define FEATURE_SIZE_SMS_SPLIT_FAST 6 29 #define FEATURE_SIZE_SMS_SPLIT 17 30 #define FEATURE_SIZE_SMS_PRUNE_PART 25 31 #define FEATURE_SIZE_SMS_TERM_NONE 28 32 #define FEATURE_SIZE_FP_SMS_TERM_NONE 20 33 #define FEATURE_SIZE_MAX_MIN_PART_PRED 13 34 #define MAX_NUM_CLASSES_MAX_MIN_PART_PRED 4 35 36 #define FEATURE_SMS_NONE_FLAG 1 37 #define FEATURE_SMS_SPLIT_FLAG (1 << 1) 38 #define FEATURE_SMS_RECT_FLAG (1 << 2) 39 40 #define FEATURE_SMS_PRUNE_PART_FLAG \ 41 (FEATURE_SMS_NONE_FLAG | FEATURE_SMS_SPLIT_FLAG | FEATURE_SMS_RECT_FLAG) 42 #define FEATURE_SMS_SPLIT_MODEL_FLAG \ 43 (FEATURE_SMS_NONE_FLAG | FEATURE_SMS_SPLIT_FLAG) 44 45 // Number of sub-partitions in rectangular partition types. 46 #define SUB_PARTITIONS_RECT 2 47 48 // Number of sub-partitions in split partition type. 49 #define SUB_PARTITIONS_SPLIT 4 50 51 // Number of sub-partitions in AB partition types. 52 #define SUB_PARTITIONS_AB 3 53 54 // Number of sub-partitions in 4-way partition types. 55 #define SUB_PARTITIONS_PART4 4 56 57 // 4part partition types. 58 enum { HORZ4 = 0, VERT4, NUM_PART4_TYPES } UENUM1BYTE(PART4_TYPES); 59 60 // AB partition types. 61 enum { 62 HORZ_A = 0, 63 HORZ_B, 64 VERT_A, 65 VERT_B, 66 NUM_AB_PARTS 67 } UENUM1BYTE(AB_PART_TYPE); 68 69 // Rectangular partition types. 70 enum { HORZ = 0, VERT, NUM_RECT_PARTS } UENUM1BYTE(RECT_PART_TYPE); 71 72 // Structure to keep win flags for HORZ and VERT partition evaluations. 73 typedef struct { 74 int rect_part_win[NUM_RECT_PARTS]; 75 } RD_RECT_PART_WIN_INFO; 76 77 enum { PICK_MODE_RD = 0, PICK_MODE_NONRD }; 78 79 enum { 80 SB_SINGLE_PASS, // Single pass encoding: all ctxs get updated normally 81 SB_DRY_PASS, // First pass of multi-pass: does not update the ctxs 82 SB_WET_PASS // Second pass of multi-pass: finalize and update the ctx 83 } UENUM1BYTE(SB_MULTI_PASS_MODE); 84 85 typedef struct { 86 ENTROPY_CONTEXT a[MAX_MIB_SIZE * MAX_MB_PLANE]; 87 ENTROPY_CONTEXT l[MAX_MIB_SIZE * MAX_MB_PLANE]; 88 PARTITION_CONTEXT sa[MAX_MIB_SIZE]; 89 PARTITION_CONTEXT sl[MAX_MIB_SIZE]; 90 TXFM_CONTEXT *p_ta; 91 TXFM_CONTEXT *p_tl; 92 TXFM_CONTEXT ta[MAX_MIB_SIZE]; 93 TXFM_CONTEXT tl[MAX_MIB_SIZE]; 94 } RD_SEARCH_MACROBLOCK_CONTEXT; 95 96 // This struct is used to store the statistics used by sb-level multi-pass 97 // encoding. Currently, this is only used to make a copy of the state before we 98 // perform the first pass 99 typedef struct SB_FIRST_PASS_STATS { 100 RD_SEARCH_MACROBLOCK_CONTEXT x_ctx; 101 RD_COUNTS rd_count; 102 103 int split_count; 104 FRAME_COUNTS fc; 105 InterModeRdModel inter_mode_rd_models[BLOCK_SIZES_ALL]; 106 int thresh_freq_fact[BLOCK_SIZES_ALL][MAX_MODES]; 107 int current_qindex; 108 109 #if CONFIG_INTERNAL_STATS 110 unsigned int mode_chosen_counts[MAX_MODES]; 111 #endif // CONFIG_INTERNAL_STATS 112 } SB_FIRST_PASS_STATS; 113 114 // This structure contains block size related 115 // variables for use in rd_pick_partition(). 116 typedef struct { 117 // Half of block width to determine block edge. 118 int mi_step; 119 120 // Block row and column indices. 121 int mi_row; 122 int mi_col; 123 124 // Block edge row and column indices. 125 int mi_row_edge; 126 int mi_col_edge; 127 128 // Block width of current partition block. 129 int width; 130 131 // Block width of minimum partition size allowed. 132 int min_partition_size_1d; 133 134 // Flag to indicate if partition is 8x8 or higher size. 135 int bsize_at_least_8x8; 136 137 // Indicates edge blocks in frame. 138 int has_rows; 139 int has_cols; 140 141 // Block size of current partition. 142 BLOCK_SIZE bsize; 143 144 // Size of current sub-partition. 145 BLOCK_SIZE subsize; 146 147 // Size of split partition. 148 BLOCK_SIZE split_bsize2; 149 } PartitionBlkParams; 150 151 #if CONFIG_COLLECT_PARTITION_STATS 152 typedef struct PartitionTimingStats { 153 // Tracks the number of partition decision used in the current call to \ref 154 // av1_rd_pick_partition 155 int partition_decisions[EXT_PARTITION_TYPES]; 156 // Tracks the number of partition_block searched in the current call to \ref 157 // av1_rd_pick_partition 158 int partition_attempts[EXT_PARTITION_TYPES]; 159 // Tracks the time spent on each partition search in the current call to \ref 160 // av1_rd_pick_partition 161 int64_t partition_times[EXT_PARTITION_TYPES]; 162 // Tracks the rdcost spent on each partition search in the current call to 163 // \ref av1_rd_pick_partition 164 int64_t partition_rdcost[EXT_PARTITION_TYPES]; 165 // Timer used to time the partitions. 166 struct aom_usec_timer timer; 167 // Whether the timer is on 168 int timer_is_on; 169 } PartitionTimingStats; 170 #endif // CONFIG_COLLECT_PARTITION_STATS 171 172 // Structure holding state variables for partition search. 173 typedef struct { 174 // Intra partitioning related info. 175 PartitionSearchInfo *intra_part_info; 176 177 // Parameters related to partition block size. 178 PartitionBlkParams part_blk_params; 179 180 // Win flags for HORZ and VERT partition evaluations. 181 RD_RECT_PART_WIN_INFO split_part_rect_win[SUB_PARTITIONS_SPLIT]; 182 183 // RD cost for the current block of given partition type. 184 RD_STATS this_rdc; 185 186 // RD cost summed across all blocks of partition type. 187 RD_STATS sum_rdc; 188 189 // Array holding partition type cost. 190 int tmp_partition_cost[PARTITION_TYPES]; 191 192 // Pointer to partition cost buffer 193 int *partition_cost; 194 195 // RD costs for different partition types. 196 int64_t none_rd; 197 int64_t split_rd[SUB_PARTITIONS_SPLIT]; 198 // RD costs for rectangular partitions. 199 // rect_part_rd[0][i] is the RD cost of ith partition index of PARTITION_HORZ. 200 // rect_part_rd[1][i] is the RD cost of ith partition index of PARTITION_VERT. 201 int64_t rect_part_rd[NUM_RECT_PARTS][SUB_PARTITIONS_RECT]; 202 203 // Flags indicating if the corresponding partition was winner or not. 204 // Used to bypass similar blocks during AB partition evaluation. 205 int is_split_ctx_is_ready[2]; 206 int is_rect_ctx_is_ready[NUM_RECT_PARTS]; 207 208 // If true, skips the rest of partition evaluation at the current bsize level. 209 int terminate_partition_search; 210 211 // If false, skips rdopt on PARTITION_NONE. 212 int partition_none_allowed; 213 214 // If partition_rect_allowed[HORZ] is false, skips searching PARTITION_HORZ, 215 // PARTITION_HORZ_A, PARTITIO_HORZ_B, PARTITION_HORZ_4. Same holds for VERT. 216 int partition_rect_allowed[NUM_RECT_PARTS]; 217 218 // If false, skips searching rectangular partition unless some logic related 219 // to edge detection holds. 220 int do_rectangular_split; 221 222 // If false, skips searching PARTITION_SPLIT. 223 int do_square_split; 224 225 // If true, prunes the corresponding PARTITION_HORZ/PARTITION_VERT. Note that 226 // this does not directly affect the extended partitions, so this can be used 227 // to prune out PARTITION_HORZ/PARTITION_VERT while still allowing rdopt of 228 // PARTITION_HORZ_AB4, etc. 229 int prune_rect_part[NUM_RECT_PARTS]; 230 231 // Chroma subsampling in x and y directions. 232 int ss_x; 233 int ss_y; 234 235 // Partition plane context index. 236 int pl_ctx_idx; 237 238 // This flag will be set if best partition is found from the search. 239 bool found_best_partition; 240 241 #if CONFIG_COLLECT_PARTITION_STATS 242 PartitionTimingStats part_timing_stats; 243 #endif // CONFIG_COLLECT_PARTITION_STATS 244 } PartitionSearchState; 245 246 static inline void av1_disable_square_split_partition( 247 PartitionSearchState *part_state) { 248 part_state->do_square_split = 0; 249 } 250 251 // Disables all possible rectangular splits. This includes PARTITION_AB4 as they 252 // depend on the corresponding partition_rect_allowed. 253 static inline void av1_disable_rect_partitions( 254 PartitionSearchState *part_state) { 255 part_state->do_rectangular_split = 0; 256 part_state->partition_rect_allowed[HORZ] = 0; 257 part_state->partition_rect_allowed[VERT] = 0; 258 } 259 260 // Disables all possible splits so that only PARTITION_NONE *might* be allowed. 261 static inline void av1_disable_all_splits(PartitionSearchState *part_state) { 262 av1_disable_square_split_partition(part_state); 263 av1_disable_rect_partitions(part_state); 264 } 265 266 static inline void av1_set_square_split_only(PartitionSearchState *part_state) { 267 part_state->partition_none_allowed = 0; 268 part_state->do_square_split = 1; 269 av1_disable_rect_partitions(part_state); 270 } 271 272 static inline bool av1_blk_has_rows_and_cols( 273 const PartitionBlkParams *blk_params) { 274 return blk_params->has_rows && blk_params->has_cols; 275 } 276 277 static inline bool av1_is_whole_blk_in_frame( 278 const PartitionBlkParams *blk_params, 279 const CommonModeInfoParams *mi_params) { 280 const int mi_row = blk_params->mi_row, mi_col = blk_params->mi_col; 281 const BLOCK_SIZE bsize = blk_params->bsize; 282 return mi_row + mi_size_high[bsize] <= mi_params->mi_rows && 283 mi_col + mi_size_wide[bsize] <= mi_params->mi_cols; 284 } 285 286 static inline void update_filter_type_cdf(const MACROBLOCKD *xd, 287 const MB_MODE_INFO *mbmi, 288 int dual_filter) { 289 for (int dir = 0; dir < 2; ++dir) { 290 if (dir && !dual_filter) break; 291 const int ctx = av1_get_pred_context_switchable_interp(xd, dir); 292 InterpFilter filter = av1_extract_interp_filter(mbmi->interp_filters, dir); 293 update_cdf(xd->tile_ctx->switchable_interp_cdf[ctx], filter, 294 SWITCHABLE_FILTERS); 295 } 296 } 297 298 static inline int set_rdmult(const AV1_COMP *const cpi, 299 const MACROBLOCK *const x, int segment_id) { 300 const AV1_COMMON *const cm = &cpi->common; 301 const GF_GROUP *const gf_group = &cpi->ppi->gf_group; 302 const CommonQuantParams *quant_params = &cm->quant_params; 303 const aom_bit_depth_t bit_depth = cm->seq_params->bit_depth; 304 const FRAME_UPDATE_TYPE update_type = 305 cpi->ppi->gf_group.update_type[cpi->gf_frame_index]; 306 const FRAME_TYPE frame_type = cm->current_frame.frame_type; 307 const int boost_index = AOMMIN(15, (cpi->ppi->p_rc.gfu_boost / 100)); 308 const int layer_depth = AOMMIN(gf_group->layer_depth[cpi->gf_frame_index], 6); 309 310 int qindex; 311 if (segment_id >= 0) { 312 qindex = av1_get_qindex(&cm->seg, segment_id, cm->quant_params.base_qindex); 313 } else { 314 qindex = quant_params->base_qindex + x->rdmult_delta_qindex + 315 quant_params->y_dc_delta_q; 316 } 317 318 return av1_compute_rd_mult( 319 qindex, bit_depth, update_type, layer_depth, boost_index, frame_type, 320 cpi->oxcf.q_cfg.use_fixed_qp_offsets, is_stat_consumption_stage(cpi), 321 cpi->oxcf.tune_cfg.tuning); 322 } 323 324 static inline int do_split_check(BLOCK_SIZE bsize) { 325 return (bsize == BLOCK_16X16 || bsize == BLOCK_32X32); 326 } 327 328 #if !CONFIG_REALTIME_ONLY 329 static inline const FIRSTPASS_STATS *read_one_frame_stats(const TWO_PASS *p, 330 int frm) { 331 assert(frm >= 0); 332 if (frm < 0 || 333 p->stats_buf_ctx->stats_in_start + frm > p->stats_buf_ctx->stats_in_end) { 334 return NULL; 335 } 336 337 return &p->stats_buf_ctx->stats_in_start[frm]; 338 } 339 340 int av1_get_rdmult_delta(AV1_COMP *cpi, BLOCK_SIZE bsize, int mi_row, 341 int mi_col, int orig_rdmult); 342 343 int av1_active_h_edge(const AV1_COMP *cpi, int mi_row, int mi_step); 344 345 int av1_active_v_edge(const AV1_COMP *cpi, int mi_col, int mi_step); 346 347 void av1_get_tpl_stats_sb(AV1_COMP *cpi, BLOCK_SIZE bsize, int mi_row, 348 int mi_col, SuperBlockEnc *sb_enc); 349 350 int av1_get_q_for_deltaq_objective(AV1_COMP *const cpi, ThreadData *td, 351 int64_t *delta_dist, BLOCK_SIZE bsize, 352 int mi_row, int mi_col); 353 354 int av1_get_q_for_hdr(AV1_COMP *const cpi, MACROBLOCK *const x, 355 BLOCK_SIZE bsize, int mi_row, int mi_col); 356 357 int av1_get_cb_rdmult(const AV1_COMP *const cpi, MACROBLOCK *const x, 358 const BLOCK_SIZE bsize, const int mi_row, 359 const int mi_col); 360 #endif // !CONFIG_REALTIME_ONLY 361 362 void av1_set_ssim_rdmult(const AV1_COMP *const cpi, int *errorperbit, 363 const BLOCK_SIZE bsize, const int mi_row, 364 const int mi_col, int *const rdmult); 365 366 #if CONFIG_SALIENCY_MAP 367 void av1_set_saliency_map_vmaf_rdmult(const AV1_COMP *const cpi, 368 int *errorperbit, const BLOCK_SIZE bsize, 369 const int mi_row, const int mi_col, 370 int *const rdmult); 371 #endif 372 373 void av1_update_state(const AV1_COMP *const cpi, ThreadData *td, 374 const PICK_MODE_CONTEXT *const ctx, int mi_row, 375 int mi_col, BLOCK_SIZE bsize, RUN_TYPE dry_run); 376 377 void av1_update_inter_mode_stats(FRAME_CONTEXT *fc, FRAME_COUNTS *counts, 378 PREDICTION_MODE mode, int16_t mode_context); 379 380 void av1_sum_intra_stats(const AV1_COMMON *const cm, FRAME_COUNTS *counts, 381 MACROBLOCKD *xd, const MB_MODE_INFO *const mbmi, 382 const MB_MODE_INFO *above_mi, 383 const MB_MODE_INFO *left_mi, const int intraonly); 384 385 void av1_restore_context(MACROBLOCK *x, const RD_SEARCH_MACROBLOCK_CONTEXT *ctx, 386 int mi_row, int mi_col, BLOCK_SIZE bsize, 387 const int num_planes); 388 389 void av1_save_context(const MACROBLOCK *x, RD_SEARCH_MACROBLOCK_CONTEXT *ctx, 390 int mi_row, int mi_col, BLOCK_SIZE bsize, 391 const int num_planes); 392 393 void av1_set_fixed_partitioning(AV1_COMP *cpi, const TileInfo *const tile, 394 MB_MODE_INFO **mib, int mi_row, int mi_col, 395 BLOCK_SIZE bsize); 396 397 int av1_is_leaf_split_partition(AV1_COMMON *cm, int mi_row, int mi_col, 398 BLOCK_SIZE bsize); 399 400 void av1_reset_simple_motion_tree_partition(SIMPLE_MOTION_DATA_TREE *sms_tree, 401 BLOCK_SIZE bsize); 402 403 void av1_update_picked_ref_frames_mask(MACROBLOCK *const x, int ref_type, 404 BLOCK_SIZE bsize, int mib_size, 405 int mi_row, int mi_col); 406 407 void av1_avg_cdf_symbols(FRAME_CONTEXT *ctx_left, FRAME_CONTEXT *ctx_tr, 408 int wt_left, int wt_tr); 409 410 void av1_source_content_sb(AV1_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data, 411 int mi_row, int mi_col); 412 413 void av1_reset_mbmi(CommonModeInfoParams *const mi_params, BLOCK_SIZE sb_size, 414 int mi_row, int mi_col); 415 416 void av1_backup_sb_state(SB_FIRST_PASS_STATS *sb_fp_stats, const AV1_COMP *cpi, 417 ThreadData *td, const TileDataEnc *tile_data, 418 int mi_row, int mi_col); 419 420 void av1_restore_sb_state(const SB_FIRST_PASS_STATS *sb_fp_stats, AV1_COMP *cpi, 421 ThreadData *td, TileDataEnc *tile_data, int mi_row, 422 int mi_col); 423 424 void av1_set_cost_upd_freq(AV1_COMP *cpi, ThreadData *td, 425 const TileInfo *const tile_info, const int mi_row, 426 const int mi_col); 427 428 void av1_dealloc_src_diff_buf(struct macroblock *mb, int num_planes); 429 430 static inline void av1_dealloc_mb_data(struct macroblock *mb, int num_planes) { 431 aom_free(mb->txfm_search_info.mb_rd_record); 432 mb->txfm_search_info.mb_rd_record = NULL; 433 434 aom_free(mb->inter_modes_info); 435 mb->inter_modes_info = NULL; 436 437 av1_dealloc_src_diff_buf(mb, num_planes); 438 439 aom_free(mb->e_mbd.seg_mask); 440 mb->e_mbd.seg_mask = NULL; 441 442 aom_free(mb->winner_mode_stats); 443 mb->winner_mode_stats = NULL; 444 445 aom_free(mb->dqcoeff_buf); 446 mb->dqcoeff_buf = NULL; 447 } 448 449 static inline void allocate_winner_mode_stats(const AV1_COMP *cpi, 450 struct macroblock *mb) { 451 const SPEED_FEATURES *sf = &cpi->sf; 452 // The winner_mode_stats buffer is not required in these cases. 453 if (is_stat_generation_stage(cpi) || 454 (sf->rt_sf.use_nonrd_pick_mode && !sf->rt_sf.hybrid_intra_pickmode) || 455 (sf->winner_mode_sf.multi_winner_mode_type == MULTI_WINNER_MODE_OFF)) 456 return; 457 458 const AV1_COMMON *cm = &cpi->common; 459 const int winner_mode_count = 460 winner_mode_count_allowed[sf->winner_mode_sf.multi_winner_mode_type]; 461 CHECK_MEM_ERROR(cm, mb->winner_mode_stats, 462 (WinnerModeStats *)aom_malloc( 463 winner_mode_count * sizeof(mb->winner_mode_stats[0]))); 464 } 465 466 void av1_alloc_src_diff_buf(const struct AV1Common *cm, struct macroblock *mb); 467 468 static inline void av1_alloc_mb_data(const AV1_COMP *cpi, 469 struct macroblock *mb) { 470 const AV1_COMMON *cm = &cpi->common; 471 const SPEED_FEATURES *sf = &cpi->sf; 472 if (!sf->rt_sf.use_nonrd_pick_mode) { 473 // Memory for mb_rd_record is allocated only when use_mb_rd_hash sf is 474 // enabled. 475 if (sf->rd_sf.use_mb_rd_hash) 476 CHECK_MEM_ERROR(cm, mb->txfm_search_info.mb_rd_record, 477 (MB_RD_RECORD *)aom_malloc(sizeof(MB_RD_RECORD))); 478 if (!frame_is_intra_only(cm)) 479 CHECK_MEM_ERROR( 480 cm, mb->inter_modes_info, 481 (InterModesInfo *)aom_malloc(sizeof(*mb->inter_modes_info))); 482 } 483 484 av1_alloc_src_diff_buf(cm, mb); 485 486 CHECK_MEM_ERROR(cm, mb->e_mbd.seg_mask, 487 (uint8_t *)aom_memalign( 488 16, 2 * MAX_SB_SQUARE * sizeof(mb->e_mbd.seg_mask[0]))); 489 490 allocate_winner_mode_stats(cpi, mb); 491 492 const int max_sb_square_y = 1 493 << num_pels_log2_lookup[cm->seq_params->sb_size]; 494 CHECK_MEM_ERROR( 495 cm, mb->dqcoeff_buf, 496 (tran_low_t *)aom_memalign(32, max_sb_square_y * sizeof(tran_low_t))); 497 } 498 499 // This function will compute the number of reference frames to be disabled 500 // based on selective_ref_frame speed feature. 501 static inline unsigned int get_num_refs_to_disable( 502 const AV1_COMP *cpi, const int *ref_frame_flags, 503 const unsigned int *ref_display_order_hint, 504 unsigned int cur_frame_display_index) { 505 unsigned int num_refs_to_disable = 0; 506 if (cpi->sf.inter_sf.selective_ref_frame >= 3) { 507 num_refs_to_disable++; 508 if (cpi->sf.inter_sf.selective_ref_frame >= 6) { 509 // Disable LAST2_FRAME and ALTREF2_FRAME 510 num_refs_to_disable += 2; 511 } else if (cpi->sf.inter_sf.selective_ref_frame == 5 && 512 *ref_frame_flags & av1_ref_frame_flag_list[LAST2_FRAME]) { 513 const int last2_frame_dist = av1_encoder_get_relative_dist( 514 ref_display_order_hint[LAST2_FRAME - LAST_FRAME], 515 cur_frame_display_index); 516 // Disable LAST2_FRAME if it is a temporally distant frame 517 if (abs(last2_frame_dist) > 2) { 518 num_refs_to_disable++; 519 } 520 #if !CONFIG_REALTIME_ONLY 521 else if (is_stat_consumption_stage_twopass(cpi)) { 522 const FIRSTPASS_STATS *const this_frame_stats = 523 read_one_frame_stats(&cpi->ppi->twopass, cur_frame_display_index); 524 const double coded_error_per_mb = this_frame_stats->coded_error; 525 // Disable LAST2_FRAME if the coded error of the current frame based on 526 // first pass stats is very low. 527 if (coded_error_per_mb < 100.0) num_refs_to_disable++; 528 } 529 #endif // CONFIG_REALTIME_ONLY 530 } 531 } 532 return num_refs_to_disable; 533 } 534 535 static inline int get_max_allowed_ref_frames( 536 const AV1_COMP *cpi, const int *ref_frame_flags, 537 const unsigned int *ref_display_order_hint, 538 unsigned int cur_frame_display_index) { 539 const unsigned int max_reference_frames = 540 cpi->oxcf.ref_frm_cfg.max_reference_frames; 541 const unsigned int num_refs_to_disable = get_num_refs_to_disable( 542 cpi, ref_frame_flags, ref_display_order_hint, cur_frame_display_index); 543 const unsigned int max_allowed_refs_for_given_speed = 544 INTER_REFS_PER_FRAME - num_refs_to_disable; 545 return AOMMIN(max_allowed_refs_for_given_speed, max_reference_frames); 546 } 547 548 // Enforce the number of references for each arbitrary frame based on user 549 // options and speed. 550 static inline void enforce_max_ref_frames( 551 AV1_COMP *cpi, int *ref_frame_flags, 552 const unsigned int *ref_display_order_hint, 553 unsigned int cur_frame_display_index) { 554 MV_REFERENCE_FRAME ref_frame; 555 int total_valid_refs = 0; 556 557 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { 558 if (*ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) { 559 total_valid_refs++; 560 } 561 } 562 563 const int max_allowed_refs = get_max_allowed_ref_frames( 564 cpi, ref_frame_flags, ref_display_order_hint, cur_frame_display_index); 565 566 for (int i = 0; i < 4 && total_valid_refs > max_allowed_refs; ++i) { 567 const MV_REFERENCE_FRAME ref_frame_to_disable = disable_order[i]; 568 569 if (!(*ref_frame_flags & av1_ref_frame_flag_list[ref_frame_to_disable])) { 570 continue; 571 } 572 573 switch (ref_frame_to_disable) { 574 case LAST3_FRAME: *ref_frame_flags &= ~AOM_LAST3_FLAG; break; 575 case LAST2_FRAME: *ref_frame_flags &= ~AOM_LAST2_FLAG; break; 576 case ALTREF2_FRAME: *ref_frame_flags &= ~AOM_ALT2_FLAG; break; 577 case BWDREF_FRAME: *ref_frame_flags &= ~AOM_GOLD_FLAG; break; 578 default: assert(0); 579 } 580 --total_valid_refs; 581 } 582 assert(total_valid_refs <= max_allowed_refs); 583 } 584 585 #ifdef __cplusplus 586 } // extern "C" 587 #endif 588 589 #endif // AOM_AV1_ENCODER_ENCODEFRAME_UTILS_H_