TS文件格式详解及解封装过程

news/2024/11/2 9:25:26/

简要

ts是一种封装格式,全名为MPEG-TS,文件分为三层:ts层(Transport Stream)、pes层(Packet Elemental Stream)、es层(Elementary Stream)。es层就是音视频数据,pes层是在音视频数据上加了时间戳等对数据帧的说明信息,ts层是在pes层上加入了数据流识别和传输的必要信息(header)。

相关概念

PAT:Program Association Table,节目关联表

PMT:Program Map Table,节目映射表

ES流(Elementary Stream):基本码流,不分段的音频、视频或其他信息的连续码流。

PES流:把基本流ES分割成段,在每一个视频/音频帧上加入了时间戳等信息。

PS流(Program Stream):节目流,将具有共同时间基准的一个或多个PES组合(复合)而成的单一数据流(用于播放或编辑系统,如m2p)。

TS流(Transport Stream):传输流,将具有共同时间基准或独立时间基准的一个或多个PES组合(复合)而成的单一数据流(用于数据传输)

ES你可以理解为一段音频或者视频的数据,ES流可能会很大,所以要拆分成PES包,PES包的长度是有限制的,64KB。所以并不是一个ES对应一个PES。

TS:ts_header(0x47开头)+payload(负载)-------188个字节

PES:pes_header( 0x000001开头)+ES(包含时间戳)------64K

ES:NAL(0x0001开头(3或者4个字节),SPS(0x67),PPS(0x68),I帧(0x65),I帧(0x65))+编码data-----不限制大小,比如I帧可能有好几百K

scrambling (system): 加扰,以改变视频,音频或编码数据流的特性,防止以明文形式传输,使未经授权者接收明文数据。

PCR (system): Program Clock Reference

PTS(system):presentation time-stamp 显示时间戳,可能存在于PES包头中的字段,用于指示在系统目标解码器中显示帧数据的时间。

DTS(system):decoding time-stamp 解码时间戳,可能存在于PES包头中的字段,用于指示在系统目标解码器中解码访问帧数据的时间。

CRC:Cyclic Redundancy Check 循环冗余检查,以验证数据的正确性。

PSI:Program Specific Information 程序特定信息,提供了单个TS流的信息,使接收方能够对单个TS流中的不同节目进行解码,这些信息都存在用表的形式提供给,如PAT、PMT、CAT等。但它无法提供多个TS流的相关业务,也不能提供节目的类型、节目名称、开始时间、节目简介等信息。

SI:Specific Information 特定信息,PSI中无法提供的相关信息,SI定义了NIT、SDT、EIT和TDT等9张表,方便用户查看多种信息。
 

结构图

通过av_read_frame获取到原始的es数据流对比可以看出.和ts原始数据缺少了ts和pes的头.左边为.ts文件,右边为.264文件。 

流程图

                                                        编码过程

TS解析图

这个图主要解析的是流的基本信息:format,filesize,duration,bitrate以及音视频的Count

  PAT和PMT的相关基本信息

下面图是多音轨的TS

 

 各种流的PID,索引及数量占的百分比,可以看到PAT和PMT是一一对应的,同时对应多个音频或者视频数据

分析

TS层的packet都是固定等长的188字节包,由ts header、adaptation field、payload组成,其中ts header固定4个字节(32位);adaptation field可能存在也可能不存在,主要作用是给不足188字节的数据做填充;payload是pes数据。结构图如下

Ts header部分

这里我们分析一段TS流其中一个Packet的Packet Data部分:
        首先给出一个数据包,其数据如下: 

Packet Header

Packet Data

0x47 0x40 0x00 0x10

0000 b0 11 00 01 c1 00 00 00 00 e0 1f 00 01 e1 00 24 ac48 84 ff ff…… ff ff

分析Packet Header如下表所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

Packet(十六进制)

4

7

4

0

0

0

1

0

Packet(二进制)

0

1

0

0

0

1

1

1

0

1

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

1

0

0

0

0

Packet Header Bits

