I帧、P帧和B帧(I-frames、P-frames and B-frames)的概念是视频压缩领域的基础。这三种帧类型在特定情况下用于提高编解码器的压缩效率、压缩流的视频质量,以及使得流去应对传输和存储时候的错误和故障。
翻译 | Alex
技术审校 | 赵军
本文来自OTTVerse,作者为Krishna Rao Vijayanagar。
I帧、P帧和B帧 Easy-Tech #002
在本篇文章中,我们将学习I帧、P帧和B帧的工作原理以及它们的用途。
好,我们先从现代视频压缩中最基本的概念开始——帧内预测和帧间预测。
帧内预测和帧间预测
在本篇文章中,我并不会深入讲解帧内预测和帧间预测(Intra and Inter-prediction)的技术细节,但是我会告诉你它们为何存在以及有什么用处。
以下方图片为例。图片显示了两个视频帧(彼此相邻),有一个黑色像素的矩形块在其中移动。在第一帧中,该块位于图像的左侧,而在第二帧中,它已经移到了右侧。
如果我想用现代视频编码器(如H.264或HEVC)压缩帧2,我会这样做:
1.将视频分解为多个像素块(宏块),并逐一压缩。
2.为了压缩每个宏块,首先在当前帧和前后帧中搜索,找到与我们想要压缩的宏块相似的宏块。
3.记录最佳匹配的宏块的位置(位于哪一帧以及在该帧中的位置)。然后,两个宏块之间的差异被压缩,并和位置信息一起被发送给解码器。
请看下方图片。如果要压缩帧2中的宏块(已用红色方框标记),你认为最佳方法是什么?该怎么做?
1.首先,我可以查看帧1,并找到相匹配的宏块。它似乎移动了一个帧宽(我知道要少一些)的距离,并与帧2中像素块的高度大约相同。好的,运动矢量出现了。
2.我在同一帧内搜索,并很快发现,位于红色方框标记的宏块与上方的宏块相同。所以,我可以让解码器复制这一宏块,而不必再去其他帧搜索。这样一来,运动矢量便是最小的(如果存在的话)。
现在我们来看下一个示例。如果想要压缩帧2中包含蓝色球体的宏块,我们该怎么做呢?
在同一帧内搜索,还是在前面的编码帧中搜索?
1.首先,我查看了帧1并找到了相匹配的球体,它似乎移动了一个帧宽(我知道要少一些)的距离,并向上移动了一些。这让我们得到了运动矢量。另外,包含两个球体的宏块之间的差异似乎非常小(猜测的)。
2.然后我在同一帧内搜索,马上意识到相同帧里面并没有包含球体的其他宏块。看来这次运气不太好,没有在同一帧内找到匹配的宏块。
从上面那些示例中,我们都学到了什么?
1.编码器搜索匹配宏块以减少需要传输的数据的大小,整个过程通过运动估计和补偿来完成,这使得编码器可以在另一帧内发现宏块的水平和垂直位移。
2.编码器可以在同一帧内(帧内预测)和相邻帧内(帧间预测)搜到匹配的宏块。
3.它比较每个宏块的帧间和帧内预测结果,并选出最佳结果。这个过程被称为“模式选择”,我认为这是视频编码器最核心的部分。
现在,看完对帧内预测和帧间预测的快速介绍,让我们来学习I帧、P帧和B帧吧!
什么是I帧?
I帧或关键帧或帧内帧(I-frame or Key-Frame or Intra-frame)仅由帧内预测的宏块组成。
I帧中的每个宏块只能在同一帧内匹配其他宏块,这意味着,它只能利用帧内“空间冗余”来进行压缩。空间冗余是一个术语,用来指单个帧的像素之间的相似性。
I帧在不同的视频编解码器中以不同的形式出现,如IDR、CRA或者BLA。这些不同类型的I帧本质相同:都不存在时域预测。
I帧有很多用处,在我们学习P帧和B帧之后,我们再来研究。
什么是P帧?
P帧代表预测帧,除了空域预测以外,它还可以通过时域预测来进行压缩。P帧参考前面的帧进行运动估计。P帧中的每个宏块都可以被:
- 时域预测
- 空域预测
- 跳过(skipped)(是指让解码器复制前一帧内的位于相同位置的宏块——0运动向量)
我制作了一张插图来说明其中的重点。上图中显示了I帧和P帧。如前面讨论,P帧参考前面的I帧或者P帧。图中,帧的编码、解码顺序与它们呈现在用户面前的顺序一致。这是因为P帧只参考前面的图像来进行编码。
什么是B帧?
B帧可以参考在其前后出现的帧。B帧中的B就代表双向(Bi-Directional)。如果你的视频编解码器使用基于宏块的压缩(如H.264/AVC所做的一样),那么B帧中的每个宏块都可以:
- 后向预测(使用未来的帧)
- 前向预测(使用过去的帧)
- 无帧间预测,仅帧内预测
- 完全跳过(帧内或帧间预测)
由于B帧可以参考和插入在它之前和之后发生的两个(或更多)帧(在时间维度上),所以它可以显著降低帧的大小,同时保持视频质量。B帧能够利用空间冗余和时间冗余(未来的帧和过去的帧),这使得它在视频压缩中非常有用。
但是,B帧是资源密集型——无论是从编码侧还是解码侧看,让我们来看看原因。
想要理解B帧的作用,我们需要先理解呈现/显示顺序和解码顺序的概念。
以I帧和P帧为例。如果你只使用这两种类型的帧,那么每一帧要么参考自身(I 帧),要么参考前一帧(P 帧)。因此,帧可以以相同的顺序进出编码器。这里,呈现顺序(或显示顺序)与编码、解码顺序相同。
但如果某一帧要参考未来显示的一帧,你要怎么做呢?这是我们在使用B帧压缩时经常遇到的情况。下图中显示了一个GOP(group of pictures)结构,GOP是一组连续的画面,在每一个mini-GOP中,都使用了两个B帧和一个P帧,也就是IBBPBBP。
解码器端也是如此操作。
按照解码顺序,解码器先解码帧1(I帧),然后是帧2(P帧)。但它却无法显示帧2,因为在解码顺序中的实际上是帧4!所以,解码器需要将帧2(按解码顺序)放入缓冲区,然后等待显示它的时机。
所以,编码器和解码器需要在内存中维护两个“顺序”或“序列”:一个将帧放置在正确的显示顺序中,另一个用于将帧按照编码和解码所需顺序放置。
由于重新排序的要求,B帧会影响解码器缓冲区的大小,并增加延迟。
这就是为什么许多系统在压缩一个B帧时,对可用作参考的帧数做出严格的限制的原因。按照同样的思路,H.264/AVC的Baseline profile因为瞄准低端设备的,所以不允许使用B帧或Slice。
参考B帧和非参考B帧
我们在上文中学过,B帧可以参考两帧或者多帧,通常,(根据其位置)一帧在前,一帧在后。我们也已知道,I帧不参考任何帧,P帧只参考前面的帧。那么问题来了——任何帧都能使用B帧作为它的参考帧吗?
答案是肯定的。
- 如果B帧可以作为参考帧,它就被称为参考B帧。
- 如果B帧不用作参考帧,它便被称为非参考B帧。
在比特流中标明参考B帧和非参考B帧非常重要,因为解码器需要在DBP(Decoded Picture Buffer,解码图像缓存)中存储参考帧。
如果某一帧被标记为非参考B帧,但却将其用作参考帧,那么解码器很可能崩溃。因为解码器大概率在解码和显示之后就已经删除此帧。
与非参考B帧相比,大部分解码器在量化参考B帧时会获得更好的质量,从而减少传播损失。
在视频压缩/流化中使用I、P和B帧
在理解了I帧、P帧和B帧的工作原理之后,我们来解决一个重要问题:为什么要使用它们?
在下面内容中,我们会学习I帧、P帧和B帧在视频压缩中最重要的用例。
在哪里使用I帧?
我们在前面的部分了解到,I帧可以被独立地编码、解码,这使得它在视频压缩中得到广泛应用。
刷新视频质量
I帧的插入通常表示GOP(或视频片段)的结束。I帧压缩不依靠前一帧编码,从而可以刷新视频质量。正因为I帧在保持视频质量方面有如此重要的作用,所以通常情况下,编码器会在大小和质量方面偏向I帧。在编码高质量的I帧后,编码器便可以使用该I帧作为参考图像来压缩P帧和B帧。
那I帧只能用于刷新视频质量吗?不仅如此。
恢复比特流错误
我们之前说过,I帧可以被独立地编码和解码。这意味着I帧可用于恢复视频文件或视频流中的灾难性故障。
我们来看看是它是如何做到的。
如果P帧和参考B帧遭到破坏,其他所有依赖于它们的帧就不能完整解码,这会直接导致视频故障。视频通常无法从此类问题中恢复。然而,当被破坏的视频流到达I帧,因为I帧被独立地编码解码,所以视频问题可以从I帧恢复。
这种I帧通常被称为IDR帧(Instantaneous Decoder Refresh,即时解码刷新),并且这种不参考I帧之前图像的行为被称为闭合GOP(Closed GOP)。
IDR帧通常在ABR流中表示视频的某个新片段。由IDR帧开始,平台可以确保新片段能够独立于其他片段被解码。即使由于传输问题导致一些片段损坏或丢失,这一特性也能保证视频可以继续播放。
Trick Modes(快进快退)
最后,关键帧对于Trick Modes来说至关重要!
如果想在一个视频中快进快退,则在视频开始时需要一个I帧,对吧?
假设你搜索到的是P帧或者B帧,但解码器已经从内存中删除了参考帧,你该怎么重建它们呢?视频播放器很自然地会找到一个起始点(I帧)并成功解码,然后从这一点开始播放。
这又引出另一个有趣的事情。
如果你的关键帧在视频中相隔时间很长,假设它们之间间隔20秒,那么你的用户只能以20秒为增量进行快进快退,这样的体验非常糟糕!
如果关键帧放置太多,那么虽然快进快退体验会很棒,但这时候视频就太大了,可能导致网路缓冲等问题。
所以设计出最佳的GOP和mini-GOP结构真的是一项平衡的艺术。
在哪里使用P帧和B帧?
人们经常会问:在哪里、什么时候以及如何使用P帧和B帧?
如果你已经理解上文中所描述的P帧和B帧的工作原理,那么你就知道P帧和B帧可以在减少视频大小的同时,保证视频质量。这就是它们的主要用途!在合适的位置插入P帧和B帧可以减小视频文件尺寸或者比特率,并且仍能保持一定的视频质量水平。
基于你所使用的GOP和mini-GOP结构,使用相关QP值压缩P帧和B帧(被参考或者不被参考),你就可以达到目标比特率或视频质量。
小 结
我希望这篇关于I帧、P帧和B帧的文章能够帮助你增加关于视频压缩的知识。想要更深入地理解它们,你可以下载静态编译好的 FFmpeg 版本,并在 FFmpeg 中使用 GOP、no-b-frame 相关设置来查看视频的大小及其质量如何变化。
本文已获得作者Krishna Rao Vijayanagar授权发布,特此感谢。
扫描图中二维码解大会更多信息
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。