ffmpeg书籍推荐: https://www.xianwaizhiyin.net/?p=51
//编码器参数设置 //sps/pps enc_ctx->profile = FF_PROFILE_H264_HIGH_444; enc_ctx->level = 50; //表示LEVEL是5.0 enc_ctx->width = 640; enc_ctx->height = 480; enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P; enc_ctx->gop_size = 250; enc_ctx->bit_rate = 600000;//600kbps enc_ctx->time_base = (AVRational){ 1, 25}; enc_ctx->framerate = (AVRational){ 25, 1};//帧率 if(octx->oformat->flags & AVFMT_GLOBALHEADER) { printf("set video GLOBAL_HEADER "); enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; }//这octx是输出上下文,有些封装格式希望pps,sps和关键帧分离。设置AV_CODEC_FLAG_GLOBAL_HEADER 代表不会在每个关键帧前加入pps和sps了。会将pps和sps写入到extradata字节当中,当播放端解码器解码时, 从extradata中读取pps和sps然后加入到每个关键帧中。不同的封装格式要求不同,这个if代码块检测你设置的封装格式如"flv"是否需要设置分离。 //解释一下pps和sps,它们对解码至关重要,如果找不到他们,那么解码就会 失败,因为它们存储的是编码器设置的参数,比如视频的heigth,width等,音频的采样率,通道数等。详见另一篇文章:[h264中的pps和sps](https://blog..net/weixin_43466192/article/details/121465618) enc_ctx->keyint_min = 25;//option 由于gop过大,当运动变化过大时,允许自动多插入一个i帧,但两个i帧相差不能小于25帧; enc_ctx->max_b_frames = 3;//option连续的B帧的数量,一般设置不超过三帧,这里设置三帧 enc_ctx->has_b_frames = 1;//option启动B帧 enc_ctx->refs = 3;//option参考帧的数量,解码器的缓冲区中可以存放的参考帧的数量。 option的选项如果不设置的话会使用默认值,会根据其他设置的值自动设置,这两个也是option选项。
两个预设值preset,tune 因为x264参数众多,且各个参数配合紧密,x264编码器专门提供了预设值,预设值的设置相当于模式的选择,设定一个预设值,代表着使用这个模式,那么这么模式会有默认的很多参数设置。后面再手动设置的参数会覆盖模式里对应的参数。因此这两个值要在其他值之前设置,除此之外tune要在preset后。 preset的值从高到低有:
ultrafast、superfast、veryfast、faster、fast、medium(默认值)、slow、slower、veryslow、placebo
注意:编码很考验cpu性能,提升编码速度能直接减少对cpu的消耗,同时还能显著减少延迟,但会牺牲画面质量。 tune的值有:
animation: 动画 grain: 需要保留大量的grain时用; stillimage: 静态图像编码时使用; psnr:为提高psnr做了优化的参数; ssim: 为提高ssim做了优化的参数; fastdecode: 可以快速解码的参数; zerolatency:零延迟,用在需要非常低的延迟的情况下,比如电视电话会议的编码。能明显减少延时,但牺牲画面质量。
下面这个网站会有更详细的介绍以上参数,并给出x264未设置options参数时,默认是多少。
http://www.chaneru.com/Roku/HLS/X264_Settings.htm
下面这个网站会介绍这些参数在ffmpeg命令行中对应的名字是什么。
https://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
附录: x264源码中base.c文件中
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 ", preset ); return -1; } return 0; }
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 ", preset ); return -1; } return 0; }
参考:https://blog..net/NB_vol_1/article/details/78363559?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163600570616780264056029%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163600570616780264056029&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-5-78363559.pc_search_result_cache&utm_term=preset%2Ctune&spm=1018.2226.3001.4187
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/290196.html