H.265 在 QRTC 场景的落地运用

2,329 阅读19分钟

编者按:

在「LiveVideoStackCon 2021 音视频技术大会北京站」,七牛云带来了技术专场。专场上,七牛云视频编解码负责人朱玲为我们带来了主题为《 H.265 在七牛云 QRTC 场景的落地运用》的精彩分享。本文根据现场分享整理。

按照惯例,大会组委会评选出了优秀讲师。评选的标准包括:工作输出,协作响应,专业能力 ,讲师评分与听众人数等指标。七牛云朱玲与阿里云、北京大学、腾讯、百度智能云及华为云的五位讲师共同上榜。

嘉宾简介

朱玲,七牛云视频编解码负责人。中科大硕士毕业,先后就职于 WebEx,网易,阿里巴巴,有 10 多年视频编解码研发及直播、RTC 等应用场景音视频质量优化实践经验。


演讲实录

我是朱玲,在视频编解码领域有 10 多年的工作经验,目前就职于七牛云,负责视频编解码方面工作。

本次主要和大家分享七牛云 RTC 场景中落地 H.265 的实践经验。

本次分享从以下三方面展开:首先是为什么在 QRTC 支持 H.265?其次是如何更好支持 H.265?最后探讨 QRTC 在视频质量优化方面的规划。


1.为什么支持 H.265

很多同学可能会疑惑,H.265 早在 2013 年就被接受为国际电信联盟(ITU-T)的正式标准了,七牛云为什么在过了将近十年后的今天才来谈在 RTC 场景落地 H.265,似乎很不 fashion。我也观察到,国内音视频行业对 H.265 的讨论在 2017 年达到高峰,内容主要集中在点播、转码、窄带高清领域,少部分关于 RTC 领域的讨论也主要是桌面共享优化中提到的 H.265 SCC Tools,甚至于,近两年关于 AV1 的讨论却逐渐多起来,这次大会就有几场分享主题是 AV1 的,其实这都很好理解,AV1 作为 Google 家 VPX 的下一代,就像 10 年前的 VP8 vs H.264 之争一样,不同的是,Google 这次联合了许多商家研发 AV1,也可见 AV1 的复杂程度。

在选择 H.265 之前七牛云进行了完备的市场调研,结果显示经过八年的发展,H.265 生态已经非常完善,基本所有 OTT 设备包括摄像头、Smartphone 都能够支持 H.265,这是 AV1 所远不能及的。当然,RTC 领域的从业者更多关注Web 端,我们也对 Web 端进行了调研,Safari 和 Edge 均支持 H.265,个人看来 Chrome 支持 H.265 可能只是时间问题。

而且,伴随着 HDR/4K、8K 高清视频的出现,H.264 已无法满足不断提升的视频质量需求了,即使带宽充足了,H.264 的压缩成本也非常高,亟需更高压缩率的编码器来解决当下的痛点。

左图中黄线代表 H.265,预测从 2020 年开始一直处于稳步上升的态势,到2029 年完全超过 H.264。我个人是非常认可这张图,从我们的后台监控流量观察,2019 年 H.265 的量并不大,大概占据 10%,但从 2020 年开始,流量就一直在不断增加了。

业内同学经常讨论 H.265 的好处和优点,在 WebRTC 中的应用效果还是那么好吗?目前没有足够的文献、数据支持定论,但我相信已经有许多厂商尝试甚至已经开始支持 H.265,七牛云也不例外。

在测试 H.265 时,我们找了一大批数据集(Class B-E,标准组织的开放源码)。我们没有测试 2K,是因为 RTC 场景主要是 720p、1080p。Qiniu 是我们自己的用户数据测试集,大概有六十多个,包括游戏、直播等场景。在所有的测试系列上对比了 X265(不是 very fast 或 ultra fast,是七牛云自己定的档次,这一档次的速度类似于 ultra fast,但性能更好)、X264 及 OpenH264(WebRTC 默认集成)。数据显示,相对于 X264,X265 压缩率提升了36.3%,相对于 Open H264 更是提升了 64.1%。简而言之就是节省了许多带宽成本。但问题在于编码速度降低了 2-5 倍,表中列举的是相对速度,在四核机器上跑 1080p 时,X265 编码的绝对速度大概 20fps。

