// Finds the best non-intrabc mode on an intra frame.int64_tav1_rd_pick_intra_sby_mode(const AV1_COMP *const cpi, MACROBLOCK *x,int*rate,int*rate_tokenonly,int64_t*distortion,uint8_t*skippable,
BLOCK_SIZE bsize,int64_t best_rd,
PICK_MODE_CONTEXT *ctx){
MACROBLOCKD *const xd =&x->e_mbd;
MB_MODE_INFO *const mbmi = xd->mi[0];assert(!is_inter_block(mbmi));int64_t best_model_rd = INT64_MAX;int is_directional_mode;uint8_t directional_mode_skip_mask[INTRA_MODES]={
0};// Flag to check rd of any intra mode is better than best_rd passed to this// functionint beat_best_rd =0;constint*bmode_costs;const IntraModeCfg *const intra_mode_cfg =&cpi->oxcf.intra_mode_cfg;
PALETTE_MODE_INFO *const pmi =&mbmi->palette_mode_info;constint try_palette =
cpi->oxcf.tool_cfg.enable_palette &&av1_allow_palette(cpi->common.features.allow_screen_content_tools,
mbmi->bsize);uint8_t*best_palette_color_map =
try_palette ? x->palette_buffer->best_palette_color_map :NULL;const MB_MODE_INFO *above_mi = xd->above_mbmi;const MB_MODE_INFO *left_mi = xd->left_mbmi;const PREDICTION_MODE A =av1_above_block_mode(above_mi);const PREDICTION_MODE L =av1_left_block_mode(left_mi);constint above_ctx = intra_mode_context[A];constint left_ctx = intra_mode_context[L];
bmode_costs = x->mode_costs.y_mode_costs[above_ctx][left_ctx];
mbmi->angle_delta[PLANE_TYPE_Y]=0;const INTRA_MODE_SPEED_FEATURES *const intra_sf =&cpi->sf.intra_sf;if(intra_sf->intra_pruning_with_hog){
// Less aggressive thresholds are used here than those used in inter frame// encoding in av1_handle_intra_y_mode() because we want key frames/intra// frames to have higher quality.constfloat thresh[4]={
-1.2f,-1.2f,-0.6f,0.4f};constint is_chroma =0;prune_intra_mode_with_hog(x, bsize, cpi->common.seq_params->sb_size,
thresh[intra_sf->intra_pruning_with_hog -1],
directional_mode_skip_mask, is_chroma);}
mbmi->filter_intra_mode_info.use_filter_intra =0;
pmi->palette_size[0]=0;// Set params for mode evaluationset_mode_eval_params(cpi, x, MODE_EVAL);
MB_MODE_INFO best_mbmi =*mbmi;constint max_winner_mode_count =
winner_mode_count_allowed[cpi->sf.winner_mode_sf.multi_winner_mode_type];zero_winner_mode_stats(bsize, max_winner_mode_count, x->winner_mode_stats);
x->winner_mode_count =0;// Searches the intra-modes except for intrabc, palette, and filter_intra.int64_t top_intra_model_rd[TOP_INTRA_MODEL_COUNT];for(int i =0; i < TOP_INTRA_MODEL_COUNT; i++){
top_intra_model_rd[i]= INT64_MAX;}// Initialize the rdcost corresponding to all the directional and// non-directional intra modes.// 1. For directional modes, it stores the rdcost values for delta angles -4,// -3, ..., 3, 4.// 2. The rdcost value for luma_delta_angle is stored at index// luma_delta_angle + MAX_ANGLE_DELTA + 1.// 3. The rdcost values for fictitious/nonexistent luma_delta_angle -4 and 4// (array indices 0 and 8) are always set to INT64_MAX (the initial value).int64_t intra_modes_rd_cost[INTRA_MODE_END][SIZE_OF_ANGLE_DELTA_RD_COST_ARRAY];for(int i =0; i < INTRA_MODE_END; i++){
for(int j =0; j < SIZE_OF_ANGLE_DELTA_RD_COST_ARRAY; j++){
intra_modes_rd_cost[i][j]= INT64_MAX;}}for(int mode_idx = INTRA_MODE_START; mode_idx < LUMA_MODE_COUNT;++mode_idx){
set_y_mode_and_delta_angle(mode_idx, mbmi,
intra_sf->prune_luma_odd_delta_angles_in_intra);
RD_STATS this_rd_stats;int this_rate, this_rate_tokenonly, s;int is_diagonal_mode;int64_t this_distortion, this_rd;constint luma_delta_angle = mbmi->angle_delta[PLANE_TYPE_Y];
is_diagonal_mode =av1_is_diagonal_mode(mbmi->mode);if(is_diagonal_mode &&!intra_mode_cfg->enable_diagonal_intra)continue;if(av1_is_directional_mode(mbmi->mode)&&!intra_mode_cfg->enable_directional_intra)continue;// The smooth prediction mode appears to be more frequently picked// than horizontal / vertical smooth prediction modes. Hence treat// them differently in speed features.if((!intra_mode_cfg->enable_smooth_intra ||
intra_sf->disable_smooth_intra)&&(mbmi->mode == SMOOTH_H_PRED || mbmi->mode == SMOOTH_V_PRED))continue;if(!intra_mode_cfg->enable_smooth_intra && mbmi->mode == SMOOTH_PRED)continue;// The functionality of filter intra modes and smooth prediction// overlap. Hence smooth prediction is pruned only if all the// filter intra modes are enabled.if(intra_sf->disable_smooth_intra &&
intra_sf->prune_filter_intra_level ==0&& mbmi->mode == SMOOTH_PRED)continue;if(!intra_mode_cfg->enable_paeth_intra && mbmi->mode == PAETH_PRED)continue;// Skip the evaluation of modes that do not match with the winner mode in// x->mb_mode_cache.if(x->use_mb_mode_cache && mbmi->mode != x->mb_mode_cache->mode)continue;
is_directional_mode =av1_is_directional_mode(mbmi->mode);if(is_directional_mode && directional_mode_skip_mask[mbmi->mode])continue;if(is_directional_mode &&!(av1_use_angle_delta(bsize)&& intra_mode_cfg->enable_angle_delta)&&
luma_delta_angle !=0)continue;// Use intra_y_mode_mask speed feature to skip intra mode evaluation.if(!(intra_sf->intra_y_mode_mask[max_txsize_lookup[bsize]]&(1<< mbmi->mode)))continue;if(prune_luma_odd_delta_angles_using_rd_cost(
mbmi, intra_modes_rd_cost[mbmi->mode], best_rd,
intra_sf->prune_luma_odd_delta_angles_in_intra))continue;const TX_SIZE tx_size =AOMMIN(TX_32X32, max_txsize_lookup[bsize]);constint64_t this_model_rd =intra_model_rd(&cpi->common, x,0, bsize, tx_size,/*use_hadamard=*/1);constint model_rd_index_for_pruning =get_model_rd_index_for_pruning(x, intra_sf);if(prune_intra_y_mode(this_model_rd,&best_model_rd, top_intra_model_rd,
intra_sf->top_intra_model_count_allowed,
model_rd_index_for_pruning))continue;// Builds the actual prediction. The prediction from// model_intra_yrd_and_prune was just an estimation that did not take into// account the effect of txfm pipeline, so we need to redo it for real// here.av1_pick_uniform_tx_size_type_yrd(cpi, x,&this_rd_stats, bsize, best_rd);
this_rate_tokenonly = this_rd_stats.rate;
this_distortion = this_rd_stats.dist;
s = this_rd_stats.skip_txfm;if(this_rate_tokenonly == INT_MAX)continue;if(!xd->lossless[mbmi->segment_id]&&block_signals_txsize(mbmi->bsize)){
// av1_pick_uniform_tx_size_type_yrd above includes the cost of the// tx_size in the tokenonly rate, but for intra blocks, tx_size is always// coded (prediction granularity), so we account for it in the full rate,// not the tokenonly rate.
this_rate_tokenonly -=tx_size_cost(x, bsize, mbmi->tx_size);}
this_rate =
this_rd_stats.rate +intra_mode_info_cost_y(cpi, x, mbmi, bsize, bmode_costs[mbmi->mode],0);
this_rd =RDCOST(x->rdmult, this_rate, this_distortion);// Visual quality adjustment based on recon vs source variance.if((cpi->oxcf.mode == ALLINTRA)&&(this_rd != INT64_MAX)){
this_rd =(int64_t)(this_rd *intra_rd_variance_factor(cpi, x, bsize));}
intra_modes_rd_cost[mbmi->mode][luma_delta_angle + MAX_ANGLE_DELTA +1]=
this_rd;// Collect mode stats for multiwinner mode processingconstint txfm_search_done =1;store_winner_mode_stats(&cpi->common, x, mbmi,NULL,NULL,NULL,0,NULL, bsize, this_rd,
cpi->sf.winner_mode_sf.multi_winner_mode_type, txfm_search_done);if(this_rd < best_rd){
best_mbmi =*mbmi;
best_rd = this_rd;// Setting beat_best_rd flag because current mode rd is better than// best_rd passed to this function
beat_best_rd =1;*rate = this_rate;*rate_tokenonly = this_rate_tokenonly;*distortion = this_distortion;*skippable = s;memcpy(ctx->blk_skip, x->txfm_search_info.blk_skip,sizeof(x->txfm_search_info.blk_skip[0])* ctx->num_4x4_blk);av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);}}// Searches paletteif(try_palette){
av1_rd_pick_palette_intra_sby(
cpi, x, bsize, bmode_costs[DC_PRED],&best_mbmi, best_palette_color_map,&best_rd, rate, rate_tokenonly, distortion, skippable,&beat_best_rd,
ctx, ctx->blk_skip, ctx->tx_type_map);}// Searches filter_intraif(beat_best_rd &&av1_filter_intra_allowed_bsize(&cpi->common, bsize)){
if(rd_pick_filter_intra_sby(cpi, x, rate, rate_tokenonly, distortion,
skippable, bsize, bmode_costs[DC_PRED],
best_mbmi.mode,&best_rd,&best_model_rd,
ctx)){
best_mbmi =*mbmi;}}// No mode is identified with less rd value than best_rd passed to this// function. In such cases winner mode processing is not necessary and return// best_rd as INT64_MAX to indicate best mode is not identifiedif(!beat_best_rd)return INT64_MAX;// In multi-winner mode processing, perform tx search for few best modes// identified during mode evaluation. Winner mode processing uses best tx// configuration for tx search.if(cpi->sf.winner_mode_sf.multi_winner_mode_type){
int best_mode_idx =0;int block_width, block_height;uint8_t*color_map_dst = xd->plane[PLANE_TYPE_Y].color_index_map;av1_get_block_dimensions(bsize, AOM_PLANE_Y, xd,&block_width,&block_height,NULL,NULL);for(int mode_idx =0; mode_idx < x->winner_mode_count; mode_idx++){
*mbmi = x->winner_mode_stats[mode_idx].mbmi;if(is_winner_mode_processing_enabled(cpi, x, mbmi,0)){
// Restore color_map of palette mode before winner mode processingif(mbmi->palette_mode_info.palette_size[0]>0){
uint8_t*color_map_src =
x->winner_mode_stats[mode_idx].color_index_map;memcpy(color_map_dst, color_map_src,
block_width * block_height *sizeof(*color_map_src));}// Set params for winner mode evaluationset_mode_eval_params(cpi, x, WINNER_MODE_EVAL);// Winner mode processing// If previous searches use only the default tx type/no R-D optimization// of quantized coeffs, do an extra search for the best tx type/better// R-D optimization of quantized coeffsif(intra_block_yrd(cpi, x, bsize, bmode_costs,&best_rd, rate,
rate_tokenonly, distortion, skippable,&best_mbmi,
ctx))
best_mode_idx = mode_idx;}}// Copy color_map of palette mode for final winner modeif(best_mbmi.palette_mode_info.palette_size[0]>0){
uint8_t*color_map_src =
x->winner_mode_stats[best_mode_idx].color_index_map;memcpy(color_map_dst, color_map_src,
block_width * block_height *sizeof(*color_map_src));}}else{
// If previous searches use only the default tx type/no R-D optimization of// quantized coeffs, do an extra search for the best tx type/better R-D// optimization of quantized coeffsif(is_winner_mode_processing_enabled(cpi, x, mbmi,0)){
// Set params for winner mode evaluationset_mode_eval_params(cpi, x, WINNER_MODE_EVAL);*mbmi = best_mbmi;intra_block_yrd(cpi, x, bsize, bmode_costs,&best_rd, rate,
rate_tokenonly, distortion, skippable,&best_mbmi, ctx);}}*mbmi = best_mbmi;av1_copy_array(xd->tx_type_map, ctx->tx_type_map, ctx->num_4x4_blk);return best_rd;}