第三章 (3) 视频压缩GOP
视频编码
在这篇博客中,我们将用简单的语言解释视频编码过程(压缩)的基本原理。
压缩/编码的主要目的是减少捕获、存储和传输视频所需的数据量。这导致存储硬件、数据传输时间和所需传输带宽的减少。
虽然存在许多不同的视频编码算法(如MPEG-2、H.264/AVC、H.265/HEVC、VP9、AV1等),但目前大多数流行的编解码器遵循本博客文章中介绍的一套共同原则。
联合摄影专家组,简称JPEG压缩
让我们从最常用的数字图像压缩算法之一说起:联合摄影专家组(JPEG)压缩,它适用于一张图片/一帧。你可能熟悉 .在保存图片文件、添加图片到演示文稿或发送照片时,使用JPEG(或.JPG)文件扩展名。
想象我们拍摄了一个骑自行车的人,背景是一棵树:

JPEG算法通过剔除人眼较少察觉的元素来压缩图像,比如某些颜色信息(因为我们对颜色信息不那么敏感——亮度的变化对人类感知更为重要,而非颜色的变化),以及图像中更复杂部分的细节(低频光线变化对我们来说比高频变化更重要)。
我们移除的所有数据都可能根据所选压缩率影响最终图像的质量。这就是为什么JPEG被称为有损压缩方法,意味着部分原始图像信息丢失且无法恢复,可能影响图像质量。
合适的压缩水平取决于图像的使用场景。例如,仅供在线使用的静态图像可以比大幅印刷的图像被进一步压缩。当文件被过度压缩以满足预期应用需求时,图像会显得像素化且质量较差。
想了解更多信息,网上有许多关于JPEG压缩的优秀文章(这里有更详细的资料)。但重要的是要明白,JPEG是一种帧内编码压缩算法。内部(Intra)意味着显示该图像所需的所有信息都集中在图像内部。
Motion JPEG
现在想象我们录制一段同样场景的视频,骑行者在移动:

相机实际上捕捉了一系列静态图像:

JPEG算法可以应用于每一帧以压缩:

Motion JPEG是最早广泛使用的视频压缩技术之一。它通过排除空间冗余来有效压缩视频,但它未考虑画面中帧间的共同部分,如背景、树等:

这种常见数据称为时间冗余,可以从视频中移除以获得更好的压缩率。
Moving Picture Experts Group codecs(MPEG)
为了消除时间上的冗余,发明了帧间压缩技术(inter 含义为“帧之间”或“帧之间”)。其中最受欢迎的是MPEG。与JPEG类似,MPEG编码采用称为“宏块”的基本单位完成。
帧被划分为切片,切片由宏块组成。宏块由像素块组成,像素是图像中最小可控的元素。宏块作为视频编码过程中的基本对象使用:

I、B、P 帧
让我们从高层次来看一下它是如何运作的。
编码器缓存一定数量的帧,并对第一个帧应用帧内算法。该帧称为编码内帧或信息帧(I-frame),被拆分为宏块,然后以类似JPEG的方式编码:

看后续帧,会发现信息大量重复。例如,树仍然存在于所有帧中,自行车则被表示为从一个帧到下一帧的平移。为了利用视频固有的时间冗余,MPEG定义了新的帧类型,称为预测帧(P帧)和双预测帧(B帧)。
P帧是如何编码的?考虑序列中更远处的第二帧,并以第一个I帧作为参考:

MPEG算法采用一种称为运动估计的技术来计算这些帧之间宏块的平移。利用这些信息,它形成一个称为运动补偿帧的帧,基本上根据运动估计结果将第一帧的宏块平算而来。然后,它将所选帧与其运动补偿帧之间的差异,并用类似JPEG的技术进行编码:

该帧中的每个宏块可以编码为I宏块或P宏块。I-宏块的编码方式与I帧中的宏块类似。P-宏块编码为过去参考图像的一个区域,加上一个误差项(两个宏块之间的差值)。所以,没有变化的像素不会被重新创建,而是从I帧(见下文)中引用的:
I 宏块 的编码方式与 I 帧 中的宏块相同。P 宏块 则编码为:来自过去参考图像中的一个区域,再加上一个误差项(即两个宏块之间的差值)。
因此,那些没有发生变化的像素不需要重新生成,而是直接从 I 帧 中引用,如下图所示。

