一 aomenc的cpu-used参数确实是用来控制编码复杂度的
这个参数的范围从0到8,其中0对应的是veryslow,8对应的ultrafast预设。--cpu-used参数控制的是编码质量与编码时间之间的权衡。较低的--cpu-used值会提供更高的编码质量但是需要更长的编码时间,而较高的值则会加快编码速度但是可能会牺牲一些编码质量。
二 代码review
2.1 cpu-used参数对应设置speed
oxcf->speed = extra_cfg->cpu_used;
2.2 如果是事实模式,speed最小只能设置为7
if (oxcf->mode == REALTIME && AOMMIN(cfg->g_w, cfg->g_h) >= 1080 &&
oxcf->speed < 7)
oxcf->speed = 7;
2.3 单帧编码策略
frame_params.speed = oxcf->speed;
这段代码是C语言的一部分,注释和代码结合起来说明了`frame_params.speed`变量的设置。下面是对这段代码的解释:
1. **注释部分**:
- `// Per-frame encode speed.`:这行注释说明`speed`参数是针对每一帧编码的速度。
- `In theory this can vary, but things may have`:理论上,这个速度是可以变化的,但是可能有些代码假设在序列中速度级别不会改变。
- `been written assuming speed-level will not change within a sequence, so`:因此,这个参数应该谨慎使用。
- `this parameter should be used with caution.`:这个参数应该谨慎使用。
2. **代码部分**:
- `frame_params.speed = oxcf->speed;`:这行代码将`oxcf`结构体中的`speed`成员的值赋给`frame_params`结构体中的`speed`成员。
这段代码将一个名为`oxcf`的结构体中的`speed`成员的值赋给另一个名为`frame_params`的结构体中的`speed`成员。注释部分提醒开发者,虽然理论上每一帧的编码速度可以变化,但在实际应用中,可能有些代码是基于速度级别在序列中不变的假设编写的,因此更改这个参数时需要谨慎。
2.4 选择sb block大小
av1_select_sb_size->
if (oxcf->speed >= 1 && is_480p_or_lesser)
return BLOCK_64x64;
//分辨率比较低,就最大块64x64
if (!is_480p_or_lesser && is_1080p_or_lesser && oxcf->mode == GOOD &&
oxcf->row_mt == 1 && oxcf->max_threads > 1 && oxcf->speed >= 5)
return BLOCK_64X64;
如果分辨率并不是低于480p, 并且大于1080p,速度大于等于5
2.5 除了它在速度8时设置了非RD(率失真)标志
// TODO(kyslov): 现在这个功能与
// set_good_speed_features_framesize_independent
// 非常相似,除了它在速度8时设置了非RD(率失真)标志。这个函数在未来可能会根据RT(实时)特定的速度特性进行修改。
static void set_rt_speed_features_framesize_independent(AV1_COMP *cpi, SPEED_FEATURES *sf, int speed)
{
AV1_COMMON *const cm = &cpi->common;
const int boosted = frame_is_boosted(cpi);
// Currently, rt speed 0, 1, 2, 3, 4, 5 are the same.
// Following set of speed features are not impacting encoder's decisions as
// the relevant tools are disabled by default.
sf->gm_sf.gm_search_type = GM_DISABLE_SEARCH;
sf->hl_sf.recode_loop = ALLOW_RECODE_KFARFGF;
sf->inter_sf.reuse_inter_intra_mode = 1;
sf->inter_sf.prune_compound_using_single_ref = 0;
sf->inter_sf.prune_comp_search_by_single_result = 2;
sf->inter_sf.prune_comp_type_by_comp_avg = 2;
sf->inter_sf.fast_wedge_sign_estimate = 1;
sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_DISABLED;
sf->inter_sf.mv_cost_upd_level = INTERNAL_COST_UPD_SBROW;
sf->inter_sf.disable_interinter_wedge_var_thresh = 100;
sf->interp_sf.cb_pred_filter_search = 0;
sf->interp_sf.skip_interp_filter_search = 1;
sf->part_sf.ml_prune_partition = 1;
sf->part_sf.reuse_prev_rd_results_for_part_ab = 1;
sf->part_sf.prune_ext_partition_types_search_level = 2;
sf->part_sf.less_rectangular_check_level = 2;
sf->mv_sf.obmc_full_pixel_search_level = 1;
sf->intra_sf.dv_cost_upd_level = INTERNAL_COST_UPD_OFF;
sf->tx_sf.model_based_prune_tx_search_level = 0;
sf->lpf_sf.dual_sgr_penalty_level = 1;
// Disable Wiener and Self-guided Loop restoration filters.
sf->lpf_sf.disable_wiener_filter = true;
sf->lpf_sf.disable_sgr_filter = true;
sf->intra_sf.prune_palette_search_level = 2;
sf->intra_sf.prune_luma_palette_size_search_level = 2;
sf->intra_sf.early_term_chroma_palette_size_search = 1;
2.6 speed == 6
if (speed >= 6) {
sf->mv_sf.use_fullpel_costlist = 1;
sf->rd_sf.tx_domain_dist_thres_level = 3;
sf->tx_sf.tx_type_search.fast_inter_tx_type_prob_thresh = 0;
sf->inter_sf.limit_inter_mode_cands = 4;
sf->inter_sf.prune_warped_prob_thresh = 8;
sf->inter_sf.extra_prune_warped = 1;
sf->rt_sf.gf_refresh_based_on_qp = 1;
sf->rt_sf.prune_inter_modes_wrt_gf_arf_based_on_sad = 1;
sf->rt_sf.var_part_split_threshold_shift = 7;
if (!frame_is_intra_only(&cpi->common))
sf->rt_sf.var_part_based_on_qidx = 2;
sf->winner_mode_sf.prune_winner_mode_eval_level = boosted ? 0 : 3;
}
2.6 speed = 7
if (speed >= 7) {
sf->rt_sf.sse_early_term_inter_search = EARLY_TERM_IDX_1;
sf->rt_sf.use_comp_ref_nonrd = 1;
sf->rt_sf.ref_frame_comp_nonrd[2] = 1; // LAST_ALTREF
sf->tx_sf.intra_tx_size_search_init_depth_sqr = 2;
sf->part_sf.partition_search_type = VAR_BASED_PARTITION;
sf->part_sf.max_intra_bsize = BLOCK_32X32;
sf->mv_sf.search_method = FAST_DIAMOND;
sf->mv_sf.subpel_force_stop = QUARTER_PEL;
sf->inter_sf.inter_mode_rd_model_estimation = 2;
// This sf is not applicable in non-rd path.
sf->inter_sf.skip_newmv_in_drl = 0;
sf->interp_sf.skip_interp_filter_search = 0;
// Disable intra_y_mode_mask pruning since the performance at speed 7 isn't
// good. May need more study.
for (int i = 0; i < TX_SIZES; ++i) {
sf->intra_sf.intra_y_mode_mask[i] = INTRA_ALL;
}
sf->lpf_sf.lpf_pick = LPF_PICK_FROM_Q;
sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL5;
sf->rt_sf.mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
sf->rt_sf.nonrd_prune_ref_frame_search = 1;
// This is for rd path only.
sf->rt_sf.prune_inter_modes_using_temp_var = 0;
sf->rt_sf.prune_inter_modes_wrt_gf_arf_based_on_sad = 0;
sf->rt_sf.prune_intra_mode_based_on_mv_range = 0;
#if !CONFIG_REALTIME_ONLY
sf->rt_sf.reuse_inter_pred_nonrd =
(cpi->oxcf.motion_mode_cfg.enable_warped_motion == 0);
#else
sf->rt_sf.reuse_inter_pred_nonrd = 1;
#endif
#if CONFIG_AV1_TEMPORAL_DENOISING
sf->rt_sf.reuse_inter_pred_nonrd = (cpi->oxcf.noise_sensitivity == 0);
#endif
sf->rt_sf.short_circuit_low_temp_var = 0;
// For spatial layers, only LAST and GOLDEN are currently used in the SVC
// for nonrd. The flag use_nonrd_altref_frame can disable GOLDEN in the
// get_ref_frame_flags() for some patterns, so disable it here for
// spatial layers.
sf->rt_sf.use_nonrd_altref_frame =
(cpi->svc.number_spatial_layers > 1) ? 0 : 1;
sf->rt_sf.use_nonrd_pick_mode = 1;
sf->rt_sf.nonrd_check_partition_merge_mode = 3;
sf->rt_sf.skip_intra_pred = 1;
sf->rt_sf.source_metrics_sb_nonrd = 1;
// Set mask for intra modes.
for (int i = 0; i < BLOCK_SIZES; ++i)
if (i >= BLOCK_32X32)
sf->rt_sf.intra_y_mode_bsize_mask_nrd[i] = INTRA_DC;
else
// Use DC, H, V intra mode for block sizes < 32X32.
sf->rt_sf.intra_y_mode_bsize_mask_nrd[i] = INTRA_DC_H_V;
sf->winner_mode_sf.dc_blk_pred_level = 0;
sf->rt_sf.var_part_based_on_qidx = 3;
sf->rt_sf.prune_compoundmode_with_singlecompound_var = true;
sf->rt_sf.prune_compoundmode_with_singlemode_var = true;
sf->rt_sf.skip_compound_based_on_var = true;
sf->rt_sf.use_adaptive_subpel_search = true;
}
2.8 speed = 8
if (speed >= 8) {
sf->rt_sf.sse_early_term_inter_search = EARLY_TERM_IDX_2;
sf->intra_sf.intra_pruning_with_hog = 1;
sf->rt_sf.short_circuit_low_temp_var = 1;
sf->rt_sf.use_nonrd_altref_frame = 0;
sf->rt_sf.nonrd_prune_ref_frame_search = 2;
sf->rt_sf.nonrd_check_partition_merge_mode = 0;
sf->rt_sf.var_part_split_threshold_shift = 8;
sf->rt_sf.var_part_based_on_qidx = 4;
sf->rt_sf.partition_direct_merging = 1;
sf->rt_sf.prune_compoundmode_with_singlemode_var = false;
sf->mv_sf.use_bsize_dependent_search_method = 2;
sf->rt_sf.prune_hv_pred_modes_using_src_sad = true;
}
}