视频头文件解析--ts

分类: 视频编解码 2013-01-16 12:34 347人阅读 评论(0) 收藏 举报
TS ts 视频封装

数据结构:

typedef struct pmt_es_component_tag

{

D_UINT8  stream_type;

D_UINT8  bfree;

D_UINT16 elementary_PID;

}pmt_component_t;

typedef struct pid_tag

{

PID_STATE   state;

PID_TYPE     type;

D_UINT16     pid;

D_UINT8      ch_idx;

D_UINT8      bfree;

}ts_pid_t;

typedef struct

{

D_UINT16 prog_number;

D_UINT16 pcr_pid;

D_UINT16 video_pid;

D_UINT16 video_stream_type;

D_UINT16 audio_pid;

D_UINT16 audio_pids_cnt;

D_UINT16 audio_pids[MAX_AUDIO_PER_CHANNEL];

D_UINT16 audio_stream_type[MAX_AUDIO_PER_CHANNEL];

D_UINT8  bfree;

}PMTEXT_T;

 

ts分组结构

TS分组前面提到,TS分组由188个字节构成,其结构如下:

transport_packet()

{

sync_byte                                   8bit

transport_error_indicator                   1 bit

payload_unit_start_indicator                1 bit

transport_priority                          1 bit

PID                                         13bit

transport_scrambling_control                2 bit

adaptation_field_control                    2 bit

continuity_counter                          4 bit

if(adaptation_field_control=='10'||daptation_field_control=='11')

{

adaptation_field()

}

if(adaptation_field_control=='01' ||adaptation_field_control=='11')

{

for (i=0;i<N;i++)

{

data_byte                           8 bit

}

}

}

前面32bit的数据即TS分组首部,它指出了这个分组的属性。

sync_byte 同步字节,固定为0x47 ,表示后面的是一个TS分组,当然,后面包中的数据是不会出现0x47的

transport_error_indicator传输错误标志位,一般传输错误的话就不会处理这个包了.

payload_unit_start_indicator这个位功能有点复杂,字面意思是有效负载的开始标志,根据后面有效负载的内容不同功能也不同,后面用到的时候再说。

transport_priority传输优先级位,1表示高优先级,传输机制可能用到,解码好像用不着。

PID 这个比较重要,指出了这个包的有效负载数据的类型,告诉我们这个包传输的是什么内容。前面已经叙述过。

transport_scrambling_control加密标志位,表示TS分组有效负载的加密模式。TS分组首部(也就是前面这32bit)是不应被加密的,00表示未加密。

adaption_field_control翻译为“调整字段控制”,表示TS分组首部后面是否跟随有调整字段和有效负载。01仅含有效负载,10仅含调整字段,11含有调整字段和有效负载为00的话解码器不进行处理。空分组没有调整字段

continuity_counter一个4bit的计数器,范围0-15,具有相同的PID的TS分组传输时每次加1,到15后清0。不过,有些情况下是不计数的。如下:(1)TS分组无有效负载(2)复制的TS分组和原分组这个值一样(3)后面讲到的一个标志discontinuity_indicator为1时

adaptation_field()调整字段的处理

data_byte有效负载的剩余部分,可能为PES分组,PSI,或一些自定义的数据。

PAT数据结构如下:

program_association_section()

{

table_id                                                                                       8

section_syntax_indicator                                          1

'0'                                                                          1

reserved                                                                 2

section_length                                                        12

transport_stream_id                                                16

reserved                                                                 2

version_number                                                      5

current_next_indicator                                            1

section_number                                                      8

last_section_number                                                8

for(i=0; i<N;i++)

{

program_number                                            16

reserved                                                         3

if(program_number== '0')

{

network_PID                                                  13

} else {

program_map_PID                                   13

}

}

CRC_32                                                                32

}

table_id 固定为0x00,标志是该表是PAT

section_syntax_indicator段语法标志位,固定为1

section_length 表示这个字节后面有用的字节数,包括CRC32。假如后面的字节加上前面的字节数少于188,后面会用0XFF填充。假如这个数值比较大,则PAT会分成几部分来传输。

transport_stream_id该传输流的ID,区别于一个网络中其它多路复用的流。

version_number范围0-31,表示PAT的版本号,标注当前节目的版本.这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经变化了,程序必须重新搜索节目.

current_next_indicator表示发送的PAT是当前有效还是下一个PAT有效。

section_number分段的号码。PAT可能分为多段传输,第一段为00,以后每个分段加1,最多可能有256个分段

last_section_number最后一个分段的号码

program_number 节目号

network_PID 网络信息表(NIT)的PID,网络信息表提供了该物理网络的一些信息,和电视台相关的。节目号为0时对应的PID为network_PID

program_map_PID 节目映射表的PID,节目号大于0时对应的PID,每个节目对应一个

CRC_32 CRC32校验码

PMT数据结构如下:

TS_program_map_section()

