TS码流解析(3)PSI/SI解析

3. PSI/SI表

PSI/SI表的构成是:一个表由一个或多个子表构成,表用table_id来标识;不同的子表由table_id和table_id_extension来区分(具有相同的table_id和不同的table_id_extension);一个子表由一个或多个段构成(具有相同的table_id和table_id_extension,不同section_number来区分);每个段由多个TS数据包的数据组成。每个段具有一个完整的数据结构,表的重要参数----描述符在段里传送。

3.1 PSI

PSI:(ProgramSpecial Information)节目专用信息表。

 

PSI信息由节目关联表PAT、条件接收表CAT、节目映射表PMT组成。PSI信息用来描述TS的组成结构;PSI提供了在传送流包中传送节目的初始化信息,信息指定了如何从一个携带多个节目的传输流中找到指定的节目。

 

表名

标准

PID

Table_id

详情

PAT(节目关联表)

MPEG-2

0x0000

0x00

定义了TS中的所有节目,是PSI信息的根节点,含有所有节目对应的PMT的PID

PMT(节目映射表)

MPEG-2

从PAT获取

0x02

提供节目号码与组成它们的原始码流之间的映射,完整地描述了一路节目是由哪些PES组成的,以及它们的PID

CAT(条件接收表)

MPEG-2

0x0001

0x01

提供了一个或者多个CA系统及其授权信息,如果对清流进行了加扰处理,那么就必须有CAT表,其包含加扰系统的细节;条件访问管理与授权信息的传送包的PID值

 

 

 

 

3.2 SI

 

SI:Service Information.业务信息表

 

SI信息内容是按照network(网络)→transport strem(传输流)→service(业务)→event(事件)的分层顺序描述。SI数据信息是按照一定的数据结构进行存储的。SI数据主要有:网络信息、传输流信息、业务信息、业务的事件信息等,并且大量的信息都是通过描述符来传输的。

为了能在一个TS流中提取出各种各样的信息,PSI/SI表里面使用了很多的标识。

Network_id、Original_network_id、Transport_stream_id、Service id、event_id、Bouquet_id

Network_id可以定位一个网络

Network_id、Original_network_id、Transport_stream_id可以定位一个TS流,该流来源于哪个原始网络,目前在哪个网络里播放

Network_id、Original_network_id、Transport_stream_id、Service id可以定位一个节目,这个就是SDT表的内容

Network_id、Original_network_id、Transport_stream_id、Service id、event_id可以定位节目里面的某一个Event,这就是EIT表

Network_id、Original_network_id、Transport_stream_id、Bouquet_id可以定位一个BAT分组,分组下面有service_id可以定位分组里所有节目

 

 

表名

PID

Table_id

详情

NIT(网络信息表)

默认0x0010

一般从PAT表获取

当前网络:0x40

其他网络:0x41

传递了与通过一个给定的网络传输的TS流的物理结构相关的 信息,以及与网络自身特性相关的信息。

SDT(业务描述表)

0x11

现行TS:0x42

其他TS:0x46

描述包含于一个特定的传输流中的业务。该业务可能是现行传输流中的一部分,也可能是其他传输流中的一部分,可以根据table_id 来确定。

BAT(业务分组表)

0x11

0x4A

提供有关业务群的信息。业务群定义为一组业务的集合,并可能横跨于不同的网络上。

EIT(节目段信息表)

0x12

当前TS:PF 0x4E

Schedule: 0x50-0x5F

其他TS:PF 0x4F

Schedule: 0x60-0x6F

事件信息表EIT按时间顺序提供每一个业务所包含的事件的信息。按照不同table_id,有四类EIT:当前TS的PF信息和Schedule信息,其他TS的PF信息和Sechedule信息。

 

 

 

3.3表的解析

组完Section之后,应该按照PID和Table_Id将Section过滤到对应的表的解析模块处进行解析,section_length等只需解析时使用的变量可以定义成局部变量不保存,其他的必要信息可以定义在结构体里,解析时进行保存。

         解析表的时候,只要根据表的结构将数据一一解析出来就可以了,一般请求的数据会使用char指针或者数组存储,解析的时候可以用char *pdata指针来读取数据,每次读取足够的字节数后,就将pdata+= 上次读取的字节数,这样不用去实时地计算数据读取到了哪个位置,编写代码更加高效。需要注意的是如果pData下传到函数里,函数运行结束后pData的值仍是传下去那一个值,就算在函数里对pdata操作了也不会影响函数外面pdata的值,所以解析描述符的时候可以将pdata下传到子函数里面去解析,但是解析完成的时候记得将pdata往后移动该描述符的长度。

