1. 数字视频压缩MPEG-2标准

MPEG-2是MPEG(Moving Picture Experts Group,运动图像专家组)组织制定的视频和音频有损压缩标准之一,它的正式名称为“基于数字存储媒体运动图像和语音的压缩标准”。与MPEG-1标准相比,MPEG-2标准具有更高的图像质量、更多的图像格式和传输码率的图像压缩标准。MPEG-2标准不是MPEG-1的简单升级,而是在传输和系统方面做了更加详细的规定和进一步的完善。它是针对标准数字电视和高清晰电视在各种应用下的压缩方案,编码率从3 Mbit/s~100 Mbit/s。
         MPEG-2标准特别适用于广播质量的数字电视的编码和传送,被用于无线数字电视、DVB(Digital Video Broadcasting,数字视频广播)、数字卫星电视、DVD(Digital Video Disk,数字化视频光盘)等技术中。

如上图,MPEG2标准DVB数据发送、传输、接收的流程。

2. MPEG-2传输流系统层

在MPEG-2标准中,有两种不同类型的码流输出到信道,一种是节目码流(PS:program stream),适合没有误差产生的媒体存储,比如,DVD等存储介质;另外一种是传输流(TS:Transport Stream),适用于有信道噪声产生的传输,可在网络中进行远距离的传送。这样的TS便于综合多路节目为单路节目进行复用。多个节目或者不必具有共同的时间基准。由于MPEG-2要求这些包由传送,则在MPEG-2 TS中传送包的大小定义为4*47B=188B长度。另外,这样的TS作为一个固定长度包大小,便于找到帧的起止位置,易于从包丢失中恢复,适合于有误码的环境,但是与PS相比难于生产与复用。
         TS 全称是 MPEG 2 Transport Stream,即MPEG-2 标准中的传输流。于此同时,我们常规使用的PS 是MPEG-2标准中的节目流。TS广泛用于广播电视系统,比如说数字电视,以及IPTV。

3. PS和TS的区别

通常我们开发中往往会遇到,PS、RTP、 TS、MP4这四种封装最为常见。
      其中:从发布者范畴来看,MP4 规范上为MPEG-4标准,而PS、TS属于MPEG-2标准、RTP属于国际电信联盟ITU-T的RFC系列标准。 
      从使用范围来看, MP4主要适用于文件的存储。 TS、RTP适用于数据流的传输,不具有存储属性。PS既有存储属性又可以做实时流的传输。 
      从复杂度来看MP4封装最为复杂、其次PS、再次RTP和TS。

种类

MP4

PS

TS

RTP

本地保存

支持,可以文件级别获取码流属性

支持,可以GOP级别获取码流属性

安卓、window支持直接播放。

IOS必须配合m3u8文件构成流媒体服务器方可预览

不支持。文件级别流属性参数不具备

实时传输

支持,但是必须是前置打包的机制。

支持,属性只能获取GOP级别的参数。 海康在文件头增加流媒体属性私有信息用于辅助

支持,配合m3u8文件构成流媒体服务器

支持。必须配合RTSP协议双方获取文件属性。

复杂度

简单

简单

4. TS包层

TS文件的基本存储单位为TS包,每一个包大小固定为188个字节。TS标准中有的地方是支持204字节的,204字节就是188个字节后面增加,16个字节的RS冗余校验信息。 一般默认188个字节。

每一个TS包的内部包含4个字节的TsPacketHeader。184字节的负载数据TsPacketPayloadData。
        当TsPacketPayloadData中的实际有效数据不足184的时候,需要填充adaptation field数据,则按照如下格式。其中,填充规则按照4.1.2节描述。


4.1 TS包文件头模块

一共四个字节,8个标记。如下图

结构体描述如下面的表:
                                                                                       Ts header结构

sync_byte

8b

同步字节,固定为0x47, 采用固定宏TS_SYNC_0X47替代。每一次PAT和PMT和每一帧数据处理的时候都要添。

transport_error_indicator

1b

传输错误指示符,表明在ts头的adapt域后由一个无用字节,通常都为0。

payload_unit_start_indicator

1b

负载开始标志位,用来表示TS包的有效净荷带有PES包或者PSI数据的情况,占位1bit;另若此值为1,且负载为PSI数据时,则在TS头后,负载起始字节会有1个调整字节point_field;

transport_priority

1b

传输优先级,0为低优先级,1为高优先级,通常取0

pid:

13b

pid值(Packet ID号码,唯一的号码对应不同的包)

指示有效负载中的数据类型,占位13bit;0x0000代表PAT,0x0001代表CAT,0x0002-0x000F保留,0x1FFF表示空包;

transport_scrambling_control

2b

传输加扰控制,00表示未加密

adaptation_field_control

2b

调整字段标志,表示此TS首部是否跟随调整字段还是负载数据,占位2bit,其中00位保留,01表示无调整字段,只有有效负载数据,10表示只有调整字段,无有效负载,11表示有调整字段,且其后跟有有效负载;空分组此字段应为01;

continuity_counter

4b

固定为11,递增计数器,从0-f,起始值不一定取0,但必须是连续的

以上4个字节是必须存在的,但还有一些特殊的。当adaptation_field_control==1x时,会出现Adaptation field字段,Adaptation field字段如下。
                                                                          Adaptation field字段

adaptation_field_length

8b

调整字段长度标示,标示此字节后面调整字段的长度,占位8bit;值为0时,表示在TS分组中插入一个调整字节,后面没有调整字段,紧跟着的是有效负载;adaptation_field_control == ‘11’时,此值在0~182之间,adaptation_field_control == ‘10’时,此值为183,若字段没这么长则填充0xFF字段;

以下字段都是在adaptation_field_length>0是才会出现的

discontinuity_indicator

1b

不连续状态指示符,占位1bit,置位1时表示此TS分组的不连续状态为真;

random_access_indicator

1b

随机访问指示符,占位1bit

elementary_stream_priority_indicator

1b

原始流数据优先级指示符,占位1bit,置位1表示此原始流数据比相同PIDTS包中的其他原始流优先级高;

PCR_flag

1b

PCR标志位,占位1bit,置位1表示调整字段中包含PCR字段,置位0则没有PCR字段;

OPCR_flag

1b

OPCR标志位,占位1bit,置位1表示调整字段中包含OPCR字段,置位0则没有OPCR字段;

splicing_point_flag

1b

splice_countdown标志位,占位1bit,置位1表示调整字段中包含splice_countdown字段,置位0则没有splice_countdown字段;

transport_private_data_flag

1b

transport_private_data标志位,占位1bit,置位1时表示调整字段中含有1个或者多个私有数据字节,置位0则无此字节;

adaptation_field_extension_flag

1b

调整字段扩展标志位,占位1bit,置位1表示含有调整字段扩展字段,置位0则无扩展字段;

以上8个bit是标识符,后面是根据标识符的值来确定的字段,顺序如下:
 @PCR字段:当PCR_flag == 1时,此字段才存在,占位48bit,依次顺序为:
     program_clock_reference_base字段:占位33bit;
     reserved字段:占位6bit;
     program_clock_reference_extension字段:占位9bit;
@OPCR字段:当OPCR_flag == 1时,此字段才存在,占位48bit,依次顺序为:
     original_program_clock_reference_base字段:占位33bit;
     reserved字段:占位6bit;
     original_program_clock_reference_extension字段:占位9bit;
@splice_countdown字段:当splicing_point_flag == 1时此字段存在,占位8bit;
@transport_private_data字段:私有数据字段,当transport_private_data_flag==1时此字段存在,占位N*8bit,字节顺序为:
     transport_private_data_length:表明私有数据的字节长度,占位8bit;
     private_data_byte:私有数据,长度由前面的长度字段确定;
