logo

视频帧名词解释

GOP / I-帧 / P-帧 / B-帧 / DTS / PTS 🎞️


在排查 WebRTC 丢包问题时,我们会接触到一些视频帧相关的名词,如 GOP、I-帧、P-帧、B-帧等。如果是之前对视频编解码不是特别了解的同学(比如笔者)可能会有些疑惑。因此本文尝试将这些名词逐一解释,方便大家查阅。

我们都知道,当多张连续图像以一定的速率(比如每秒 24 张)播放,即可形成视频。但视频传输却并不是单纯地发送连续图像这么简单。假设一张图像分辨率为 1280x720,且每个 ARGB 像素点大小为 32bits,则单张图像大小约为 29.5Mbits;如果每秒需要传输 24 张,则大约需要占用约 708Mbits/s 的带宽。显然这样的带宽占用是不现实的。

由此便引申出了视频编码技术,比如常见的 H.264、VP8 等编码格式。这些技术的基本思想都是类似的。我们可以将一张完整的图像分为很多小的图像块(Macroblock)。如下图 1 所示,人在挥手时身体并没有动,那么身体部分的图像块即是冗余信息,没必要每次都传输;可以只传输挥手的那部分,接收方再将其与之前的某些参考图像 diff 即可得到最新的图像:

图中的 Intraframe 即我们常说的 I-帧,而 Interframe 则包含了 P-帧和 B-帧。

GOP 结构

由一个 I-帧和若干个 P-帧和 B-帧组成的连续帧序列则称为一个 GOP(Group of Pictures)。编码器会将视频编码为多个连续的 GOP,以下便是一个典型的 GOP 结构图:

I-帧即帧内编码,是一种不需要其他参考帧即可编码的视频帧。一个视频文件总是以 I-帧开头,并拥有一定间隔的 I-帧序列。I-帧有时也被称为关键帧(Keyframe),我们可以通过 I-帧随机访问该文件中的(几乎)任意位置,实现快退和快进;也可以通过读取 I-帧序列实现视频预览,比如下图便是 Google Photos 编辑视频的拖动条:

当然,由于 I-帧每次都对整个图像进行编码,它所占的体积(磁盘或带宽)也是最大的。

P-帧(Predicted)属于帧间预测的一种,它需要之前的 I-帧或 P-帧作为参考帧进行编码。P-帧会分析出参考帧中总是不变的部分,只有变化的部分会被编码,因此 P-帧比 I-帧的体积要小得多。当然,由于 P-帧需要参考帧,所以它对传输错误的容忍度较低。

B-帧(Bi-directional Predicted)也属于帧间预测,它需要同时使用之前的 I-帧或 P-帧和之后的 I-帧或 P-帧进行编码,记录的是前后参考帧之间的差别,压缩比更高。但 B-帧显然增加了编码复杂度,且对延迟要求较高,所以在实时通话领域通常不使用 B-帧。

DTS 和 PTS

由于 B-帧需要未来的参考帧才能解码,于是便有了 DTS(Decode Timestamp,解码时间戳)和 PTS(Presentation Timestamp,显示时间戳)的概念。

编码器在编码时需要提供 DTS 和 PTS;而解码器在解码时会根据 DTS 顺序解码,再根据 PTS 顺序播放。当然,编码器是按照 DTS 顺序进行编码的,视频帧也是按照 DTS 顺序传输的。

以上述 GOP 结构图为例,PTS 顺序为图中的 1-9 顺序,对应的 DTS 顺序如下:

     I B P B P B P B I
PTS: 1 2 3 4 5 6 7 8 9
DTS: 1 3 2 5 4 7 6 9 8

即在解码 B-帧之前,先根据 DTS 解码它需要的所有参考帧,再根据 PTS 组帧播放。不过我们在实时通话领域通常不使用 B-帧,所以 DTS 通常等于 PTS。

以上便是 WebRTC 中常见的视频帧名词了,理解这些名词有助于我们后续理解 WebRTC 的 NACK、PIL 和 FIR 等丢包处理机制。当然,本文也仅仅涉及了视频编码的基础内容,更多编码相关的内容已经超出了笔者目前的能力范围,感兴趣的读者可以自行深入。