P帧比I帧提供更好的压缩,因为它们利用了时间和空间压缩,并且在视频流中使用的比特更少。
接下来,编码器选择位于I帧和第一个P帧之间的帧:

与P帧类似,该帧以运动矢量和变换系数表示。但运动分析是双向进行的,分别对前一个I帧和后一个P帧进行。其他所有处理方式与我们描述的P帧相似:

这种类型的帧称为双向预测帧或B帧。B帧可以同时使用前帧和前帧作为数据参考,以获得最高的数据压缩。
继续深入序列。编码器会创建另一个预测帧,在这种情况下,它可以从前一个P帧和I帧获取信息。
并重复此过程,用P和B帧填充序列,直到每一帧都被编码:

展示时间戳(PTS)和解码时间戳(DTS)
现在需要将画面展示给观众,并按照拍摄顺序进行拍摄。为确保该顺序,每个帧都分配一个呈现时间戳:

但帧需要按照编码顺序重建或解码。首先建造了I帧,然后又制造了P帧。然后可以构建B帧来跟踪该顺序,每个帧被应用解码时间戳以携带以下数据:

因此,解码器会按解码顺序重建帧,然后以展示顺序显示给观众观看视频:

图片组(GOP)
出于多种原因,上述B和P帧序列不可能无限。某个时候,应该再次插入一个I帧。
图片组,或称GOP结构,规定了帧内和帧间的排列顺序。通常I帧表示GOP的开始。
GOP长度/大小是指两个关键帧之间的距离,以帧数或关键帧之间的时间(I帧)来衡量。
理想的GOP长度取决于应用,但典型的组画或GOP大小可能是30、60或90帧,或25、50或100帧,具体取决于地区。
GOP从一个I帧运行到下一个I帧前的最后一个帧,然后重复这个过程。

从根本上讲,视频压缩通过寻找并消除图像或一组图像中的冗余来工作。如果你想到一个典型的视频,比如新闻播报,每一帧视频通常都与前后非常相似。新闻主播说话时嘴唇可能会动,信息可能在屏幕底部滚动,但图像中很大一部分内容在帧之间要么相同,要么非常相似。



Big Buck Bunny连续三帧视频,帧数为30fps。注意大部分帧间内容保持不变,只有蝴蝶的翅膀略有变化。
为了利用这一点,大多数视频压缩通过只发送部分完整帧(称为关键帧),然后只发送关键帧与后续帧之间的差值来实现。接收端(解码器)可以利用关键帧加上这些差异,以合理的准确度重现所需的帧。这种压缩方法被称为时间压缩,因为它利用了视频中信息随时间缓慢变化的特性。
第二种压缩方式称为空间压缩,也用于压缩关键帧本身,通过寻找并消除同一图像中的冗余部分。同样,想象一张新闻主播正在播报新闻的照片。在大多数情况下,图像中的像素与周围像素相似,因此我们可以应用同样的技术,只发送一组像素与下一组像素之间的差异。这也是我们在保存JPEG格式图像时熟悉的压缩技术。