@adaptation_field_extension字段:调整字段扩展字段,占用长度不确定,当adaptation_field_extension_flag == 1时此字段存在,字段中也有3个标志位,来确定一些字段存不存在,其具体字节顺序如下:
   adaptation_field_extension_length:调整字段扩展字段的长度,占位8bit;
   ltw_flag:ltw字段标志位,置位1时表示此字段存在,占位1bit;
   piecewise_rate_flag:piecewise_rate字段标志位,置位1时此字段存在,占位1bit;
   seamless_splice_flag:seamless_splice标志位,置位1时此字段存在,占位1bit;
   Reserved:保留字段,占位5bit;
   Ltw字段:当ltw_flag == 1时此字段存在,占位16bit,其由以下两个字段组成
  ltw_valid_flag:占位1bit,当ltw_valid_flag == 1时,ltw_offset才有效;
   ltw_offset:占位15bit;
   piecewise_rate字段:当piecewise_rate_flag == 1时此字段存在,占位24bit,其字节顺序如下:
   reserved字段:保留字段,占位2bit;
   piecewise_rate字段:占位22bit;此字段只有在当ltw_flag == 1和ltw_valid_flag == 1时才有定义,有定义时此字段是一个正整数;
   seamless_splice字段:当seamless_splice_flag == 1时此字段存在,占位40bit;字节顺序依次为:
   splice_type字段:占位4bit;标识delay和rate值;
   DTS_next_AU[32..30]:占位3bit;
   marker_bit字段:占位1bit;
   DTS_next_AU[29..15]字段:占位15bit;
   marker_bit:占位1bit;
   DTS_next_AU[14..0]:占位15bit;
   marker_bit:占位1bit;
   stuffing_byte:填充字段,固定为0xFF;
   Payload_bytes:有效负载字段,字节来自PES包,PSI部分等;
注意:
        当TS包带有PES包数据时,payload_unit_start_indicator具有以下的特点:置为1,标识TS包的有效净荷以PES包的第一个字节开始,即此TS包为PES包的起始包,且此TS分组中有且只有一个PES包的起始字段;置为0,表示TS包不是PES包的起始包,是后面的数据包。
       当 TS包带有PSI数据时,payload_unit_start_indicator具有以下特点:置为1,表示TS包中带有PSI数据分段的第一个字节,即这个TS包是PSI Section的起始包,则此TS包的负载的第一个字节带有pointer_field;置为0,表示TS包不带有PSI Section的第一个字节,即此TS包不是PSI的起始包,即在有效负载中没有point_field,有效负载的开始就是PSI的数据内容。point_field的定义将在下面的PSI节中进行介绍;对于空包的包,payload_unit_start_indicator应该置为0。
        例如:若TS包载荷为PAT,则当接收到的TS包的payload_unit_start_indicator为1时,表明这个TS包包含了PAT头信息,从这个包里面解析出section_length和continuity_counter,然后继续收集后面的payload_unit_start_indicator = 0的TS包,并判断continuity_counter的连续性,不断读出TS包中的净载荷(也就是PAT数据),用section_length作为收集TS包结束条件。
        TS包头之后,就是负载payload的内容了,里面可以是PES分组的数据,也可以是PSI信息,PSI信息主要由PAT,PMT,CAT等,在这里主要介绍PAT和PMT两种信息表;由上所描述信息可知,payload的类型是由PID来确定的,一般PID==0x0000则payload为PAT,PID== 0x0001,则payload为CAT,而PMT的PID则是在PAT中进行指定的;
       PSI还有可能有一个特殊的字段:
       Point_field字段:跟在包头之后,占位8bit,属于有效负载,表示从此字段开始到负载中PSI Section的第一个字节之间的字节数;当payload_unit_start_indicator == 1时,此字段才存在;若point_field == 0x00,则表示此字节后跟着的就是PSI Section的起始字节;此字段是在有效负载中的,计入有效负载的长度;

       其中PID是TS流中唯一识别标志,Packet Data是什么内容就是由PID决定的。如果一个TS流中的一个Packet的Packet Header中的PID是0x0000,那么这个Packet的Packet Data就是DVB的PAT表而非其他类型数据(如Video、Audio或其他业务信息)。下表给出了一些表的PID值,这些值是固定的,不允许用于更改。

类型

PID 值

PAT

0x0000

CAT

0x0001

TSDT

0x0002

EIT,ST

0x0012

RST,ST

0x0013

TDT,TOT,ST

0x0014

表1 pid 类型表

下面以一个TS流的其中一个Packet中的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

0

7

e

5

1

2

Packet(二进制)

0

1

0

0

0

1

1

1

0

0

0

0

0

1

1

1

1

1

1

0

0

1

0

1

0

0

0

1

0

0

1

0

Packet Header 信息

1 sync_byte=0x47

2

3

4

5 PID=0x07e5

6

7

8

表2 header 例程数据表

@ sync_byte=01000111,               就是0x47,这是DVB TS规定的同步字节,固定是0x47.
      @ transport_error_indicator=0,             表示当前包没有发生传输错误.
      @ payload_unit_start_indicator=0,         含义参考ISO13818-1标准文档
      @ transport_priority=0,                      表示当前包是低优先级.
      @ PID=00111 11100101即0x07e5,       Video PID
      @ transport_scrambling_control=00,      表示节目没有加密
      @ adaptation_field_control=01             即0x01,具体含义请参考ISO13818-1
      @ continuity_counte=0010                  即0x02,表示当前传送的相同类型的包是第3个

ts层的内容是通过PID值来标识的,主要内容包括:PAT表、PMT表、音频流、视频流。解析ts流要先找到PAT表,只要找到PAT就可以找到PMT,然后就可以找到音视频流了。PAT表的PID值固定为0。PAT表和PMT表需要定期插入ts流,因为用户随时可能加入ts流,这个间隔比较小,通常每隔几个视频帧就要加入PAT和PMT。PAT和PMT表是必须的,还可以加入其它表如SDT(业务描述表)等。
      ts流最早应用于数字电视领域,其格式非常复杂包含的配置信息表多达十几个,视频格式主要是mpeg2。苹果公司发明的http live stream流媒体是基于ts文件的,不过他大大简化了传统的ts流,只需要2个最基本的配置表PAT和PMT,再加上音视频内容就可以了,hls流媒体视频编码的主要格式为h264/mpeg4,音频为aac/mp3。

4.2 TS包填充模块

adaption为自适应填充功能,主要目的为填充凑齐不足188字节的TS包。

图6 TS adaptation填充结构

@ adaptation_field_length:8bit,自适应域长度,后面的字节数 
    @ flag :1bit,取0x50表示包含PCR或0x40表示不包含PCR
    @ PCR:1bit,Program Clock Reference,节目时钟参考,用于恢复出与编码端一致的系统时序时钟STC(System Time Clock)。
     @ stuffing_bytes:填充字节,取值0xff
         自适应区的长度要包含传输错误指示符标识的一个字节。pcr是节目时钟参考,pcr、dts、pts都是对同一个系统时钟的采样值,pcr是递增的,因此可以将其设置为dts值,音频数据不需要pcr。如果没有字段,ipad是可以播放的,但vlc无法播放。打包ts流时PAT和PMT表是没有adaptation field的,不够的长度直接补0xff即可。视频流和音频流都需要加adaptation field,通常加在一个帧的第一个ts包和最后一个ts包里,中间的ts包不加。

5. ES层数据

es层就是音视频裸数据了,常用的音频编码格式为AAC,和MP3 。视频编码格式为H.264和HEVC。
其数据结构可以分别参考相应的编码规范手册。

6. PES包层

pes层是在每一个视频/音频帧上加入了时间戳等信息,pes包内容很多,我们只留下最常用的。

如图7,按照苹果协议定义规范,PES内容可以是, PMT项数据,PAT项数据, 也可以是正常的音视频数据。

6.1 PAT格式

PAT全称Program Association Table,节目关联表,定义了当前TS流中所有的节目,其PID为0x0000,它是PSI的根节点,当播放器对视频开始检索分析的时候,针对每个TS 包的header中pid成员进行判定,直到找到PAT表开始的地方进行有效数据起始分析。

table_id

8b

PAT表固定为0x00

section_syntax_indicator

1b

固定为1

zero

1b

固定为0

reserved

2b

固定为11

section_length

12b

后面数据的长度

transport_stream_id

16b

传输流ID,固定为0x0001

reserved

2b

固定为11

version_number

5b

版本号,固定为00000,如果PAT有变化则版本号加1

current_next_indicator

1b

固定为1,表示这个PAT表可以用,如果为0则要等待下一个PAT表

section_number

8b

固定为0x00

last_section_number

8b

固定为0x00

开始循环

program_number

16b

节目号为0x0000时表示这是NIT,节目号为0x0001时,表示这是PMT

reserved

3b

固定为111

PID

13b

节目号对应内容的PID值

结束循环

CRC32

32b

前面数据的CRC32校验码

表3 PAT 例程数据表

