TS码流分析
概述
- ES流(Elementary Stream) 基本码流,不分段的音频、视频或其他信息的连续码流。
PES流 把基本流ES分割成段,并加上相应头文件打包成形的打包基本码流。
PS流(Program Stream) 节目流,将具有共同时间基准的一个或多个PES组合(复合)而成的单一数据流(用于播放或编辑系统,如m2p)。
- TS流(Transport Stream) 传输流,将具有共同时间基准或独立时间基准的一个或多个PES组合(复合)而成的单一数据流(用于数据传输)。
*NOTE:
TS流和PS流的区别:TS流的包结构是长度是固定的;PS流的包结构是可变长度的。 这导致了 TS流的抵抗传输误码的能力强于PS流 (TS码流由于采用了固定长度的包结构, 当传输误码破坏了某一TS包的同步信息时,接收机可在固定的位置检测它后面包中的同步信息,从而恢复同步,避免了信息丢失。 而PS包由于长度是变化的,一旦某一 PS包的同步信息丢失, 接收机无法确定下一包的同步位置,就会造成失步,导致严重的信息丢失。 因此,在信道环境较为恶劣,传输误码较高时,一般采用TS码流;而在信道环境较好,传输误码较低时,一般采用PS码流。)
由于TS码流具有较强的抵抗传输误码的能力,因此目前在传输媒体中进行传输的MPEG-2码流基本上都采用了TS码流的包格。
TS流生成流程图
从上图可以看出,视频ES和音频ES通过打包器和共同或独立的系统时间基准形成一个个PES, 通过TS复用器复用形成的传输流。 注意这里的TS流是 位流格式(分析Packet的时候会解释),也即是说TS流是可以按位读取的。
TS流的格式
TS流是基于Packet的位流格式,即由n个包组成;每个包是188个字节(或204个字节,在188个字节后加上了16字节的CRC校验数据)
包头
name | bit位 | 描述 |
---|---|---|
sync_byte | 8 bits | 同步字节,固定是0x47 |
transport_error_indicator | 1 bits | 错误指示信息(1:该包至少有1bits传输错误) |
payload_unit_start_indicator | 1 bits | 负载单元开始标志(packet不满188字节时需填充) |
transport_priority | 1 bits | 传输优先级标志(1:优先级高) |
PID | 13 bits | Packet ID号码,唯一的号码对应不同的包 |
transport_scrambling_control | 2 bits | 加密标志(00:未加密;其他表示已加密) |
adaptation_field_control | 2 bits | 附加区域控制 |
continuity_counter | 4 bits | 包递增计数器 |
TS流中PID的分配
TS流中PID的分配
表 | PID值 |
---|---|
PAT | 0x0000 |
CAT | 0x0001 |
TSDT | 0x0002 |
预留 | 0x0003 至0x000F |
NIT ST | 0x0010 |
SDT , BAT, ST | 0x0011 |
EIT, ST | 0x0012 |
RST, ST | 0x0013 |
TDT, TOT, ST | 0x0014 |
网络同步 | 0x0015 |
预留使用 | 0x0016 至 0x001B |
带内信令 | 0x001C |
DIT | 0x001E |
SIT | 0x001F |
术语
业务与事件
PSI/SI表
如上图所示,现实情况下,举个例子,在上图位于Services,而比如CCTV1~CCTV14对应不同的components,
PAT 节目关联表 Program Association Tabl
PID为0x0000 ,TS码流解析从PAT表开始
PAT表携带以下信息
TS流ID | transport_stream_id | 该ID标志唯一的流ID |
---|---|---|
节目频道号 | program_number | 该号码标志TS流中的一个频道,该频道可以包含很多的节目(即可以包含多个Video PID和Audio PID) |
PMT的PID | program_map_PID | 表示本频道使用哪个PID做为PMT的PID。因为可以有很多的业务,因此DVB规定PMT的PID可以由用户自己定义 |
PAT数据包分为两个部分,一个是PAT数据包头部(前8个Byte),一个是循环部分
/*头部部分 8个Byte*/
program_association_section()
{
unsigned table_id : 8; //固定为0x00 ,标志是该表是PAT表
unsigned section_syntax_indicator : 1; //段语法标志位,固定为1
unsigned ‘0’ : 1; //0
unsigned reserved_1 : 2; // 保留位
unsigned section_length : 12; //段长度字节,表示从下一个字段开始到CRC32(含)之间有用的字节数
unsigned transport_stream_id : 16; //该传输流的ID,区别于一个网络中其它多路复用的流
unsigned reserved_2 : 2;// 保留位
unsigned version_number : 5; //范围0-31,表示PAT的版本号
unsigned current_next_indicator : 1; //发送的PAT是当前有效还是下一个PAT有效
unsigned section_number : 8; //分段的号码。PAT可能分为多段传输,第一段为00,以后每个分段加1,最多可能有256个分段 给出section号,在sub_table中,第一个section其section_number为"0x00",每增加一个section,section_number加一
unsigned last_section_number : 8; //最后一个分段的号码 ,sub_table中最后一个section的section_number
/*循环部分 4个Byte*/
for(i=0;i<N;i++)
{
program_number :16; //节目号
reserved :3; //保留位
network_id 或 program_map_PID :13; //网络信息表(NIT)的PID,节目号为0时对应的PID为network_PID;其余情况是program_map_PID(PMT的PID)
}
CRC_32 :32;
}
PMT 节目映射表 Program Map Table
1
(1) 当前频道中包含的所有Video数据的PID
(2) 当前频道中包含的所有Audio数据的PID
(3) 和当前频道关联在一起的其他数据的PID(如数字广播,数据通讯等使用的PID)
PMT 表头
TS_program_map_section() {
table_id :8; //固定为0x02 标识PMT表
section_syntax_indicator :1; //固定为0x01
'0' :1; //
reserved :2; // 保留位
section_length :12 //该字段的头两bit必为‘00’,剩余10bit指定该分段的字节数,紧随section_length 字段开始,并包括CRC。此字段中的值应不超过1021(0x3FD)。
program_number :16 //指出TS流中Program map section的版本号
reserved :2 // 保留位
version_number :5 //指出TS流中Program map section的版本号
current_next_indicator :1 //当该位置1时,当前传送的Program map section可用;
//当该位置0时,指示当前传送的Program map section不可用,下一个TS流的Program map section有效
section_number :8 //固定为0x00
last_section_number :8 //固定为0x00
reserved :3 //保留
PCR_PID :13 //指明TS包的PID值,该TS包含有PCR域,
//该PCR值对应于由节目号指定的对应节目。
//如果对于私有数据流的节目定义与PCR无关,这个域的值将为0x1FFF。
reserved :4 //保留位
program_info_length :12 //节目信息长度。该字段的头两比特必为‘00’,剩余10 比特指定紧随program_info_length 字段的描述符的字节数 ,
//(之后的是N个描述符结构,一般可以忽略掉,这个字段就代表描述符总的长度,单位是Bytes)紧接着就是频道内部包含的节目类型和对应的PID号码了
for (i = 0; i < N; i++) {
descriptor()
}
for (i = 0; i < N1; i++) {
stream_type :8 //流类型,标志是Video还是Audio还是其他数据。这里是MPEG2视频类型
reserved :3 //保留位
elementary_PID :13 //该节目的音频或视频PID
reserved :4 //保留位
ES_info_length :12 //该字段的头两比特必为‘00’,剩余10比特指示紧随ES_info_length字段的相关节目元描述符的字节数。
for (i = 0; i < N2; i++) {
descriptor()
}
}
CRC_32 :32
}
上一篇: leetcode【71】Simplify Path
下一篇: 矢量量化——LBG算法