H.264 把码流自顶向下分成五级:序列级、图像级、片级、宏块级、子块级——越往上写得越少,越往下越重复,丢一个 SPS 会让整段码流报废。
9.2 讲完了原理与流程,9.3 这三节回到码流本身,把它拆到字节级。
一、五级各自管什么
自顶向下,H.264 的分层结构是这五级: 序列级(SPS)——分辨率、帧率、档次、级别; 图像级(PPS)——熵编码方式、QP 初值; 片级(Slice header)——帧类型、参考帧列表、QP 偏移; 宏块级(宏块头)——分块方式、运动矢量差; 子块级(残差)——变换量化后的系数。
二、【片】这一级为什么重要
五级里最容易忽略、却最有工程价值的是【片】: 片是独立的解码单元——一个片可以在不理解其他片的情况下解出来; 这就给丢包提供了边界——一片丢了,其他片还能解(会有一块花屏); 也让并行成为可能——多片可以分给多个线程或核; 代价是每个片都要重新写片头、重新初始化上下文,压缩比会下降; 所以片切得越细,抗丢包越好、压缩比越差——又一组取舍。 直播与弱网场景常把一帧切成多个片,就是这个道理。
三、为什么【越往上越少】
这个规律不是刻意的,而是内容的重复程度决定的: 分辨率、帧率这些参数整段视频只有一套,写一次就够; 片头的部分字段变化也不多; 而每个宏块都有自己的分块方式与矢量——重复次数等于宏块数; 所以把稳定的信息提到上层,是压缩的常识(第 9.1.2 节)。 这也是为什么【丢上层参数】的后果远大于【丢几个宏块】。
四、参数集可以单独传输
SPS 与 PPS 还有一个特殊之处——它们是独立单元,不属于任何一帧: 可以被重复发送,也可以被单独缓存; 于是客户端中途加入时,只要收到 SPS/PPS + 一个 IDR,就能立刻开始播; 这正是 HLS/DASH 分片能无缝衔接的底层原因之一; 反过来,转封装或裁剪时如果弄丢了 SPS/PPS,文件就播不了——这是实际工作中很常见的一类故障。
五、从分层结构到码流字节
这一节给的是骨架,后面两节给的是血肉: 9.3.2 码流结构——这些层级按什么顺序排列在一段码流里; 9.3.3 NAL Unit——每个单元具体由哪些字节组成; 读这两个小节时,可以随时回头对照本节的五级目录,看每一级落在哪个 NAL 单元里。
六、动手 Demo:H.264 的五级分层结构
H.264 把码流自顶向下分成五级,每级各有自己的头。
rows = [("序列级", "SPS", "分辨率、帧率、档次、级别"),
("图像级", "PPS", "熵编码方式、QP 初值"),
("片级", "Slice header", "帧类型、参考帧、QP 偏移"),
("宏块级", "宏块头", "分块方式、运动矢量差"),
("子块级", "残差", "变换量化后的系数")]
for a, b, c in rows:
print("%-6s %-14s %s" % (a, b, c))
实跑输出:
--------------------------------------------------------------------
H.264 的五级分层结构
--------------------------------------------------------------------
H.264 把码流自顶向下分成五级,每级各有自己的头。
层级 头 管什么
-----------------------------------------------------
序列级 SPS 分辨率、帧率、档次、级别
图像级 PPS 熵编码方式、QP 初值
片级 Slice header 帧类型、参考帧、QP 偏移
宏块级 宏块头 分块方式、运动矢量差
子块级 残差 变换量化后的系数
这套结构的意义在**重用**:
**序列级的东西只写一次,图像级的变化少,越往下越具体、越重复。**
所以丢一个 SPS,**后面成千上万个宏块一起报废**——这也是为什么 SPS/PPS 通常要重复发送。
这套结构的意义在重用:序列级只写一次,越往下越具体、越重复。 所以丢一个 SPS,后面成千上万个宏块一起报废——这也是 SPS/PPS 通常要重复发送的原因。
30 秒实验
- 用 FFmpeg 的
-f h264把视频导出成裸码流,用十六进制工具看开头几个字节。 - 找到 0x67(SPS)与 0x68(PPS),它们就是五级结构最上面的两级。
常见误区
- 以为【片】只是数据分块。它是独立的解码单元,决定抗丢包与并发能力。
- 以为参数集属于第一帧。它们是独立单元,可以被单独发送与缓存。
- 以为分层只是【组织方式】。它直接决定丢包后果的严重程度。
自测三问(点开对答案)
1. H.264 码流分成哪五级? —— 序列级、图像级、片级、宏块级、子块级。 2. 【片】为什么重要? —— 它是独立解码单元,提供丢包边界与并行能力。 3. 丢一个 SPS 会有什么后果? —— 解码器不知道分辨率与参数,后续整段码流都无法解析。- ☐ 下一节(9.3.2 H.264码流结构)
相关笔记
- H.264码流结构 — 这些层级的排列顺序
- H.264的NAL Unit — 字节级格式
- H.264的句法元素 — 五层的初始介绍
- 封装格式 — 分层与封装的关系
- 🎬 FFmpeg入门详解 · 索引