音视频编解码 -- 编码参数 CRF
文章图片
之前多多少少接触过一些编解码参数,CRF 参数也用过,但是最近在和朋友们聊天时,说到使用 FFMPEG 过程中碰到 CRF 参数,以及具体作用流程,这个之前一直没有跟踪过,也没有详细记录过,所以吊起了自己的好奇心,于是决定搞清楚一下,便开始了这次 CRF 的神奇之旅。CRF 简介:
恒定速率因子(CRF,Constant Rate Factor)是一种编码模式,可以向上或向下调整文件数据速率以达到选定的质量级别,而不是特定的数据速率。
如果要保持最佳质量,而又不怎么担心文件大小,这时候就可以使用 CRF 速率控制模式。 这是大多数情况下建议的速率控制模式。当输出文件的大小不太重要时,此方法允许编码器尝试为整个文件实现期望目标视频质量的文件输出,即所谓的一次编码便可在预期视频质量下获得最大的视频压缩效率。CRF 模式主要原理是在编码过程中通过动态调整每帧视频的 QP 值,以便可以获得保持所需视频质量水平比特率。
但是 CRF 缺点是不能告知编码器期望获得特定大小的文件或不超过特定大小或比特率。同时需要注意的是采用 CRF 时不建议直接用来编码视频以进行流媒体传输。
通常建议一般使用两种速率控制模式:恒定速率因子(CRF)或 2-pass ABR。 速率控制决定每个帧将使用多少位。 这将确定文件大小以及质量分配方式。CRF 实操演示
通过 FFMPEG 二进制文件尝试用参数 CRF 进行压缩,如下图所示:
FFMPEG 采用 CRF 分别为 18、24 进行压缩,以及和源文件的比较。
ffmpeg -i test.mp4 -c:v libx264 -crf 18 test18.mp4
文章图片
实际转码中
文章图片
转码结束后,会显示具体的编码相关信息,包括 ref,crf 值,qp 量化步长等,以及 I 帧、P 帧、B 帧所占比重。还包含了音频相关信息如下图:
文章图片
用命令 ffmpeg -i test.mp4 -c:v libx264 -crf 24 test24.mp4,进行 CRF=24 的转码,转码结果如下图所示:
文章图片
转码后分别对三个文件进行参数查看,并形成对比,其结果如下图所示:
文章图片
【音视频编解码 -- 编码参数 CRF】上述参数只能大概了解三个视频基本信息,之后通过 Elecard eye 专业工具查看该变化产生原因的直观图,三个文件码流分析结果:
文章图片
三个文件对比情况总结如下:
文章图片
可以看出:CRF 参数的使用,I 帧数量急剧减少、同时引入 B 帧;熵编码采用了 CABAC 方式,这样压缩率就提升很多,文件大小变小。同时随着 CRF 值变大,P 帧和 B 帧压缩率也变大,文件更小。CRF 代码走读
虽然之前走读过 FFMPEG 代码,但是具体 CRF 参数的品读还没完全注意到过。为了不是一知半解的明白该问题,还是强迫自己走一遍代码,增强印象,深刻认识,也为关心该参数的小伙伴铺垫一下基础。*?CRF 定义
首先在 X264 中可以看到该值的定义:
typedef struct X264Context {
AVClass*class;
x264_param_tparams;
......float crf;
......
}
在 AVOption 具体定义如下:
static const AVOption options[] = {
{ "preset","Set the encoding preset (cf. x264 --fullhelp)",OFFSET(preset),AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE},
{ "tune","Tune the encoding params (cf. x264 --fullhelp)",OFFSET(tune),AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE},
{ "profile","Set profile restrictions (cf. x264 --fullhelp) ", OFFSET(profile),AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE},
......
{"x264opts", "x264 options", OFFSET(x264opts), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
{ "crf","Select the quality for constant quality mode",OFFSET(crf),AV_OPT_TYPE_FLOAT,{.dbl = -1 }, -1, FLT_MAX, VE },
{ "crf_max","In CRF mode, prevents VBV from lowering quality beyond this point.",OFFSET(crf_max), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE },
......
}
CRF 仍然属于 Rate control 的一中,所以可以看到其 RC 相关定义如下:
#define X264_RC_CQP0
#define X264_RC_CRF1
#define X264_RC_ABR2
?FFMPEG 接口梳理
文章图片
涉及到 FFMPEG 代码走读的部分太多了,在此只是简述 CRF 对应的部分,其他编解码流程大家可以根据网上其他大神的代码走读流程完成即可。此篇文章默认大家有足够基础:X264 的编解码入口符合 FFMPEG 接口定义,对应关系如下图所示:
此处借用雷神的一张图说明:(https://blog.csdn.net/leixiaohua1020/article/details/45960409)
文章图片
- X264_init()
文章图片
在 X264_init 的最后,进行 X264Codec 的 OPEN 动作,以及编码全局 header 的动作。
文章图片
- x264_param_default
同时注意,观察到在 x264_param_default 默认参数中 B 帧是再次设置并置位的,而且 cabac 默认开启。所以如果用 FFMPEG bin 文件进行转码出来的文件中 cabac 是默认开启的,这也是工具端查看时会出现 CABAC 以及增加 B 帧的根本原因了。
文章图片
- x264_encoder_open
文章图片
之后在 x264_encoder_open 中主要用于打开编码器,其中校验、初始化了 libx264 编码所需要的各种变量,并完成 sps、pps、qm 初始化。
- validate_parameters
文章图片
其他流程部分可以参考其他大神的文章,再次不再累述。(雷神的解析非常详尽了,敬请膜拜即可x264源代码简单分析:编码器主干部分-1_雷霄骅(leixiaohua1020)的专栏-CSDN博客)
- x264_ratecontrol_new
文章图片
x264_ratecontrol_new,主要设置码率控制的核心参数,需要对 x264 码率控制比较了解才能真正明白,否则会容易看晕。
x264_ratecontrol_new 函数中依据传入参数是 CRF 模式,以及 b_stat_read 默认值为 0 即可将 b_abr 参数的置位为 1,同时 b_2pass 置位为 0,也就是说 CRF 模式在 rate_control 中按照 abr、非 2-pass 进行处理的。
文章图片
在 x264_ratecontrol_init_reconfigurable 函数中会进行 VBV 参数初始化,以及 CRF 相关参数 base_cplx、rate_factor_constant 的更新。
文章图片
同时 x264_ratecontrol_init_reconfigurable 中设置被调用时,传入 b_init=1 的参数,这时 CRF 置位了 VBV 模式,为后续的 rate_control 做了铺垫。
文章图片
- X264_frame
文章图片
- reconfig_encoder
- x264_encoder_encode
文章图片
x264_encoder_encode 是真正编码的开始,在 x264_encoder_encode 这个函数里面将一帧完整 YUV 图像编码成 H264 视频流,这个过程可以参考雷神的文章,解析非常好,https://blog.csdn.net/leixiao...
文章图片
这边关心的是 CRF 中涉及到的部分内容,在 x264_encoder_encode 中和码率控制相关的内容主要是一下接口:
x264_thread_sync_ratecontrol():
x264_ratecontrol_zone_init():
x264_ratecontrol_start():开启码率控制,针对每一帧进行码率控制。在 x264_ratecontrol_start 中会根据码率控制模式的不同,选择不同的 qp 进行压缩。之前分析可知,CRF 是属于 abr 模式,同时增加了 B 帧,所以导致每帧图像的 qp 都是不同的,这样压缩后相同质量的条件下编码后文件大小就不能确定了。
文章图片
x264_ratecontrol_qp():
码率控制是一个大块内容,设计的算法也比较复杂,该文只关注了如何将 crf 模式转换到 vbv 模式,以及对影响编码的部分参数,整个过程下一篇文章我们再进行分析和跟踪。
以上是个人的一些看法,可能有不正确的地方,欢迎大家一起讨论学习。
如果该文章对您有帮忙,欢迎点赞,收藏,转发、关注,在下持续更新音视频相关内容。
推荐阅读
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 二十年后的家乡
- 请叫我冉责编
- python青少年编程比赛_第十一届蓝桥杯大赛青少年创意编程组比赛细则
- 戏文的女生绝不认输
- 编写字典程序
- 图文小编《杨浦、成毅》为你发布!无价之宝随意摆放的公园
- 涵养字外功
- HTML基础--基本概念--跟着李南江学编程
- 2018-06-13金句系列7(金句结构-改编古现代诗词)