作为成熟的编解码产品,libvpx VP9已经在工业界大规模使用超过5年。本文由谷歌Senior Staff Engineer韩敬宁在LiveVideoStackCon 2020 线上峰会的演讲内容整理而成,文中主要讨论Google最新的编码器优化工作使得VP9客观压缩性能提升超过10%,并且大幅提高了其在电影等视频内容下的主观压缩质量。
文 / 韩敬宁
整理 / LiveVideoStack
大家好,我是韩敬宁,来自WebM Codec团队。今天非常高兴有机会能向大家介绍一下我们近期的关于VP9编码器优化的工作。VP9是在2013年release,从2013年底开始逐渐被包括YouTube在内的多家video service provider采纳成为编码内核。从2013年到2016年前后,我们的团队一直在做的就是不断优化VP9编码器。优化的目标主要是:首先,提高其核心压缩性能也就是在PSNR和SSIM这些客观Metric条件下的编码。还有一个方向是在同样的压缩性能条件下,我们会降低编码器的复杂度,让编码器跑得更快。
我们今天要讲的工作主要是反映我们在2018年开始进行了一个为期大约1年左右的对VP9编码器的技术升级,这个技术升级主要实现了两个个大的目标,第一个是在VOD条件下,提高它的客观加速性能,也就是以PSNR和SSIM为Metric,提高它的客观加速性能10%;第二个目标是对包括电影在内的高清的视频在输入条件下,我们去提高它的主观压缩质量。我们今天讨论的一些工作,从2019年开始在YouTube、Google play movie等服务平台上进行了大范围的运行,它们的性能目前看是比较稳定可靠的。
我们今天的介绍主要分为2个部分,第一个部分是Core Compression Efficiency,我们会讨论4个方向的工作。前三个主要是为了提高我们Compression Performance,第四个会讨论我们通过引入deep learning model来降低编码器复杂度。这四个工作合在一起会让我们的VPX、VP9编码器在Compression Efficiency上提高10%,与此同时它的编码器速度是加快30%。
第二大部分主要讲主观压缩质量,它的主要运用场景就像我们刚刚讲的对高清视频(比如电影这些)输入材料。它主要会考虑2大部分,一个是对film grain的处理,第二部分是对不同的低频和高频信号在它不同的背景下,我们会采用不同的自适应量化技术去提高它恢复出来的图像质量,让它在人眼的视觉中更接近原始的输入信号。
1. Temporal Dependency Model
第一个工作我们主要讨论Temporal Dependency Model,它主要做的工作是说我们考量一般的RD 优化,我们通常做法是给定一个coding block,给定它的Lagrange Multiplier。我们会去测试不同的编码模式,然后在所有coding mode当中我们会选一个,这个coding mod 会给我们最低的RD cost作为我们的final decision。这种做法通常是会适用于所有,就是说这个Lagrange Multiplier是一个可以决定在比率失真中取舍的因素。我们通常对整帧的所有编码块使用相同的Lagrange Multiplier。这是我们一直使用的传统方法。这项工作的主要想法是不同的coding block在一个coding frame以内的时候它的重要性是不一样的。
Motion Propagation
重要性怎么来理解?我们可以举一个例子,比如我们当前帧是N帧,黄色的编码块通过运动补偿预测会被后续的多个帧不断引用作为参考和预测,相比之下,蓝色和红色编码块的运动补偿预测树要短得多,绿色的只会出现在当前帧中,而不会被后一帧用作运动补偿参考。
在这种情况下,当我们回到当前帧,我们会认为黄色的块失真对整个视频压缩效率的影响比绿色的块要大。这是我们的一个想法,我们希望我们可以量化每个编码块对整个视频序列的重要性,或至少对一个组架构形式的时间依赖模型。
The Measurement
最后两张PPT将更详细地描述我们是如何实现时间依赖模型的。它的主要思想是,对于每一个编码帧,我们向前看几个帧,首先建立一个运动轨迹,然后我们从最远的编码帧以回溯的方式往回推,把它推到当前帧。然后我们继续构建,看看有多少后续的编码块将使未来若干帧中的每个编码块成为运动补偿参考。
我们通常通过计算内部预测残差和内部预测残差的比值来确定这些参考文献的重要性。如果前者远大于后者,则物理意义是预测编码增益相对较高。在这种情况下,我们认为当前区块对未来区块的影响是巨大的。如果两者相似,那么在这些条件下,我们认为运动补偿预测的预测编码增益很小,那么我们可以说当前块对未来的影响是非常有限的。这是物理学的设计原则。
在这里我就不详细说明具体的递归传播是如何完成的了,如果大家感兴趣可以去查看一下我们的相关论文。
2. Advanced ARF Temporal Filtering
下一个方向主要是做所谓的alternate reference frame,也就是ARF。先简单介绍一下ARF,它是从VP8开始,就一直被包括VP9、AV1等一直在采用的一个算法。这个算法是我们编码的一个成熟的图像。例如,它有16帧,我们通常的测量是做帧,但ARF提供了一个选项,这意味着ARF是一个帧。我们将使用编码器制作一个帧,该帧将被编码的正常编码管道和发送到解码器。该帧将只作为其他帧的参考,而不是在解码器上解码后显示。这个缺点是当我们编码一个16帧的成人图像时,加上一个ARF,我们可以有效地解码整个成人图像的17帧。所以这个ARF是一个专用的参考系,所以它给了我们一个选择,有一个很大的可行性来决定ARF的来源是什么样子的。
它以什么形式能够最大限度地优化我们整个grow up picture的其它帧的预测质量。通常,我们假如每个帧都有两部分,一部分是底层信号,另一部分是采集信号。第一部分通常是不同帧之间高度相关的,第二部分通常是每个帧唯一的。对于ARF,我们通过时域滤波生成一个合成帧,然后对该帧进行去噪处理以去除其特有的捕获噪声。我们得到的只是潜在的信号。此时,我们可以减少其重构失真,提高其周围grow up picture的制作质量。
我们通常的时间滤波实践是选择一个锚定帧作为目标ARF,然后对每个锚定帧在32x32的多个周边帧中进行运动搜索,这样我们就可以有效地建立一个运动轨迹。通常的方法是将这些编码块进行线性叠加,这些线性叠加将应用到这个编码块上,即编码块中的每个像素将使用相同的线性系数来进行叠加。这是我们之前的传统方法。
我们在新的编码算法当中,我们想到一个问题,这种统一的线性组合不是最优的,因为编码块是一个32x32为单位的grade在往前走,它不一定总能捕捉实际真实运动物体当中的边界,这个边界不一定在32x32的边界内。
在此过程中,我们引入了一个非局部均值滤波器。非局部均值滤波是一种较新的、功能强大的图像去噪方法。通常的做法是讨论,例如锚块的一个像素和参考块,在这种情况下,我们不会将这个像素作为中心(3x3或5x5)作为模板或一个补丁作为基准进行比较。我们将比较两个3x3像素的patch的MSE有多少。而MSE越大,两个像素属于同一运动轨迹的可能性越小。在这种情况下,由于MSE的存在,它们之间的距离较大,我们在整个滤波过程中都会降低参考像素的权值。但如果两个patch相似,则R(0,0)和B(0,0)更有可能属于同一运动轨迹。在这种情况下,我们要加上R(0,0)的权值这就是非局部均值滤波器的基本用法。
因此,在我们得到每个参考块中每个像素的权重因子后,我们将对它进行归一化,我们希望所有的线性系数加起来等于1。然而事实上大家如果仔细看的话这里non-local mean filter return的kernel永远是正数,这意味着最坏的情况是当两个patch的距离较大时,其系数接近于0。这样做的一个优点是,它提供了很大的可行性,即在同一个编码块上,虽然我们使用同一个运动角色来寻找它的参考块,但是我们可以通过非局部均值在不同的像素上添加不同的权值。因此,我们可以更有信心地说,几个像素是去噪过滤器的应用安全在同一运动轨迹上。
3. Non-greedy Motion Estimation
下一个方向是关于运动估计。在现代代码中,通常有两个因素来决定最终的运动矢量。第一个因素是比较当前块和作为基准的参考块之间的距离(绝对差和或平方误差和)。第二个因素是,我们通常在当前块的顶部和左侧观察相邻块的运动矢量,然后取一个预测的运动矢量。当前块的运动向量和预测的运动向量之间的差异通常转化为关联权值代价。两个因素一起加权,这也可以反映其RD成本在最终行动的率失真。
所以通常是这两个因素,这里面有个sub-optimal的问题在于,我们所预测的运动矢量总是从上、左编码块中取出,由于不考虑当前右、下编码块的运动矢量会有更进一步的影响,那么这个运动向量从某种意义上讲它其实也是在special domain propagate。所以这个运动向量在某种意义上专门用于领域传播。所以我们的工作是说如果我们不能只考虑相邻块的运动矢量在左边和顶部,右边的运动矢量和底部,然后可以让我们进一步优化每一块的运动矢量的决定。
这里是一个大概的示意图,我们的解决方案是在一帧编码中建立一个运动场,这个运动场通常是16x16块,也就是说我们在每一个16x16编码块中都有运动矢量。在未来进行编码块运动搜索时,我们不仅可以得到顶部和左侧的信息,还可以通过运动场来预测编码块会选择什么样的运动向量去到右边和底部。
这样的话它有两个主要的优势,一是我们可以通过这种surrounding neighbor的motion vector的信息去做更好的motion vector inconsistency的penalty,稳定我们运动搜索的结果。更进一步,在客观加速的情况下,我们更有可能尽早检测,就像一个编码块处理两个对象的边界。我们可以提前在边界处检测到它,并利用更新后的运动向量来及时优化整个帧级的RD代价。
我们举一个例子,在conventional greedy motion estimation的算法下,,所有帧经过RD优化选出的运动矢量,这个原始的视频material basic是天上的云彩以均匀的速度向左侧移动。如果我们用conventional greedy motion estimation运算的话,因为本身云彩它变化的pixel很小,所以它的motion search的结果不是很稳定。当我们观察视觉质量时,会不会有效果,也就是说,一些云以一个速度移动,然后下一部分以另一个速度移动。它看上去就有很强的artifact。这就是我们在考虑顶部和左侧编码块的运动信息时所做的。
如果你使用这种运动场方法,也就是说,我们允许一个编码块预测它的四个方向的运动矢量,并得到最好的运动估计。我们看到整个框架会比之前的这个更加一致,它会大幅提高特别是在中低码率条件下的视觉质量。
比如这个是当前的coding block,那么我们通常根据现有编码区域的运动向量来确定其当前最佳的运动向量。现在的算法是去看它的未来的一个区域,目前的算法是着眼于未来的一个区域,即这些区域的编码块将依赖于当前运动矢量的结果来做后面的参考。如果我们发现灰色区域与下面的运动矢量非常不同,那么我们将有更多的选项告诉编码器在这个时候。我们很可能处在两个运动物体的交界处。我们可能会更放松对motion vector difference这个recost的penalty,提高对distortion,即让它更快地跟踪运动物体的实际方向。
4. ML Based Partition Search Speed-up
下一个问题我们是讲关于对使用deep learning model提高编码器速度的一些想法。VP9的最大编码块大小为64x64,我们通常做法是采用四叉树划分,它可以将编码块在水平或垂直方向划分为4部分或2部分,这意味着一个编码块有四个不同的划分选项。通常我们将有4种不同的选择来选择最好的最小化RD成本。
我们对ML模型的使用就像我们展示的这样,当编码块进来的时候,我们不会尝试提前四个决定中的哪一个,因为这样输出的symbol数量会比较多,会对我们做training也好,做test也好,模型的可靠性通常不是很高。当我们使用deep learning model的时候通常会希望它的结果更加简单,所以我们实际在用的时候,我们每一都是做了二元决策。
对于第一个模型,我们可以说如果我们要做N乘N的RD搜索。如如果我们这样做了,我们会决定是否要进行的分割搜索。注意到,我们在做下一个模型之前我们其实已经访问N by N的路径,这个时候我们可以再次访问N×N的RD coot这一次包括中间的运动向量,预测残差的资料实际上是可用的。这个时候这些additional的信息会给到下一个deep learning model里面,去用来做“half N by half N”的决策。
同样原理在第三个模型的时候让我们去决定去测水平还是去测垂直的时候呢,我们就会有前面两次RD 搜索的结果,这样我们就会不断积累新的信息,但我们的每个模型都试图将上一个RD搜索的结果和编码作为其输入,但每次输出都是二进制的,这大大减少了deep learning model本身内部的补偿,提高了其稳定性。
5. Film Grain Mode
首先我们来谈谈胶片的纹理。这种电影纹理就像艺术,经常出现在很多电影的视频信号中,它的同一特性在某种意义上来说非常近似于白噪声,也就是说,如果从前面的角度看膜纹,相邻像素和它之间的相关性会非常小。我们都知道,当我们做决定时,潜在的假设和邻近像素的相关性更好,或者它是某种程度上定义的传播模型。薄膜颗粒通常使我们的编解码器压缩性能非常差,因为它的频谱几乎是平的。为了达到良好的施工质量,我们的实际开工率将非常高。
我们在实际操作的时候,我们会遇到有一个问题,比如我们的目标比特率是在25mbps时,我们会看到非常多伪影,这个原因是因为VP9它的设计很差,就像我们刚才讲的alternate reference frame(ARF)它是应用时间滤波器来降噪,当去噪完成后它有很大概率把这种film grain去掉。
例如,我们可以做这两帧,左边这个是没有做ARF filtering它的比特率接近于两倍我们做了ARF filtering的比特率。大家从肉眼上看这两个图其实是很相似的,尽管它们的大小差了将近一倍。
然后我们放大。当我们看到没有时间滤波时,我们可以看到中间仍然有一个采集噪声。但在ARF进行时间滤波后,它是相对平坦的。时域滤波后的ARF性能可以大大提高视频编解码器的加速性能。
但是它的缺点是它会把film grain给大规模过滤掉。
例如,在由暗到亮的转变过程中,这中间是film grain,有很多随机的信号分布,这是因为我们应用了时域滤波去噪,我们实际看到的结果就是这样的,一边是纯黑色,另一边是纯白色。如果我们放大2K或4k的电影,我们就会看到很多patchy artifacts,本来它应该是胶片颗粒的地方它会变成一块一块的reconstruction quality。
所以我们现在有两个选项,第一个方案是我们大幅度提高目标比特率,那么这个时候在实际的产品线上是无法使用的,因为比如说我们从25Mbit/s提高到100Mbit/s,在实际用的时候是没法进行传输的。还有一个办法就是我们通过一些编码器方向的优化去更好的retain这种film grain noise,或者我们在同样的码率条件下不被允许保留真实的film grain noise,我们希望去模拟出film grain noise。
所以我们通常的一些做法是当出现film grain noise的时候,我们尽量使用小的编码块,然后我们在做ARF的时候,我们会更加的保守,也就是我们做ARF filtering的时候,我们会尽可能减少过滤帧的数目,然后降低它的阈值。如果两个的patch的distance大于某一个阈值我们就直接关闭这个ARF,这样我们能更好的在ARF中保存film grain noise。
还有一个很重要的问题就是DC prediction,大家都知道这相当于我们做intra prediction above and left boundaries做平均,然后用平均值做预测。特别是DC prediction加上一个transform coding bound, all the coefficient of the coding block 所有coefficient都会quantize成0以后,这就是一个非常典型的patchy artifact,所以我们在编码端会更小心,尽量禁止这种DC或者vertical horizontal intra-prediction,如果必须使用它们,我们也要尽量避免所有的变换系数都被量化为零的情况。因为这种情况发生时很明显。
其它的一些方法就是,我们会bias到内部预测模式而不是用内部预测模式,因为内部预测模式没有办法从ARF当中取到噪声信息。因为我们不可能在编码器的stack里面去生成噪声,相反,更多的是说ARF有一些类似于noise的数据库,然后我们在display frame的时候,我们通常是从ARF当中拿到有相似度的,与当前原始信号variance 相似的 pixel block的这种motion compensated reference去做我们的预测。
让我们通过一个简单的例子了解它的缺点是什么。我们做这种approximation的时候,如果我们的row source是像上图这个样子的。那么在两个预测当中,通常预测1的这种reissue会远远小于预测2,但是visual quality看上去预测2和原始源看上去是非常相似的。它们两个其实都是白噪声,所以我们用film grain mode的时候通常是在返回噪声的条件下,我们会看到PSR的伤害很大,因为优化PSR的时候我们通常会选择一个平的区间来近似白噪声区间,但我们承诺,在未来,我们会选择一个看起来像感知质量的,也就是封闭块作为我们的预测模式。
6. Sharpness Tuning
下一个问题是讲锐度调优。锐度调优的背景是因为在VPX的编码器中,我们通常会采用soft quantization 的方法。即在量化后对一个变换编码块进行网格优化估计,如果我们把特定的某些高频信号强制它的相关系数从非零变成零,或者是从一个高一点的非零变成负一或负二,也就是降低它量化指标的幅度。如果我们通过这种变化能取到更好RD 成本,那么就可以有效地去除一些高频信号。
那么这个问题同样是在特别是有film grain条件下出现的时候,我们会发现因为film grain它的光谱接近于是平的,它的RD 成本通常会非常非常高,所以codec如果直接soft quantization 它会倾向于把很多的高频信号都给砍掉,我们sharpness tuning就是专门在这种特定条件下试图return film grain的时候,我们会尽可能地更保守一点,不要去砍掉很多的高频信号的量化指标。
7. Per ceptual AQ Mode
下一个问题是,当你看2K或4K的视频时,我们通常会注意到,我们人眼注意的区间、区域是不同的,我们同样的失真在比较平缓的区间会更容易被人眼注意到,而在快速运动物体或非常复杂的内容下的失真通常是不容易被人眼注意到,也就是artifact不容易被人眼注意到。一个简单的例子,我们最开始用普通的PSNR 或者 SSIM 优化这种codec、encoder去做编码的时候,会发现在对于一个4K 视频,有达到45甚至50db/s的时候,我们依然能够看到很明显的video artifacts。比如说在平缓区间出现的block artifact,那么这个时候和我们的常识就不太相符,因为我们一般都知道如果信噪比大于10db的时候,它的重构信号就非常接近原始信号了。
所以我们仔细去考量的话,这里面有一个区别,就是我们通常说的10db信噪比的区别,然后用这个除以它自身信号的方差。但PANR作为分子具有最大的像素方差,因此两个公式的差异也告诉我们一个直接的算法。对于不同的区间,不同的像素块,首先可以计算其原始信号的方差,当方差很低时,我们通常期望降低我们的quantization step size。也就是说我们希望这个信号方差和失真的比值尽可能保持是一个常数。对于方差较大的区域,我们可以释放失真的限制。特别是在高码率下,大家都知道distortion通常是由我们的quantization step size直接决定的,所以在这种情况下我们做的感知AQ Mode的一个方法。
这意味着预先估计每个编码块的方差。如果方差很大,我们就会apply一个quantize更大的quantization step size,反之如果方差很小,也就是说我们认为当前pixel的区域是比较平缓的,那么我们机会需要一个更小的quantization step size这样才能match
近似于一个常数。它为量化的应用提供了一个很好的方向。因为16x16 pixel通常会是比较小,它不一定能捕获它周围更大区间的视频信号。
在VP9当中采用自适应量化器的时候,我们会有一个限制,我们会通过分割特征来实现。在VP9中,一帧可以支持至少8个分段,,每一个分段对应一个不同的quantization step size,所以为了更好地拟合整帧的空间信号方差,我们将计算每一个16x16像素块的方差。然后我们用k-means去做clustering。相当于我们做成了8个不同的聚类,对每一个centroid去算出corresponding quantization step size,每个将映射一个分割索引。在实际操作过程中,我们将计算每个编码块的方差,然后根据与方差结果最接近的centroid,使用相应的分割指标来实现自适应量化器算法。
8. Conclusion
以上就是我们工作的主要方向,我们在PSNR中获得了近10%的目标压缩质量编码增益,在SSIM中获得了15%。在这种情况下,我们仍然有30%的编码器加速。当然我们这些客观指标优化更多的是为了下一步,也就是提高我们主观的压缩质量。我们在主观压缩质量方面主要讨论了一些在电影场景下和高清视频场景下的算法。
在此我要特别感谢我们的合作团队,包括YouTube team、包括Google play movie,包括我们的external partner,Disney和Fox studios。
本文分享自 LiveVideoStack 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!