接上文,本篇介绍下TS的封装格式。
1.什么是TS?
TS(Transport Stream,传输流),一种常见的视频封装格式,是基于MPEG-2的封装格式(所以也叫MPEG-TS),后缀为.ts。
2.TS的分层结构
TS文件分为三层,如下所示(可以倒序看更好理解):
◆ TS层(Transport Stream):在PES层基础上加入了数据流识别信息和传输信息。
◆ PES层(Packet Elemental Stream):在ES层基础上加入时间戳(PTS/DTS)等信息。
◆ ES层(Elementary Stream):压缩编码后的音视频数据。
2.TS层
◆ ts包大小固定为188字节,ts层分为三个部分:ts header、adaptation field、payload。
◆ ts header固定4个字节;
◆ adaptation field可能存在也可能不存在,主要作用是给不足188字节的数据做填充。
◆ payload是 PES 数据,或者PAT,PMT等。
◆ ts Header + adaptation field 格式如下:
2.1 TS Header
◆ TS Header格式如下:
◆ pid 决定了负载内容的类型,主要包括:PAT表,PMT表,视频流,音频流。常用的PID值:
表 | PAT | CAT | TSDT | EIT,ST | RST,ST | TDT,TOT,ST |
PID | 0x0000 | 0x0001 | 0x0002 | 0x0012 | 0x0013 | 0x0014 |
2.2 调整字段
2.3 PAT表结构(指明PMT表的PID值)
typedef struct TS_PAT{
unsigned table_id :8 //固定位0x00,表示该表是PAT
unsigned section_syntax_indicator :1 //段语法标志,固定为1
unsigned zero :1 //固定为0
unsigned reserved_1 :2 //第一个保留位
unsigned section_length :12 //表示这个字节之后有用的字节数,包括CRC_32
unsigned transport_stream_id :16 //传输流的ID,区别于一个网络中其他多路复用的流
unsigned reserved_2 :2 //第二个保留位
unsigned version_number :5 //表示PAT的版本号
unsigned current_next_indicator :1 //表示发送的PAT是当前有效还是下一个有效,为1时代表当前有效
unsigned section_number :8 //如果PAT分段传输,那么此值每次递增1
unsigned last_section_number :8 //最后一个分段的号码
for(int i=0;i<N;i++){
unsigned Program_number :16 //节目号
unsigned Reversed_3 :3 //保留位
if(Program_number == 0)
Network_id :13 //网络信息表(NIT)的PID
else
Program_MAP_PID :13 //节目映射表的PID,每个节目都有一个
}
unsigned CRC_32 :32 //CRC32校检码
}TS_PAT
2.4 PMT表(指明音视频流的PID值)
typedef struct TS_program_map_section{
unsigned Table_id :8 //标志PSI分段的内容,对于PMT,此值为0x02
unsigned Section_syntax_indicator :1 //置为1
unsigned '0' :1
unsigned Reserved :2 //保留位
unsigned Section_length :12 //指明了自此到最后CRC_32的字节数
unsigned Program_number :16 //指出该节目的节目号,与PAT表对应
unsigned Reserved :2 //保留位
unsigned Version_number :5 //取值0-31,代表当前PMT的版本号
unsigned Current_next_indicator :1 //代表当前PMT是否有效
unsigned Section_number :8 //给出了当前所处段的数目
unsigned Last_section_number :8 //给出了最后一个分段,即分段的最大数目
unsigned Reserved :3 //保留位
unsigned PCR_PID :13 //指示TS包的PCR值,该TS包含有PCR字段
unsigned Reserved :4 //保留位
unsigned Program_info_length :12 //该字段描述跟随其后对节目信息描述的字节数
for(int i = 0; i < N; i++)
Descriptr()
for(int i = 0; i < N; i++){
unsigned Stream_type :8 //0x00:保留, 0x01:MPEG1视频,0x02:MPEG2视频,0x03:MPEG1音频,0x04:MPEG2音频,0x05:私有字段,0x06:含有私有数据的PES包 ......
unsigned Reserved :3 //保留
unsigned Elementary_PID :13 //指示TS包的PID,这些TS包含有相同的PID
unsigned Reserved :4 //保留
unsigned ES_info_length :12 //指示跟随其后描述相关节目元素的字节数
for(int j = 0; j < N2; j++)
Descriptr()
}
unsigned CRC_32 :32 //循环校检位
}
2.4 补充说明
◆ 打包ts流时PAT和PMT表是没有调整字段的,不够的长度直接补0xff即可。
◆ 视频流和音频流都需要加adaptation field,通常加在一个帧的第一个ts包和最后一个ts包里,中间的ts包不加。
3.PES 层
◆ PES(Packetized Elementary Stream,打包的ES),在 ES 层的基础上加入了时间戳(PTS/TDS)等信息。
◆ ES数据包比较大,加入PES头时需将ES进行分割,只在第一个分割的ES上加PES头,如下图所示:
◆ PES packet length — 指示PES 包中跟随该字段最后字节的字节数。0 值指示PES 包长度既未指示也未限定并且仅在这样的PES 包中才被允许,该PES 包的有效载荷由来自传输流包中所包含的视频基本流的字节组成。
◆ PES结构如下:
◆ PES 关键字段说明
5.ES 层
◆ ES(Elementary Stream,基本码流),就是音视频编码数据流,比如视频H.264,音频AAC。
◆ 一个 ES 流中只包含一种类型的数据(视频,或音频,或字幕)。
6.easyice下载链接:
easyice:https://www.easyice.cn/archives/85
音视频入门系列,同步录制了学习视频,已上传至bilibili(八小时码字员):音视频入门系列(图像、音频、字幕、视频封装格式,FFmpeg、ffplay源码分析,解码、编码、转码,流媒体协议,服务器部署)_哔哩哔哩_bilibili