X264的ABR、CBR码率控制

看了一下X264的码控相关,参考了一些大佬的博客,简单的做一些记录。

1.什么是码控

一张图像在经过编码后生成的文件大小主要与三个因素有关:

  1. 图像本身的内容复杂度;
  2. 与参考图像的相似程度(这里跟帧间编码有关,比较相似的话我们需要编码的数据就很少);
  3. 编码的量化程度;

简单来说图像越复杂,与参考帧的相似程度越小,编码量化程度越小,编码后生成的码流就越大;

1和2都由原始视频源决定了的,编码器内部改变不了,似乎编码器唯一能做的只有通过控制量化程度来控制编码码率了。

个人理解量化程度就是QP值,一个宏块,QP设置的越大,咱们丢弃的数据就越多,码流文件也就越小。所以简单理解,码控就是去设置每个块的QP值,让整体编码达到我们想要的结果。

2.码控模式

X264有三种码控模式

1.CQP(Constant Quantitative Parameters), 固定QP,直接整帧都用相同的QP值。

2.CRF (Constant Rate Factor),固定码率因子,更注重质量,x264默认的码控方式,CRF会动态的调整每帧的QP,对比CQP在同等码率下CRF能提供更高的编码质量。

3.ABR,平均编码码率,牺牲一定的编码质量来提供比CRF更稳定的码率控制,让我们最终得到的平均码率达到预设的值。

3.ABR帧级码控

X264的ABR模式中在真正的“预测+变换”编码之前,会结合当前图像的复杂度(lookahead)、目标码率、实际码率情况、码控方式等因素,计算出一个帧级QP,表示当前图像量化的基准值(实际量化用到的QP是宏块QP),QP越大,量化程度越大,图像质量就越低。函数调用:

x264_ratecontrol_start()   rate_estimate_qscale()    get_qscale()

通过三个函数获得当前帧的帧级QP

编码结束后调用x264_ratecontrol_end()再调控下一帧的码控(这样才能整体控制)

get_qscale()可以概括为两个公式:

q = pow( rce->blurred_complexity, 1 - rcc->qcompress );   q /= rate_factor;

其中blurred_complexity表示图像的模糊复杂度,rate_factor是参数3即码率因子,q为qscale可见q的值与blurred_complexity、rate_factor相关,且blurred_complexity越大q越大,rate_factor越大q越小。

4.CBR与VBV

CBR模式是在ABR模式的基础上加上VBV控制,因为ABR还是会有些波动,不能完全的控制码率,CBR就是为了更好的控制码率加上了VBV限制。

VBV全称Video Buffer Verifier(视频缓冲区校验器)。 可以将VBV当做一个容量受限的管道,有一个上限容量值下限容量值,在经过此管道的调节之后能限制编码码率在上限容量值和下限容量值之前。(其实原理也就是通过两条线来简单的调节QP值)

每编码一帧后都会往水池里面注入一部分水,同时也会流出一部分水。注入的水量为单帧的期望比特数,流出的水量为实际的编码比特数。如果注水量大于出水量即实际编码码率低于目标码率,那么水池的水会持续上涨,直至向上溢出(称之为VBV上溢出overflow);如果注水量小于出水量即实际编码码率高于目标码率,那么水池的水会持续下降,直至水流光(称之为VBV下溢出underflow);

为了保证实际码率等于目标码率,我们尽量要保证VBV不出现上溢或者下溢,因此给水池设置两条警戒线,上溢警戒线和下溢警戒线。当水池中的水量超过上溢警戒线时为了预防出现上溢,需要适当降低当前帧的QP,让水量在编码后能够稍微下降;反之如果水量低于下溢警戒线时为了预防出现下溢,需要适当增大当前帧的QP,让水量在编码后能够稍微上升。

通过clip_qscale()函数来实现VBV,编码一帧后更新使用update_vbv()函数

5.块级码控

得到了帧级的QP,还会对每一个宏块来微调QP,毕竟宏块的复杂度不一样。比较复杂的块用小点的QP值,比较简单的块用大点的QP值(例如系数全0的块量化拉满也不会有什么损失),这样质量会好很多。块级码控看了一下,是在analysis.c文件里的分析阶段了,可以算是一个率失真问题了,比较复杂,以后再好好看看。这里附上大佬的流程图:

X264学习3-码率控制-CSDN博客

6.XAVC与AVC Intra

 参考了大佬的博客:FFmpeg XAVC实现/XAVC编码标准调研 (1)-CSDN博客

简单理解感觉这个XAVC就是在X264上设置了一些参数来做到完全的固定码率CBR模式(做到每一帧的大小都一致),在最新版本的X264和ffmpeg上实验了一下,发现已经支持Class 300/480了。

 

基本上都是针对10bit的422格式编码不同的Class代表了不同的参数集设置,可以直接固定编码后每帧的大小,根据设置的帧率也可以直接得到最终的码率大小。

例如我测试了一些码率25FPS的Class 300 得到的264码流文件每帧的大小都是1250304bytes,最终码率是250Mbps左右.

具体参数,加上那两个avcintra就可以了,如下:

./x264 --input-res 3840x2160 --output 输出文件.264 --avcintra-class 300 --avcintra-flavor sony --input-depth 10 --output-depth 10  --output-csp i422 --input-csp i422 输入文件.yuv

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值