TS 数据流分析学习

Posted doscho

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TS 数据流分析学习相关的知识,希望对你有一定的参考价值。

 

 

TS 流、包结构以及同步

1. TS 流: 可以将TS流理解为一种单一码流、混合码流。

  单一码流:TS流的基本组成单位是长度为188字节的TS包。

       混合码流:TS流有多种数据组成,一个TS包中的数据可以是视频数据、音频数据、填充数据,PSI/SI表格数据.....(唯一的PID对应)

2. TS 包结构分析:

  TS 包由包头、有效载荷区组成。(有些包中包括自适应区)。大小: 188 字节

  TS包头:4 个字节

    同步字节 0x47,用于检测码流是否同步。

    包ID: PID, 解码器通过该标志号确定该TS包中的数据属于那种类型。

   PCR:    自适应区, 解码器通过该时间参数,进行解码端的时钟重置。

        有效载荷:  最高 184 字节

    视频、音频 or 其他数据

语法:

  

 

 

   

 

五、

     

  

       

 

 

 

HLS,Http Live Streaming 是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件。

1、M3U8文件

   用文本方式对媒体文件进行描述,由一系列标签组成。

#EXTM3U

#EXT-X-TARGETDURATION:5

#EXTINF:5,

./0.ts

#EXTINF:5,

./1.ts

#EXTM3U:每个M3U8文件第一行必须是这个tag。

#EXT-X-TARGETDURATION:指定最大的媒体段时间长度(秒),#EXTINF中指定的时间长度必须小于或等于这个最大值。该值只能出现一次。

#EXTINF:描述单个媒体文件的长度。后面为媒体文件,如./0.ts 

2、ts文件

  ts文件为传输流文件,视频编码主要格式h264/mpeg4,音频为acc/MP3。

  ts文件分为三层:ts 层 Transport Stream, 就是在pes层加入数据流的识别和传输必须的信息;

           pes 层 Packet Elemental Stream,pes层是在音视频数据上加了时间戳等对数据帧的说明信息;

                                  es层 Elementary Stream. es层就是音视频数据。

(1)ts层 

    ts包大小固定为188字节,ts层分为三个部分:ts header、adaptation field、payload。ts header固定4个字节;adaptation field可能存在也可能不存在,主要作用是给不足188字节的数据做填充;payload是pes数据。

 

         ts header
sync_byte 8 同步字节,固定为0x47
transport_error_indicator 1 传输错误指示符,表明在ts头的adapt域后由一个无用字节,通常都为0,这个字节算在adapt域长度内
payload_unit_start_indicator 1 负载单元起始标示符,一个完整的数据包开始时标记为1, 表示携带的是PSI或PES第一个包
transport_priority 1 传输优先级,0为低优先级,1为高优先级,通常取0
pid 13 pid值
transport_scrambling_control 2 传输加扰控制,00表示未加密,TS包中的有效数据未经加扰处理。
adaptation_field_control 2 是否包含自适应区,‘00’保留;‘01’为无自适应域,仅含有效负载;‘10’为仅含自适应域,无有效负载;‘11’为同时带有自适应域和有效负载。
continuity_counter 4 递增计数器,从0-f,起始值不一定取0,PID相同的包,计数器必须是连续的

     ts层的内容是通过PID值来标识的,主要内容包括:PAT表、PMT表、音频流、视频流。解析ts流要先找到PAT表,只要找到PAT就可以找到PMT,然后就可以找到音视频流了。PAT表的PID值固定为0。PAT表和PMT表需要定期插入ts流,因为用户随时可能加入ts流,这个间隔比较小,通常每隔几个视频帧就要加入PAT和PMT。PAT和PMT表是必须的,还可以加入其它表如SDT(业务描述表)等,不过hls流只要有PAT和PMT就可以播放了。

            PAT表:主要的作用就是指明了PMT表的PID值。
            PMT表:主要的作用就是指明了音视频流的PID值。
            音频流/视频流:承载音视频内容。
    PID是TS流中唯一识别标志,Packet Data是什么内容就是由PID决定的。如果一个TS流中的一个Packet的Packet Header中的PID是0x0000,那么这个Packet的Packet Data就是DVB的PAT表而非其他类型数据(如Video、Audio或其他业务信息)。下表给出了一些表的PID值,这些值是固定的,不允许用于更改。
            

                

 

      
 
    adaptio