{

table_id                                                   8

section_syntax_indicator                           1

'0'                                                            1

reserved                                                   2

section_length                                         12

program_number                                       16

reserved                                                   2

version_number                                       5

current_next_indicator                             1

section_number                                       8

last_section_number                                 8

reserved                                                   3

PCR_PID                                                13

reserved                                                   4

program_info_length                               12

for (i=0;i<N; i++)

{

descriptor()

}

for(i=0;i<N1;i++)

{

stream_type                                     8

reserved                                            3

elementary_PID                               13

reserved                                           4

ES_info_length                                12

for(i=0; i<N2; i++)

{

descriptor()

}

}

CRC_32                                                  32

}

table_id 固定为0x02,标志是该表是PMT。

section_syntax_indicatorsection_length version_number current_next_indicator 以上四个字段意思和PAT相同,可参考上面解释

section_numberlast_section_number 以上两个字段意思和PAT相同,不过值都固定为0x00,我觉得这样的原因可能是因为PMT不需要有先后顺序,因为先定义哪个节目都是无所谓。

program_number 节目号,表示该PMT对应的节目

PCR_PID PCR(节目时钟参考)所在TS分组的PID,根据PID可以去搜索相应的TS分组,解出PCR信息。

program_info_length该节目的信息长度,在此字段之后可能会有一些字节描述该节目的信息

解析步骤:

1、D_UINT32 ts_stream_verify(char *pathfile,D_UINT8 *buffer)

1)此函数功能是,首先打开文件,从文件中读取前128个包(一个包188字节大)

2)查找前面的500个字节,从找到的第一个0X47开始,如果紧接着的两个包里(每个包按188字节来算)的第一个字节都是0X47,那么就断定此文件为TS文件

2、D_UINT32 pmt_check_pids(char *pathfile)

1)此函数功能是,首先打开文件,从文件中读取前128个包(一个包188字节大)

2)查找前面的500个字节,从找到的第一个0X47开始,如果紧接着的两个包里(每个包按188字节来算)的第一个字节都是0X47

3)从此字节开始往后读取128个包到内存里,然后从这个内存里读取4字节作为包头packet_header进行解析。packet_header与上0XFFC00000如果为0X47000000表明这个头是ts188字节的包的包头,之所以与上0XFFC00000是因为在包头的4字节中,第一字节是同步字节0X47

4)包头右移8位再与上0X1fff,可以获得包头中的PID(包识别)

5) 包头右移4位再与上0X03,可以获得包头中的自适应区控制位adaption_field,如果adaption_field为0X01表示有有用信息无自适应区,为0X03表示有有用信息有自适应区,为0X00无定义,为0X02表示无有用信息有自适应区,如果adaption_field为0X01或者是0X03此包不在解析。跳到下一个188字节的包。

6)判断现在获得的pid是不是在pid列表里面,如果pid列表里面已经有了,那么跳出,做下一个188字节的解析

7)如果找到的是一个不存在于列表中的新的pid,把这个pid存入列表

8)此时把位置指针后移4个字节,跳过包头数据,然后判断如果此包里面有自适应区,跳过自适应区,解析后面的数据

9)跳过头数据和自适应区之后,到包数据,取得前4个字节,其中包含pat数据结构的部分参数. second_u32 = (ts_packets[pos]<<24) | (ts_packets[pos +1]<<16) | (ts_packets[pos + 2]<<8) | (ts_packets[pos + 3]);此时的pos已经是跳过包头和自适应区的指针位置

10)通过second_u32与上不同的值得到的结果可以判断这个内容里面到底是哪种类型的pid

eg:if( (second_u32& 0xFFFFFFF0) == 0x000001E0) //Video PES

if( (second_u32 & 0xFFFFFFE0) ==0x000001C0)//Audio PES

if( (second_u32 & 0xFFFFFFE0) ==0x000001A0) //Audio PES

if( (second_u32 & 0xFFFFFF00) ==0x00000100 )// Other PES

if( (second_u32 & 0xFF00F000) ==0x0000B000) //Sections PMT表

11)通过second_u32右移16位,与上0XFF可以得到table_id,如果table_id为0X20表明为pmt表

12)通过second_u32与上0XFFF可以得到section_length

13)pos指针后移一个字节进行解析1、PCR(节目时钟参考)所在TS分组的PID 2、频道号3、频道描述信息。具体参考parser_pmt_section函数。接续出来的信息有很多组。因为同一个ts流里面可能有很多组频道信息等,parser_pmt_section返回值就是解析出来的频道数

14)把解析出来的信息赋值给pmt_infor结构体列表,具体参考assign_pmt_info函数

15)如果此包解析完了之后(pos <188 && ts_packets[pos] != 0xFF),继续解析次pmt表里面的其他组信息

16)之后做pmt表信息的检查,如果此pmt表信息里面包含多个audiopid信息,那么为此频道找到一个幼小的audio pid

17)如果这个pmt表中没有发现有效的video和audio pid,那么这个pmt的pid将被从pmt信息列表中删除。

18)如果之后pmt表中的pid个数大于0.表明有频道信息,返回pids_chan_cnt频道个数。

