【网络通信 -- 直播】音视频常见封装格式 -- MEPG2 TS
【1】相关码流基本概念
- ES 流(Elementary Stream)基本码流,直接取自编码器的数据流,可以为音频(AAC 等)、视频(H264,MJPEG 等)或其他数据流,ES 流经过 PES 打包器之后,被转换成 PES 包;
- PES 流(Packetized Elementary Stream)把基本流 ES 分割成段,并加上相应头文件打包成形的打包基本码流;ES 形成的分组称为 PES 分组,是用来传递 ES 的一种数据结构;PES 流是 ES 流经过 PES 打包器处理后形成的数据流,在这个过程中完成了将 ES 流分组、打包、加入包头信息等操作(对 ES 流的第一次打包),PES 流的基本单位是 PES 包,PES 包由包头和载荷(payload)组成;
- PTS,PresentationTime Stamp(显示时间标记)表示显示单元出现在系统目标解码器(H.264、MJPEG 等)的时间;
- DTS,Decoding Time Stamp(解码时间标记)表示将存取单元的全部字节从解码缓存器移走的时间;
- PTS/DTS 存在于 PES 包的包头中,这两个参数是解决音视频同步显示,防止解码器输入缓存上溢或下溢的关键;每一个 I(关键帧)、P(预测帧)、B(双向预测帧)帧的包头都有一个 PTS 和 DTS,但 PTS 与 DTS 对于 B 帧不一样,无需标出 B 帧的 DTS,对于 I 帧和 P 帧,显示前一定要存储于视频解码器的重新排序缓存器中,经过延迟(重新排序)后再显示,因此一定要分别标明 PTS 和 DTS;
- PS 流(Program Stream)节目流,由 PS 包组成,一个 PS 包由若干 PES 包组成,PS 包的包头包含了同步信息与时钟恢复信息,一个 PS 包最多可以包含具有同一时钟基准的 16 个视频 PES 包和 32 个音频 PES 包;
- TS 流(Transport Stream)传输流,由定长的 TS 包组成,TS 包是对 PES 包的一个重新封装,PES 包的包头信息仍存在于 TS 包中;
- TS 流 VS PS 流
- TS 流与 PS 流的区别在于 TS 流的包结构是固定长度的,PS 流的包结构是可变长度的;
- PS 包由于长度是变化的,一旦丢失某一 PS 包的同步信息,接收机就会进入失步状态,从而导致严重的信息丢失事件;
- TS 码流由于采取了固定长度的包结构,当传输误码破坏了某一 TS 包的同步信息时,接收机可在固定的位置检测其后面包中的同步信息,从而恢复同步,避免了信息丢失;
- 通常在信道情况较为恶劣、传输误码较高时一般采取 TS 码流,在信情况较好、传输误码较低时一般采取 PS 码流;
- TS 单一码流、混合码流
- 单一性,TS 流的基本组成单位是长度为 188 字节的 TS 包;
- 混合性,TS 流由多种数据组合而成,一个 TS 包中的数据可以是视频数据,音频数据,填充数据,PSI/SI 表格数据等(唯一的 PID 对应);
- TS 流 VS PS 流
【1.1】MEPG2 系统中编码实现单一码流的过程
- 1) A/D 转换后,通过 MPEG-2 压缩编码得到 ES 基本流,该数据流很大,并且只是 I,P,B 视频帧或音频取样信息;
- 2) 通过 PES 打包器,打包并在每个帧中插入 PTS/DTS 标记,生成 PES,从原来的流的格式,变成了数据包的分割形式;
- 3) PES 根据需要打包成 PS 或 TS 包举行存储(DVD)或传输(DVB);因每路音/视频只包含一路的编码数据流,所以每路 PES 也只包含相应的数据流;
【2】码流格式
【2.0】TS 文件分层
ts 文件为传输流文件,视频编码主要格式为 H264/MPEG4,音频为 AAC/MP3;
ts 文件分为三层
- ts 层 : Transport Stream 是在 pes 层的基础上加入数据流的识别和传输必须的信息;
- pes 层 : Packet Elemental Stream 是在音视频数据上加了时间戳等对数据帧的说明信息;
- es 层 : Elementary Stream 即音视频数据;
【2.1】PES 包
PES(Packetized Elementary Stream) 分组的基本码流,将基本码流 ES 流根据需要分成长度不等的数据包,并加上包头就形成了打包的基本码流 PES 流,是用来传输 ES 的一种数据结构;
PES 包由包头和 playload 组成,一般视频一个帧被打包成一个 PES 包,长度一般都大于 TS 包的 188 字节,因此需要进行切分;PES 包具体格式如下
pes start code | 3B | 开始码,固定为 0x000001 |
stream id | 1B | 音频取值(0xc0-0xdf),通常为 0xc0 视频取值(0xe0-0xef),通常为 0xe0 |
pes packet length | 2B | 后面 pes 数据的长度,0 表示长度不限制,只有视频数据长度会超过 0xffff |
flag | 1B | 通常取值 0x80,表示数据不加密、无优先级、备份的数据 |
flag | 1B | 取值 0x80 表示只含有 pts,取值 0xc0 表示含有 pts 和 dts |
pes data length | 1B | 后面数据的长度,取值5或10 |
pts | 5B | 33bit 值 |
dts | 5B | 33bit 值 |
点播视频 dts 算法
- dts = 初始值 + 90000 / video_frame_rate,初始值可以随便指定,但是最好不要取 0,video_frame_rate 就是帧率,如 23、30;
- pts 和 dts 是以 timestamp 为单位,1s = 90000 time scale, 一帧是 90000/video_frame_rate 个 timescale;
- 用一帧的 timescale 除以采样频率就可以转换为一帧的播放时长;
点播音频 dts 算法
- dts = 初始值 + (90000 * audio_samples_per_frame) / audio_sample_rate,audio_samples_per_frame 值与编解码相关, aac 取值 1024, mp3 取值 1158,audio_sample_rate 是采样率,如 24000、41000;
- AAC 一般解码出来是每声道 1024 个 sample,即一帧的时间为 1024/sample_rate 秒,所以每一帧时间戳依次为 0, 1024/sample_rate, ..., 1024*n/sample_rate 秒;
注:直播视频的 dts 和 pts 应该直接用直播数据流中的时间,不应该按公式计算;
【2.2】PS 流
PS(Program Stream) 节目流,PS 流与 TS 流的区别在于,PS 流的包结构是可变长度的,而 TS 流的包结构是固定长度的;
PS 流的具体格式如下
【2.3】TS 流
TS(Transport Stream) 传输流,是由固定长度的包组成,含有独立时间基准的一个或多个节目,适用于误码较多的环境,并且从流的任意一段开始都可以独立解码;TS 流是原始的 PES 流(音视频等)中按照一定的频率插入 PSI/SI 和一些标识符(辅助数据)信息,然后按固定长度打包形成的传输流;值得注意的是,PSI/SI 信息在 TS 流中并不是只发送一次,而是按照一定的频率插入码流,是重复发送的;
ts 层的内容通过 PID 值来标识,主要内容包括 : PAT 表、PMT 表、音频流、视频流;解析 ts 流要先找到 PAT 表,只要找到 PAT 就可以找到 PMT,然后就可以找到音视频流;PAT 表的和 PMT 表需要定期插入 ts 流,因为用户随时可能加入 ts 流,该间隔比较小,通常每隔几个视频帧就要加入 PAT 和 PMT;PAT 和 PMT 表是必须的,还可以加入其它表如 SDT(业务描述表) 等,不过 hls 流只要有 PAT 和 PMT 就可以播放;
TS 包长度定义为 188 字节,其中 4 字节为包头,184 字节为有效负载;TS 流的具体格式如下
【2.3.1】包头格式
包头字段 | 长度(bits) | 说明 |
Sync-byte | 8 | =0X47;同步头 |
Transport-error-indicator | 1 | 出错标志 |
Payload-unit-start-indicator(PUSI) | 1 | 载荷单元起始指示 |
Transport-priority | 1 | 传输优先级规定 |
PID | 13 | 包识别标志,PID 用于区分载荷的类型,通过 PID 可以将规定的信道总频带在视频、音频、数据、系统控制信息间进行灵活的分配 |
Transport-scrambling-control | 2 | 加扰标志 |
Adaptation-field-control | 2 | 适配域标志 |
Continuity-counter | 4 | 连续递增计数器 |
【2.3.2】Adaptation Field
adaptation_field_length | 1B | 自适应域长度 |
flag | 1B | 取 0x50 表示 PCR 或 0x40 表示不包含 PCR |
PCR | 5B | Program Clock Reference 节目时钟参考,用于恢复出与编码端一致的系统时序时钟 STC(System Time Clock) |
stuffing_bytes | XB | 填充字节,取值 0xFF |
MPEG-2 TS 包载荷所传送的信息有两种类型
- 1)视频、音频的 PES 包以及辅助数据;
- 2)描述节目复接信息的 PSI 信息(Program Specific Information,节目专用信息);
PSI (Program Specific Information) 信息能提供从复用器到接受机的节目配置,复用及解复用不同的节目码流的必要信息;
PSI 类别
- PAT 表(Program Associate Table,节目关联表),描述多路节目复接信息;
- PMT 表(Program Map Table,节目映射表),描述单路节目复接信息;
- CAT 表(Conditional Access Table,条件接收表),描述条件接收信息;
- NIT 表(Network Information Table,网络信息表);
【2.3.1】PAT 节目关联表
PAT 表 : 主要的作用就是指明了 PMT 表的 PID 值
节目关联表(PAT, Program Association Table)是数字电视系统中节目指示的根节点;其包标识符(Packet IDentifier、简称 PID )为 0;终端设备(如机顶盒)搜索节目时最先都是从这张表开始搜索,从 PAT 中解析出节目映射表(PMT),再从 PMT 解析出基本元素(如视频、音频、数据等)的 PID 及节目号、再根据节目从节目业务描述表(Service Description Table、简称 SDT)中搜索出节目名称;
字段 | 长度 | 说明 |
table_id | 8 | 表 ID |
section_synatx_indication | 1 | 段同步标识 |
“0” | 1 | 0 值 |
reserved | 2 | 保留值 |
section_length | 12 | 分段长度 |
transport_stream_id | 16 | 传输流标识 |
reserved | 2 | 保留值 |
version_number | 5 | PAT 的版本号 |
current_next_indicator | 1 | 标识 |
section_number | 8 | 分段号 |
last_section_number | 8 | 最后一个分段号 |
program_number(循环开始,N从0开始) | 16 | 节目的编号 |
reserved | 3 | 保留值 |
network_PID | 13 | NIT 表的 PID 值 |
program_map_PID | 13 | PMT 的 ID 值 |
crc_32 | 32 | CRC 校验 |
注,N loop 部分的个数计算方法 (section_length - 6 - 4 字节 / 4),6 为 section_length 到 last_section_number 字段和,减去 4 是 CRC_32;
【2.3.2】PMT 节目映射表
PMT 表 : 主要的作用就是指明了音视频流的 PID 值
节目映射表(PMT, Program Map Table),该表的 PID 由 PAT 提供,通过该表可以得到一路节目中包含的信息,例如,该路节目由哪些流构成和这些流的类型(视频,音频,数据),指定节目中各流对应的 PID,以及该节目的 PCR 所对应的 PID;
字段 | 长度 | 说明 |
table_id | 8 | 表 ID |
section_synatx_indication | 1 | 段同步标识 |
“0” | 1 | 0 值 |
reserved | 2 | 保留值 |
section_length | 12 | section_length |
program_number | 16 | 传输流标识 |
reserved | 2 | 保留值 |
version_number | 5 | PMT 的版本号 |
current_next_indicator | 1 | 标识 |
section_number | 8 | 分段号 |
last_section_number | 8 | 最后一个分段号 |
reserved | 3 | 保留值 |
PCR_PID | 13 | PCR 值 |
reserved | 4 | 保留值 |
program_info_length 不为 0,后面进行循环层 1 | 12 | 节目信息长度 |
stream_type | 8 | 流类型 |
reserved | 3 | 保留值 |
elementary_pid | 13 | 负载该 PES 流的 TS 包的 PID 值 |
reserved | 4 | 保留值 |
es_info_length | 12 | ES 流描述相关的字节数 |
crc_32 | 32 | CRC 校验 |
【2.4】ES 流
ES 流包含音视频数据;
ES(Elementary Stream) 基本码流,不分段的音频、视频或其他信息的连续码流;
【2.4.1】ES 流 -- H264
打包 h.264 数据时必须给视频数据加上一个 nalu(Network Abstraction Layer Unit),nalu 包括 nalu header 和 nalu type,nalu header 固定为 0x00000001(帧开始)或 0x000001(帧中);h.264 的数据是由 slice 组成的,slice 的内容包括 : 视频、sps、pps 等;nalu type 决定了后面的 h.264 数据内容;
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|F|NRI| TYPE |
+-+-+-+-+-+-+-+-+
F : 1 bit,forbidden_zero_bit,h.264 规定必须取 0;
NRI : 2 bits,nal_ref_idc,取值为 0~3,指示这个 nalu 的重要性,I 帧、sps、pps 通常取 3,P 帧常取 2,B 帧通常取 0;
Type : 5 bits
Type 取值如下
打包 es 层数据时 pes 头和 es 数据之间要加入一个 type=9 的 nalu,关键帧 slice 前必须要加入 type=7 和 type=8 的 nalu 而且是紧邻的;
【2.4.2】ES 流 -- AAC
打包 aac 音频必须加上一个 adts(Audio Data Transport Stream)头,共 7Byte,adts 包括 fixed_header 和 variable_header 两部分,各 28bit;
参考资料
MPEG2-SYSTEM 中文版,链接:https://pan.baidu.com/s/1UXDtFVLR04bizlDQWVXeRw 提取码:vc58
参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
【6】TS流的分析和理解
【7】从TS流到PAT和PMT