左视频由 OpenH264 编码,右视频由 X265 编码。大家可以观察两个视频中“数字 19”及地面上绿色的线,可以明显看到左边比较模糊。

总之,由于 AV1 的生态不完善,而 H.265 落地就能为用户带来价值,所以七牛云优先选择 H.265。


2.如何支持 H.265

图中是 X265 的框架,做编码器的同学应该非常熟悉。X264 和 X265 在框架图中的区别仅在于 SAO 和 Split into CTUs,既然框架大致相同,那么为何前者相对后者能够提升较大性能呢?

主要原因是 X265 的分块更大更灵活,编码单元最大是 64x64,64x64 可以继续以死叉树形式划分为 32x32, 16x16,到 8x8 的分割,块划分方式一共有85 种可能性,比 H.264 更丰富。

X265 的帧内、帧间预测模式也更丰富,这里截取的是 Inter 模式下的 PU 划分方式,左侧的对称性分割两者都有,但 H.265 还能进行 4x16 或 12x16 的非对称性分割。

X265 的 TU 也更大,从之前的 4x4,8x8 到现在的 16x16,32x32,TU 越大,去冗余也就越多,(当然计算量也会越大,下文会详细讨论)。

除此以外,X265 也增加了新的 coding tools,如 SAO、AMVP,AMVP 相较于 H.264 中的 MVP 加了时域 MV 预测,还有 Merge 模式等等。

以上是 X265 性能提升的主要原因。

既然 H.265 这么好,那是否有现成的编码器实现可以直接应用到我们的产品中呢?带着这个疑问,我们重点测试了硬件实现的代表:Video TooLbox,学术界实现:HM,以及开源实现 X265,从测试数据看来,Video TooLbox 并不乐观,两个指标甚至都不如 X.264,所以大家在直接使用 Apple 硬件支持 H.265时也许会发现,怎么性能可能还不如 X264 啊;而 HM 的速度真的太慢了,完全不能产品化,但压缩率确实好。至于 X265,前面也介绍了在特定环境下绝对速度只有 20fps,达不到实时高清要求,而且相对于 HM,X265 的压缩也有很大提升空间。

我们的目标是产品化的 H.265 的速度能达到或接近 H.264 的水平,压缩率达到 HM 水平。

七牛云对 265 编码器的优化包括码率控制优化、编码工具优化、汇编优化。

2.1 码率控制分析&优化

WEBRTC 传输层为了能够实时检测带宽,耗费了很大精力在带宽估计上,比如推出了 GCC、TCC 等,光带宽估计准确是不够的,编码器的码率控制(尤其在WebRTC 场景下)同样重要。

码率控制的主要内容是预估当前帧/宏块的相对复杂度,结合可分配码率,计算当前帧/宏块的编码 QP,可以简化为 Bit->QP,码率控制要注意以下问题:

1、控制粒度,控制到帧级还是宏块级,如果控制到宏块级,那么一帧里的每个宏块的 QP 都是不同的。

2、帧/宏块复杂度估计,如何计算复杂度。

3、如何建立 Bit-QP 之间的关系模型,使用 R-Q 还是 R-λ 模型。

4、实时反馈调整机制,估计不准确要尽快进行调整。

优秀的码率控制首先要能控住,但这并不是最重要的,比如 500k 的带宽控制到 200k,视频质量会非常差,这样的控住没有意义,所以应该是控制且最大化发挥带宽能力。其次还需要平稳的视频质量和最优的压缩性能。

下面让我们带着这四个问题,分析下 X265 的码控实现。

