x264的preset和tune
preset
preset是x264中最重要的选项,它影响编码性能和编码速度,它由不是一个单一的参数,而是由一组参数构成。preset分为下面几种类型:
static const char * const x264_preset_names[] = {
"ultrafast", "superfast", "veryfast",
"faster", "fast", "medium", "slow",
"slower", "veryslow", "placebo", 0
};
从左到右,编码速度越来越慢,编码质量越来越好,其中placebo不建议使用,没有太大意义,对视频的质量要求很严格时才使用veryslow,ultrafast产生的视频可能会非常大,使用前也需要仔细思考
x264设置preset
static int x264_param_apply_preset( x264_param_t *param, const char *preset )
{
char *end;
int i = strtol( preset, &end, 10 );
if( *end == 0 && i >= 0 && i < sizeof(x264_preset_names)/sizeof(*x264_preset_names)-1 )
preset = x264_preset_names[i];
/*
* 下面的这些参数设置会对编码质量和编码速度造成极大影响,因此,优化时首先考虑优化下面的参数
*/
/* 极快(最快)
*/
if( !strcasecmp( preset, "ultrafast" ) )
{
/* 参考帧数量设置为1
*/
param->i_frame_reference = 1;
/* 场景切换设置阈值
*/
param->i_scenecut_threshold = 0;
/* 不进行去方块滤波
*/
param->b_deblocking_filter = 0;
/* 不使用cabac
*/
param->b_cabac = 0;
/* 没有B帧
*/
param->i_bframe = 0;
/* 设置intra划分的partition,这里应该是不进行划分,只使用16x16
*/
param->analyse.intra = 0;
/* 设置inter划分的partition,这里应该是不进行划分,只使用16x16
*/
param->analyse.inter = 0;
/* 不使用8x8的的DCT变换
*/
param->analyse.b_transform_8x8 = 0;
/* 运动估计:DIA
*/
param->analyse.i_me_method = X264_ME_DIA;
/* 亚像素运动估计精度:0,表示只进行整像素运动估计
*/
param->analyse.i_subpel_refine = 0;
/* 关闭自适应量化
*/
param->rc.i_aq_mode = 0;
/* 禁止每个宏块的分区拥有自己的参考编号
*/
param->analyse.b_mixed_references = 0;
/* 不使用trellis优化
*/
param->analyse.i_trellis = 0;
/* 自适应B帧判断的概率(从-100到100)
*/
param->i_bframe_adaptive = X264_B_ADAPT_NONE;
/* 不使用mbtree
*/
param->rc.b_mb_tree = 0;
/* 权重预测中,P帧的权值
*/
param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
/* 显式的B帧权重预测
*/
param->analyse.b_weighted_bipred = 0;
/* mbtree前向预测的帧的数量
*/
param->rc.i_lookahead = 0;
}
/* 超级快
*/
else if( !strcasecmp( preset, "superfast" ) )
{
/* inter划分:4x4和8x8
*/
param->analyse.inter = X264_ANALYSE_I8x8|X264_ANALYSE_I4x4;
/* 运动估计:DIA
*/
param->analyse.i_me_method = X264_ME_DIA;
/* 亚像素运动估计精度
*/
param->analyse.i_subpel_refine = 1;
/* 参考帧数量:1
*/
param->i_frame_reference = 1;
/* 不允许每个宏块的分区有自己的参考编号
*/
param->analyse.b_mixed_references = 0;
/* 关闭trellis优化
*/
param->analyse.i_trellis = 0;
/* 关闭mbtree
*/
param->rc.b_mb_tree = 0;
/* P帧的权值
*/
param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
/* mbtree向前预测的帧数:0
*/
param->rc.i_lookahead = 0;
}
/* 非常快
*/
else if( !strcasecmp( preset, "veryfast" ) )
{
/* 亚像素运动估计精度
*/
param->analyse.i_subpel_refine = 2;
/* 参考帧数量:1
*/
param->i_frame_reference = 1;
/* 不允许每个宏块的分区有自己的参考编号
*/
param->analyse.b_mixed_references = 0;
/* 关闭trellis优化
*/
param->analyse.i_trellis = 0;
/* P帧的权值
*/
param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
/* mbtree向前预测的帧数:10
*/
param->rc.i_lookahead = 10;
}
/* 很快
*/
else if( !strcasecmp( preset, "faster" ) )
{
/* 不允许每个宏块的分区有自己的参考编号
*/
param->analyse.b_mixed_references = 0;
/* 参考帧数量:2
*/
param->i_frame_reference = 2;
/* 亚像素运动估计精度
*/
param->analyse.i_subpel_refine = 4;
/* P帧的权值
*/
param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
/* mbtree向前预测的帧数:20
*/
param->rc.i_lookahead = 20;
}
/* 快
*/
else if( !strcasecmp( preset, "fast" ) )
{
/* 参考帧数量:2
*/
param->i_frame_reference = 2;
/* 亚像素运动估计精度
*/
param->analyse.i_subpel_refine = 6;
/* P帧的权值
*/
param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
/* mbtree向前预测的帧数:30
*/
param->rc.i_lookahead = 30;
}
/* 正常:在速度与质量之间平衡
*/
else if( !strcasecmp( preset, "medium" ) )
{
// 使用默认的参数
/* Default is medium */
}
/* 慢
*/
else if( !strcasecmp( preset, "slow" ) )
{
param->analyse.i_subpel_refine = 8;
param->i_frame_reference = 5;
param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
param->analyse.i_trellis = 2;
param->rc.i_lookahead = 50;
}
/* 很慢
*/
else if( !strcasecmp( preset, "slower" ) )
{
param->analyse.i_me_method = X264_ME_UMH;
param->analyse.i_subpel_refine = 9;
param->i_frame_reference = 8;
param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
param->analyse.inter |= X264_ANALYSE_PSUB8x8;
param->analyse.i_trellis = 2;
param->rc.i_lookahead = 60;
}
/* 非常慢
*/
else if( !strcasecmp( preset, "veryslow" ) )
{
param->analyse.i_me_method = X264_ME_UMH;
param->analyse.i_subpel_refine = 10;
param->analyse.i_me_range = 24;
param->i_frame_reference = 16;
param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
param->analyse.inter |= X264_ANALYSE_PSUB8x8;
param->analyse.i_trellis = 2;
param->i_bframe = 8;
param->rc.i_lookahead = 60;
}
/* 极慢
*/
else if( !strcasecmp( preset, "placebo" ) )
{
param->analyse.i_me_method = X264_ME_TESA;
param->analyse.i_subpel_refine = 11;
param->analyse.i_me_range = 24;
param->i_frame_reference = 16;
param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
param->analyse.inter |= X264_ANALYSE_PSUB8x8;
param->analyse.b_fast_pskip = 0;
param->analyse.i_trellis = 2;
param->i_bframe = 16;
param->rc.i_lookahead = 60;
}
else
{
x264_log( NULL, X264_LOG_ERROR, "invalid preset '%s'\n", preset );
return -1;
}
return 0;
}
tune
tune是x264中重要性仅次于preset的选项,它是视觉优化的参数,tune可以理解为视频偏好(或者视频类型),tune不是一个单一的参数,而是由一组参数构成。tune分为下面几种类型:
static const char * const x264_tune_names[] = {
"film", "animation", "grain",
"stillimage", "psnr", "ssim",
"fastdecode", "zerolatency", 0 };
film:电影类型,对视频的质量非常严格时使用该选项
animation:动画片,压缩的视频是动画片时使用该选项
grain:颗粒物很重,该选项适用于颗粒感很重的视频
stillimage:静态图像,该选项主要用于静止画面比较多的视频
psnr:提高psnr,该选项编码出来的视频psnr比较高
ssim:提高ssim,该选项编码出来的视频ssim比较高
fastdecode:快速解码,该选项有利于快速解码
zerolatency:零延迟,该选项主要用于视频直播
x264设置tune
static int x264_param_apply_tune( x264_param_t *param, const char *tune )
{
char *tmp = x264_malloc( strlen( tune ) + 1 );
if( !tmp )
return -1;
tmp = strcpy( tmp, tune );
char *s = strtok( tmp, ",./-+" );
int psy_tuning_used = 0;
/* 下面的参数设置,主要影响去方块滤波的参数和量化参数
*/
while( s )
{
/* 电影,侧重于质量和细节
*/
if( !strncasecmp( s, "film", 4 ) )
{
if( psy_tuning_used++ ) goto psy_failure;
param->i_deblocking_filter_alphac0 = -1;
param->i_deblocking_filter_beta = -1;
param->analyse.f_psy_trellis = 0.15;
}
/* 动画
*/
else if( !strncasecmp( s, "animation", 9 ) )
{
if( psy_tuning_used++ ) goto psy_failure;
param->i_frame_reference = param->i_frame_reference > 1 ? param->i_frame_reference*2 : 1;
param->i_deblocking_filter_alphac0 = 1;
param->i_deblocking_filter_beta = 1;
param->analyse.f_psy_rd = 0.4;
param->rc.f_aq_strength = 0.6;
param->i_bframe += 2;
}
/* 纹理,侧重与细节
*/
else if( !strncasecmp( s, "grain", 5 ) )
{
if( psy_tuning_used++ ) goto psy_failure;
/* 去方块滤波的参数
*/
param->i_deblocking_filter_alphac0 = -2;
param->i_deblocking_filter_beta = -2;
/* Psy Trellis强度
*/
param->analyse.f_psy_trellis = 0.25;
/* P帧变换系数阈值
*/
param->analyse.b_dct_decimate = 0;
/* P帧和B帧之间的量化因子(QP)比值
*/
param->rc.f_pb_factor = 1.1;
/* I帧和P帧之间的量化因子(QP)比值
*/
param->rc.f_ip_factor = 1.1;
/* 自适应量化的强度,减少平趟和纹理区域的块效应和模糊度
*/
param->rc.f_aq_strength = 0.5;
/* 亮度量化中使用的盲区大小
*/
param->analyse.i_luma_deadzone[0] = 6;
param->analyse.i_luma_deadzone[1] = 6;
/* 量化曲线压缩参数,会影响mbtree的强度,0.0表示恒定比特率,1.0表示恒定QP
* 更高的值表示更弱的mbtree,qcomp=1.0时,mbtree=0
*/
param->rc.f_qcompress = 0.8;
}
/* 图像,侧重于静止图像
*/
else if( !strncasecmp( s, "stillimage", 10 ) )
{
if( psy_tuning_used++ ) goto psy_failure;
param->i_deblocking_filter_alphac0 = -3;
param->i_deblocking_filter_beta = -3;
param->analyse.f_psy_rd = 2.0;
param->analyse.f_psy_trellis = 0.7;
param->rc.f_aq_strength = 1.2;
}
/* psnr,侧重于使用psnr来判断画面质量
*/
else if( !strncasecmp( s, "psnr", 4 ) )
{
if( psy_tuning_used++ ) goto psy_failure;
param->rc.i_aq_mode = X264_AQ_NONE;
param->analyse.b_psy = 0;
}
/* ssim,侧重于使用ssim来判断画面质量
*/
else if( !strncasecmp( s, "ssim", 4 ) )
{
if( psy_tuning_used++ ) goto psy_failure;
param->rc.i_aq_mode = X264_AQ_AUTOVARIANCE;
param->analyse.b_psy = 0;
}
/* 快速解码
*/
else if( !strncasecmp( s, "fastdecode", 10 ) )
{
param->b_deblocking_filter = 0;
param->b_cabac = 0;
param->analyse.b_weighted_bipred = 0;
param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
}
/* 零延迟,适合流媒体
*/
else if( !strncasecmp( s, "zerolatency", 11 ) )
{
param->rc.i_lookahead = 0;
param->i_sync_lookahead = 0;
param->i_bframe = 0;
param->b_sliced_threads = 1;
param->b_vfr_input = 0;
param->rc.b_mb_tree = 0;
}
/* touhou,按照翻译是“东方”,可能是中国的武打片或者印度的歌舞片
*/
else if( !strncasecmp( s, "touhou", 6 ) )
{
if( psy_tuning_used++ ) goto psy_failure;
param->i_frame_reference = param->i_frame_reference > 1 ? param->i_frame_reference*2 : 1;
param->i_deblocking_filter_alphac0 = -1;
param->i_deblocking_filter_beta = -1;
param->analyse.f_psy_trellis = 0.2;
param->rc.f_aq_strength = 1.3;
if( param->analyse.inter & X264_ANALYSE_PSUB16x16 )
param->analyse.inter |= X264_ANALYSE_PSUB8x8;
}
else
{
x264_log( NULL, X264_LOG_ERROR, "invalid tune '%s'\n", s );
x264_free( tmp );
return -1;
}
if( 0 )
{
psy_failure:
x264_log( NULL, X264_LOG_WARNING, "only 1 psy tuning can be used: ignoring tune %s\n", s );
}
s = strtok( NULL, ",./-+" );
}
x264_free( tmp );
return 0;
}