转自:http://www.cnblogs.com/hjj801006/p/3837435.html

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。

packet 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校验码
}

例子  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包
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(描述符),说明了该原始流的一些信息。

大部分是转载的别人的,中间加了些自己的理解。非常感谢给予我帮助的大神们!谢谢你们。

TS数据流PAT和PMT分析(转载)的更多相关文章

  1. TS数据流PAT和PMT分析

    TS流,是基于packet的位流格式,每个packet是188个字节或者204个字节(一般是188字节,204字节格式是在188字节的packet后面加上16字节的CRC数据,其他格式相同),解析TS ...

  2. SRS之TS封装PAT和PMT

    1. SrsTsContext::encode_pat_pmt 在该函数中,将 PAT 和 PMT 封装到 TS Packet 中,并将这两个 TS packet 写入到 ts 文件中. /* the ...

  3. TS 数据流分析学习

    TS 流.包结构以及同步 1. TS 流: 可以将TS流理解为一种单一码流.混合码流. 单一码流:TS流的基本组成单位是长度为188字节的TS包. 混合码流:TS流有多种数据组成,一个TS包中的数据可 ...

  4. 简单解析PAT、PMT的程序

    刚开始学习有关TS.PAT.PMT方面的内容,参考了别人的一些程序,然后写了一个简单的解析TS的小程序.如果有地方错误,请发邮件给我843036544@qq.com. #include<stdi ...

  5. TS流PAT/PMT详解

    一 从TS流开始 从MPEG-2到DVB,看着看着突然就出现了一大堆表格,什么PAT.PMT.CAT……如此多的表该怎样深入了解呢? 我们知道,数字电视机顶盒接收到的是一段段的码流,我们称之为TS(T ...

  6. 从TS流到PAT和PMT

    转自:https://blog.csdn.net/rongdeguoqian/article/details/18214627 一 从TS流开始 最近开始学习数字电视机顶盒的开发,从MPEG-2到DV ...

  7. PAT、PMT、SDT详解

    下面针对解复用程序详细分析一下PAT,PMT和SDT三类表格的格式. 如下图,四个频道复用 PAT---Program Association Table,节目关联表 .PAT表携带以下信息: (1) ...

  8. 修复FFMPEG 复用 PAT、PMT发送间隔小于25ms的错误

    目录 分析ffmpeg源码 分析问题 修改源码解决问题 分析ffmpeg源码 分析问题 mpegtsenc.c 找到发送PAT.PMT的函数 /* send SDT, PAT and PMT tabl ...

  9. Graphic32中TBitmap32.TextOut性能分析[转载]

    转载:http://blog.csdn.net/avan_lau/article/details/6958497 最近在分析软件中画线效率问题,发现在画一些标志性符号的方法,存在瓶颈,占用较大的时间. ...

随机推荐

  1. BZOJ4580: [Usaco2016 Open]248

    n<=248个数字,可以进行这样的操作:将相邻两个相同的数字合并成这个数字+1,求最大能合成多少. f(i,j)--区间i到j能合成的最大值,f(i,j)=max(f(i,k)+1),f(i,k ...

  2. Codeforces Round #294 (Div. 2) D. A and B and Interesting Substrings [dp 前缀和 ]

    传送门 D. A and B and Interesting Substrings time limit per test 2 seconds memory limit per test 256 me ...

  3. python学习之-- redis模块操作 集合和有序集合

    redis 模块操作之 集合set和有序集合zset Set 集合操作,不允许重复的列表sadd(name,value):name对应的集合中添加元素scard(name):获取name对应的集合中元 ...

  4. js的基础(平民理解的执行上下文/调用堆栈/内存栈/值类型/引用类型)

    与以前的切图比较,现在的前端开发对js的要求似乎越来越高,在开发中,我们不仅仅是要知道如何运用现有的框架(react/vue/ng), 而且我们对一些基础的知识的依赖越来越大. 现在我们就用平民的方法 ...

  5. pycharm查看代码注释的方法,代码编写日志及作者信息等

    竟然在边栏有个右键的快捷键.annotate可以查看代码书写日期及作者 鼠标悬停可以看到更加详细的时间等信息 原理应该是利用git blame

  6. 多平台密码绕过及提权工具Kon-Boot的使用与防范

    在单用户的机器上密码可能没那么重要,但是一旦有多个用户可以使用这台机器,密码就显得十分必要了(比如有儿童账户的电脑).所以说为你的电脑增设一条防线的最常用,最简单的方法就是用密码将你的电脑保护起来,但 ...

  7. CEF3研究(三)

    一.Off-Screen Rendering 脱屏绘制 CEF的脱屏渲染并不创建源生的浏览器窗口,而是CEF提供主应用程序在无效区域和像素buffer里渲染,然后主应用程序通过鼠标.键盘和焦点事件通知 ...

  8. TUN/TAP区别

    在计算机网络中,TUN与TAP是操作系统内核中的虚拟网络设备.不同于普通靠硬件网路板卡实现的设备,这些虚拟的网络设备全部用软件实现,并向运行于操作系统上的软件提供与硬件的网络设备完全相同的功能. TA ...

  9. Oracle 数据库管理员的任务

    设计.实施和维护 Oracle 数据库时,按优先次序排列的任务包括:   1. 确定数据库服务器硬件   2. 安装 Oracle 软件   3. 为数据库和安全策略制定计划   4. 创建.移植和打 ...

  10. linuxc线程信号-pthread_cond_wait理解

    pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t*mutex)函数 传入的參数mutex用于保护条件,由于我们在调用pthread_con ...