adaptation_field_length 1B 自适应域长度,后面的字节数
flag 1B 取0x50表示包含PCR或0x40表示不包含PCR
PCR 5B Program Clock Reference,节目时钟参考,用于恢复出与编码端一致的系统时序时钟STC(System Time Clock)。
stuffing_bytes xB 填充字节,取值0xff

  自适应区的长度要包含传输错误指示符标识的一个字节。pcr是节目时钟参考,pcr、dts、pts都是对同一个系统时钟的采样值,pcr是递增的,因此可以将其设置为dts值,音频数据不需要pcr。如果没有字段,ipad是可以播放的,但vlc无法播放。打包ts流时PAT和PMT表是没有adaptation field的,不够的长度直接补0xff即可。视频流和音频流都需要加adaptation field,通常加在一个帧的第一个ts包和最后一个ts包里,中间的ts包不加。    

  PAT格式

table_id 8b PAT表固定为0x00
section_syntax_indicator 1b 固定为1
zero 1b 固定为0
reserved 2b 固定为11
section_length 12b 后面数据的长度
transport_stream_id 16b 传输流ID,固定为0x0001
reserved 2b 固定为11
version_number 5b 版本号,固定为00000,如果PAT有变化则版本号加1
current_next_indicator 1b 固定为1,表示这个PAT表可以用,如果为0则要等待下一个PAT表
section_number 8b 固定为0x00, 表明这个段是该pat表的第几个段。
last_section_number   8b 固定为0x00, 表明PAT表一共有多少段。
开始循环
program_number 16b 节目号为0x0000时表示这是NIT,节目号为0x0001时,表示这是PMT
reserved 3b 固定为111
PID 13b 节目号对应内容的PID值
结束循环
CRC32 32b 前面数据的CRC32校验码

  PMT格式

table_id 8b PMT表取值随意,0x02
section_syntax_indicator 1b 固定为1
zero 1b 固定为0
reserved 2b 固定为11
section_length 12b 后面数据的长度
program_number 16b 频道号码,表示当前的PMT关联到的频道,取值0x0001
reserved 2b 固定为11
version_number 5b 版本号,固定为00000,如果PAT有变化则版本号加1
current_next_indicator 1b 固定为1
section_number 8b 固定为0x00
last_section_number 8b 固定为0x00
reserved 3b 固定为111
PCR_PID 13b PCR(节目参考时钟)所在TS分组的PID,指定为视频PID
reserved 4b 固定为1111
program_info_length 12b 节目描述信息,指定为0x000表示没有
开始循环
stream_type 8b 流类型,标志是Video还是Audio还是其他数据,h.264编码对应0x1b,aac编码对应0x0f,mp3编码对应0x03
reserved 3b 固定为111
elementary_PID 13b 与stream_type对应的PID
reserved 4b 固定为1111
ES_info_length 12b 描述信息,指定为0x000表示没有
结束循环
CRC32 32b 前面数据的CRC32校验码

 

(2)pes层

 

    pes层是在每一个视频/音频帧上加入了时间戳等信息,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值

    pts是显示时间戳、dts是解码时间戳,视频数据两种时间戳都需要,音频数据的pts和dts相同,所以只需要pts。有pts和dts两种时间戳是B帧引起的,I帧和P帧的pts等于dts。如果一个视频没有B帧,则pts永远和dts相同。从文件中顺序读取视频帧,取出的帧顺序和dts顺序相同。dts算法比较简单,初始值 + 增量即可,pts计算比较复杂,需要在dts的基础上加偏移量。

       音频的pes中只有pts(同dts),视频的I、P帧两种时间戳都要有,视频B帧只要pts(同dts)。打包pts和dts就需要知道视频帧类型,但是通过容器格式我们是无法判断帧类型的,必须解析h.264内容才可以获取帧类型。

    举例说明:

                                 I          P          B          B          B          P

        读取顺序:         1         2          3          4          5          6

        dts顺序:           1         2          3          4          5          6

        pts顺序:           1         5          3          2          4          6

    点播视频dts算法:

      dts = 初始值 + 90000 / video_frame_rate,初始值可以随便指定,但是最好不要取0,video_frame_rate就是帧率,比如23、30。

    pts和dts是以timescale为单位的,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应该直接用直播数据流中的时间,不应该按公式计算。

