空间冗余(帧内预测)
如果我们分析一个视频里的每一帧,我们会看到有许多区域是相互关联的。
让我们举一个例子。这个场景大部分由蓝色和白色组成。
这是一个 I 帧
,我们不能使用前面的帧来预测,但我们仍然可以压缩它。我们将编码我们选择的那块红色区域。如果我们看看它的周围,我们可以估计它周围颜色的变化。
我们预测:帧中的颜色在垂直方向上保持一致,这意味着未知像素的颜色与临近的像素相同。
我们的预测会出错,所以我们需要先利用这项技术(帧内预测),然后减去实际值,算出残差,得出的矩阵比原始数据更容易压缩。
自己动手:查看帧内预测
你可以使用 ffmpeg 生成包含宏块及预测的视频。请查看 ffmpeg 文档以了解每个块颜色的含义。
或者我们也可使用 Intel® Video Pro Analyzer(需要付费,但也有只能查看前 10 帧的免费试用版)。
视频编解码器是如何工作的?
是什么?为什么?怎么做?
是什么? 就是用于压缩或解压数字视频的软件或硬件。为什么? 人们需要在有限带宽或存储空间下提高视频的质量。还记得当我们计算每秒 30 帧,每像素 24 bit,分辨率是 480x240 的视频需要多少带宽吗?没有压缩时是 82.944 Mbps。电视或互联网提供 HD/FullHD/4K 只能靠视频编解码器。怎么做? 我们将简单介绍一下主要的技术。
视频编解码 vs 容器
初学者一个常见的错误是混淆数字视频编解码器和数字视频容器。我们可以将容器视为包含视频(也很可能包含音频)元数据的包装格式,压缩过的视频可以看成是它承载的内容。
通常,视频文件的格式定义其视频容器。例如,文件video.mp4
可能是 MPEG-4 Part 14 容器,一个叫video.mkv
的文件可能是 matroska。我们可以使用 ffmpeg 或 mediainfo 来完全确定编解码器和容器格式。
历史
在我们跳进通用编解码器内部工作之前,让我们回头了解一些旧的视频编解码器。
视频编解码器 H.261 诞生在 1990(技术上是 1988),被设计为以 64 kbit/s 的数据速率工作。它已经使用如色度子采样、宏块,等等理念。在 1995 年,H.263 视频编解码器标准被发布,并继续延续到 2001 年。
在 2003 年 H.264/AVC 的第一版被完成。在同一年,一家叫做 TrueMotion 的公司发布了他们的免版税有损视频压缩的视频编解码器,称为 VP3。在 2008 年,Google 收购了这家公司,在同一年发布 VP8。在 2012 年 12 月,Google 发布了 VP9,市面上大约有 3/4 的浏览器(包括手机)支持。
AV1 是由 Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel, Cisco 等公司组成的开放媒体联盟(AOMedia)设计的一种新的免版税和开源的视频编解码器。第一版 0.1.0 参考编解码器发布于 2016 年 4 月 7 号。
AV1 的诞生
2015 年早期,Google 正在开发VP10,Xiph (Mozilla) 正在开发Daala,Cisco 开源了其称为 Thor 的免版税视频编解码器。
接着 MPEG LA 宣布了 HEVC (H.265) 每年版税的的上限,比 H.264 高 8 倍,但很快他们又再次改变了条款:
不设年度收费上限
收取内容费(收入的 0.5%)
每单位费用高于 h264 的 10 倍
开放媒体联盟由硬件厂商(Intel, AMD, ARM , Nvidia, Cisco),内容分发商(Google, Netflix, Amazon),浏览器维护者(Google, Mozilla),等公司创建。
这些公司有一个共同目标,一个免版税的视频编解码器,所以 AV1 诞生时使用了一个更简单的专利许可证。Timothy B. Terriberry 做了一个精彩的介绍,关于 AV1 的概念,许可证模式和它当前的状态,就是本节的来源。
前往 https://arewecompressedyet.com/analyzer/, 你会惊讶于使用你的浏览器就可以分析 AV1 编解码器。
附:如果你想了解更多编解码器的历史,你需要了解视频压缩专利背后的基本知识。
通用编解码器
我们接下来要介绍通用视频编解码器背后的主要机制,大多数概念都很实用,并被现代编解码器如 VP9, AV1 和 HEVC 使用。需要注意:我们将简化许多内容。有时我们会使用真实的例子(主要是 H.264)来演示技术。
第一步 - 图片分区
第一步是将帧分成几个分区,子分区甚至更多。
但是为什么呢有许多原因,比如,当我们分割图片时,我们可以更精确的处理预测,在微小移动的部分使用较小的分区,而在静态背景上使用较大的分区。
通常,编解码器将这些分区组织成切片(或瓦片),宏(或编码树单元)和许多子分区。这些分区的最大大小有所不同,HEVC 设置成 64x64,而 AVC 使用 16x16,但子分区可以达到 4x4 的大小。
还记得我们学过的帧的分类吗?你也可以把这些概念应用到块,因此我们可以有 I 切片,B 切片,I 宏块等等。
自己动手:查看分区
我们也可以使用 Intel® Video Pro Analyzer(需要付费,但也有只能查看前 10 帧的免费试用版)。这是 VP9 分区的分析。
第二步 - 预测
一旦我们有了分区,我们就可以在它们之上做出预测。对于帧间预测,我们需要发送运动向量和残差;至于帧内预测,我们需要发送预测方向和残差。
第三步 - 转换
在我们得到残差块(预测分区-真实分区
)之后,我们可以用一种方式变换它,这样我们就知道哪些像素我们应该丢弃,还依然能保持整体质量。这个确切的行为有几种变换方式。
尽管有其它的变换方式,但我们重点关注离散余弦变换(DCT)。DCT 的主要功能有:
将像素块转换为相同大小的频率系数块。
压缩能量,更容易消除空间冗余。
可逆的,也意味着你可以还原回像素。
2017 年 2 月 2 号,F. M. Bayer 和 R. J. Cintra 发表了他们的论文:图像压缩的 DCT 类变换只需要 14 个加法。
如果你不理解每个要点的好处,不用担心,我们会尝试进行一些实验,以便从中看到真正的价值。
我们来看下面的像素块(8x8):
下面是其渲染的块图像(8x8):
当我们对这个像素块应用 DCT 时, 得到如下系数块(8x8):
接着如果我们渲染这个系数块,就会得到这张图片:
如你所见它看起来完全不像原图像,我们可能会注意到第一个系数与其它系数非常不同。第一个系数被称为直流分量,代表了输入数组中的所有样本,有点类似于平均值。
这个系数块有一个有趣的属性:高频部分和低频部分是分离的。
在一张图像中,大多数能量会集中在低频部分,所以如果我们将图像转换成频率系数,并丢掉高频系数,我们就能减少描述图像所需的数据量,而不会牺牲太多的图像质量。
频率是指信号变化的速度。
让我们通过实验学习这点,我们将使用 DCT 把原始图像转换为频率(系数块),然后丢掉最不重要的系数。
首先,我们将它转换为其频域。
然后我们丢弃部分(67%)系数,主要是它的右下角部分。
然后我们从丢弃的系数块重构图像(记住,这需要可逆),并与原始图像相比较。
如我们所见它酷似原始图像,但它引入了许多与原来的不同,我们丢弃了67.1875%,但我们仍然得到至少类似于原来的东西。我们可以更加智能的丢弃系数去得到更好的图像质量,但这是下一个主题。
使用全部像素形成每个系数
需要注意的是,每个系数并不直接映射到单个像素,而是所有像素的加权和。这个神奇的图形展示了如何使用每个指数唯一的权重来计算第一个和第二个系数。
来源:https://web.archive.org/web/20150129171151/https://www.iem.thm.de/telekom-labor/zinke/mk/mpeg2beg/whatisit.htm
你也可以尝试通过查看在 DCT 基础上形成的简单图片来可视化 DCT。例如,这是使用每个系数权重形成的字符 A。
维基百科给出了一个DCT的演示动画:
自己动手:丢弃不同的系数
你可以玩转 DCT 变换
第四步 - 量化
当我们丢弃一些系数时,在最后一步(变换),我们做了一些形式的量化。这一步,我们选择性地剔除信息(有损部分)或者简单来说,我们将量化系数以实现压缩。
我们如何量化一个系数块?一个简单的方法是均匀量化,我们取一个块并将其除以单个的值(10),并舍入值。
我们如何逆转(重新量化)这个系数块?我们可以通过乘以我们先前除以的相同的值(10)来做到。
这不是最好的方法,因为它没有考虑到每个系数的重要性,我们可以使用一个量化矩阵来代替单个值,这个矩阵可以利用 DCT 的属性,多量化右下部,而少(量化)左上部,JPEG 使用了类似的方法,你可以通过查看源码看看这个矩阵。
自己动手:量化
你可以玩转量化