1 sync_byte=0x47

2

3

4

5 PID=0x0000

6

7

8

根据包头数据格式,我们可以知晓整个数据包的属性,列表如下:

sync_byte

0x47

固定同步字节

transport_error_indicator

“0”

没有传输错误

payload_unit_start_indicator

“1”

在前4个字节后会有一个调整字节。所以实际数据应该为去除第一个字节后的数据。即上面数据中红色部分不属于有效数据包。

transport_priority

“0”

传输优先级低

PID

0x0000

PID=0x0000说明数据包是PAT表信息

transport_scrambling_control

“00”

未加密

adaptation_field_control

“01”

附加区域控制

continuity_counte

“0000”

包递增计数器

如上表所示,我们可以知道,首先Packet的Packet Data是PAT信息表,因为其PID为0x0000,并且在包头后需要除去一个字节才是有效数据(payload_unit_start_indicator="1"),即上面数据中红色部分不属于有效数据包。这样,Packet Data就应该是“ 00 b0 11 00 01 c1 00 00 00 00 e0 1f 00 01 e1 00 24 ac48 84 ff ff …… ff ff ”。

Packet Data分析

第n个字节

  1  

  3  

4

5

6

7

8

9

 10 

 11 

  12 

  13 

14 

15 

16

17

18

19

20

Packet Data(除去开头的0x00)

00

b0

11

00

01

c1

00

00

00

00

e0

1f

00

01

e1

00

24

ac

48

84

字段名

具体值

次序

说明

table_id

8

0000

第1个字节 0000 0000B(0x00)

PAT的table_id只能是0x00

section_syntax_indicator

1

1

第2、3个字节

1011 0000 0001 0001B(0xb0 11)

段语法标志位,固定为1

zero

1

0

reserved

2

11

section_length

12

0000 0001 0001B=0x011=17

段长度为17字节

transport_stream_id

16

0x0001

第4、5个字节 0x00 0x01

reserved

2

11

第6个字节 1100 0001B(0xc1)

version_number

5

00000

一旦PAT有变化,版本号加1

current_next_indicator

1

1

当前传送的PAT表可以使用,若为0则要等待下一个表

section_number

8

0x00

第7个字节0x00

last_section_number

8

0x00

第8个字节 0x00

开始循环

program_number

16

0x0000-第一次

2个字节(0x00 00)

节目号 

reserved

3

111

2个字节

1110 0000 0001 1111B(0xe0 1f)

network_id(节目号为0时)

program_map_PID(节目号为其他时)

13

0 0000 0001 1111B=31

-第一次

节目号为0x0000时,表示这是NIT,PID=0x001f,即31

节目号为0x0001时,表示这是PMT,PID=0x100,即256

结束循环

CRC_32

32

--

4个字节

PID


       PID是TS流中唯一识别标志,Packet Data是什么内容就是由PID决定的。如果一个TS流中的一个Packet的Packet Header中的PID是0x0000,那么这个Packet的Packet Data就是DVB的PAT表而非其他类型数据(如Video、Audio或其他业务信息)。 

 从这两个图,可以看出,PAT的PID是0。 下表给出了一些表的PID值,这些值是固定的,不允许用于更改。

PAT

PAT表(Program Association Table,节目关联表) ,PAT的PID为0x0000,它的主要作用是针对复用的每一路传输流,提供传输流中包含哪些节目、节目的编号以及对应节目的节目映射表(PMT)的位置,即PMT的TS包的包标识符(PID)的值,同时还提供网络信息表(NIT)的位置,即NIT的TS包的包标识符(PID)的值。

  •  table_id: 标识一个TS PSI 分段的内容是节目关联分段,条件访问分段还是节目映射分段。对于PAT,置为0x00。
  • section_syntax_indicator: 对于PAT,置为0x01。
  • section_length: 分段长度字段,其值为从section_length(包括在内)到CRC_32字段的字节数,其值不超过1021。
  • transport_stream_id: 区别与其他复用流的标识。
  • version_number: PAT的版本号,如果PAT有变,则版本号加1。
  • current_next_indicator:置0时,表明该传送的表分段不能使用,下一个表分段才有效。
  • section_number: 表明该TS包属于该PAT的第几个分段,分段号从0开始。
  • last_section_number: 表明最后一个分段号,同时表明该PAT的最大分段数目。一般,一个PAT表由一个TS包传送。
  • program_number: 节目的编号。
  • network_PID: NIT表的PID值。
  • program_map_PID: PMT表的PID值。
  • CRC_32: CRC校验。
     
