网易云信 NERTC 高清画质体验之 H.265 的工程实践 | 体验共享技术专题
导读:H.265 是 ITU-T VCEG 继 H.264 之后制定的新一代视频编码标准,相比于 H.264,H.265 能够进一步提高压缩效率,提升画质,在当前的很多音视频场景中,得到了越来越广泛的应用,我们在网易云信 NERTC 中对 H.265 做了大量的工程实践,本文为体验共享系列第三篇—视频篇,文章将从四个方面做具体介绍。
能力协商
一个客户端能否发送指定的特征的码流,不仅由本端是否支持编码决定,也由房间里其他接收端能否解码决定。即发送端和接收端共同决定了本端能发送什么样的码流。对于 H.265,可能会出现下面的情况:
那么他们之间将如何通信?客户端 B 如果发 H.265 的流,客户端 A 和客户端 D 由于只支持 H.264 解码,它们接收到客户端 B 发送的 H.265 的码流,是无法解码的,所以我们需要设计一套能力协商机制,来保证支持不同编解码能力的客户端之间可以正常的通信。
下图为能力协商的整体设计图:
下面详细介绍一下我们能力协商的设计方案。
能力集设计
能力集定义为 { uint32 key : [ uint8 value1, uint8 value2 ... ] },使用 1 位掩码
sdk 的 key 范围是 [ 0, 2^8 )
video 的 key 范围是 [ 2^8, 2^16 )
audio 的 key 的范围是 [ 2^16, 2^24 )
字节示意如下:
举例说明如下:
能力协商流程(客户端)
1. 客户端本地定义能力集
2. 客户端本地实现能力集上报,能力集下发配置的机制
3. 服务端提供频道内能力集的生成、综合以及下发功能
举例说明:
定义:能力字段 VideoCodec : 256 (2^8),能力值 H.264 : 0,H.265 : 1
客户端 A 和客户端 B 进入同一个频道时,客户端 A 上报能力集{ 256 : [0, 1]},客户端 B 上报能力{ 256 : [0]}
服务端收到客户端 A 和客户端 B 的能力集上报之后,知道 A 支持 H.264 和 H.265,B 支持 H.264,综合 A 和 B 的能力集,得到频道内支持 H.264 的结论,下发能力集 {256: [0]}
客户端 A 收到能力集后,主动关闭自己的 H.265 能力;客户端 B 收到能力集后,和自己的能力集一致,不做改变。
能力协商流程(服务器)
1. 房间创建时,生成默认能力集,默认能力集由引擎提供,服务器用作一个全局配置
2. 第一个 edge_login 请求如果有能力集字段,则使用这个能力集覆盖默认能力集,作为房间的能力集;如果没有能力集字段,则使用默认能力集作为房间的能力集。由于是第一个,不需要广播。
3. 后续每个用户进来,如果能力集大于房间的能力集,则返回房间的能力集给这个用户,房间的能力集不变。举例说明如下图:
4. 后续每个用户进来,如果能力集小于房间的能力集,则取交集,缩小房间的能力集,并把结果广播给所有的用户。举例说明如下图:
H.265 编解码器实践
各个平台有自己特有的硬件 265 编解码器,同时还有各种开源的软件 265 编解码器,那么我们将如何选择,才能实现最佳的使用效果?
下面我们将分 Android,iOS,Mac 和 Windows 四个平台分别介绍各平台 265 编解码器的实践情况。其中软件编码器选用 x265 做测评,软解选用 ffmpeg,libhevc 做测评。
Android 端
首先我们看一下 android 端硬件编解码器的功耗和码率情况(测试机型 Mi 10 : Qualcomm Technologies, Inc SM8250,测试 Profile:720P 30fps 1.7M)
再看一下 android 端各软件编解码器的性能情况(测试机型 Mi 10 : Qualcomm Technologies, Inc SM8250,测试 Profile:720P 30fps 1.7M)
最后看一下画质对比(测试机型 Mi 10 : Qualcomm Technologies, Inc SM8250,测试 Profile:720P 30fps 858k),左为 H.264,右为 H.265
总结:
1. android 硬编 265 在功耗方面基本跟硬编 264 持平,同时 android 硬编 265 码率比硬编 264 更稳一些
2. android 端软编 265 的性能还是比较差的,不能满足需求
3. android 端 ffmpeg 软解 265 在 arm64 上面性能比较差,CPU 占用达 15%,同样条件下,使用 libhevc,CPU 占用只有 4.5%,性能上有很大提升空间
4. android 硬编 265 的画质明显要比硬编 264 的画质更清晰,画质收益很明显
所以 android 端我们 265 编解码器的使用策略如下:
1. 优先使用 265 硬解。一些设备存在 265 硬解兼容问题的,高端机型选择 265 软解码器,低端设备直接认为不支持 265 解码
2. 优先使用 265 硬编。一些设备存在 265 硬编兼容问题的,则认为不支持 265 编码,降级到 264 编码
3. 由于 libhevc 软解的性能明显优于 ffmpeg 软解 265,所以 265 软解码器我们会优先选择 libhevc
iOS 端
首先我们看一下 iOS 端硬件编解码器的功耗情况(测试机型 iPhone11,测试 Profile:720P 30fps 1.7M)
另外我们发现在某些机型上或者某些场景下,iOS 硬编 265 会出现明显的码率不足的问题(测试机型 iPhoneXR,测试 Profile:720P 30fps 1.7M)
H.264:
H.265:
像这种出现码率严重不足的情况,我们基于 iOS 硬编码控,设计了一套码率监控方法,如果监控到码率出现严重不足,会从 H.265 回退到 H.264
最后看一下在硬编码率稳定的情况下的画质对比(测试机型 iPhone11,测试 Profile:720P 30fps 858k)
左 H.264,右 H.265
总结:
1. 使用 iOS 硬编 265 功耗明显比硬编 264 要大,同样的使用 iOS 硬解 265 功耗也明显比硬解 264 要大一些
2. iOS 硬编 265 偶现一些码率不足的情况,导致画质反而不如 264
3. iOS 硬编 265 的画质要比硬编 264 的画质更清晰一些,有一些画质收益
所以最后 iOS 端我们 265 编解码器的使用策略如下:
1. 优先使用硬编 265,不支持软编 265
2. 优先使用硬解 265,只有在硬解 265 多次解码失败无法恢复后才会回退到 ffmpeg 265 软解
3. 由于 iOS 265 硬件编码功耗比硬件 264 要大,监测 iOS 设备整体电量,在低电量情况下(比如到 20%临界点),我们把硬件 265 切回到了 264 硬件编码器
4. 使用 iOS 硬编码控模块,监测实际编码码率情况,若出现明显的码率不足或者码率超发,我们把硬编 265 切回到了硬编 264
iOS 硬编码控
下图为硬编码控模块设计图:
码控流程:
首先硬编码器将目标码率 Target Bitrate 传递给码控模块 HWBitrateController
每编码完成一帧,将编码后的帧大小更新给 HWBitrateController 估算出每秒的实际编码码率 Estimated Bitrate
计算目标码率与实际码率直接的差值 Diff
通过二分法,取 0.5 倍的 Diff 加 Target Bitrate,作为需要调整的码率 Adjusted Bitrate
将需要调整的码率 Adjusted Bitrate 设置回硬编码器 HWEncoder,作为 HWEncoder 的目标码率 Target Bitrate
再回到第一步,硬编码器将当前目标码率 Target Bitrate 传递给码控模块 HWBitrateController
计算 Diff/Target Bitrate,如果持续大于 30%,则认为码率出现明显不足,需要触发降级编码器
Mac 端
首先我们看一下 Mac 端 265 软硬件编解码器的 CPU 和码率情况(测试机型 MacBook Pro (15-inch, 2016): Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz,测试 Profile:720P 30fps 1.7M)
硬编 265 码率情况:
软编 265 码率情况:
同时,我们通过 dump Mac 硬编 265 的码流,发现使用前向 B 帧取代了 P 帧
最后,我们看一下画质对比(测试机型 MacBook Pro (15-inch, 2016): Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz,测试 Profile:720P 30fps 1M)
总结:
1. Mac 上面硬件 265 相对于软件 265,CPU 占用更低,性能收益比较明显
2. 硬编 265 码率稳定性不如软编 265,波动比较大,但都是围绕目标码率上下波动,经过长时间测试,发现整体码率平均下来没有明显的超发或者不足情况出现
3. 硬编编码码流前向 B 帧取代了 P 帧,整体压缩率会更高,同等码率画质更优
4. 硬编 265 画质明显优于 264,而软编 265 与硬编 265 画质差异不大
所以 Mac 端我们 265 编解码器的使用策略如下:
1. 优先使用 265 硬解。一些设备存在 265 硬解兼容问题或者不支持 265 硬解的,在 CPU 性能比较强的设备上面使用软解 265(ffmpeg),如果是 CPU 比较弱的设备,则认为不支持 265 解码
2. 优先使用 265 硬编。一些设备存在 265 硬编兼容问题或者不支持 265 硬编的,在 CPU 性能比较强的设备上面使用软编 265,如果是 CPU 比较弱的设备,则认为不支持 265 编码
Windows 端
windows 上面由于硬编硬解碎片化比较严重,我们暂时没有考虑使用硬编硬解,目前以使用软编软解为主。
下图为 win 上面软编软解 265 的情况(测试机型 Dell Latitude 5290: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz,测试 Profile:720P 30fps 1.7M)
可以看到:
1. 软编 265 和软解 265 在 x86 上面的性能表现不如 x86_64
2. 软编 265 在 x86_64 上面的 CPU 消耗也是远远高于软编 264 的
所以最后 Win 端我们 265 编解码器的使用策略如下:
1. 在使用 win x86 的情况下,直接不支持 265 软编软解
2. 在使用 win x86_64 的情况下,CPU 性能比较强的设备上开启 265 软编软解;同时软编 265 对 CPU 性能要求比软解 265 更高,所以对设备的性能要求也会更加严格
工程策略
白名单策略
前面有提到,我们在使用 265 硬编硬解的时候,需要考虑设备兼容性的问题;同时在使用 265 软编软解的时候,由于涉及大量的编解码运算,也要考虑设备的性能问题。
为了在整体工程层面提供最佳的用户体验,我们使用到了白名单策略。通过白名单配置下发,把是否支持 265 硬编硬解和软编软解的设备区分出来。
以下是我们的具体做法:
通过大量的设备适配,把对 265 硬编硬解支持比较好的设备,配置到线上白名单里面
通过设备跑分,区分出设备 CPU 性能的高低,配置高性能的设备支持 265 软编软解,低性能设备不支持 265 软编软解,然后将配置更新到线上白名单里面
最后通过线上白名单配置下发,客户端获取到当前是否支持硬编硬解和是否支持软编软解的配置信息
H.265 能力协商
协商的是 H.265 解码能力,协商结果最后作用于编码侧,是否使用 H.265 编码
H.265 解码的配置下发,用户设置以及当前设备支持能力,三者综合得出当前 H.265 的解码能力
能力协商模块,根据当前 H.265 的解码能力,生成能力集,上报给能力协商服务器
能力协商服务器综合频道内各客户端的能力集,生成新的房间能力集,下发给各客户端
客户端收到来自于服务器下发的能力集,解析出当前频道内 H.265 的能力集
根据当前频道内 H.265 的能力集,H.265 编码的配置下发、用户设置以及当前设备支持能力,服务器对 H.265 的支持能力,三部分综合得出当前是否支持 H.265 编码,最后作用于编码侧是否编 H.265 的流
CPU OverUse 策略
通过跑分,区分出不同设备 CPU 性能的高低,可能不是完全的准确。在实际场景中,有可能存在跑分数据很高,但是编码性能不够的情况,这时候我们需要通过实时监测统计当前视频编码耗时,来判断当前是否 CPU 过载。
我们的做法是:
硬编 265 考虑到可能存在 pipeline delay 的情况,目前我们暂不统计每帧编码的编码耗时
在使用软编 265 的时候,统计每帧编码的编码耗时,如果出现持续编码耗时过长,那么就认为当前 CPU 过载,265 软编将会立即回退到 264
QP 阈值调整
我们的 QOE 模块,会根据 QP 阈值调整帧率和分辨率,以达到主观视频质量最优,所以设定合理的编码器 QP 阈值就显得非常重要,那么在实际工程实践中,准对硬件 265 编码器,我们如何探索出合理的 QP 上下限阈值?
我们的做法是:
确保 H.264 和 H.265 在主观画质基本对齐的情况下,打出 QP 值,生成 QP 曲线,基于 QP 曲线得出 QP 上下限阈值基本的范围
我们以这款机型为例:(测试机型 Mi 10 : Qualcomm Technologies, Inc SM8250,测试 Profile:720P 30fps)
可以看到:
1. 在 720p 30fps 这个 Profile 档位,硬编 265 与硬编 264 在画质基本对齐的情况下,硬件 265 码率能够节省 40%,QP 波动基本相似,上下阈值也基本接近。所以如果当前 android 硬编 264 的 QP 上下阈值是[A, B],那么建议 android 硬编 265 的 QP 上阈值范围为[A-1, A+1],QP 下阈值范围为[B-1,B+1]
2. 基于步骤 1 得出的 QP 上下阈值范围,逐步网损逐步放开,观测 QOE 模块基于 QP 阈值的分辨率和帧率的调整情况,从 QP 阈值范围中摸出最合理的一个 QP 阈值,以下面的数据为例:
我们发现在 QP 阈值为[A-1,B-1]的时候,整体 QOE 表现最好,所以选定[A-1,B-1]为最后的硬编 265 的 QP 阈值
收益
目前第一阶段的收益评测,我们是基于与 H.264 分辨率码率对齐,看画质收益、端到端延迟、CPU 占用、流畅度这四个指标。这里先列举了与硬编 264 对比,Android 硬编 265 和 iOS 硬编 265 的画质收益情况,从我们评测下来的情况看,端到端延迟、CPU 占用、流畅度这三个指标基本上差异不大,而画质收益,可以参考以下图表数据:
总体来看:
1. 相比于 264,265 在视频画质上是有明显收益的
2. 在低码率、弱网或者画面变化比较剧烈的场景下,画质收益会更加明显
3. android 硬编 265 的画质收益要明显优于 iOS 硬编 265
总结
不管是硬编 265,还是软编 265,相比于 264,视频画质都有明显的收益;后续网易云信将准对画质对齐,节省码率这个维度做进一步的探索。
作者介绍
施灵凯,网易云信音视频引擎开发工程师,负责 NERTC 视频引擎的开发与维护。
版权声明: 本文为 InfoQ 作者【网易云信】的原创文章。
原文链接:【http://xie.infoq.cn/article/290c49c6a39b008396d03e433】。文章转载请联系作者。
评论