x264 的码率控制是如何实现的 ?
本文介绍 x264 码率控制算法的数学原理,和基本框架。
1.理论假设
有助于往下阅读,可以暂时跳过。
设变量: qscale = 拉格朗日常数 lamda = 0.85 * 2^((QP-12)/6) ≈ 量化步长 Qstep = 2^((QP-4)/6)
设变量: 复杂度 complexity ≈ 运动补偿后残差的satd
二次编码中: complexity ≈ 第一趟编码的实际比特数
设变量: bits = 实际编码后比特数
假设1: qscale不变, bit 和 复杂度 成正比
假设2: 复杂度不变, bit 和 qscale 成反比
也就是说: complexity ∝ qscale * bits
或者: bits 正比于 complexity / qscale
x264 的码率控制的基础是基于这个假设。
虽然它不是很精确,但是工程上足够了。
2. 基本公式
有助于往下阅读,可以跳过
qscale = 0.85 * 2^((QP-12)/6) ----- (1)
QP = 12 + 6 * log2(qscale/0.85) ----- (2)
Qstep = 2^((QP-4)/6) ----- (3)
QP = 6 * log2(Qstep) + 4 ----- (4)
3. 基础算法–帧间级
x264 码率控制分为帧间级 和 帧内级,这里先介绍帧间级码率控制算法。
帧级别码率控制需要为每一帧分配QP, 也就是分配每一帧的大小。
每一帧的大小主要取决于两个变量: 本帧的复杂度,码率预算。
复杂度更高的帧,需要更多的比特。但给多少码率,和复杂度不是正比的。
下面是x264模块控制模块的简化框图。包括了帧间级码率控制,和帧内级(宏块级)码率控制。

x264 中, 首先根据每帧的复杂度,在帧与帧之间分配码率比例。然后根据码率预算,将每帧缩放到合适大小。这个缩放系数称为 ratefactor 。
然后 qscale = complexity / ratefactor
所谓 crf (constant ratefactor) 模式,就是固定ratefactor 参数, 码率分配由复杂度决定。(这里暂不考虑宏块级码率控制)
ABR 和 CBR 模式,都是通过实时调整 ratefactor 实现的。
qscale 最后会再经过 vbv 模块调整,确保不会发生缓冲区下溢。vbv模块也是实现CBR模式的关键模块。
本文主要关注帧间级,它的主要框架如下: