目录
[1. 帧间和帧内预测(Inter- and Intra- Prediction)](#1. 帧间和帧内预测(Inter- and Intra- Prediction))
[2. I帧(帧内编码帧或独立帧)(Intra-Frame or Independent Frame)](#2. I帧(帧内编码帧或独立帧)(Intra-Frame or Independent Frame))
[3. P帧(预测帧)(Inter- and Intra- Prediction)](#3. P帧(预测帧)(Inter- and Intra- Prediction))
[4. B帧(双向帧) (Bi-Directional Frame)](#4. B帧(双向帧) (Bi-Directional Frame))
I帧、P帧和B帧是视频压缩的基础。这三种帧类型在特定情况下用于提高编解码器的压缩效率、压缩后视频流的质量以及视频流对传输和存储错误及故障的恢复能力。
1. 帧间和帧内预测(Inter- and Intra- Prediction)
例如,下图显示了两个相邻的视频帧,每个帧中都有一个黑色像素组成的矩形块。在第一帧中,该像素块位于图像的左侧;在第二帧中,它移动到了右侧。
如果我想使用像 H.264 或 HEVC 这样的现代视频编解码器来压缩第 2 帧,我们会这样做:
**(1)**将视频分割成像素块(宏块(macblock)),并逐个压缩。
**(2)**为了压缩每一个宏块,第一步是在当前帧、前一帧或后一帧中查找与待压缩宏块相似的宏块。
(3) 记录最佳匹配宏块的位置(帧数及其在该帧中的位置)。然后,压缩两个宏块的差异,并将其与位置信息一起发送给解码器。
请看下图。如果我们想压缩第 2 帧中的宏块(我们用红方框标记了它),你认为最佳方案是什么?或者应该如何操作?

(1) 首先,我们可以在第一帧中找到匹配的方块。它似乎移动了大约一帧的宽度,高度也大致相同。这个移动提供了运动向量。
(2) 我们可以在同一帧内搜索,并很快发现红色标记方块上方的方块与它完全相同。因此,我可以指示解码器复制这个方块,而无需在另一帧中查找。运动向量(如果有的话)也非常小。
现在来看下一个例子。我们想要压缩第 2 帧中包含蓝色球体的宏块。我们应该怎么做呢?是在同一帧内搜索,还是在之前编码过的帧中搜索?

**(1)**首先,我可以查看第 1 帧,找到匹配的球面。它似乎移动了大约帧宽的距离(我匀知道实际距离略小一些),并且向上移动了一点。这给了我们运动向量。包含球面的两个方块之间的差异似乎非常小(只是估计!)。
**(2)**其次,我可以在同一帧内搜索,发现没有其他方块包含球成。所以,在同一帧内寻找匹配项的尝试失败了!
那么,我们从这些示例中学到了什么?
(1) 编码器通过寻找匹配的宏块来减少需要传输的数据量。这是通过运动估计和补偿实现的。这使得编码器能够找到宏块在另一帧中的水平和垂直位移。
(2) 编码器可以在同一帧内(帧内预测)和相邻帧内(帧间预测)寻找匹配的宏块。
(3) 它比较每一个宏块的帧内预测和帧间预测结果,并选择"最佳"结果。这个过程称为"模式选择",它应当是视频编解码器的核心。
2. I 帧(帧内编码帧或独立帧)(Intra-Frame or Independent Frame)
I 帧(也称关键帧 (Key-Frame)或帧内帧 (Intra-frame),或独立帧(independent))仅由使用帧内预测的宏块组成。
I 帧中的每个宏块只能引用同一帧内的其他宏块。它只能利用帧内的"空间冗余"进行压缩。空间冗余是指单帧像素之间的相似性(相关性)。
I 帧在不同的视频编解码器中以不同的形式出现,例如 IDR、CRA 或 BLA 帧,但这些类型 I 帧的本质相同------不允许进行时间预测。
I 帧有很多用途,我们将在介绍 P 帧和 B 帧之后进行探讨。
3. P 帧(预测帧)(Inter- and Intra- Prediction)
P帧代表预测帧 (Predicted-Frame),它允许使用时间预测(而非空间预测)来压缩宏块。对于运动估计(motion estimation),P帧使用先前已编码的帧。在本质上,P帧中的每一个宏块都可以:
时间上预测,或
空间上预测,或
跳过(即,告诉解码器从上一帧复制同位置的块------"零"运动矢量)。

你可以在上图中看到 I 帧和 P 帧。如前所述,P 帧指的是之前编码过的 I/P 帧。你还可以看到,帧的编码/解码顺序与它们呈现给用户的顺序相同。这是因为 P 帧仅引用之前编码过的图片。
4. B 帧(双向帧) (Bi-Directional Frame)
B帧是指可以引用其前后帧的帧。因此,B代表双向(Bi-Directional)。如果你的视频编解码器使用基于宏块的压缩(例如H.264/AVC),那么B帧的每一个宏块都可以是
· 使用后向预测(使用未来发生的帧)进行预测
· 使用前向预测(使用过去发生的帧)进行预测
· 不使用帧间预测进行预测------仅使用帧内预测
· 完全跳过(使用帧内或帧间预测)。
由于 B 帧可以引用并插值其前后(时间维度上)的两个(或更多)帧 ,因此 B 帧能够在保持视频质量的同时,极其有效地减小帧的大小。它们可以利用空间和时间上的冗余(未来的帧和过去的帧),这使得它们在视频压缩中非常有用。
然而,B帧会消耗大量资源------无论是在编码器还是解码器端。原因在于:
为了理解B帧的影响,我们先来了解一下呈现/显示顺序和解码顺序的概念。
以I帧和P帧为例。如果只使用这两种图像类型,每一帧都会指向自身( I帧 )或前一帧( P帧 )。因此,帧可以按照相同的顺序进入和输出编码器。这里,呈现顺序(或显示顺序)与解码/编码顺序相同。

但如果一帧引用的是未来才会显示的另一帧,该怎么办呢?这种情况在我们用 B 帧进行压缩时就会遇到。请看下图,它展示了一个 GOP(图像组)结构,其中每一个 mini-GOP 使用了两个 B 帧和一个 P 帧,即 IBBPBBP。

显示顺序中的第 2 帧是 B 帧,它依赖于第 1 帧和第 4 帧作为参考帧。但是,要对第 2 帧进行编码,我们需要等到第 4 帧进入编码器并完成编码后,才能将其作为第 2 帧的参考帧。
解码器也存在同样的情况。在解码顺序中,解码器先解码第 1 帧( I 帧 ),然后再解码第 2 帧( P 帧 )。但是播放器无法显示第 2 帧,因为它在显示顺序中是第 4 帧!因此,解码器需要将第 2 帧(在解码顺序中)放入缓冲区,直到需要显示它时再取出。
因此,编码器和解码器需要在其内存中维护两个"顺序"或"队列"------一个用于将帧按正确的显示顺序放置,另一个用于将帧按编码和解码所需的顺序放置。
由于需要重新排序,B帧会影响解码器缓冲区的大小并增加延迟。
因此,许多系统会限制可用于压缩单个B帧的参考帧数量。同样,H.264/AVC的Baseline 配置文件面向低端设备,不允许使用B帧或分片。