用Elevator优化AV1视频播放

简介: AOM会员Vimeo通过Elevator改善AV1解码过程中的丢帧和质量下降问题。感谢Google软件工程师姜健对本文做的技术审校。

文 / Raphaël Zumer


译 / 刘俊


技术审校 / 姜健


原文


https://medium.com/vimeo-engineering-blog/enhancing-av1-playback-with-elevator-6a2991c1aac0


作为AV1编码标准的早期使用者,为了给Vimeo网站的用户带来更好的视频观看体验,我们需要开发诸多处理方案。其中有一种方案,取名为Elevator,是一个能在AV1格式视频码流中设置尽可能最低的编码等级的工具。在解码器端无法判断视频编码等级的时候,这种处理能优化播放过程中丢帧和视频质量下降的问题,在当前以及将来保证尽可能多的设备能够解码播放我们的视频内容。


Elevator工具在2019年9月公开发布,并且于当月在日本东京举办的视频技术开发日大会上首次展示。在这篇文章中,我们将介绍一些AV1格式的背景知识;结合一些例子来介绍Elevator是如何工作的;并分享我们在开发过程中的所思所得。


理解AV1格式的编码等级


AV1格式的编码等级是一组视频码流参数约束,一般每帧或每秒计算所得,包括码率、帧率等。从MPEG-2发布以来,编码等级的概念就存在于每一个当今常用的视频编解码器中。据编码等级规范约定,给定等级的解码器必须能够解码符合该编码等级的码流。视频编码等级使那些低功耗、解码能力有限的设备能够能够提供性能保证,在不牺牲用户体验的前提下,提前确定是否能正常播放给定码流。


在AV1和其他编码标准中,视频的编码等级参数在编码的早期阶段就已经确定了。对编码器而言,为准确设定等级有如下三种方式可用:


  1. 将等级参数设置为可能的最大值(对码流参数无约束)


  1. 在编码时收集数据,将数据返回到包头,最终获知准确的编码等级(这种方式不适用于某些部分编码过程,比如直播)


  1. 编码之前设定编码等级,在整个编码过程中严格执行该等级约束。


编码器也可以尝试预估得到准确的编码等级并且有一定的成功率。但由于不可预测的码率突增,这种方法不可能每次都输出有效码流。如下图中示例,Elevator工具为Chimera AV1格式的示例视频计算得到的编码等级就比由libaom参考编码器在编码时设置的可能的等级要高。

image.png

我们在Vimeo网站上编码AV1视频使用的编码器,rav1e,采用上述方法中的第一种。虽然这是最简单的,但是其前向兼容性并不够理想。我们希望高编码级别的码流不会被错误地送到只能解码低编码等级的低功耗设备上,于是我们开发了与rav1e不一样的Elevator,用于分析已编码的视频,设置准确的编码等级。


Elevator能做什么?


Elevator是一个用于计算AV1格式视频编码等级相关参数的开源命令行工具。这个工具计算码流所符合的最低编码等级,将该值输出在命令行窗口,也可以直接将其设置到视频流或新文件中。


尽管我们使用Elevator去降低Vimeo网站上被高估的编码等级,在编码器无法有效地约束视频的编码等级的时候,Elevator的表现也很出色。比如,我们根据Elevator计算结果反馈,逐步调整参数去重新编码视频内容,最终可得到足够低的编码级别。


为了充分利用Av1parser(开放多媒体联盟的AV1视频解析器),Elevator采用Rust语言编写。据我们所知,Av1parser在开发的时候是唯一独立的AV1码流解析器。由于计算编码等级参数所需信息的有些内容被封装在码流中间的包头中,编写我们自己的解析逻辑困难又耗时。我们对Av1parser做了很少一些改造,将这些问题的处理交给Av1parser,这样我们就少编写了很多用于分析复杂的AV1码流的代码。Elevator中唯一需要的位计数和位操作是在处理结束时将视频的编码等级设置为正确值。


由于某些码流特性以我们尚未支持的方式影响着参数的计算,Elevator尚不支持所有的AV1格式视频。到目前为止,Elevator只支持处理IVF容器封装的视频。在此,我们特别欢迎任何对该项目感兴趣的人在本项目GitHub上贡献缺陷报告、功能建议,或者上传补丁。


Elevator做了什么


Elevator的使用可以高度概括为两个步骤:分析和修补(后者是可选的)。修补步骤相对简单,因为编码等级参数被设定在AV1码流序列头的开始部分。在分析过程中,我们把序列头的位置记录下,以方便后续再次查找;然后,统计等级信息在码流序列头部中的偏移字节数,确保在准确的位置对编码等级进行编辑。


下图为分析的处理流程图:

image.png

图 1 分析步骤流程图