图:one-pass 的 ABR 算法下 X265 帧级码控流程图

X265 在计算当前帧的复杂度时,不仅使用了当前帧的 SATD,还使用了之前的SATD。所以 X265 码控特征是波动小,新的一帧对整个系统影响和冲击比较小,延续了 X264 作者说到的希望 QP 波动不大。虽然这个想法很好,但当某一个场景下的 R-Q 关系发生大的变化后,这时如果 QP 波动还很小,无法对系统造成冲击,势必不能较好地控制码率。X265 也打了一些补丁,当出现新的一帧或新场景的时候,就会重置整个系统的码控。

针对 RTC 场景,我们对 X265 帧级码控了个有趣的测试。

横坐标是时间维度的帧数(25帧/s),在 250 帧(10s)这一点改变目标码率,从 1000k 改为 500k(码率实时波动是 RTC 场景的一个显著特征),可以看到,如果在 ABR 码控中只修改 Bit 值,不进行其他操作,图示蓝线(代表实际码率)和目标码率的跟随很不紧密,一直到 350 帧也就是 14s 左右才能接近目标码率,而且码率很快又降低很多,和目标码率差距较大。如果在改变目标码率的同时刷新码控模型,就会像红线(代表重置后的实际码率)的表现一样,紧紧跟随目标码控并且很快达到目标码率水平。

测试说明如果在 RTC 场景使用 X265 的 ABR,设置新的目标码率同时需要刷新码控模型,否则会像蓝线一样表现非常差。

宏块级码率控制不是 X265 默认选项,需要先设置 VBV 才会启动宏块级调控,更准确地说是编码一行之后再调整 QP。VBV 对 QP 的调整区间为[-6,+6],当超过 +6 时,系统判断为此时码率明显不够,将使用新的 QP 重新编码这一行。

我们将码率控制在 500kbps,对 RTC 场景下使用 VBV 算法的 X265 宏块级码控系统做了大量测验,数据显示如果不打开 VBV,码率是能控住的,打开之后,PSNR 表现差不多。

图示 QP-Limit 的意思是,我们限制了码控输出的 QP 范围:WebRTC 的代码中经常会将量化范围设置为 24~37,认为这个区间的视频质量是人眼能够接受的,低于 24 会浪费 bit,人眼也不太能主观看出差别,大于 37 人眼则不能接受。所以我们也设置了 24~37 的码控限制,试图造一个“不打开宏块级别码控,码率控不住,打开之后就能控住的 case”,结果显示, 打不打开 VBV 都控制不住,宏块级别码控没什么作用。我个人怀疑是复杂度计算出了问题,但没有深究。至少在大量测试数据的佐证下,VBV 在 RTC 场景发挥的空间较小。另外,QP 限制是有一定作用的,PSNR 提升很多,视频质量也会更好。

在保证单帧质量的情况下,X265 控不住码率,那么如何解决这个问题呢?既然 X265 不是针对 RTC 场景优化的编码器,那我们就找到了为 RTC 场景诞生的 OpenH264 来进行测试。

图为 OpenH264 的码率控制模型,和 X265 的码控系统相同,它也有复杂度、不断更新的模型、上溢下溢。它的特别之处在于 skip,当码率控不住的情况下,会选择跳帧来控制码率,否则对带宽应用影响很大。当然,跳帧也需要聪明的逻辑加持:如果 10 帧给了 300k 冗余,结果 3 帧就用完了后面 7 帧的冗余,其它全部跳帧,会导致画面不连续。

对 OpenH264 进行的测验中,QP 限制是必须的,因为需要保证单帧质量,否则出现马赛克会严重影响用户体验。在已经进行 QP 限制的情况下,控不住码率时就要打开 skip,对比最后两行数据,打开 skip 控住后的码率是 496.8,未打开 skip 控不住时码率达到 653.3,当然帧数也是从本来的 1000 帧到 694 帧,跳了 300 多帧。