(3)es层

    es层指的就是音视频数据,我们只介绍h.264视频和aac音频。

    h.264视频:

    打包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数据内容。

 

F 1b forbidden_zero_bit,h.264规定必须取0
NRI 2b nal_ref_idc,取值0~3,指示这个nalu的重要性,I帧、sps、pps通常取3,P帧通常取2,B帧通常取0
Type 5b 参考下表
nal_unit_type 说明
0 未使用
1 非IDR图像片,IDR指关键帧
2 片分区A
3 片分区B
4 片分区C
5 IDR图像片,即关键帧
6 补充增强信息单元(SEI)
7 SPS序列参数集
8 PPS图像参数集
9 分解符
10 序列结束
11 码流结束
12 填充
13~23 保留
24~31 未使用

         红色字体显示的内容是最常用的,打包es层数据时pes头和es数据之间要加入一个type=9的nalu,关键帧slice前必须要加入type=7和type=8的nalu,而且是紧邻。

  
四、gs流
    由于DVB—S在带宽利用率以及调制编码方面的不足,在第二代数字卫星广播标准(the second generation of digital video broadcasting.satellite, DVB・S2) 中,
    采用了更先进的调制编码方式,在兼容TS流的基础上,引入一种全新的码流,即通用流 (general stream,GS)。在相同的条件下,DVB.S2比DVB.S节省了约30%的带宽 。

      协议数据单元(protocol data unit,PDU)

 
         通用流封装(general stream en. capsulation,GSE)
 
  根据基带帧:
    MATYPE的首个字节(MATYPE.1)的TS/GS域,指示了传输流格式是Ts流或GS流,
    SIS/MIS域指示了输入流是单输人还是多输入。SIS/MIS值为“l”,表示单输入流,
    MATYPE的第2个字节(MATYPE.2)等于输入流标示符(inputstream identi.tier,IsI),不为“0”
    SIS/MIS值为“0”,表示多输入流,MATYPE.2为预留字节,值一般为“Ox00”。UPL域表示用户包长度,单位是比特。UPL值为“0000。。。”,表示输入流是连续流,UPL值为“188X8。”,表示用户包是MPEG传输流包,包长为188字节。
    IP数据的GS流的基带帧头部有以下特征:(1)MATYPE.1的TS/GS值为二进制“01”;(2)MATYPE一1的SIS/MIS值为“1”时,MATYPE-2字节不为“0”;SIS/MIS值为“0”时,MATYPE一2字节为“0x00”;(3)UPL值为“0x0000”;(4)DFL值被8整除,因为DFL域的第1个字节为高位字节,所以DFL域的第2个字节即低位字节也被8整除:(5)CRC.8不对基带帧头部前9个字节进行错误校验。