typedef struct TS_PAT  
{  unsigned table_id                     : 8; //固定为0x00 ,标志是该表是PAT表  unsigned section_syntax_indicator     : 1; //段语法标志位,固定为1  unsigned zero                         : 1; //0  unsigned reserved_1                   : 2; // 保留位  unsigned section_length               : 12; //表示从下一个字段开始到CRC32(含)之间有用的字节数  unsigned transport_stream_id          : 16; //该传输流的ID,区别于一个网络中其它多路复用的流  unsigned reserved_2                   : 2;// 保留位  unsigned version_number               : 5; //范围0-31,表示PAT的版本号  unsigned current_next_indicator       : 1; //发送的PAT是当前有效还是下一个PAT有效  unsigned section_number               : 8; //分段的号码。PAT可能分为多段传输,第一段为00,以后每个分段加1,最多可能有256个分段  unsigned last_section_number          : 8;  //最后一个分段的号码  std::vector<TS_PAT_Program> program;  unsigned reserved_3                    : 3; // 保留位  unsigned network_PID                    : 13; //网络信息表(NIT)的PID,节目号为0时对应的PID为network_PID  unsigned CRC_32                        : 32;  //CRC32校验码  
} TS_PAT;   

从图中可以看到,这个TS里有一个节目,而PMT_PID=0x1000(4096)

PMT

PMT表(Program Map Table,节目映射表)

指明该节目包含的内容,即该节目由哪些流组成,这些流的类型(音频、视频、数据),以及组成该节目的流的位置,即对应的TS包的PID值,每路节目的节目时钟参考(PCR)字段的位置。

PMT表中包含的数据如下:

  • 当前节目中所有Video ES流的PID
  • 当前节目所有Audio ES流的PID
  • 当前节目PCR的PID等。

 从图中可以看到这个TS包含一个program,program里包含一路视频和四路音频

 主要的字段解析如下:

  • table_id: 标识一个TS PSI 分段的内容是节目关联分段,条件访问分段还是节目映射分段。对于PMT,置为0x02。
  • section_syntax_indicator: 对于PMT,置为0x01。
  • section_length: 分段长度字段,其值为从section_length(包括在内)到CRC_32字段的字节数,其值不超过1021。
  • program_number: 表明一共有多少个节目。
  • version_number: PMT的版本号,如果字段中有关信息有变,则版本号以32为模加1。版本号是对一个节目的定义。
  • current_next_indicator:置0时,表明该传送的表分段不能使用,下一个表分段才有效。
  • section_number: 总为0x00。
  • last_section_number: 总为0x00。
  • PCR_PID: 指示含有该节目的PCR字段的TS包的PID。
  • program_info_length: 表明跟随其后的对节目信息描述的字节数,也就是第一个N loop descriptors的字节数。
  • stream_type: 表明PES流的类型。譬如,0x01表明是MPEG-1视频,0X03表明是MPEG-1音频。
  • elementary_PID: 表明该负载有该PES流的TS包的PID值。
  • ES_info_length: 表明跟随其后的描述相关节目元素的字节数,也就是第二个N loop descriptors的字节数。
  • CRC_32: 在CEDARX代码中仅对DVB的场景下作校验。
     

