全新系列文章已更新:
- Android Media Framework - 开篇
- Android Media Framework(一)OpenMAX 框架简介
- Android Media Framework(二)OpenMAX 类型阅读与分析
- Android Media Framework(三)OpenMAX API阅读与分析
- Android Media Framework(四)Non-Tunneled组件的状态转换与buffer分配过程分析
- Android Media Framework(五)Tunnel Mode
- Android Media Framework(六)插件式编程与OMXStore
- Android Media Framework(七)MediaCodecService
- Android Media Framework(八)OMXNodeInstance - Ⅰ
- Android Media Framework(九)OMXNodeInstance - Ⅱ
- Android Media Framework(十)OMXNodeInstance - Ⅲ
TS码流有PSI和PES两种负载,这一节主要来了解PSI是如何解析的。
1、PSI
PSI(Program Specific Information)节目专用信息,用来描述TS码流的节目组成等信息。PSI中包含的几个比较重要且常用的表有:
PAT(Program Association Table)
:节目关联表,记录有当前TS码流中所有的节目以及对应的PID;PMT(Program Map Table)
:节目映射表,记录有当前节目包含的所有视频流以及流对应的PID;CAT(Conditional Access Table)
:条件访问表,用于记录节目的加密和解密信息(这一节仅作了解)。
看过上一篇TS Header解析的朋友们会知道,Adaption Field的长度是不能超过一个TS包的,所以解析起来比较简单。但是PAT、PMT、CAT表长度可长可短,我觉得可以分成三类:
- 长度较小,一个TS包就可传输完成;
- 长度较大,需要分为多个TS包传输;
- 长度超大(超过1024字节),需要把表分为多段(section),并且给每个section编上号,最后再用TS包传输,section也可能会跨包传输;
第一类解析最简单,第二类需要接收到完整的表之后才能开始解析工作,第三类每个section都包含有元信息,可以单独解析,解析完成后可以把表汇总起来。
我觉得是为了统一,TS包在传输PSI信息时,无论信息长短都用了section分段传输的方式。section在TS payload中的分布可能如下:
- section可能会从payload起始位置开始,占满一整个TS包;
- section可能会紧接上一个section,从payload中间开始。
这里可能有人要问了,有没有可能一个payload中有超过有一个完整的section?答案是不会的,如果两个section可以在同一包中,为什么不合并为一个section呢?
这里会有一个问题,section如果从payload中间开始,我们如何知道它从哪里开始?
2、PAT
规定PAT表的PID是0x00,当接收的TS包的PID为0时,我们就知道该TS包的负载数据是属于PAT表了。
我们需要从PSI section中解析出PAT表的内容,规定当section的table_id字段为0时,section payload中是PAT表信息,所以PID为0时需要检查section payload的第一个字节是否为0x00。table_id为0x00时,section payload结构如下:
section payload中存储的是节目数组循环,结构如下: