//编码器参数设置 //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\n"); 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.csdn.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:零延迟,用在需要非常低的延迟的情况下,比如电视电话会议的编码。能明显减少延时,但牺牲画面质量。
turne主要是关注画质和视觉感受,如果视频有对应的选项和需求可以使用,否则建议不使用如tune grain是为高比特率的编码而设计的。这两个预设值在x264中的源码在文末尾有贴上。
可以通过x264 --fullhelp查看preset,profile,tune这些预设分别启用了不同的编码工具,启用不同的编码工具,会改变编码效率,因此如果目标码率设置足够的值,则不会降低画质。
补充:
编码器帧相关参数 :
no-deblock/deblock //去块化 解码后播放发现块比较多,像马赛克,是因为宏块预测,可以设置deblock用滤波器进行平滑处理。(no-deblock不适用滤波器)
no-cabac/cabac //不使用/使用熵编码 使用熵编码后压缩比比较高。
流控:
Qp关注量化器,与bitrate/crf互斥
bitrate,关注码流,间接控制质量
crf,关注质量,默认是23,数值越低质量越好
Partitions p8x8,b8x8,i8x8,i4x4 //i,b,p帧的宏块大小
下面这个网站会有更详细的介绍以上参数,并给出x264未设置options参数时,默认是多少。
http://www.chaneru.com/Roku/HLS/X264_Settings.htm
x264的各个参数
下面这个网站会介绍这些参数在ffmpeg命令行中对应的名字是什么。
https://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
哎呦喂ヾ(✿゚▽゚)ノ~路长馆小,雪轻帘薄,酒热乎,这位爷~您ヾ(✿゚▽゚)ノ~ 里面坐~
本公众号专注分享C++,ffmpeg,opencv等相关音视频知识
webrtc,udp,tcp,rtsp,rtmp,srt/nginx+rtmp等流媒体协议和服务器
同时也会有大厂音视频技术专家不定期直播分享…
国人开发流媒体srs服务器,及yangrtc(国人版的webrtc)协议新动向
偶尔分享下程序员梦呓碎碎念(๑•॒̀ ູ॒•́๑)啦啦啦
目前刚刚开通,接受读者的优质投稿…
鉴于国内音视频圈子小,起步晚,以致分享少,门槛高,特开通分享,一起扇动这阵风吧!
附录:
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'\n", 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'\n", preset ); return -1; } return 0; }