typedef struct TS_PMT_Stream  
{  unsigned stream_type                       : 8; //指示特定PID的节目元素包的类型。该处PID由elementary PID指定  unsigned elementary_PID                    : 13; //该域指示TS包的PID值。这些TS包含有相关的节目元素  unsigned ES_info_length                    : 12; //前两位bit为00。该域指示跟随其后的描述相关节目元素的byte数  unsigned descriptor;  
}TS_PMT_Stream;//PMT 表结构体
typedef struct TS_PMT
{unsigned table_id                        : 8; //固定为0x02, 表示PMT表unsigned section_syntax_indicator        : 1; //固定为0x01unsigned zero                            : 1; //0x01unsigned reserved_1                      : 2; //0x03unsigned section_length                  : 12;//首先两位bit置为00,它指示段的byte数,由段长度域开始,包含CRC。unsigned program_number                    : 16;// 指出该节目对应于可应用的Program map PIDunsigned reserved_2                        : 2; //0x03unsigned version_number                    : 5; //指出TS流中Program map section的版本号unsigned current_next_indicator            : 1; //当该位置1时,当前传送的Program map section可用;//当该位置0时,指示当前传送的Program map section不可用,下一个TS流的Program map section有效。unsigned section_number                    : 8; //固定为0x00unsigned last_section_number            : 8; //固定为0x00unsigned reserved_3                        : 3; //0x07unsigned PCR_PID                        : 13; //指明TS包的PID值,该TS包含有PCR域,//该PCR值对应于由节目号指定的对应节目。//如果对于私有数据流的节目定义与PCR无关,这个域的值将为0x1FFF。unsigned reserved_4                        : 4; //预留为0x0Funsigned program_info_length            : 12; //前两位bit为00。该域指出跟随其后对节目信息的描述的byte数。std::vector<TS_PMT_Stream> PMT_Stream;  //每个元素包含8位, 指示特定PID的节目元素包的类型。该处PID由elementary PID指定unsigned reserved_5                        : 3; //0x07unsigned reserved_6                        : 4; //0x0Funsigned CRC_32                            : 32; 
} TS_PMT;

PAT与PMT两张表帮助我们找到该传送流中的所有节目与流,PAT告诉我们,该TS流由哪些节目组成,每个节目的节目映射表PMT的PID是什么,而PMT告诉我们,该节目由哪些流组成,每一路流的类型与PID是什么。

TS流的形成过程:

  • 将原始音视频数据压缩之后,压缩结果组成一个基本码流(ES)。
  • 对ES(基本码流)进行打包形成PES。
  • 在PES包中加入时间戳信息(PTS/DTS)。
  • 将PES包内容分配到一系列固定长度的传输包(TS Packet)中。
  • 在传输包中加入定时信息(PCR)。
  • 在传输包中加入节目专用信息(PSI) 。
  • 连续输出传输包形成具有恒定比特率的MPEG-TS流。


TS流的解析过程:

  • 从复用的MPEG-TS流中解析出TS包;
  • 从TS包中获取PAT及对应的PMT(PSI中的表格);
  • 从而获取特定节目的音视频PID;
  • 通过PID筛选出特定音视频相关的TS包,并解析出PES;
  • 从PES中读取到PTS/DTS,并从PES中解析出基本码流ES;
  • 将ES交给解码器,获得压缩前的原始音视频数据

分析TS解析过程

ffmpeg对mpeg2-TS详细解析_ChenYuanshen的博客-CSDN博客_ffmpeg mpeg2

FFMpeg对MPEG2 TS流解码的流程分析

FFMpeg对MPEG2 TS流解码的流程分析_iteye_4476的博客-CSDN博客

FFMpeg对MPEG2 TS流解码的流程分析[2]

FFMpeg对MPEG2 TS流解码的流程分析[2] - it610.com

TS流PAT/PMT详解

TS流PAT/PMT详解_rolandz_的博客-CSDN博客_pat pmt

TS 流解析流程

  • 复用的MPEG-TS流中解析出TS包;
  • 从TS包中获取PAT及对应的PMT;
  • 从而获取特定节目的音视频PID;
  • 通过PID筛选出特定音视频相关的TS包,并解析出PES;
  • 从PES中读取到PTS/DTS,并从PES中解析出基本码流ES;
  • 将ES交给解码器,获得压缩前的原始音视频数据。

