欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TS码流分析

程序员文章站 2022-03-04 18:22:40
...

概述

  • 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流生成流程图

TS码流分析

从上图可以看出,视频ES和音频ES通过打包器和共同或独立的系统时间基准形成一个个PES, 通过TS复用器复用形成的传输流。 注意这里的TS流是 位流格式(分析Packet的时候会解释),也即是说TS流是可以按位读取的。

TS流的格式

TS流是基于Packet的位流格式,即由n个包组成;每个包是188个字节(或204个字节,在188个字节后加上了16字节的CRC校验数据)

包头

TS码流分析

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

术语

业务与事件

TS码流分析

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  
    unsigned0’                          : 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 
}