从《大巴克兔》提取的示例视频帧。注意像素往往被颜色相近的其他像素包围——例如,在天空中,蓝色像素被其他蓝色像素包围,白色像素在云中被其他白色像素包围。编码器利用这一特性通过空间压缩压缩图像。
理想情况下,视频编码器可以为视频的第一帧发送关键帧,然后后续的每一帧都以差值表示,直到视频结束。然而,有几个原因导致这种做法在实际中效果不佳:
- 随机访问:如果每个用户从第一帧开始只向前看,发送第一帧并进行后续差异,就可以有效。但这并不是观众实际消费视频的方式。观众可以跳过,并在随机时间点加入直播视频。为了适应这种行为,需要在视频中放置更多关键帧,让观众能够从这些点开始观看。这些被称为随机接入点。
- 错误韧性:仅发送差异的另一个问题是,传输媒介并不完美。数据包丢失,位被翻转,现实中还会发生各种错误。如果你只发送与之前内容差别的信号,且发生错误或损坏,这个错误会继续传播到视频流的其余部分,直到结束。在视频中添加额外关键帧,通过将解码器返回“已知良好”帧并清除可能传播的先前错误,从而增强了错误韧性。你可能在看视频时见过这种情况,比如出现错误导致屏幕变块状,或者屏幕上出现带绿色的形状。然后画面突然恢复为清晰清晰的画面。
- 场景转换:只发送帧间差异在帧间差异较小时效果非常好。在内容切换或场景切换时,几乎整个图像可能从一帧到下一帧都充满新信息。这种情况下,通常只发送差异信息是没有意义的。视频编码器通常会检测到这种情况,并自动在边界点插入新关键帧。这被称为场景转换检测。
既然你已经明白为什么定期在视频流中插入关键帧很重要,我可以谈谈一组图片(GOP)。简单来说,GOP是两个关键帧之间的距离,以帧数或关键帧之间的时间长度衡量。例如,如果每1秒插入一个关键帧,视频以每秒30帧的速度插入,GOP长度为30帧,即1秒。虽然现实中的GOP时长因应用而异,但通常在0.5到2秒之间。

关键帧和差异
关键帧通常被称为编码内帧,简称I帧。之所以得名,是因为这些帧通过空间压缩被压缩,因此解码这类帧所需的所有信息都来自自身内部(“内部”)。解码器不依赖也不要求其他帧来生成图像。在 H.264 及以后版本中,引入了一种称为瞬时解码器刷新(Instantaneous Decoder Refresh,简称 IDR 帧)的特殊帧。虽然I框架和IDR框架之间存在细微差别,但为了理解GOP,我们可以把它们当作同一对应。你可以把I帧看作是帧的JPEG图像。通常,I帧在视频流中使用最多的比特,因为它们仅利用空间压缩,而非时间压缩。
差异:我们用两种帧来向解码器传递差异信息。第一种称为预测帧,或P帧。它被称为预测帧,因为它预测了与前一个帧发生了哪些变化。P帧提供当前帧与之前一个(或多个)帧之间的“差异”。P帧比I帧提供更好的压缩,因为它们同时利用时间和空间压缩,并且在视频流中使用更少的比特。
最后一种“差分”帧是双向预测帧,或称B帧。B帧是双向的,因为它们取前后相继的帧,只发送当前帧与过去和未来参考系之间的差异。由于B帧将时间压缩放大到11倍,因此提供了最高的压缩率,并且在视频流中占用的位元最少。

典型的GOP包含B和P帧的重复模式,夹在I帧之间。典型模式的例子可能是:
I B B P B B P B B P B B I
上述序列可以用两个数字表示:M 和 N。M 表示两个 I 或 P 帧之间的距离,而 N 表示两个 I 帧之间的距离。上述GOP被描述为M=3,N=12。
专业视频分析仪可以直观地显示GOP和帧类型:

但你也可以用像ffprobe这样的开源工具,看到GOP对编码电影的顺序:
$ ffprobe -i SAMPLE_MOVIE.mp4 -show_frames | grep 'pict_type'pict_type=Ipict_type=Bpict_type=Bpict_type=Ppict_type=Bpict_type=Bpict_type=Ppict_type=Bpict_type=Bpict_type=Ppict_type=Bpict_type=Ppict_type=I
根据上述输出,我们的样本电影GOP时长为12帧。
GOP配置如何影响视频质量?
GOP长度越短,I帧之间存在的B帧和P帧就越少。请记住,B帧和P帧提供了最高效的压缩,因此在低码率电影中,较短的GOP长度会导致视频质量下降。较长的GOP长度能更高效压缩内容,提供更低比特率的视频质量,但代价是牺牲随机接入点和错误弹性。大多数编码通常使用1-2秒的GOP长度。
举例来说,以下两张图片代表了《Big Buck Bunny》一帧的放大部分,编码速度为2.5Mbps,编码设置相同,唯独GOP长度不同。第一张图片配置为4帧GOP,第二张GOP长度为90帧。