分析了这么多算法后,七牛云也提出了自己的码控算法 QNRC。目前只做了帧级的码率控制。

QNRC 采用的是 R-λ 模型。右上图是我们拟合的一条 bpp(bits per pixel)和 qs cale 的关系,这样就可以跳过帧复杂度的计算,因为在实时场景下复杂度计算也不准确。QNRC 允许 skip,同时设置 QP 调节范围。

右下图是测试结果,横坐标每 2s 为一个点,可以看到 500k 时 QN265 表现非常平稳(1s为一点时会有一些波动),而蓝线 X265-ABR 波动比较大。从码控来看,QN265 基本接近目标码控 500k,码率大概浪费了 0.04,PSNR 高了0.5,质量高很多,这就是七牛云目前所做的码控系统,还有一定的优化空间。

2.2 编码工具分析&优化

编码工具优化我们主要介绍广义 B 帧、AMP、Adaptive QP、SAO、帧间模式选择(整个编码器中最耗时的部分)的优化。

2.2.1.广义 B 帧

H.264 或 H.265 的传统 B 帧用到后向参考帧,实时系统中实现传统 B 帧势必会增加延时。广义 B 帧的出现就解决了这个问题,它的预测编码模式选择都和 B 帧一样,但只用了前向参考帧,这就是广义 B 帧(Generalized P and B picture)。

目前苹果硬件码流支持 GPB,HM 也是支持的,X265 不支持,所以我们在 HM上测试了广义 B 帧的功能,观察 GPB 是否能在 RTC 场景中产生效益。

为 HM 配的参数适用于 zero lantency 场景,从数据来看,GPB 是有效果的,1080p 能带来超过 10% 的压缩率,这是非常可观的数据。

我们也尝试了在 X265 上集成支持并做了些测试,将 X265 的 P 帧全部改为了GPB 帧,压缩速率并没有达到预期效果。分析码流发现,左上图是 HM 中第一个 GPB 帧中的第一个采用双向预测的宏块,L0 和 L1 不同。按理说,参考帧相同 L0 应该等于 L1(第一个宏块,后面的可能被 AMVP 影响就不列举),这是因为 B 帧的双向预测会固定 L0 的 mv,再重新降低范围,增大精度进行精确搜索,而 X265 尚不支持双向预测运动估计。

于是,在支持 GPB 的同时 QN265 也只吃了 Bi- prediction motion search,右图数据显示支持 BI search 和 GPB 后能够带来 8.36% 的压缩率。

所以大家如果想要实现 RTC 场景下的编码器,最好能够支持 BI search 和 GPB。

2.2.2.AMP

上文也提到了 X264 都是对称性分割,X265 增加了不对称性分割,结合视频块运动的复杂多样性,增加不对称 PU 划分时,往往能找到更精确的 mv。

测试显示:X265 也支持 AMP +RECT,整体带来了 9.5% 的性能提升,速度也降低的比较多了,怎么降低复杂度呢?

我们做了些测试,设置一个 QP 值 37,码率不太高的平滑运动场景,发现打开和关闭 AMP 其实影响不大,选中 AMP 的没有多少,可见,针对码率比较低低,比较平缓运动的视频序列,可以自适应关闭 AMP。

另外,我们对打开 AMP 的码流进行了仔细的分析,如图所示左边是前一帧,右边是后一帧。红色箭头所指的帧选中了非对称性的划分方式,它的前一帧不是 skip。总结得出一个结论:如果当前帧用 AMP 的划分方式,它的前一帧中相应块大概率不是 skip 的,我们将这个逻辑运用到快速算法 中,结果显示:可以看到压缩性能提升了 7.7%,速度略有一点降低。

2.2.3.Adaptive QP