3.3.1 PAT和PMT表的解析

 

 

 

 

 

PAT结构体可以如下定义

/*PAT表结构*/

typedef struct CSTSPATSection_S

{

    DWORD m_dwTransport_Stream_Id;                                

    int  m_nLoopNum;                   //PAT表ProgramNumber的个数

    PATProgram *m_pstPATProgram;

    struct CSTSPATSection_S *m_pstNext;//以链表的形式存储PAT表,这个是next指针

}PATSection;

 

PAT表ProgramNumber为0所指示的PID是NIT表的PID,如果没有ProgramNumber为0的PID,则默认0x10为NIT表的PID;

解析PAT表只需存储TSId、ProgramNumber及其PID;如果PAT表不止一个Section(一般是一个),还需要用链表的方式将信息存储起来

PMT表必须在PAT表解析完成之后进行解析,获得所有当前节目的节目号(ProgramNumber)及其PID之后,就可以请求PMT表了,所以PMT表可能会有很多个,可以使用链表的形式存储,也可以使用结构体数组的形式,为了和SDT等表兼容,最终采用了链表的形式。每个PMT表都可以解析出音视频PID的信息,后续就可以根据这些PID去请求音视频数据了

 

3.3.2 NIT、SDT、BAT表的解析

 

 

三个表的结构如上,解析依旧按照上述PAT、PMT表的方式进行解析就可以,如果有多重循环就使用多个while语句进行解析,基本能解出第一重,后续多几重循环也就是多写大同小异的几个子函数。

这几个表是可能有多个子表的,多个子表也需要判全的,因为不像PAT表,一个频点就只会有一个表,只要Section找全了表就收全了,而PMT表每个PID只会有一个Section,只要多个节目对应的PID收全了就OK。NIT表分为Actual和Other,分表代表当前网络和其他网络,一个网络里面会有多个TS_id,每个TS_id代表一个频点,每个频点里面有Service_id、Service_name等信息,所以SDT子表就可以根据NIT来判全。如果是NIT Actual和SDT Actual,只需搜索当前频点就可以了,判全也只需判断Section是否收全了,如果是SDT Other表,就可能会有多个子表了,要判断除去主频点TS_id,其他TS_id的频点是否收全了,才可以完全判断SDT是否收全了。BAT个人理解没有可以提前判断有多少个bouquet_id的方法,但是bouquet_id的个数有上限,所以BAT都是有几个子表就收几个

 

3.3.3EIT表的解析

首先,EIT表对于每一个子表的判全也是不一样的,这部分应该跟其他表区分开来,EIT表每个Section的Section_length上限是4096,并且有segment的概念,每个segment里面最多有8个Section,所以EIT不仅要对单个Section进行判全,还要对Segment里面多个Section进行判全,项目解析里面是利用Segment_last_section_number对8取余再加一,结果就是Segment里面Section的个数了。

对于EIT子表的判全,必须利用SDT表进行,SDT表里面每个ServiceId下都有两个EIT相关的字段,分别是EIT_schedule_flag、EIT_Present_following_flag,如果两个标记为1,就表示这个Service_Id有对应的EIT子表,根据这个就可以判全EIT子表了。

 

 

 

3.3.4 描述符的解析

 

描述符是存在于Section里面的,可以跟表的其他重要字段一起解析出来,解析方法大同小异。

对于PSI/SI表来说,有些描述符是比较重要的,一般都要解析出来,如下面所示:

 

 

 

表名

描述符

tag

描述

 

network_name_descriptor

0x40

提供网络的名称

 

service_list_descriptor

0x41

提供网络下的节目列表

NIT

satellite_delivery_system_descriptor

0x43

提供卫星相关频点等信息

 

cable_delivery_system_descriptor

0x44

提供有线相关频点等信息

 

terrestrial_delivery_system_descriptor

0x5A

提供地面相关频点等信息

BAT

bouquet_name_descriptor

0x47

提供分组名称信息

 

service_list_descriptor

0x41

提供分组下的节目列表

SDT

service_descriptor

0x48

提供节目描述信息

EIT

short_event_descriptor

0x4D

短事件描述符

 

extended_event_descriptor

0x4E

拓展信息事件描述符

 

你可能感兴趣的:(DVB,dvb,ts流解析,C语言,PSISI,数据)