同一视频的帧,编码为2.5Mbps,GOP为4帧(顶部),GOP为90帧(下),极度展示了GOP设置对视频质量的影响。由于上方示例中B和P帧较少,编码器必须更粗糙地量化I帧(压缩更多),以适应配置的比特率,这会导致块状、模糊和细节损失。
以上情况适用于大多数用例。对于非常高比特率的编码器,当保持高画质比节省比位更重要(通常为50Mbps及以上),可以使用GOP长度为1(即每帧均为I帧时)。这通常仅用于广播或制作质量和档案编码。
IRAP 图像
视频序列里包含不同类型的图像,I帧(只使用帧内预测)、P帧(单向帧间预测)、B帧(双向帧间预测)。由于P帧和B帧在帧间预测时要参考其他帧,所以形成了不同帧间的时域依赖关系(时域预测帧必须在其参考帧解码后才能解码)。

上图展示了不同帧间的时域依赖关系。图上数字是编解码顺序,从左到右是播放顺序,即解码顺序为1,2,3,4,5,6,7,8,9,播放顺序为1,4,3,5,2,8,7,9,6。
编码视频序列(coded video sequence,CVS)中定义了以下几种图像类型。每帧图像的类型可以在其所属的NALU header中找到。
随机介入点图像(Intra Random Access Point,IRAP):IRAP是I帧,且播放顺序在其后的图像可以独立解码,无需参考IRAP前的图像。上图中图像2为IRAP图像。
前置图像(Leading Pictures):解码顺序在IRAP后,而播放顺序在其前的图像称为该IRAP的前置图像。上图中图像5为图像2的前置图像。
后置图像(Trailing Pictures):播放顺序在IRAP后(解码顺序必在其后)的图像称为IRAP的后置图像。上图中图像8为图像2的后置图像。
IRAP只包含帧内编码,不采用帧间预测可以独立解码。但只包含帧内编码的不一定都是IRAP图像,还要看其后置图像能否独立正确解码(不用参考IRAP前的图像)。
前置图像可以分为RADL(Random Access Decodable Leading)图像和RASL(Random Access SkippedLeading)图像。不依赖于IRAP前码流信息的前置图像成为RADL图像,即从IRAP介入,RADL可以正确解码。依赖于IRAP前码流信息的前置图像成为RASL图像,即从IRAP介入,RASL不可以正确解码。上图中图像3为图像2的RASL图像。
IRAP图像又可以分为IDR(Instantaneous Decoding Refresh)图像、CRA(Clean Random Access)图像和BLA(Broken Link Access)图像。
当IRAP的所有前置图像都是RADL图像时,该IRAP图像就是IDR图像。当IRAP的前置图像包含RASL图像时,该IRAP图像就是CRA图像。当直接从CRA介入时RASL图像无法正确解码。当从CRA开始的码流的一部分也属于另一段码流时,如上图中播放顺序在图像2后的图像,其RASL肯定无法正确解码,为了方便处理,这时CRA图像被定义为BLA图像,即明确其RASL图像不需要解码。
编码序列中每幅图像都有一个时域层标识号,低层图像(时域层标识号小)不能参考高层图像,即低层图像不依赖于高层图像。IRAP的时域层标识号为0,H.265/HEVC规定最高时域层号为6。
时域层标识号反映了图像的时域重要性,可以据此进行时域分级。当网络信号不好时,可以选择某个时域层值,丢掉时域标识号大于该值的图像。在HEVC码流中,从某幅图像开始丢弃其后(码流顺序)具有更高层时域标识号的图像,称为时域层下切换。从某幅图像开始可以发送具有该层时域标识号的图像,称为时域层上切换。
在时域可分级中HEVC又定义了两种图像:TSA(Temporal Sub-layer Access)和STSA(Step-wise Temporal Sub-layer Access)。TSA图像表示从该图像开始可以切换到时域层标识号大于或等于该图像时域层标识号的时域层。STSA图像表示从该图像开始可以切换到该图像所属的时域层。TSA图像和STSA图像的时域层标识号必须大于0。
结论
我们希望你现在能更好地理解常见压缩算法的工作原理,以及关键概念,比如图片组、不同帧类型、PTS和DTS。
参考文献:Back to basics: Mechanisms used behind the scenes in video compression | AWS for M&E Blog

浙公网安备 33010602011771号