总下简单的说就是,解析ts的过程就是通过找到PAT表,从PAT表中找出对应存在的节目的id,按照这些id找到这些节目的PMT表,从中获到这些节目总的相对的媒体数据id,然后通过这些id,再从ts文件中找到这些文件的es数据,来完成解码或者别的什么操作。

TS流PAT/PMT详解 - rlandj - 博客园


http://www.ppmy.cn/news/641625.html

相关文章

高清视频格式-BD-remux、BD-RE、BDRip的区别

网络上的高清片源很丰富&#xff0c;但对于一个刚接触高清的菜鸟来说&#xff0c;过于丰富的高清片源格式&#xff0c;有时并不是一件好事情。比如某一个片子&#xff0c;有所谓的Blu-ray版本&#xff0c;有BDRip版本&#xff0c;还有杂七杂八的HDTV版&#xff0c;1080p版&…

frp的搭建以及使用·

搭建 下载地址 https://github.com/fatedier/frp/releases frps、frps.ini用于服务端&#xff0c;frpc、frpc.ini用于客户端&#xff0c;另外两个是更深的配置。对于要简单实现内网穿透就不需要进行配置。 分别把包放到服务器和本地需要转发的内网主机中&#xff0c;这里用的…

虚幻引擎(UE5)-大世界分区WorldPartition教程(二)

文章目录 前言一、OFPA怎么用二、OFPA怎么用总结 上一篇&#xff1a;虚幻引擎(UE5)-大世界分区WorldPartition教程(一) 前言 在UE4版本中中&#xff0c;Actor是保存在关卡文件中的&#xff0c;也就是说&#xff0c;如果要编辑关卡中的某些Actor&#xff0c;需要签出关卡文件进…

ips版面与tn的区别

IPS是广视角面板&#xff0c;可视角度&#xff0c;色彩还原好&#xff0c;过度自然&#xff0c;适合看电影&#xff0c;图片&#xff0c;价格高 TN面板视角窄&#xff0c;色材还原不真实&#xff0c;细节表现力差&#xff0c;但响应速度快&#xff0c;耗电低&#xff0c;适合游…

前端代码规范与最佳实践

1. 代码规范的重要性 在前端开发中&#xff0c;代码规范是非常重要的。它可以提高代码的可读性、可维护性和可扩展性&#xff0c;减少bug的产生&#xff0c;并且方便多人协作开发。本文将介绍一些前端代码规范的最佳实践&#xff0c;并给出一些示例。 2. HTML代码规范 2.1 使…

哪个骨传导蓝牙耳机的好,分享几款知名度高的骨传导耳机

骨传导耳机是一种通过头骨传递声波的耳机&#xff0c;相比于传统的耳机&#xff0c;骨传导耳机不用塞进耳道&#xff0c;而是在耳后的骨头里将声音传递到耳膜。而且因为不塞进耳朵&#xff0c;所以不用担心在使用过程中因为佩戴时间过长而导致的耳朵不适。所以相比于传统耳机来…

骨传导耳机哪个品牌的音质好、骨传导耳机音质对比

骨传导耳机相对于普通蓝牙耳机&#xff0c;佩戴不入耳能解放我们的耳朵&#xff0c;同时也可以听见外界的声音&#xff0c;在户外运动或者健身房锻炼时佩戴都特别的方便。但是很多朋友表示骨传导耳机是只能听个响&#xff0c;没有音质可言&#xff01;其实随着科技的发展&#…

苹果系统tft选哪个服务器不卡,tft和ips选哪个 tft和ips区别介绍【图文】

手机屏幕是智能手机的一大卖点&#xff0c;很多手机企业都会在屏幕上大作文章&#xff0c;吸引消费者们的关注。随着宣传多了&#xff0c; 现代 人在购买手机的时候&#xff0c;也会留意手机屏幕。目前手机屏幕主要有两种类型&#xff0c;一为tft屏幕&#xff0c;一为ips屏幕&a…