PAT结构根据表3 PAT 例程数据表加上我们节目数量为1的时候以得知PAT的数据结构如下:
        因此PAT长度为16个字节,而payloadSize为184个字节, 那么adaptFileLen填充为168个长度。
        根据表3的描述,有如下的例程。
        通过一段TS流中一个Packet分析PAT表,这里我们分析一段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为0,并且在包头后需要除去一个字节才是有效数据(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

2

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个字节

由以上几个表可以分析出PAT表和PMT表有着内在的联系。也就是之前提到的。PAT表描述了当前流的NIT(Network Information Table,网络信息表)中的PID、当前流中有多少不同类型的PMT表及每个PMT表对应的频道号。

6.2 PMT格式

PMT 全称Program Map Table,节目映射表,PMT数据的信息可以理解为这个节目包含的音频和视频信息。海康目前用它来填充海康自己内部的私有信息。

table_id

8b

PMT表取值随意,0x02

section_syntax_indicator

1b

固定为1

zero

1b

固定为0

reserved

2b

固定为11

section_length

12b

后面数据的长度

program_number

16b

频道号码,表示当前的PMT关联到的频道,取值0x0001

reserved

2b

固定为11

version_number

5b

版本号,固定为00000,如果PAT有变化则版本号加1

current_next_indicator

1b

固定为1

section_number

8b

固定为0x00

last_section_number

8b

固定为0x00

reserved

3b

固定为111

PCR_PID

13b

PCR(节目参考时钟)所在TS分组的PID,指定为视频PID

reserved

4b

固定为1111

program_info_length

12b

节目描述信息,指定为0x000表示没有

开始循环

stream_type

8b

流类型,标志是Video还是Audio还是其他数据,h.264编码对应0x1b,aac编码对应0x0f,mp3编码对应0x03

reserved

3b

固定为111

elementary_PID

13b

与stream_type对应的PID

reserved

4b

固定为1111

ES_info_length

12b

描述信息,指定为0x000表示没有

结束循环

CRC32

32b

前面数据的CRC32校验码

表4 PMT数据表

通过一段TS流中一个Packet分析PMT表,通过分析一段TS流的数据包Packet来学习PMT表。下面给出了一段TS流数据中的一个Packet(十六进制数)。

Packet Header

Packet Data

0x47 0x43 0xe8 0x12

00 02 b0 12 00 01 c1 00 00 e3 e9 f0 00 1b e3 e9 f0 00 f0 af b4 4f 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

3

e

8

1

2

Packet(二进制)

0

1

0

0

0

1

1

1

0

1

0

0

0

0

1

1

1

1

1

0

1

0

0

0

0

0

0

1

0

0

1

0

Packet Header Bits

1 sync_byte=0x47

2

3

4

5 PID=0x03e8

6

7

8

Packet Header分析

Packet Header:0x47 0x40 0x00 0x10

1

sync_byte

0x47

固定同步字节

2

transport_error_indicator

“0”

没有传输错误

3

payload_unit_start_indicator

“1”

在前4个字节后会有一个调整字节。所以实际数据应该为去除第一个字节后的数据。

4

transport_priority

“0”

传输优先级低

5

PID

0x03e8

PID=0x03e8说明数据包是PMT表信息

6

transport_scrambling_control

“00”

未加密

7

adaptation_field_control

“01”

附加区域控制

8

continuity_counte

“0010”

包递增计数器

因为payload_unit_start_indicator=‘1’,在解析数据包的时候需要去除Packet Data的第一个字节。下面是对Packet Data的详细解析:

PMT表的Packet Data分析

第n个字节

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

Packet Data

02

b0

12

00

01

c1

00

00

e3

e9

f0

00

1b

e3

e9

f0

00

f0

1b

e3

字段名

位数

具体值

次序

说明

table_id

8

0x02

第1个字节

section_syntax_indicator

1

1B

第2、3个字节

1011 0000 0001 0010B=0xb012

段语法标志

zero

1

0B

reserved

2

11B=0x03

section_length

12

0000 0001 0010B=0x12

段长度,从program_number开始,到CRC_32(含)的字节总数

program_number

16

0x0001

第4、5个字节 0x00 01

频道号码,表示当前的PMT关联到的频道

reserved

2

11B=0x03

第6个字节

1100 0001B=0xc1

version_number

5

00000B=0x00

版本号码,如果PMT内容有更新,则它会递增1通知解复用程序需要重新接收节目信息

current_next_indicator

1

1B=0x01

当前未来标志符

section_number

8

0x00

第7个字节0x00

当前段号码

last_section_number

8

0x00

第8个字节 0x00

最后段号码,含义和PAT中的对应字段相同

reserved

3

111B=0x07

第9、10个字节

1110 0011 1110 1001B=0xe3e9

PCR_PID

13

000111110B=0x3e9

PCR(节目参考时钟)所在TS分组的PID

reserved

4

1111B=0x0f

第11、12个字节

1111 0000 0000 0000=0xf000

program_info_length

12

000000000000B=0x000

节目信息长度(之后的是N个描述符结构,一般可以忽略掉,这个字段就代表描述符总的长度,单位是Bytes)紧接着就是频道内部包含的节目类型和对应的PID号码了

stream_type

8

0x1b

第13个字节 0x1b

流类型,标志是Video还是Audio还是其他数据

reserved

3

111B=0x07

第14、15个字节

1110 0011 1110 1001B=0xe3e9

elementary_PID

13

000111110 1001=0x3e9

该节目中包括的视频流,音频流等对应的TS分组的PID

reserved

4

1111B=0x0f

第16、17个字节

1111 0000 0000 0000B=0xf000

es_info_length

12

0000 0000 0000=0x000

CRC

32

——

——

6.3 音视频数据封装

音视频数据是在每一个视频/音频帧上加入了时间戳等信息,pes包内容很多,我们只留下最常用的。

pes start code

3B

开始码,固定为0x000001

stream id

1B

音频取值(0xc0-0xdf),通常为0xc0
视频取值(0xe0-0xef),通常为0xe0

pes packet length

2B

后面pes数据的长度,0表示长度不限制,
只有视频数据长度会超过0xffff

flag

1B

通常取值0x80,表示数据不加密、无优先级、备份的数据

flag

1B

取值0x80表示只含有pts,取值0xc0表示含有pts和dts

pes data length

1B

后面数据的长度,取值5或10

pts

5B

33bit值

dts

5B

33bit值

pts是显示时间戳、dts是解码时间戳,视频数据两种时间戳都需要,音频数据的pts和dts相同,所以只需要pts。有pts和dts两种时间戳是B帧引起的,I帧和P帧的pts等于dts。如果一个视频没有B帧,则pts永远和dts相同。从文件中顺序读取视频帧,取出的帧顺序和dts顺序相同。dts算法比较简单,初始值 + 增量即可,pts计算比较复杂,需要在dts的基础上加偏移量。
      音频的pes中只有pts(同dts),视频的I、P帧两种时间戳都要有,视频B帧只要pts(同dts)。打包pts和dts就需要知道视频帧类型,但是通过容器格式我们是无法判断帧类型的,必须解析h.264内容才可以获取帧类型。
       时钟配置,MPEG2-TS 中规定系统采用45K的基准时钟。而我们DSP进程封装功能为90K(兼容RTP、PS封装目的)。因此需要进行转换。
       假如帧率为25帧每秒, 那么每一帧的系统间隔时间为40ms。按照TS封装45K的采样率基准时钟来计算, 需要1800个时钟(40 * 45)。
      假如音频采样率为16K,单个点耗时1/16ms即62.5us,那么1024个点为一帧一共64ms(62.5us * 1024),,则转为45K下为2880个时钟,(0.0625*45*1024)。

网络流媒体(四)———TS流相关推荐

  1. java 解析m3u8的实例_m3u8文件完整实例及TS流抓取

    参考文档: http://blog.csdn.net/blueboyhi/article/details/40107683 如下 是一个华数影视的M3U8文件链接 http://chyd-sn.was ...

  2. 截获视频网站 ts流 视频 网络嗅探 IPTV OTT 数据流 音视频数据 码流 ts 流

    忽然想把最近的技术总结一下.做ts流 IP数据流也有5年之久了.接触了大大小小的项目.例如网络嗅探 通过sniffer 获取IP包.ts 码流分析等.今天把二者结合起来可以应用到手机终端.或者工程仪表 ...

  3. 流媒体基础知识TS流 PS流 ES流区别

    IP数据报有首部和数据两部分组成的,首部的前一部分是固定长度20字节,是所有IP数据报必须具有的.首部包括:总长度.标识.MF.DF.片偏移. 数字信号实际传送的是数据流,一般数据流包括以下三种: ( ...

  4. vlc源码分析(四) 调用libts接收TS流

    http://www.cnblogs.com/jiayayao/p/6858253.html 代码分析前,先要了解TS流基本概念:TS流之基本概念. VLC解析TS流是通过libts库来分离的,lib ...

  5. TS流解析 二 *****

    1.TS格式介绍 TS:全称为MPEG2-TS.TS即"Transport Stream"的缩写.它是分包发送的,每一个包长为188字节(还有192和204个字节的包).包的结构为 ...

  6. 基于FFmpeg接收RTSP的ts流

    RTSP用于建立的控制媒体流的传输,通过wireshark抓包可以看到rtsp消息交互的过程: 1. 第一步:查询服务器端可用方法 C->S:OPTION request     // 询问S有 ...

  7. 对TS流的一些理解TS流的结构

     TS流的结构 TS流由很多个TS包组成,而每个TS包的结构包括:4B的包头,可变长的调整字段,有效净荷(payload).现在分别说一下这三部分的结构和作用. 包头 包头最小为4字节,这四字节分 ...

  8. ffmpeg基础三:H264,从MP4文件获取(av_bsf_get_by_name(“h264_mp4toannexb“))和从TS流获取保存H264

    参考:零声学院 1.流媒体编解码流程 2.编码原理 在⾳视频传输过程中,视频⽂件的传输是⼀个极⼤的问题:⼀段分辨率为19201080,每个像 素点为RGB占⽤3个字节,帧率是25的视频,对于传输带宽的 ...

  9. 网络流媒体--SDP会话描述协议(RFC-4566)

    1.SDP协议简介 SDP(Session Description Protocol)是为了描述多媒体会话而设计的,主要用来描述会话通告,会话邀请或者其他形式的多媒体会话初始化.为了初始化多媒体会话, ...

最新文章

  1. Rhel6.0部署Oracle10g报错相关问题记录
  2. 学编程又一火爆网站:哔哩哔哩
  3. java最小访问原则_Android基础进阶之EffectiveJava翻译系列(第七章:通用原则)
  4. Nginx在Windows平台的配置与使用
  5. Oracle Study之--Oracle 11gR2通过RMAN克隆数据库
  6. http://www.od85c.com.cn/html/,OllyDbg script for unpacking Enigma 4.xx and 5.xx
  7. 为什么要使用信道复用技术?常用的信道复用技术有哪些?
  8. lsqnonlin函数_matlab非线性最小二乘函数
  9. 比亚迪汉家族3月热销12359辆 汉EV单车销量破万
  10. java 正方形_java-确定正方形和矩形之间的关系的算法
  11. 《ANSYS 14.0超级学习手册》一2.5 本章小结
  12. [Ext JS]12.12.1 必填字段组件扩展
  13. Echarts数据可视化tooltip提示框,开发全解+完美注释
  14. java.exe 不是有效的win32_WinXP提示不是有效的Win32应用程序怎么办?
  15. java 27 - 7 反射之 通过反射越过泛型检查
  16. flash幻灯片源码
  17. C++string类常用函数 c++中的string常用函数用法总结
  18. Qt之Dialog\widget\ mainwindow的区别和布局管理器 分裂器的区别
  19. 初踩阿里云效代码管理
  20. 机器学习 - 概念学习

热门文章

  1. Python 多进程 multiprocessing.Pool类详解
  2. 中国各城市首轮感染高峰期预测!(最新更新版)
  3. Python学习(3)计算个人所得税
  4. DCOS(centos 7.4/7.6)
  5. Greenplum 分布键 distribute hash分布和随机分布
  6. 从二维到三维,可见Web3D技术的重要性,让线上3D产品展示所见即所得
  7. php如何除去图片水印,如何去掉图片水印,一键去除文字logo图片水印更简单
  8. 5.16 按照自定义序列对城市进行排序 [原创Excel教程]
  9. PHP网页的工作原理
  10. 工业生产管理-数据采集初探