在处理完容器的数据后,Elevator进入分析的主循环:对视频中的每个OBU进行解析,每当遇到时间分隔符则保存下每帧内容的帧大小、头部数目等相关信息(OBU,即Open Bitstream Unit,开放比特单元,是AV1格式数据的最小划分单元)。


在分析阶段的最后,根据主循环更新迭代每帧内容得到的参数最大值,计算编码等级。然而,等级参数的定义并未统一,或是以每帧,或是以每秒计算。正因为如此,在AV1规范中没有明确定义该如何计算等级参数。在开发过程中我们得到的一些或许可行的计算方法如下:


  1. 统计每帧的指标,将结果缩放至以秒为度量;


  1. 统计每秒的指标,向下取整到最接近的帧数;


  1. 统计每秒的指标,向上取整到最接近的帧数;


我们发现,计算每帧的参数再将结果进行缩放处理会由于参数的尖峰异常值而得到与实际不符的编码等级。因此我们换了个方法,同样使用每帧的数据来更新参数,但使用每秒视频的多帧数据为组进行计算。如果帧率非整值,则对数据作向上取整处理,例如,对于帧率为23.976fps的视频,取24帧为一组。为抵消由于向上取整导致的计算偏差,我们会将结果适度缩小,比如,在23.976fps的情况下,将结果乘以23.976/24。


在实验过程中,我们发现相当多不太规范的AV1格式视频(如上面提到的Chimera的示例视频),其编码等级低于Elevator的计算值。如果Elevator计算的结果是正确的,这意味着在其他平台可能发布了大量不符合AV1编码规范的视频。不幸的是,目前并没有验证AV1编码等级正确性的公共测试序列。我们希望随着越来越多的硬件解码器在市场上发布,人们会更加关注正确标注视频编码等级的问题,产生更多能相互验证的解决方案或工具。


参考链接


Chimera的示例视频


http://download.opencontent.netflix.com.s3.amazonaws.com/Chimera/Chimera_DCI4k2398p_HDR_P3PQ.mp4


libaom参考编码器


https://github.vimeows.com/gist/raphael-zumer/d9fd0419827b64da1554e70b93de46f5


rav1e项目


https://github.com/xiph/rav1e


av1parser项目


https://github.com/yohhoy/av1parser

————————————————

版权声明:本文为CSDN博主「LiveVideoStack_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/103626046


「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。

阿里云视频云@凡科快图.png

相关文章
|
29天前
|
C语言 C++ 内存技术
SDL基础使用06 (SDL播放pcm文件)
如何使用SDL库在C和C++中播放PCM音频文件,包括初始化SDL音频、设置音频参数、读取PCM数据、播放音频以及资源释放的完整流程。
23 1
|
存储
av_register_all分析
av_register_all分析
87 0
av_register_all分析
|
6月前
|
内存技术
SDL播放PCM
SDL播放PCM
39 0
av_seek_frame实战--跳转到文件指定时间后开始推流或写入新文件
av_seek_frame实战--跳转到文件指定时间后开始推流或写入新文件
134 0
av_seek_frame实战--跳转到文件指定时间后开始推流或写入新文件
|
编解码
《RealityCodec H.265HEVC Low Delay(I&P)Encoder》电子版地址
RealityCodec H.265/HEVC Low Delay(I&P)Encoder
64 3
《RealityCodec H.265HEVC Low Delay(I&P)Encoder》电子版地址
|
编解码 Android开发
【Android FFMPEG 开发】FFMPEG 音视频同步 ( 音视频同步方案 | 视频帧 FPS 控制 | H.264 编码 I / P / B 帧 | PTS | 音视频同步 )(二)
【Android FFMPEG 开发】FFMPEG 音视频同步 ( 音视频同步方案 | 视频帧 FPS 控制 | H.264 编码 I / P / B 帧 | PTS | 音视频同步 )(二)
713 1
|
编解码 Android开发 开发者
【Android FFMPEG 开发】FFMPEG 音视频同步 ( 音视频同步方案 | 视频帧 FPS 控制 | H.264 编码 I / P / B 帧 | PTS | 音视频同步 )(一)
【Android FFMPEG 开发】FFMPEG 音视频同步 ( 音视频同步方案 | 视频帧 FPS 控制 | H.264 编码 I / P / B 帧 | PTS | 音视频同步 )(一)
494 0
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
247 0
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
302 0
|
消息中间件 vr&ar 数据格式
【音视频连载-007】基础学习篇-SDL 播放 PCM 音频文件(上)
在前面的文章中已经能够利用 SDL 去播放 YUV 视频文件了,接下来要通过 SDL 去播放 PCM 音频文件。
577 0
【音视频连载-007】基础学习篇-SDL 播放 PCM 音频文件(上)