若基带帧为GS流提取GSE header如下
  (1)s域表明是起始分段,e域为结束分段
  (2)lt为label_type类型:
    值为“00”,label域为6字节,用于寻址,相当于以太网中的MAC地址;LT值为“11”,表示同一个基带帧中先前的GSE包已经使用过的label可以再用,该GSE包头不再有label域,也就是说,对于按顺序传输的具有相同label的GSE包,GSE包头的label域不需要重复出现。需要注意的是,基带帧第1个GSE包的LT值不能为“11”,即基带帧的第1个GSE包不能为PDU中间分段所在的GSE包。
  (3)gse_length: 该gse包大小
  (4)total_length: 该pdu整段总长,第一分段出现
  (5)protocol_type : 协议类型, 第一分段出现
  (6)frag_id:用来指示该pdu段属于哪一个pdu
  (7)CRC:pdu_end段出现用来进行crc校验
 
 

 TS数据流PAT和PMT分析

    TS流,是基于packet的位流格式,每个packet是188个字节或者204个字节(一般是188字节,204字节格式是在188字节的packet后面加上16字节的CRC数据,其他格式相同),解析TS流,先解析每个packet ,然后从一个packet中解析出PAT的PID,根据PID找到PAT包,然后从PAT包中解析出PMT的PID,根据PID找到PMT包,在从PMT包中解析出Video和Audio(也有的包括Teletext和EPG)的PID。然后根据PID找出相应的包。
    所有packet格式都是同一的,包括packet header和packet datas。
 
    acket header格式如下:
      typedef struct {
        unsigned sync_byte           :  8位;     /*8bits的同步字节,固定为0x47,表示后面是一个TS分组。*/
        unsigned transport_error_indicator     :  1位      /*1位的错误指示信息,1表示当前packet至少有1bit的传输错误,0表示所有数据都正确. 一般传输错误的话就不会处理这个包了。*/
        unsigned payload_unit_start_indicator  :  1位      /*负载单元开始标志,*/
        unsigned transport_priority       :  1位      /*1bit的传输优先级标志,1表示高优先级,0表示低优先级,传输机制可能用到,解码好像用不到*/
        unsigned PID                                         :  13 位   /*13 bits的packet ID号码,唯一的号码对应不同的包,指出了这个包的有效负载数据的类型,告诉我们这个包传输的是什么内容*/
                            unsigned transport_scrambling_control :  2位      /*2 bits 的加密标志,00表示没有加密,其他表示已被加密,表示TS分组有效负载的加密模式。
                              TS首部(也就是前面着32个 bit)是不应被加密的*/
        unsigned adaptation_field_control    :  2位      /* 2bits的附加区域控制,表示TS分组首部后面是否跟随有调整字段和有效负载。
                               01仅有有效负载,10仅含调整字段,11含有调整字段和有效负载。00的话解码器不进行处理。空分组没有调整字段。*/
        unsigned continuity_counter      : 4位       /*4bits的包递增计数器,范围是0-15,具有相同PID的TS分组传输时每次加1,到15后清0.不过有些时候是不计数的。
                              如下:1 、TS分组无有效负载,2、复制的TS分组和原分组这个值一样。3、后面讲到的一个标志discontinuity——indicator为1时*/
      } packet_header
 
    PAT数据结构
     program_association_section() {
        table_id                // 8位  固定为0x00,表示该表是PAT表
        section_syntax_indicator       // 1   段语法标志位,固定为1
        \'0\'                    // 1   固定为1 为了防止和ISO13818Video流格式中的控制字冲突而设置的
        reserved                 // 2   保留位,一般都是0
        section_length             // 12  段的大小,表示这个字节后面有用的字节数,包括CRC32.假如后面的字节加上前面的字节数少于188,后面会用0xFF填充,
                          假如这个数值比较大,则PAT会分成几部分来传输。
        transport_stream_id         // 16  该传输流的ID,区别于一个网络中其他多路复用的流,
        reserved                   // 2
        version_number             // 5    范围0-31,表示PAT的版本号,标注当前节目的版本,这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经改变了,程序必须重新收索节目
        current_next_indicator        // 1    表示发送的PAT是当前有效还是下一个PAT有效
        section_number                  // 8    分段的号码,PAT可能分为多个段传输,第一段为00,以后每个分段加1,最大可能有256个分段
        last_section_number           // 8    最后一个分段的号码
        for(i=0;i<N;i++) {
          program_number           // 16  节目号
          reserved                  // 3
          if (program_number == \'0\')  {
            network_PID                // 13   网络信息表(NIT)的PID,网络信息表提供了该物理网络的一些信息,和电视台相关的,节目号为0时对应的PID为network_PID
          }
          else { 
            program_map_PID       // 13   节目映射表的PID,节目号大于0时对应的PID,每个节目对应一个
            }    
           }
           CRC_32                    // 32   CRC32校验码
      }

      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;    //表示从下一个字段开始到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个分段
        unsigned last_section_number       : 8;   //最后一个分段的号码

        std::vector<TS_PAT_Program> program;
        unsigned reserved_3          : 3;   // 保留位
        unsigned network_PID           : 13;   //网络信息表(NIT)的PID,节目号为0时对应的PID为network_PID
        unsigned CRC_32               : 32;    //CRC32校验码
      } TS_PAT;

 
    例子  47 40 00 1c 00 00 b0 15 13 f6 e7 00 00 00 00 e0 10 00 01 e0 20 00 02 e0 21 1a 34 b4 77 ff ff ff ff ......ff
    
    其中,前4个字节是TS分组的头部,01000111 01000000 00000000 0001 1100 ,可以解析 出PID= (buf[1]&0x0f)<<8 | buf[2] =0x00,表示为该分组的有效负载是PAT
      第五个字节00称为“指针域”,表示一个偏移量,即从后面第几个字节开始时PAT部分。为00表示后面紧跟着的就是PAT:00 b0 15 13 f6 e7 00 00 00 00 e0 10 00 01 e0 20 00 02 e0 21 1a 34 b4 77(00000000 10110000 00010101 00010011 11110110 11100111 00000000 00000000 00000000 00000000 11100000 00010000 00000000 00000001 11100000 00100000 00000000 00000010 11100000 00100001 00011010 00110100 10110100 01110111)
    利用PAT数据结构解析出PAT,可得到如下信息:
      table_id          : 0x00
      section_syntax_indicator    : 0x01
      section_length       : 0x015  表示后面有21个字节有用
      transport_stream_id    : 0x13f6
      version_number       : 0x13
      current_next_indicator     : 0x01
      section_number        : 0x00
      last_section_number      : 0x00  表示只有一个分段。
      
      program_number      : 0x0000
      network_PID        : 0010
        
      program_number      : 0001
      program_map_PID    : 0020
      
      program_number      : 0002
      program_map_PID    : 0021
      
      CRC_32          : 1a34b477
    此PAT只有一段,包含了三个节目,节目号0000对应于network_PID=0010 ,节目号0001对应于program_map_PID =0020,节目号0002对应于program_map_PID =0021,从实际的角度,我们应该把这三个节目号理解为三个频道,第一个频道中的内容是网络信息,第二、三个频道包含了节目信息。在数字电视中,一个频道上可以有多个节目,后面的PMT即是告诉了我们某个频道中所有节目对应的PID。
