TS 头结构
MPEG-TS 包的头部(TS Header) 固定为 4 字节,是 TS 包中最核心的部分,承载了包同步、流标识、加扰、连续性计数等关键信息。TS 头完整结构(4 字节固定 + 自适应域)

TS 头部结构(4 字节 = 32 bits)
| 比特位 | 字段名 | 长度 (bits) | 说明 |
|---|---|---|---|
| 0-7 | sync_byte |
8 | 同步字节,固定为 0x47 |
| 8 | transport_error_indicator |
1 | 传输错误指示符 |
| 9 | payload_unit_start_indicator |
1 | 有效负载单元起始指示符 |
| 10 | transport_priority |
1 | 传输优先级 |
| 11-23 | PID |
13 | 包标识符 |
| 24-25 | transport_scrambling_control |
2 | 传输加扰控制 |
| 26-27 | adaptation_field_control |
2 | 适配域控制 |
| 28-31 | continuity_counter |
4 | 连续性计数器 |
sync_byte(8 bits)
-
固定值:
0x47(ASCII 字符 'G') -
作用:TS 包的同步标识,解码器通过搜索
0x47来定位包起始位置
transport_error_indicator(1 bit)
-
值:
1= 当前 TS 包中至少有一个比特错误;0= 无错误 -
作用:由解调器或信道解码器置 1,表示该包在传输中损坏,解码器应丢弃该包
payload_unit_start_indicator(1 bit)
-
作用:指示当前 TS 包的有效负载是否包含 PES 包或 PSI 表的起始
-
具体含义:
-
对于携带PES 包起始 的 TS 包:该位为
1,且 TS 包负载的第一个字节是 PES 包头 -
对于携带 PSI 表起始 的 TS 包:该位为
1,且 TS 包负载的第一个字节是pointer_field -
对于纯数据包(非起始):该位为
0
-
transport_priority(1 bit)
-
作用:标识该 TS 包的优先级。
1= 高优先级,0= 普通优先级 -
应用:在信道带宽有限时,优先传输高优先级包(如音频或关键视频帧)
PID(13 bits)
-
作用:最重要的字段,标识该 TS 包属于哪个流
-
特殊 PID 值:
| PID 值 | 用途 |
|---|---|
0x0000 |
PAT(节目关联表) |
0x0001 |
CAT(条件访问表) |
0x0002 |
TSDT(传输流描述表) |
0x0003 |
IPMP 控制信息 |
0x0004 - 0x000F |
保留 |
0x0010 - 0x1FFE |
可分配给音视频流、PMT 等 |
0x1FFF |
空包(填充用,解码器应忽略) |
-
PID 分配建议:
-
PMT 表:
0x0100(256) -
视频流:
0x0101(257) -
音频流:
0x0102(258) -
字幕流:
0x0103(259)
-
transport_scrambling_control(2 bits)
-
值:
-
00:未加扰 -
01:保留 -
10:使用偶数密钥加扰 -
11:使用奇数密钥加扰
-
-
作用:指示 TS 包的有效负载是否经过加扰
adaptation_field_control(2 bits) - 重要字段
- 值及含义:
| 值 | 含义 |
|---|---|
00 |
保留(不合法) |
01 |
仅有效负载(无适配域) |
10 |
仅适配域(无有效负载) |
11 |
适配域 + 有效负载 |
-
应用场景:
-
绝大多数 TS 包:
01 -
需要插入 PCR 的包:
11(适配域中存放 PCR) -
填充空包:
10(PID =0x1FFF时)
-
continuity_counter(4 bits)
-
作用:4 位循环计数器,从 0 到 15 递增,用于检测丢包
-
规则:
-
每个 PID 独立的计数器
-
每发送一个该 PID 的 TS 包,计数器加 1
-
当
adaptation_field_control = 10(仅适配域,无负载)时,计数器不递增 -
解码器检查连续性:若连续两个同 PID 包计数器差不为 1(且非上述情况),则检测到丢包
-
TS头部 4 字节
| 字节 | 字段 | 记忆要点 |
|---|---|---|
| 0 | sync_byte |
固定 0x47,TS 包的"身份证" |
| 1 | 标志位 + PID高5位 | 第9位=1 表示 PES/PSI 起始 |
| 2 | PID低8位 | 与字节1组成13位流标识 |
| 3 | 控制位 | bit26-27 决定是否有适配域 |
TS 固定头(4 字节)
代码中的实现:
// 字节0: 同步字节
m_tsBuffer[0] = TS_SYNC_BYTE; // 0x47
// 字节1: payload_start_indicator + PID 高5位
m_tsBuffer[1] = (payloadStart ? 0x40 : 0x00) | ((pid >> 8) & 0x1F);
// 字节2: PID 低8位
m_tsBuffer[2] = pid & 0xFF;
// 字节3: 控制位 + 连续性计数器(稍后设置)
字节0: sync_byte (8 bits)
-
固定值 :
0x47 -
作用:TS 包同步标识
字节1: 高8位
| 比特 | 字段 | 代码实现 |
|---|---|---|
| 7 | transport_error_indicator |
始终为 0(未实现) |
| 6 | payload_unit_start_indicator |
payloadStart ? 0x40 : 0x00 |
| 5 | transport_priority |
始终为 0 |
| 4-0 | PID 高5位 |
(pid >> 8) & 0x1F |
字节2: PID 低8位
- 与字节1的高5位组成完整的 13 位 PID
字节3: 低8位(控制字段)
代码分两种情况设置:
情况1:无自适应域(仅有效负载)
m_tsBuffer[3] = 0x10 | (counter & 0x0F);
// 0x10 = 0001 0000
// 比特7-6: transport_scrambling_control = 00
// 比特5-4: adaptation_field_control = 01 (仅负载)
// 比特3-0: continuity_counter
情况2:有自适应域(自适应域 + 有效负载)
m_tsBuffer[3] = 0x30 | (counter & 0x0F);
// 0x30 = 0011 0000
// 比特7-6: transport_scrambling_control = 00
// 比特5-4: adaptation_field_control = 11 (适配域 + 负载)
// 比特3-0: continuity_counter
| 比特 | 字段 | 值 | 说明 |
|---|---|---|---|
| 7-6 | transport_scrambling_control |
00 |
未加扰 |
| 5-4 | adaptation_field_control |
01 或 11 |
是否有自适应域 |
| 3-0 | continuity_counter |
counter |
连续性计数器 |
自适应域(Adaptation Field)- 可选
当 needAdaptation = true 时,在 TS 固定头后面写入自适应域。
自适应域长度字段
m_tsBuffer[4] = (uint8_t)totalAdaptLen;
// totalAdaptLen = 1(flags) + (writePcr?6:0) + stuffingLen
自适应域标志位
uint8_t flags = 0x00;
if (isKeyFrame) {
flags |= 0x40; // random_access_indicator (RAI)
}
if (writePcr) {
flags |= 0x10; // PCR_flag
}
| 标志位 | 值 | 说明 |
|---|---|---|
random_access_indicator |
0x40 |
指示当前包包含随机访问点(关键帧起始) |
PCR_flag |
0x10 |
指示自适应域中包含 PCR 字段 |
PCR 字段(6 字节)
uint64_t pcrBase = (uint64_t)(m_pcrValue & 0x1FFFFFFFF); // 33 位
uint16_t pcrExt = 0; // 27MHz 扩展部分,设为 0
PCR 编码格式(6 字节 = 48 bits):

