📄 一句话概括
B 帧同时参考前后两个方向,残差最小所以最省码率——代价是它必须先解码后面的帧,这就是 DTS 与 PTS 要分开的原因。
📝 本节和前面几节的关系
6.4.4 讲了单方向的运动补偿,这一节讲参考两个方向的版本。
一、三种预测方式
前向预测:只参考前一帧——延迟最低。 后向预测:只参考后一帧——需要先缓存后面的帧。 双向预测:前后都参考,取加权平均——残差最小。 所以 B 帧在码率上最划算,但在时序上最麻烦。
二、为什么双向更省
因为两个参考方向提供的信息是互补的: 前一帧告诉你【它从哪儿来】,后一帧告诉你【它要到哪儿去】。 两者的加权平均往往比任何单个参考都更接近目标——残差自然更小。 这就是 B 帧能压到 I 帧 15% 左右的原因。
三、代价:必须重排序
因为 B 帧要等后面的帧,所以解码顺序与显示顺序不再一致。 编码器必须把【该显示的顺序】与【该解码的顺序】都写进码流—— 前者是 PTS,后者是 DTS。 6.5.3 会给出一个具体的顺序例子,这里先把原因记住。
四、什么时候不用 B 帧
低延迟场景(视频会议、直播)常常禁用 B 帧: 因为 B 帧要缓存后续帧,会引入额外的延迟; 而且一旦丢包,重排序会变得更复杂。 所以在【省码率】与【低延迟】之间,B 帧是一个明确的取舍开关。
五、动手 Demo:双向预测为什么能再省一半
B 帧同时参考前后两个方向,取两者的加权平均。
rows = [("前向预测", "前一帧", "中等", "低延迟"),
("后向预测", "后一帧", "中等", "要缓存"),
("双向预测", "前后两帧", "最小", "要重排序")]
for a, b, c, d in rows:
print("%-8s %-10s %-8s %s" % (a, b, c, d))
实跑输出:
--------------------------------------------------------------------
双向预测为什么能再省一半
--------------------------------------------------------------------
B 帧同时参考前后两个方向,取两者的加权平均。
预测方式 参考 残差大小 代价
------------------------------------------------
前向预测 前一帧 中等 低延迟
后向预测 后一帧 中等 要缓存
双向预测 前后两帧 最小 要重排序
双向预测的残差最小,**所以 B 帧最省码率。**
代价是:**它必须先解码后面的帧**——这就是 DTS 与 PTS 要分开的原因。
双向预测的残差最小,所以 B 帧最省码率。 代价是:它必须先解码后面的帧——这就是 DTS 与 PTS 要分开的原因。
30 秒实验
- 用 ffprobe 看一段视频的帧序列,找出 B 帧的位置。
- 观察它前后是不是都有 P 帧或 I 帧。
常见误区
- 以为 B 帧总是更好。它引入延迟,实时场景常常禁用。
- 把【后向预测】理解成【预测未来】。它只是参考已经编码好的后一帧。
自测三问(点开对答案)
1. 三种预测方式分别参考什么? —— 前向参考前一帧、后向参考后一帧、双向参考前后两帧。 2. 为什么双向预测残差最小? —— 前后两个方向提供的信息互补,加权平均更接近目标。 3. 什么时候应该禁用 B 帧? —— 低延迟场景,如视频会议与直播。- ☐ 下一节(6.5.1 I/P/B/IDR帧)
相关笔记
- 运动补偿 — 单方向的那一套
- DTS和PTS详细讲解 — 重排序的具体例子
- 帧间编码 — B 帧的压缩率从哪来
- 🎬 FFmpeg入门详解 · 索引