于是现在就搜寻PID=0x0020的TS分组,即是频道2对应的PMT信息。
 
    PMT数据结构:
     TS_program_map_section() {
      table_id                             // 8   固定为0x02,表示该表是PMT
      section_syntax_indicator        // 1   段语法标志位,固定为1     
      \'0\'                     // 1                                           
      reserved                       // 2                                
      section_length                 // 12   表示这个字节后面有用的字节数,包括CRC32。假如后面的字节加上前面的字节数少于188,后面会用0XFF填充。
                        假如这个数值比较大,则PAT会分成几部分来传输。                            
      program_number                  // 16   节目号,表示该PMT对应的节目
      reserved                          // 2                               
      version_number                    // 5    范围0-31,表示PAT的版本号,标注当前节目的版本,这是个非常有用的参数,
                          当检测到这个字段改变时,说明TS流中的节目已经改变了,程序必须重新收索节目                           
      current_next_indicator          // 1   表示发送的PAT是当前有效还是下一个PAT有效                        
      section_number                    // 8   分段的号码  固定为0x00                         
      last_section_number             // 8   最后分段的号码 固定为0x00                        
      reserved                           // 3                                
      PCR_PID                        // 13   PCR(节目时钟参考)所在TS分组的PID,根据PID可以去搜索相应的TS分组,解出PCR信息。                          
      reserved             // 4
      program_info_length              // 12   该节目的信息长度,在此字段之后可能会有一些字节描述该节目的信息                         
      for (i=0; i<N; i++)  {  
        descriptor()
      }
      for (i=0;i<N1;i++) {  
        stream_type                       // 8   指示了PID为elementary_PID的PES分组中原始流的类型,比如视频流,音频流等                        
        reserved                             // 3                           
        elementary_PID                    // 13  该节目中包括的视频流,音频流等对应的TS分组的PID                      
        reserved                        // 4                                 
        ES_info_length              // 12  该节目相关原始流的描述符的信息长度
        for (i=0; i<N2; i++) {   
          descriptor()  
        }
      }
      CRC_32                             // 32                                                       
    }
 

    //PMT 表结构体
    typedef struct TS_PMT
    {
      unsigned table_id          : 8;   //固定为0x02, 表示PMT表
      unsigned section_syntax_indicator    : 1;   //固定为0x01
      unsigned zero           : 1;   //0x01
      unsigned reserved_1          : 2;   //0x03
      unsigned section_length          : 12;  //首先两位bit置为00,它指示段的byte数,由段长度域开始,包含CRC。
      unsigned program_number      : 16;  // 指出该节目对应于可应用的Program map PID
      unsigned reserved_2          : 2;   //0x03
      unsigned version_number             : 5;   //指出TS流中Program map section的版本号
      unsigned current_next_indicator   : 1;   //当该位置1时,当前传送的Program map section可用;
                            //当该位置0时,指示当前传送的Program map section不可用,下一个TS流的Program map section有效。
      unsigned section_number        : 8;   //固定为0x00
      unsigned last_section_number      : 8;   //固定为0x00
      unsigned reserved_3         : 3;   //0x07
      unsigned PCR_PID          : 13;   //指明TS包的PID值,该TS包含有PCR域,
                             //该PCR值对应于由节目号指定的对应节目。
                           //如果对于私有数据流的节目定义与PCR无关,这个域的值将为0x1FFF。
      unsigned reserved_4          : 4;   //预留为0x0F
      unsigned program_info_length     : 12;    //前两位bit为00。该域指出跟随其后对节目信息的描述的byte数。

      std::vector<TS_PMT_Stream> PMT_Stream;  //每个元素包含8位, 指示特定PID的节目元素包的类型。该处PID由elementary PID指定
      unsigned reserved_5         : 3;    //0x07
      unsigned reserved_6         : 4;    //0x0F
      unsigned CRC_32 : 32;
    } TS_PMT;

    
    例子PMT包:  47 40 20 1c 00 02 b0 1f 00 01 e7 00 00 e1 00 f0 00 02 e1 00 f0 05 02 03 b2 44 5f 04 e1 10 f0 03 03 01 67 c9 ab c8 d2
    前4个字节是TS分组头部, 第五个字节00是指针域。后面的就是PMT的内容了。
      table_id           :  02
      section_syntax_indicator  : 01
      section_length        : 01f
      program_number      : 0001
      version_number          : 13
      current_next_indicator      : 01
                     section_number      : 00
                     last_section_number    : 00
                     PCR_PID            : 0100
      program_info_length         : 000
      descriptor:
        steam_type         : 00
        elementary_PID     : 0001
        ES_info_length      : 000
  
      descriptor:
        steam_type         : 02
        elementary_PID       : 0001
        ES_info_length        : 005
        descriptor       : 02 03 b2 44 5f
        
        steam_type       : 04
        elementary_PID     : 0011
        ES_info_length      : 003
        descriptor          : 03 01 67
      CRC_32                                  : c9abc8d2
    可以看出,该节目号0001包含了三个流的信息,流类型分别为00,02,04,00的流为保留值,可以不考虑,02表示原始流为视频流,其elementary_PID为0001,04表示原始流为音频流,其elementary_PID为0011,两个流分别还带有descriptor(描述符),说明了该原始流的一些信息。

    