Adaptive QP 是 X264 作者的拿手之作, 它的实际思想是人眼对视频中平坦区的失真是非常敏感的,而对于快速变化的失真没有那么敏感,所以应该把码率主要用在平坦的地方。它会检测帧的复杂度,如果是平坦的就降低 QP,提升整体主观质量。

我们也集成了 Adaptive QP 算法,进行了大量测试,但设计了很多 case 都没有看到明显的主观质量提升,虽然压缩率降低是符合预期,但是画质没有增强就有点意外了,QN265 暂时没有打开此功能选项。

2.2.4.SAO

SAO(Sample Adaptive Offset ,样本自适应偏移),它的出发点是:在编码端既有重建解码图像也有原始图像,对二者像素进行比较,如果将这个像素值偏移 offset 写到码流里传到解码端,解码端解码重建时候加上这个 offset,那么就更接近原始帧了。这个工具主要是用来提升编码的 PSNR,使解码帧接近于原始帧。想法自然是很好的,但每个 pixel 都计算残差写入码流是是非常浪费 bits,无法达到视频压缩目的的。因此,SAO 的研发者提出了对图像进行分类传输,只对特定类别的像素 offset 进行传递,这样即能节省码流也能降低视频压缩失真。

SAO 在 X265 的实现可以说是直接从 HM 拿来的,站在巨人的肩膀上,避免重复造轮子一点问题也没有,同时也说明了这部分的优化空间非常大,因为 HM 的实现侧重点不在产品化上。

X265 里面有个 SAO 加速工具 “SAO-Limited”挺好使的,建议大家支持 SAO,毕竟能带来可观的视频质量提升,同时也要研发更多的快速算法实现宏块级别自适应 SAO 功能,整体提升效率和压缩率。

2.2.5.帧间模式选择

图示是 X265 的帧间模式流程图简化版,相较于 HM 的流程有很大变化。前面也提到,X265 和 HM 比较有 30% 的压缩率差异,这一块就占了较大比重。QN265 的帧间模式选择流程充分接近 HM 实现,同时集成了自己的快速算法(主要是 early skip),从现阶段的测试数据来看,QN265 帧间预测部分相较于 X265 压缩率提升了 5%。建议大家在实现或优化自己的 265 编码器的时候,尝试打破 X265 的思路,也许会有意想不到的效果。

2.3 代码分析&汇编优化

最后是代码的汇编优化部分,我们首先使分析工具对代码进行复杂度/cpu 耗时分析,如图所示,对耗时比较多的函数进行逐个分析优化来降低函数执行时间。

举个例子:X265 的“ComlexityCheckCU”函数,实现的功能是:先求像素平均值,再用每个像素值减去平均值得出差值。编译器自动解析需要 12 条机器指令外加两个大循环来实现,复杂耗时。

对这个函数进行指令集优化,所谓指令集优化或汇编优化,它的底层逻辑即使是一条指令并行处理多个数据,增加指令处理的吞吐量。如图所示,使用 AVX2 的汇编指令集,用四条指令,每条指令并行处理八个像素,整体耗时是原先的 1/5。

经过以上几方面的优化,QN265 编码器速度和 X265 的 ultra fast 相当,在 720p 上能达到实时编码,1080p 大概在 20 多帧。压缩率提升 20%。

当然了,光有好的算法还不够,在 RTC 场景中还需要实现一整套的质量控制系统,将具体应用的场景特性,设备特性,利用大数据的手段整合起来作为我们编码器使用的指导。QN265 在保证实时性的前提下提供了三个档次可供选用,大概的性能指标如图所示。可编码速度越快,压缩率会随之下降。一般而言,好的设备最好用最慢的档次,压缩率会节省更多,毕竟带宽占据视频应用的大部分成本。


3.未来规划

未来,我们会持续优化 H.265,虽然速度已超过 ultra fast,但我们不满足于此。其次会集成一些抗弱网工具,RTC 场景最大的问题就是弱网。最后,我们拥抱所有的好技术,新标准。