FFmpeg进阶-h264编码器性能优化


在进行rtmp推流的时候发现h264编码器特别耗CPU机器有点扛不住。这里稍微研究了一下h264调参,通过调节参数来控制编码的性能损耗。

编码速度preset

preset的参数主要调节编码速度和质量的平衡, 里面预设了一系列的编码速度,包括:ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo,从前到后编码速度逐渐降低。更慢的编码速度提供更好的压缩质量。也就是说在固定码率的时候, 越慢的压缩速度压缩后的图像质量越好; 在保持画质不变的情况下,越慢的压缩速度码流越小。

总的来说:编码速度越快,压缩率越低,相同码流下的图片质量越低。通过降低编码速度,可以提高压缩率,单位码流下的图片质量越高。

av_opt_set(codec_ctx_->priv_data, "preset", "ultrafast", 0);

视频类型tune

tune的参数主要配合视频类型和视觉优化的参数。如果视频的内容符合其中一个可用的调整值又或者有其中需要,则可以使用此选项,否则建议不使用
(如tune grain是为高比特率的编码而设计的),tune值包括:

animation(动画)  
grain(需要保留大量的grain时用)  
stillimage(静态图像编码时使用)
psnr(为提高psnr做了优化的参数)
ssim(为提高ssim做了优化的参数)
fastdecode(可以快速解码的参数)
zerolatency(零延迟,用在需要非常低的延迟的情况下,比如电视电话会议的编码)
av_opt_set(CodecCtx->priv_data, "tune", "zerolatency", 0);

多线程控制thread

可以通过控制线程数量来控制CPU的损耗,但是控制线程数量会影响编码速度,配置的时候要考虑机器的性能。

CodecCtx->thread_count = 2;

控制QP值

默认qmin=0,qmax=51,QP越小、图像质量越好,但对性能损耗越大,通过调大对应的QP值,可以降低性能损耗。

videoCodecCtx->qmin = 10;//最小的量化因子。取值范围1-51。建议在10-30之间。
videoCodecCtx->qmax = 51;//最大的量化因子。取值范围1-51。建议在10-30之间。

控制gop_size

MPEG编码将画面(即帧)分为I、P、B三种,I是内部编码帧,P是前向预测帧,B是双向内插帧。简单地讲,I帧是一幅完整的画面,而P帧和B帧记录的是相对于I帧的变化。没有I帧,P帧和B帧就无法解码,这就是MPEG格式难以精确剪辑的原因,也是我们之所以要微调头和尾的原因。

一般来说,I帧的压缩率是7(与JPG差不多),P是20,B可以达到50,可见使用B帧能节省大量的空间,节省出来的空间可以哦用来更多的保存I帧,这样就能在相同的码率下提供更好的画质。

GOP(Group of Pictures)代表两个I帧之间的帧数量,一个GOP中容量最大的就是I帧,所以相对来讲,gop_size设置的越大,整个画面就会越好,但是在解码端必须从接收接收到一个I帧的第一个I帧开始I才可以正确解码出原始图像,否者无法正常解码。所以我们要根据不同的业务场景,适当的设置gop_size的大小,已得到更高质量的视频。

 videoCodecCtx->gop_size = 25;

控制B帧数量

B帧为视频图片空间的前后预测帧, B帧相对于I、P帧来说,压缩率比较大,也就是说相同码率的情况下,越多B帧的视频越清晰,现在很多打视频网站的高清视频,就是采用多编码B帧去提高清晰度,但同时对于编解码的复杂度比较高,比较消耗性能与时间。

videoCodecCtx->max_b_frames=3

降低CPU损耗的组合配置

//控制QP值
videoCodecCtx->qmin = 10;
videoCodecCtx->qmax = 51;

//控制gop_size和max_b_frame
videoCodecCtx->gop_size = 25;
videoCodecCtx->max_b_frames = 3;

if (videoCodecCtx->codec_id == AV_CODEC_ID_H264) 
{
    
    
        av_opt_set(videoCodecCtx->priv_data, "preset", "slow", 0);
        //设置零延迟(本地摄像头视频流保存如果不设置则播放的时候会越来越模糊)
        av_opt_set(videoCodecCtx->priv_data, "tune", "zerolatency", 0);
} 
else if (videoCodecCtx->codec_id == AV_CODEC_ID_HEVC) 
{
    
    
        av_opt_set(videoCodecCtx->priv_data, "x265-params", "qp=20", 0);
        av_opt_set(videoCodecCtx->priv_data, "preset", "ultrafast", 0);
        av_opt_set(videoCodecCtx->priv_data, "tune", "zero-latency", 0);
}

猜你喜欢

转载自blog.csdn.net/yang1fei2/article/details/129764153