PES(Packetized Elementary Stream,分组化基本码流)头部是 MPEG-TS 封装中的关键部分,位于 TS 包的负载中,承载了音视频帧的解码和显示时间戳(PTS/DTS)等核心信息。
音频典型 PES 头:14 字节(仅 PTS),视频典型 PES 头:19 字节(PTS + DTS)
字段详细说明
packet_start_code_prefix(3 字节)
-
固定值:
0x00 0x00 0x01 -
作用:PES 包起始标志
stream_id(1 字节)
标识负载的类型:
| 值范围 | 类型 | 示例 |
|---|---|---|
0x80-0x9F |
视频流 | 0xE0 常用于 H.264/H.265 |
0xC0-0xDF |
音频流 | 0xC0 用于 MPEG 音频 |
0xBC |
节目流目录 | |
0xBD |
DVD 私有流 | |
0xBE |
填充流 | |
0xBF |
私有流 2 |
PES_packet_length(2 字节)
-
值:
PES 头部长度 + 负载长度 -
特殊值:
0表示 PES 包长度未指定,PES 包将持续到流结束
- 标志位 (2 字节,字节6-7)
字节6 (bits 0-7):
| 比特 | 字段 | 长度 | 说明 |
|---|---|---|---|
| 0-1 | PES_scrambling_control |
2 | 00=未加扰,01=保留,10=偶数密钥,11=奇数密钥 |
| 2 | PES_priority |
1 | 1=高优先级 |
| 3 | data_alignment_indicator |
1 | 1=PES 包与访问单元对齐 |
| 4 | copyright |
1 | 1=有版权 |
| 5 | original_or_copy |
1 | 1=原始,0=拷贝 |
| 6-7 | PTS_DTS_flags |
2 | 00=无 PTS/DTS,10=仅 PTS,11=PTS+DTS |
字节7 (bits 8-15):
| 比特 | 字段 | 长度 | 说明 |
|---|---|---|---|
| 0-1 | ESCR_flag |
2 | 01=包含 ESCR |
| 2 | ES_rate_flag |
1 | 1=包含 ES 速率 |
| 3 | DSM_trick_mode_flag |
1 | 1=包含特技模式 |
| 4 | additional_copy_info_flag |
1 | 1=包含附加拷贝信息 |
| 5 | CRC_flag |
1 | 1=包含 CRC |
| 6 | extension_flag |
1 | 1=包含扩展字段 |
| 7 | PES_header_data_length |
8 | 可选字段长度(实际在字节7的低8位?需确认) |
注意 :标准中,PES_header_data_length 独占字节 8,标志位在字节 6 和字节 7 的高位。
PES_header_data_length(1 字节)
-
作用:指明其后
optional_fields+stuffing_bytes的总长度 -
最小值:
0x05(当有 PTS 时)
- 可选字段 (optional_fields)
当 PTS_DTS_flags 不为 00 时,包含以下内容:
| PTS_DTS_flags | 包含内容 | 总长度 |
|---|---|---|
10 |
PTS (5 字节) | 5 字节 |
11 |
PTS (5 字节) + DTS (5 字节) | 10 字节 |
视频帧含pts
00 00 01 E0 00 00 80 80 05 21 00 04 12 05 22 00 04 12 ...
| 字节 | 值 | 字段 | 说明 |
|---|---|---|---|
| 0-2 | 00 00 01 |
packet_start_code_prefix | 起始码 |
| 3 | E0 |
stream_id | 视频流 |
| 4-5 | 00 00 |
PES_packet_length | 未指定长度 |
| 6 | 80 |
标志位高8位 | 1000 0000 → PTS_DTS_flags=10 |
| 7 | 80 |
标志位低8位 | 1000 0000 → 各 flag 为 0 |
| 8 | 05 |
PES_header_data_length | 可选字段长度 = 5 |
| 9-13 | 21 00 04 12 05 |
PTS (5字节) | 解码时间戳 |
| 14+ | ... | 负载 | 视频数据 |
音频帧含pts
00 00 01 C0 00 20 80 80 05 21 00 04 12 05 ...
| 字节 | 值 | 字段 | 说明 |
|---|---|---|---|
| 0-2 | 00 00 01 |
packet_start_code_prefix | 起始码 |
| 3 | C0 |
stream_id | 音频流 |
| 4-5 | 00 20 |
PES_packet_length | 32 字节 |
| 6 | 80 |
标志位高8位 | PTS_DTS_flags=10 |
| 7 | 80 |
标志位低8位 | |
| 8 | 05 |
PES_header_data_length | 5 字节 |
| 9-13 | 21 00 04 12 05 |
PTS | |
| 14+ | ... | 负载 | 音频数据 |
第一帧视频为什么要加AUD 4 字节
第一帧视频加 AUD(Access Unit Delimiter,访问单元分隔符) 的核心原因是:为解码器明确标识一个视频访问单元的起始边界,并携带关键的类型信息,以确保解码器能正确解析后续的 NALU。
这 4 字节不是必需的,但加入 AUD 可以提高视频流的兼容性和鲁棒性,尤其在 MPEG-TS 这种需要频繁随机接入的场景中。
AUD 是一个特殊的 NALU(Network Abstraction Layer Unit),其结构非常简单:

起始码:0x00 0x00 0x00 0x01,标识 NALU 的开始
nal_unit_type = 9:标识这是一个 AUD
primary_pic_type:3 bits,表示后续图像的类型(I/P/B 等)
AUD作用:
AUD 的 3 bits primary_pic_type 告诉解码器该帧的基本类型
解码器无需解析后面的 slice 头就能知道这一帧的类型,有助于快速决策(如丢帧策略、参考帧管理)