19)如果pmt表中的pid个数小于0.表明没有pmt表,解析之前解出来的pid,比较pid的type参数,按不同类型完成pmt表

3、ts_get_channel_info(DG_MEDIA_FILE_INFO *file_info)

把pmt_infor结构的信息赋值给file_info。供解码器调用

视频头文件解析--ts相关推荐

  1. java获得U盘根目录、读取图片视频头文件信息、获取视频时长

    1.获得U盘根目录,例如我们取名U盘名称为"测试U盘",一般插入U盘后,在系统的H盘 /** * 得到系统U盘根目录 */ public String findURootPath( ...

  2. NSObject头文件解析 / 消息机制 / Runtime解读 (一)

    NSObject头文件解析 当我们需要自定义类都会创建一个NSObject子类, 比如: #import <Foundation/Foundation.h>@interface Class ...

  3. time.h头文件解析

    本文从介绍基础概念入手,探讨了在C/C++中对日期和时间操作所用到的数据结构和函数,并对计时.时间的获取.时间的计算和显示格式等方面进行了阐述.本文还通过大量的实例向你展示了time.h头文件中声明的 ...

  4. 第一次创建Qt程序,对里面源代码头文件解析,常用快捷键,Qt助手

    Qt助手: 命名规范和常用快捷方式: 命名规范 类名 首字母大写,单词和单词之间首字母大写 函数名 变量名称 首字母小写,单词和单词之间首字母大写注释ctrl + / 运行 ctrl + r 编译 c ...

  5. C语言中的stdlib头文件解析

    stdlib 头文件即standard library(标准库)头文件,里面包含了C.C++语言的最常用的系统函数.包括动态内存管理.随机数生成.与环境之间的通信.整数运算.搜索.排序及转换等. st ...

  6. C语言中的string头文件解析

    标准库提供了一些函数用于处理字符串,它们的原型位于头文件string.h中. •string.h头文件定义了一个变量: size_t:这是无符号整数类型,它是 sizeof 关键字的结果. •定义了一 ...

  7. C语言头文件 “ 细节 ”

    很多事不深入以为自己懂了,但真正用到项目上,才发现了问题.曾以为自己写C语言已经轻车熟路了,特别是对软件文件的工程管理上,因为心里对自己的代码编写风格还是有自信的.(毕竟刚毕业时老大对我最初的训练就是 ...

  8. C语言编程规范 — 头文件、函数

    0 编码规范说明 0.1 前言 为了提高产品或项目代码质量,软件开发人员编写出简洁.可靠.可维护.可测试.高效.可移植的代码,树立良好的编程规范是非常有必要的,良好的编程规范能提高编程效率,规避很多编 ...

  9. C语言中头文件包含的处理原则

    很多事不深入以为自己懂了,但真正用到项目上,才发现了问题.曾以为自己写C语言已经轻车熟路了,特别是对软件文件的工程管理上,因为心里对自己的代码编写风格还是有自信的.(毕竟刚毕业时老大对我最初的训练就是 ...

最新文章

  1. 文本框可编辑查看页面
  2. python之接口开发
  3. SQL基础学习总结:5(HAVING子句的使用ORDER BY排序子句的使用)
  4. mysql innodb_data_file_path_关于innodb_data_file_path设置
  5. Java初阶知识总结
  6. HDU2021多校第五天 1009 Array-树状数组求二阶前缀和
  7. 【管理】如何有效管理自己的时间
  8. 添加 XmlDocument 元素 和 属性
  9. PyTorch实战福利从入门到精通之九——数据处理
  10. SSM-1-SSM整合
  11. 图解FFMPEG打开媒体的函数avformat_open_input
  12. 【每日算法Day 105】打家劫舍第二弹:看好你的电瓶车!
  13. python与java通信——使用socket模块
  14. Win10 企业版 LTSC 安转.appx的方式
  15. 【PMP】风险应对策略
  16. 苹果录屏没声音_不会真有人MacBook录屏没声音吧?别用了SoundFlower了!
  17. java微博分享代码实例
  18. ArcMap通过空间连接和数据汇总实现批量统计
  19. C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(上)
  20. 自媒体必备工具:免费的音文对齐生成SRT字幕,快速打轴匹配声音及文字的在线工具

热门文章

  1. OpenCV 无法启动此程序,因为计算机中丢失opencv_core249.dll(类似的),解决方法
  2. 科普:影子模式shadow mode
  3. Navigation跳跃导航
  4. 技能梳理34@自举电路+无刷/有刷电机驱动电路
  5. 计算机维护维修实训报告,计算机维护维修实训报告.doc
  6. Blender:Lowpoly头部建模流程 第二部分(附blender源文件下载)
  7. EasyNVR结合阿里云/腾讯云CDN实现微信/小程序直播的方案
  8. 华为鸿蒙和海思,华为鸿蒙+海思,值得你期待!
  9. scrapy使用item,pipeline爬取数据,并且上传图片到oss
  10. 知识点滴 - 中国有多少省,简称是什么