// Can we use CfL for the current block?static INLINE CFL_ALLOWED_TYPE is_cfl_allowed(const MACROBLOCKD *xd){const MB_MODE_INFO *mbmi = xd->mi[0];const BLOCK_SIZE bsize = mbmi->bsize;assert(bsize < BLOCK_SIZES_ALL);if(xd->lossless[mbmi->segment_id]){// In lossless, CfL is available when the partition size is equal to the// transform size.constint ssx = xd->plane[AOM_PLANE_U].subsampling_x;constint ssy = xd->plane[AOM_PLANE_U].subsampling_y;constint plane_bsize =get_plane_block_size(bsize, ssx, ssy);return(CFL_ALLOWED_TYPE)(plane_bsize == BLOCK_4X4);}// Spec: CfL is available to luma partitions lesser than or equal to 32x32return(CFL_ALLOWED_TYPE)(block_size_wide[bsize]<=32&&
block_size_high[bsize]<=32);}
/*!\brief Pick the optimal parameters for Chroma to Luma (CFL) component
*
* \ingroup intra_mode_search
* \callergraph
*
* This function will use DCT_DCT followed by computing SATD (sum of absolute
* transformed differences) to estimate the RD score and find the best possible
* CFL parameter.
*
* Then the function will apply a full RD search near the best possible CFL
* parameter to find the best actual CFL parameter.
*
* Side effect:
* We use ths buffers in x->plane[] and xd->plane[] as throw-away buffers for RD
* search.
*
* \param[in] x Encoder prediction block structure.
* \param[in] cpi Top-level encoder instance structure.
* \param[in] tx_size Transform size.
* \param[in] ref_best_rd Reference best RD.
* \param[in] cfl_search_range The search range of full RD search near the
* estimated best CFL parameter.
*
* \param[out] best_rd_stats RD stats of the best CFL parameter
* \param[out] best_cfl_alpha_idx Best CFL alpha index
* \param[out] best_cfl_alpha_signs Best CFL joint signs
*
*/staticintcfl_rd_pick_alpha(MACROBLOCK *const x,const AV1_COMP *const cpi,
TX_SIZE tx_size,int64_t ref_best_rd,int cfl_search_range, RD_STATS *best_rd_stats,uint8_t*best_cfl_alpha_idx,int8_t*best_cfl_alpha_signs){assert(cfl_search_range >=1&& cfl_search_range <= CFL_MAGS_SIZE);const ModeCosts *mode_costs =&x->mode_costs;
RD_STATS cfl_rd_arr_u[CFL_MAGS_SIZE];
RD_STATS cfl_rd_arr_v[CFL_MAGS_SIZE];
MACROBLOCKD *const xd =&x->e_mbd;int est_best_cfl_idx_u, est_best_cfl_idx_v;av1_invalid_rd_stats(best_rd_stats);// As the dc pred data is same for different values of alpha, enable the// caching of dc pred data. Call clear_cfl_dc_pred_cache_flags() before// returning to avoid the unintentional usage of cached dc pred data.
xd->cfl.use_dc_pred_cache = true;// Evaluate alpha parameter of each chroma plane.
est_best_cfl_idx_u =cfl_pick_plane_parameter(cpi, x,1, tx_size, cfl_search_range);
est_best_cfl_idx_v =cfl_pick_plane_parameter(cpi, x,2, tx_size, cfl_search_range);if(cfl_search_range ==1){// For cfl_search_range=1, further refinement of alpha is not enabled. Hence// CfL index=0 for both the chroma planes implies invalid CfL mode.if(est_best_cfl_idx_u == CFL_INDEX_ZERO &&
est_best_cfl_idx_v == CFL_INDEX_ZERO){set_invalid_cfl_parameters(best_cfl_alpha_idx, best_cfl_alpha_signs);clear_cfl_dc_pred_cache_flags(&xd->cfl);return0;}int cfl_alpha_u, cfl_alpha_v;
CFL_SIGN_TYPE cfl_sign_u, cfl_sign_v;const MB_MODE_INFO *mbmi = xd->mi[0];cfl_idx_to_sign_and_alpha(est_best_cfl_idx_u,&cfl_sign_u,&cfl_alpha_u);cfl_idx_to_sign_and_alpha(est_best_cfl_idx_v,&cfl_sign_v,&cfl_alpha_v);constint joint_sign = cfl_sign_u * CFL_SIGNS + cfl_sign_v -1;// Compute alpha and mode signaling rate.constint rate_overhead =
mode_costs->cfl_cost[joint_sign][CFL_PRED_U][cfl_alpha_u]+
mode_costs->cfl_cost[joint_sign][CFL_PRED_V][cfl_alpha_v]+
mode_costs
->intra_uv_mode_cost[is_cfl_allowed(xd)][mbmi->mode][UV_CFL_PRED];// Skip the CfL mode evaluation if the RD cost derived using the rate needed// to signal the CfL mode and alpha parameter exceeds the ref_best_rd.if(RDCOST(x->rdmult, rate_overhead,0)> ref_best_rd){set_invalid_cfl_parameters(best_cfl_alpha_idx, best_cfl_alpha_signs);clear_cfl_dc_pred_cache_flags(&xd->cfl);return0;}}// Compute the rd cost of each chroma plane using the alpha parameters which// were already evaluated.cfl_pick_plane_rd(cpi, x,1, tx_size, cfl_search_range, cfl_rd_arr_u,
est_best_cfl_idx_u);cfl_pick_plane_rd(cpi, x,2, tx_size, cfl_search_range, cfl_rd_arr_v,
est_best_cfl_idx_v);clear_cfl_dc_pred_cache_flags(&xd->cfl);for(int ui =0; ui < CFL_MAGS_SIZE;++ui){if(cfl_rd_arr_u[ui].rate == INT_MAX)continue;int cfl_alpha_u;
CFL_SIGN_TYPE cfl_sign_u;cfl_idx_to_sign_and_alpha(ui,&cfl_sign_u,&cfl_alpha_u);for(int vi =0; vi < CFL_MAGS_SIZE;++vi){if(cfl_rd_arr_v[vi].rate == INT_MAX)continue;int cfl_alpha_v;
CFL_SIGN_TYPE cfl_sign_v;cfl_idx_to_sign_and_alpha(vi,&cfl_sign_v,&cfl_alpha_v);// cfl_sign_u == CFL_SIGN_ZERO && cfl_sign_v == CFL_SIGN_ZERO is not a// valid parameter for CFLif(cfl_sign_u == CFL_SIGN_ZERO && cfl_sign_v == CFL_SIGN_ZERO)continue;int joint_sign = cfl_sign_u * CFL_SIGNS + cfl_sign_v -1;
RD_STATS rd_stats = cfl_rd_arr_u[ui];av1_merge_rd_stats(&rd_stats,&cfl_rd_arr_v[vi]);if(rd_stats.rate != INT_MAX){
rd_stats.rate +=
mode_costs->cfl_cost[joint_sign][CFL_PRED_U][cfl_alpha_u];
rd_stats.rate +=
mode_costs->cfl_cost[joint_sign][CFL_PRED_V][cfl_alpha_v];}av1_rd_cost_update(x->rdmult,&rd_stats);if(rd_stats.rdcost < best_rd_stats->rdcost){*best_rd_stats = rd_stats;*best_cfl_alpha_idx =(cfl_alpha_u << CFL_ALPHABET_SIZE_LOG2)+ cfl_alpha_v;*best_cfl_alpha_signs = joint_sign;}}}if(best_rd_stats->rdcost >= ref_best_rd){av1_invalid_rd_stats(best_rd_stats);// Set invalid CFL parameters here since the rdcost is not better than// ref_best_rd.set_invalid_cfl_parameters(best_cfl_alpha_idx, best_cfl_alpha_signs);return0;}return1;}