- TS数据流的解析
-
文档修改信息
-
1 TS 数据流简介
- 1.1 TS流的构成
- 1.2 TS流的产生
- 1.3 TS流的格式
- 1.4 参考文档
- 1.5 小结
-
2 TS数据流包头的解析
- 2.1 解析步骤
- 2.2 包长解析
- 2.3 PID解析
- 2.4 负载单元开始标志解析
- 2.5 小结
-
3 PAT表的解析
- 3.1 解析步骤
- 3.2 PAT表的描述
- 3.3 PAT表的获取
- 3.4 PAT表信息的解析
- 3.5 小结
-
4 PMT表的解析
- 4.1 解析步骤
- 4.2 PMT表的描述
- 4.3 PMT表的获取
- 4.4 PMT表信息解析
- 4.5 小结
-
5 SDT表的解析
- 5.1 解析步骤
- 5.2 SDT表的描述
- 5.3 SDT表的获取
- 5.4 SDT表信息解析
- 5.5 小结
-
6 NIT表的解析
- 6.1 解析步骤
- 6.2 NIT表的描述
- 6.3 NIT表的获取
- 6.4 NIT表信息解析
- 6.5 小结
-
7 描述符的解析
- 7.1 描述符的介绍
- 7.2 描述符的获取
- 7.3 描述符的解析
- 7.4 小结
-
8 数据包的处理
- 8.1 数据的存储
- 8.2 完整数据包的获取
- 8.3 数据包的合并
- 8.4 小结
-
9 Makefile的编写
-
10 总结
-
11 参考文献
-
TS数据流的解析
文档修改信息
版本 | 时间 | 备注 | |
---|---|---|---|
1.0 | 李海杰 | 2022-03-07 | 搬运到CSDN并修改相关数据 |
1 TS 数据流简介
? 简单来说,数字机顶盒是能够接收到一段段的码流,这样的码流我们可以称之为TS(Transport Stream,传输流),每个TS流里都携带的有一些信息,例如Video、Audio、PAT、PMT等。
1.1 TS 流的构成
? TS 流是一种用于数据传输的单一传输流,它是由一些具有共同时间基准或独立时间基准的一个或多个PES复合而成的。
在这里我们需要知道一些其他数据流:
- ES流(Elementary Stream) 基本码流,不分段的音频、视频或其他信息的连续码流。
- PES流 把基本流ES分割成段,并加上相应头文件打包成形的打包基本码流。
1.2 TS 流的产生
在实际传输中,PES包会被切割后装载到TS包中,上图就是PES和TS之间的关系图。
注意:
- 一个PES包可以装载到不同的TS包。
- 每一个TS包必须只含有从一个PES来的数据。
- PES包头必须跟在TS包的链接头后面。
- 对于一个特定的PES,最后一个TS包可以含有填充比特。
1.3 TS 流的格式
? TS流是基于Packet的位流格式,每个包的长度是固定的188个字节(或者204个字节,原因是在188个字节后加上了16个字节的CRC校验数据,其他格式一样)。整个TS流组成形式如下:
- 我们先通过fopen()函数来打开TS文件,并保存文件流指针。然后用fgetc()函数来读取文件中的每个字节数据,再加上while()循环语句来实现遍历读取。当我们遇到为0x47的数据时,就调用一个判断函数来进行下一步的判断。
- 在判断函数中我是采用从当前0x47位置向后偏移188字节或者204字节的方式来判断下一段数据是否为0x47。如果是,说明是一段完整数据包;如果不是,说明我们并未找到包头,那么继续遍历。
- 在这里我们为了排除偶然情况,我们可以选择利用for()函数进行一定次数的循环,往后多移动几次来确定所获取的的确是一段完整的TS数据包。
- 通过这几步骤的循环判断,我们就可解析出我们的数据包长度是188字节还是204字节。
2.3 PID解析
? 当我们解析出一段完整的数据包后就可以利用一个数组来对这一段完整的数据进行保存,方便我们后面的解析。对包头解析时我们需要知道我们的包头结构,每个字节代表什么含义,每个数据有占有多少字节位数。下面就是我们的包头结构表:
Packet Header(包头)信息说明 | 标识 | 位数 | 说明 |
---|---|---|---|
1 | sync_byte | 8bits | 同步字节 |
2 | transport_error_indicator | 1bit | 错误指示信息(1:该包至少有1bits传输错误) |
3 | payload_unit_start_indicator | 1bit | 负载单元开始标志(packet不满188字节时需填充) |
4 | transport_priority | 1bit | 传输优先级标志(1:优先级高) |
5 | PID | 13bit | Packet ID 码,唯一的 码对应不同的包 |
6 | transport_scrambling_control | 2bits | 加密标志(00:未加密;其他表示已加密) |
7 | adaptation_field_control | 2bits | 附加区域控制 |
8 | continuity_counter | 4bits | 包递增计数器 |
? 我们可以看出我们所想获取到的PID是包头的第2个字节的5bits加上第3个字节的8bits,那么我们可以先创建一个结构体,来对包头数据进行存储。
- 因为我们知道,TS数据包的包头是固定4个字节。那么我们就将之前所保存的数据包数据取出前四个字节来放入结构体中。这样一来我们就能够通过结构体来获取到我们该段数据包的PID数据。
TS_Package_Head ParseTS_PackageHead(TS_Package_Head TS_PackageHead, unsigned char PackageHead_data[4]){ TS_PackageHead.sync_byte = PackageHead_data[0]; TS_PackageHead.transport_error_indicator = PackageHead_data[1] >> 7; TS_PackageHead.payload_
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!