码率控制技术RC(Rate Control)是视频编码中一个非常重要的技术模块。不同的应用场景对视频编码的码率控制有不同的需求,离线编码通常采用可变码率(VBR),实时视频系统通常采用恒定码率(CBR)。本篇技术干货将深度剖析视频编码中的码率控制算法,分析其背后的数学模型及理论,希望能帮助大家更好地理解视频通信中的码率控制算法。
码率控制主要指编码过程中,通过调整QP来控制视频码率的行为。在不同的使用场景下,用户对视频的码率大小、稳定性会有不同的要求,因此码率控制的类型也多种多样。比如观看离线视频文件时,往往不需要此视频具备恒定的码率,因为整个文件都在本地,只要磁盘IO和设备解码能力都合格,基本就不会发生卡顿问题(这里不讨论硬件解码的buffer限制以及内网NAS的带宽限制)。所以压制这类视频时会倾向于保证质量而非码率平稳性。画面纹理比较复杂或运动剧烈的场景,码率给高一些,以保证画面质量;而画面简单的场景,码率就给低一些,节省硬盘空间。这种码率控制策略我们统称为可变码率(VBR)。
但在观看在线视频时,由于用户带宽是恒定的,能够缓存的数据量也有限,所以需要对码率做一些限制。否则一些瞬时码率过高的片段可能会引起卡顿。此外还有一点,由于CDN是按流量计费的,视频网站如果使用VBR编码视频会使带宽成本变得不可控。所以压制这类视频时,会倾向于选择恒定码率(CBR)。
不同场景下的码率控制需求
本文接下来的讨论内容主要集中在CBR,但其中的一些改良算法其实也可以用在VBR。
首先看一下码率控制的大体流程:
码率控制基本流程
可以看到整个流程都是围绕着RQ模型进行。这里的RQ模型指的是码率与QP的推导关系,可以说是码率控制算法的根基。它经历过多次改进,精度也在不断提高,这里举几个例子:
一阶模型:
最简单的模型,在x264、OpenH264等编码器中被广泛使用。式中Q指Q-step,即量化步长。R指Rate,表示码率。Comp表示图像复杂度,一般可以使用MAD(Mean Absolute Difference)来计算。α是一个系数,需要我们在编码过程中不断根据实际输出码率来更新。
二阶模型:
一阶模型的进阶版,JM中有使用。
R-λ模型:
在HM(HEVC Test Model)中被引入的模型[1],显著提升了码率控制精度。式中的λ是率失真优化中使用的拉格朗日乘子,放在下节作为拓展内容介绍。而f(λ)则是通过实验拟合得到的。比如HM中就是:
上面提到图像复杂度可以使用MAD来计算,但是当前帧的MAD值只能在编码后才能得到。这与QP需要在编码前确定这一点相矛盾。另外,在模型确定后,我们还需要确定模型的更新方式及速率。通过提高模型系数的更新速率,可以使编码器的输出码率更加平稳;但相对的,画面质量可能由于QP变化幅度过大而下降。
针对这些问题,不同的编码器选择了不同的方案:
在JM中,使用了一个一阶线性模型根据过去帧的MAD来预测当前帧的对应值。而RQ模型的系数则直接通过当前帧的编码结果来反向计算得到。
在OpenH264和x264中,则放弃了MAD的计算,转而合并了
,把它作为一个整体来计算。
对于R-λ模型,其提出者也已经设计了对应的更新公式和经验值供我们参考[1]。
模型更新这部分内容,更多是工程实践上的考量,需要根据经验和测试情况不断调整。
拓展:λ是什么
R-λ模型中的λ是率失真优化中的一个系数。这里的率失真优化,指的是编码过程中的一个优化步骤。要详细解释它,我们需要先了解率失真理论。它起源于香农的研究[2],大致可以概括为:在给定的信源分布以及可接受的失真度D下,求信息数据量R的理论最小值。显然,可接受的D越大,其对应的R也就越小。这个R-D的关系边界,我们称为率失真曲线,即下图中的红线[3]。旁边的绿线则是编码器实际工作区域的边界,它和理论值存在一定差距。
R-D曲线
视频编码标准提供了大量的工具集,或者说编码模式,它们就相当于上图的绿点。在它们之中选择一个恰当的来使用是一件比较复杂的事情。注意到这个问题本质是一个数学最优化问题,所以可以利用拉格朗日乘数法的离散形式来解决它。简单地说,引入一个拉格朗日乘子λ,构建代价函数,再去求取代价函数的最小值即可:
通俗地理解,λ就相当于失真与码率的权值。给定了λ,也就给定了一个判定模式好坏的标准。如下图所示,求代价函数最小值,相当于求斜率为λ的直线与R-D曲线的切点。在编码过程中,不论是模式选择,还是运动矢量的比较,都会利用到这个方法。
拉格朗日乘子R-D曲线斜率R-λ模型的提出者首先根据实验数据提出R-D曲线可以近似拟合为一条双曲线,再根据λ是R-D曲线斜率这一点,求得了R-λ模型:
上文介绍的内容,属于码率控制核心算法,其目的仅为控制输出码率,使其尽可能地接近目标。但在实际应用中,我们并不需要这么严格地执行。在输出码率基本满足要求的前提下,我们依然有一定的调整空间来改善画面质量。下文将介绍几种这方面的算法。
Adaptive-Quantization
由于人眼对不同类型的画面的细节感知程度是不同的,所以给不同画面内容给予相同的权重来分配码率实际上是比较浪费的。比如高速运动的物体就可以相对静态物体模糊一点。在这方面做文章的算法一般归类为基于感知的码率控制算法。而其中一类比较简单且使用广泛的算法,叫做Adaptive Quantization(AQ)。简单来说,它利用图像的方差或其他类似特征来衡量当前宏块的复杂度,对于内容较复杂的宏块,算法认为可以适当舍弃其细节,所以增大其QP;而简单的宏块则反之。经过这种调整,视频的主观质量能得到大幅提升。如今很多编码器都实现了AQ,比如x264的实现如下所示。计算得到的qp_adj即QP偏移量,会叠加到R-Q模型计算出来的QP上:
// x264的AQ核心实现。ac_energy_mb计算宏块像素值方差。strength代表AQ强度,由用户配置。 uint32_t energy = ac_energy_mb( h, mb_x, mb_y, frame ); qp_adj = strength * (x264_log2( X264_MAX(energy, 1) ) - (14.427f + 2*(BIT_DEPTH-8)));
利用人眼感知能力的码率控制算法还有很多,比如基于最小可觉察误差(JND, Just Noticeable Distortion)的,或者基于机器学习的,这里不再展开。值得一提的是,由于是针对主观视觉体验的优化算法,通过PSNR等客观手段测试往往无法体现这些算法的优势。
MB-Tree
MB-Tree是由x264的开发者提出的算法,它的基本思想是:由于视频数据在编码时存在依赖关系,被参考的数据的失真程度直接影响到后续的预测精度,所以根据依赖关系给予不同画面不同码率权重可以从整体上提升画面质量。
MB-Tree的实现依赖于x264内部的lookahead结构。所谓的lookahead,是一种预编码模块。它会使用经过下采样的低分辨率图像预先对视频进行一轮编码(这种预编码只进行到SATD的计算),并缓存大量有用的信息供后续正式编码使用。我们在使用x264编码视频时,经常会看到-lookahead参数,它表示预编码的帧数,增加这个值利于提升编码质量,但是会增加编码时延。
有了lookahead缓存下来的信息,我们就可以从最后一帧开始,逐帧回溯每个MB的依赖性,或者说重要性,再根据这个重要性计算QP的偏移量。MB-Tree的原理非常有特色,如果读者对细节感兴趣,推荐阅读x264开发者的文章[4]。
本文概述了码率控制算法的基本思想和原理,而实际的代码实现,往往是和应用场景高度相关的。开发者不仅需要关注编码器本身,还要结合网络QoS和视频特征等因素综合考量。并且,优秀的码率控制模块也不太可能是一蹴而就的。不论是画面质量与码率平稳性的取舍,还是参数默认值的配置,都需要通过测试来不断调优。
参考文献
[1] JCTVC-K0103
[2] C.E. Shannon, Coding theorems for a discrete source with a fidelity criterion, in IRENational Conventwn Record, Part4, pp. 142-163, 1959.
[3] A. Ortega; K. Ramchandran, Rate-distortion methods for image and video compression, IEEE Signal Processing Magazine, Volume: 15, Issue: 6, Nov 1998.
[4] Garrett-Glaser J. A novel macroblock-tree algorithm for high-performance optimization of dependent video coding in H.264/AVC[J]. Tech. Rep., 2009.