:流类型取值说明

取值

描述

0x00

国际标准保留

0x01

视频

0x02

视频或受限参数视频流

0x03

音频

0x04

音频

0x05

private_sections

0x06

包含专用数据的PES分组

0x07

ISO/IEC 13533 MHEG

0x08

 

0x09

ITU-T Rec.H.222.1

0x0A~0x0D

GB/T类型

0x0E

GB/T辅助

0x0F~0x7F

GB/T保留

0x80~0xFF

用户专用

 

 

 从TS开始

  ES流(Elementary Stream):基本码流,不分段的音频、视频或其他信息的连续码流。
  PES流(Packet Elementary Stream):把基本流ES分割成段,并加上相应头文件打包成形的打包基本码流。
  PS流(Program Stream):节目流,将具有共同时间基准的一个或多个PES组合(复合)而成的单一数据流(用于播放或编辑系统,如m2p)。
  TS流(Transport Stream):传输流,将具有共同时间基准或独立时间基准的一个或多个PES组合(复合)而成的单一数据流(用于数据传输)
 
  PSI(Program Specific Information 节目特定信息)信息,其作用是从一个携带多个节目的某一个TS流中正确找到特定的节目。
          PSI表包括节目关联表(PAT)、条件接收表(CAT)、节目映射表(PMT)和网络信息表(NIT)组成。

     PAT 节目关联表(PAT Program Association Table):      PAT是机顶盒接收的入口点,是它获取数据的开始

     CAT 条件接收表(CAT Conditional Access Table): 
     PMT 节目映射表(PMT Program Map Table)      PMT表的作用就在于,它提供了每个节目视频、音频(或其他)数据包的PID
    NIT 网络信息表(NIT Nerwork Information Table)
  SI 业务信息表 (Service information )  :                                  由一下九个表组成,其中SDT、EIT、TDT是必须包括的,其它是可选的。
    
    SDT表(Service Descriptor Table,业务描述表): 描述了包含在特定TS流中的全部业务的相关信息,如业务名称、业务提供者等。
    EIT(事件信息表): 描述了包含在特定业务中的所有事件的相关信息。包含了与事件或节目相关的数据,如事件名称、开始时间、持续时间等。
              TDT(时间和日期表): 给出了与当前的时间和日期相关的信息。由于这些信息频繁更新,所以需要使用一个单独的表。
    BAT(业务群关联表)
    RST(运行状态表)
    TOT(时间偏移表)
     ST(填充表)
    SIT(选择信息表)
    DIT(间断信息表)
 
  TSDT 传输流描述表(TSDT Transport Stream Description Table)
   

 

  TS是经过节目复用和传输复用两层完成的,即在节目复用时,加入了PMT,在传输复用时,加入了PAT。同样在节目解复用时,可以得到PMT,在传输解复用时,可以得到PAT。
 

结构名

中文

所定义标准

PID

描述

PAT

节目关联表

MPEG2标准

0x0000

节目号码和节目映射表PID相关联,是获取数据的开始

PMT

节目映射表

MPEG2标准

PAT中指出

指定一个或多个节目的PID

CAT

条件接收表

MPEG2标准

0x0001

将一个或多个专用EMM流分别与唯一的PID相关联

NIT

网络信息表

SI标准

PAT中指出

描述整个网络,如多少个TS流、频点和调制方式等信息

     *NOTE:

   TS流和PS流的区别:TS流的包结构是长度是固定的;PS流的包结构是可变长度的。这导致了TS流的抵抗传输误码的能力强于PS流(TS码流由于采用了固定长度的包结构,当

以上是关于TS 数据流分析学习的主要内容,如果未能解决你的问题,请参考以下文章

TS流分析-packet header

python数据分析之:时间序列二

TS流分析-PES包头实例分析

Tushare学习文档(交易数据)

重读《学习JavaScript数据结构与算法-第三版》-第2章 ES和TS

TS/16949中的DFMEA怎样才能实际应用到工作中?