SRT协议封装MPEG-TS 流的视频和音频TS头结构

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 连续性计数器
  1. sync_byte (8 bits)
  • 固定值:0x47(ASCII 字符 'G')

  • 作用:TS 包的同步标识,解码器通过搜索 0x47 来定位包起始位置

  1. transport_error_indicator (1 bit)
  • 值:1 = 当前 TS 包中至少有一个比特错误;0 = 无错误

  • 作用:由解调器或信道解码器置 1,表示该包在传输中损坏,解码器应丢弃该包

  1. payload_unit_start_indicator (1 bit)
  • 作用:指示当前 TS 包的有效负载是否包含 PES 包或 PSI 表的起始

  • 具体含义:

    • 对于携带PES 包起始 的 TS 包:该位为 1,且 TS 包负载的第一个字节是 PES 包头

    • 对于携带 PSI 表起始 的 TS 包:该位为 1,且 TS 包负载的第一个字节是 pointer_field

    • 对于纯数据包(非起始):该位为 0

  1. transport_priority (1 bit)
  • 作用:标识该 TS 包的优先级。1 = 高优先级,0 = 普通优先级

  • 应用:在信道带宽有限时,优先传输高优先级包(如音频或关键视频帧)

  1. 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)

  1. transport_scrambling_control (2 bits)
  • 值:

    • 00:未加扰

    • 01:保留

    • 10:使用偶数密钥加扰

    • 11:使用奇数密钥加扰

  • 作用:指示 TS 包的有效负载是否经过加扰

  1. adaptation_field_control (2 bits) - 重要字段
  • 值及含义:
含义
00 保留(不合法)
01 仅有效负载(无适配域)
10 仅适配域(无有效负载)
11 适配域 + 有效负载
  • 应用场景:

    • 绝大多数 TS 包:01

    • 需要插入 PCR 的包:11(适配域中存放 PCR)

    • 填充空包:10(PID = 0x1FFF 时)

  1. 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 0111 是否有自适应域
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 可变 - 自适应域(可选)
相关推荐
Cxiaomu3 小时前
Flutter 录制视频+大文件上传 MinIO + NodeJS落库
flutter·音视频·文件上传
.select.3 小时前
TCP 4(四次挥手)
服务器·网络·tcp/ip
一个行走的民3 小时前
Ceph PG 状态详解与线上故障处理
网络·ceph
RTC老炮3 小时前
WebRTC PCC (Performance-oriented Congestion Control) 算法精解
网络·算法·webrtc
李宏伟~3 小时前
大文件分片案例html + nodejs + 视频上传案例
javascript·html·音视频
初遇见3 小时前
【DGX Spark v3.0:基于多智能体交互网络与 Alpaca 实盘集成的企业级量化交易系统】
大数据·网络·spark·nvidia
码云数智-大飞3 小时前
解耦的艺术:.NET 中依赖注入(DI)的核心原理与实战
网络·网络协议·rpc
云边云科技_云网融合4 小时前
网关接入异常监测预警:从固定阈值到 AI 动态感知的技术革新
运维·服务器·网络·人工智能