-
pcr_base:33 位,90kHz 时钟基值 -
pcr_ext:9 位,27MHz 扩展值(代码中设为 0) -
字节4 中的
0x7E是保留位,必须为01111110
填充字节
if (remain > 0) {
memset(ad, 0xFF, remain); // 用 0xFF 填充
}
完整 TS 包结构示例
示例1:普通视频包(无自适应域)
writeTsHeader(pid=0x0101, payloadStart=false, counter=5, writePcr=false, isKeyFrame=false, stuffingLen=0);
生成 TS 头(4 字节):
47 41 01 1547:同步字节
41:0100 0001 → payload_start=0, PID高5位=0x01
01:PID低8位=0x01 → 完整 PID=0x101
15:0001 0101 → 适配域=01(仅负载),计数器=5
示例2:关键帧第一个包(带自适应域和 RAI)
writeTsHeader(pid=0x0101, payloadStart=true, counter=5, writePcr=false, isKeyFrame=true, stuffingLen=0);
生成 TS 头(4 + 2 = 6 字节):
47 41 01 35 01 40 47 41 01:同上
35:0011 0101 → 适配域=11(适配域+负载),计数器=5
01:自适应域长度 = 1(仅 flags,无 PCR)
40:flags → random_access_indicator=1
示例3:带 PCR 的包
writeTsHeader(pid=0x0101, payloadStart=false, counter=5, writePcr=true, isKeyFrame=false, stuffingLen=0);
生成 TS 头(4 + 1 + 1 + 6 = 12 字节):
47 41 01 35 07 10 [PCR 6字节...]
35:适配域=11
07:自适应域长度 = 7(1字节flags + 6字节PCR)
10:flags → PCR_flag=1
[PCR 6字节]:节目时钟参考
TS 头字段速查表
| 字节 | 字段 | 长度 | 典型值 | 说明 |
|---|---|---|---|---|
| 0 | sync_byte |
8 bits | 0x47 |
同步 |
| 1 | transport_error_indicator |
1 bit | 0 |
错误标志 |
| 1 | payload_unit_start_indicator |
1 bit | 0/1 |
PES/PSI 起始 |
| 1 | transport_priority |
1 bit | 0 |
优先级 |
| 1-2 | PID |
13 bits | 0x0101 |
包标识符 |
| 3 | transport_scrambling_control |
2 bits | 00 |
加扰 |
| 3 | adaptation_field_control |
2 bits | 01/11 |
适配域控制 |
| 3 | continuity_counter |
4 bits | 0-15 |
连续性计数器 |
| 4+ | adaptation_field |
可变 | - | 自适应域(可选) |