您的当前位置:首页正文

浅析mpeg-ts封装结构

2024-11-20 来源:个人技术集锦

一、引言

因为Apple公司提出的HLS(http live streaming)格式的流行,mpeg-ts封装的文件在互联网上已经随处可见。这套体系的强大之处就在于它的简单,试想,只要你有工具可以把一个或多个视频文件切割成一堆的小ts文件,并且生成一个内容非常简单的m3u8文件,然后只要有一个标准的web server(apache, nginx)就能对外提供点播视频流媒体服务了。假如可以对直播数据流进行切片存储成小文件,那就又具备了直播流媒体服务能力。

本文在此不对流媒体的应用进行研究,仅是对mpeg-ts格式进行分析,而分析的手段则是依照mpeg-ts的specification说明文档进行解构。之后会介绍一个非常好用的解析库bitstream,并提供据此库实现的ts解析工具与大家共同学习探讨。

 

二、基本结构

TS流的最小数据单元是188字节,所以可以认为一个TS文件的长度一定是188的整数倍。

2.1 TS包头部解析

    TS包的头部固定占据四字节,这4个字节总共32bit分布着9个字段,现在对这些字段进行说明。

字段名称

长度

描述

备注

sync_byte

8 bit

同步字节

永远为0x47,可用作ts包是否完整的判断

Error indicator

1 bit

传输误码指示符

 

Payload unit start indicator

1 bit

有效单元荷载起始指示符

当若干TS包构成一个独立单元时,可以此作为判断依据

Transport priority

1 bit

优先传输

 

PID

13 bit

包标识符

最重要的字段,标识该包所属的流

Transport scrambling control

2 bit

传输控制标识

 

Adaption field control

1 bit

自适应区标识

此标志被置1意味着包内还有附加数据

Playload flag

1 bit

有效载荷标识

是否含有负载数据

Continue counter

4 bit

连续计数器

这是一个在0~15之间循环的数字,可用来判断TS包是否连续

 

  通过头部四字包含的这9个字段数据,我们可以做的事情有:

1.     取得流PID(最重要)

2.     判断TS流是否完整

3.     判断TS流是否连续

 

2.2 Adaptation field解析

Adaptation field是自适应数据区,用以指示接下来的数据是否为逻辑上独立的一段内容,并且存放了PCR信息。

 

字段名称

长度

描述

备注

adaptation_field_length

8 bit

自适应区长度

值为0 表示仅为占位符,大于0则指示自适应区长度

discontinuity_indicator

1 bit

非连续提示符

值为1时说明基准时间戳发生变化,PCR值重置

random_access_indicator

1 bit

随机访问提示符

值为1表示该PES包是一帧视频或者音频的起始包

elementary_stream_priority_indicator

1 bit

元组流优先提示符

值为1表示ES包数据优先于其他包的数据

PCR_flag

1 bit

PCR标志

值为1表示自适区存在PCR值

OPCR_flag

1 bit

OPCR标志

值为1表示自适区存在OPCR值

splicing_point_flag

1 bit

分割点标志

值为1表示存在splice_countdown字段

transport_private_data_flag

1 bit

传输私有数据标志

值为1表示自适区内包含一段或多段私有数据

adaptation_field_extension_flag

1 bit

自适应区扩展标志

值为1 时表示自适区内存在扩展数据

program_clock_reference_base

33 bit

节目参考时间基线

占30位,其分布规律为从最高位3位起,间隔一个marker,然后每15位一段

reserved

6 bit

 

 

program_clock_reference_extension

9 bit

节目参考时钟扩展

基准PCR的扩展

2.3 PAT包解析

根据从头部取得的PID我们接下来要做的一件事情就是确定这个PID所属的类型。而类型可分为TS固有类型与音视频流类型等。TS流的特点是没有严格意义上的起始或结束部分,所以也不能像mp4或者avi格式那样从meta域取得整体信息,这样我们势必要有一个办法知道当前的TS流的结构是怎样的,包含哪些音视频流等。所有的一切都要从一个叫做PAT的包开始,就像世界来自上帝七天创世纪,宇宙始于大爆炸,你要结婚总要从遇见一个姑娘开始。

TS固有类型的第一个要知道的就是PAT包,它的全称是Program Association Table(节目关联表),要说明它的作用先从介绍它的结构开始。

        如何判断是否PAT包?非常简单,2.1节中我们看到有PID这个字段,PID的值等于0就对了。0,这个在计算机程序中无比神圣的数字被赋予了PAT了,也可见PAT对于TS的重要性。PAT包采用section格式封装,section结构简单说来可分为头部与负载区,头部区由若通用干字段组成,下面对其结构进行说明。

字段名称

长度

描述

备注

Table id

8 bit

表标识

值为0 代表是PAT表

section_syntax_indicator

1 bit

段同步提示符

默认设置为1

‘0’

1 bit

 

 

reserved

2 bit

 

 

section_length

12 bit

段长度

段总长度,包括CRC值在内

transport_stream_id

16 bit

传输流标识

可由用户自定义的传输流标识

reserved

2 bit

 

 

version_number

5 bit

版本号

在1至32数值之间递增,当current_next_indicator为1 时是当前可用的,为0则代表当然无效,需要等待下一个PAT

current_next_indicator

1 bit

当前后续提示

为1 时是当前可用的,为0则代表当然无效,需要等待下一个PAT

section_number

8 bit

段号

起始段号为0,随着段数加1

last_section_number

8 bit

最后段号

最大的段号

program_number

16 bit

节目号

用于在PAT包内区分不同节目

reserved

3 bit

 

 

program_map_PID

13 bit

节目映射标识

每个节目的PID值,可由用户自行定义,但须保证唯一

CRC_32

32 bit

循环校验值

用于判断section段是否完整


2.4 PMT包解析

        PMT包括了一个节目相关的所有流信息。流这个概念对应的是一路音频或一路视频。我们知道,一个节目播放时有图像也有声音,但在编码层面它们往往是分开并且独立的,因为它们在最终呈现时是由不同的硬件设备来渲染的。音频与视频的同步则要借助于PCR,它是同步参考时钟,决定着哪一帧画面与哪一段音频相对应。

字段名称

长度

描述

备注

Table id

8 bit

表标识

值设为0x02

section_syntax_indicator

1 bit

段同步提示符

必须设置为1

‘0’

1 bit

 

 

reserved

2 bit

 

 

section_length

12 bit

段长度

段总长度,包括CRC值在内

program_number

16 bit

节目号

一个单独节目的标识,在复合流中相关的音视频流要归在此标识下用以分流

reserved

2 bit

 

 

version_number

5 bit

版本号

在1至32数值之间递增,当current_next_indicator为1 时是当前可用的,为0则代表当然无效,需要等待下一个PMT

current_next_indicator

1 bit

接续提示符

当current_next_indicator为1 时是当前可用的,为0则代表当然无效,需要等待下一个PMT

section_number

8 bit

段号

此值应设为0x00

last_section_number

8 bit

最后段号

此值应设为0x00

reserved

3 bit

 

 

pcr_pid

13 bit

同步时钟标识

此节目所对应的同步参考时钟的标识号

reserved

4 bit

 

 

program_info_length

12 bit

节目信息长度

头两位置0,后10位数值表示所有信息的字节数

stream_type

8 bit

流类型

用以指示流的音视频属性

reserved

3 bit

 

 

elementary_PID

13 bit

元组标识

节目内包含的元组元素的标识号

reserved

4 bit

 

 

ES_info_length

12 bit

元组信息长度

无级描述信息的长度,内容紧跟其后

CRC_32

32 bit

循环校验值

用于判断section段是否完整

 

Streamtype值的列表:

0x00ITU-T | ISO/IEC Reserved

0x01ISO/IEC 11172 Video

0x02ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or ISO/IEC 11172-2 constrainedparameter video stream

0x03ISO/IEC 11172 Audio

0x04ISO/IEC 13818-3 Audio

0x05ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections

0x06ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing private data

0x07ISO/IEC 13522 MHEG

0x08ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A DSM-CC

0x09ITU-T Rec. H.222.1

0x0AISO/IEC 13818-6 type A

0x0BISO/IEC 13818-6 type B

0x0CISO/IEC 13818-6 type C

0x0DISO/IEC 13818-6 type D

0x0EITU-T Rec. H.222.0 | ISO/IEC 13818-1 auxiliary

0x0FISO/IEC 13818-7 Audio with ADTS transport syntax

0x10ISO/IEC 14496-2 Visual

0x11ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC14496-3 / AMD 1

0x12ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets

0x13ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried inISO/IEC14496_sections.

0x14ISO/IEC 13818-6 Synchronized Download Protocol

0x15-0x7FITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved

0x80-0xFF User Private.

2.5SDT包解析

        SDT是流信息描述表,它的作用是传输节目的内容名称。例如我们在制作节目单时就可以从这个表中取出cctv 1, cctv2这样的内容名称。

字段名称

长度

描述

备注

Table id

8 bit

表标识

值设为0x02

section_syntax_indicator

1 bit

段同步提示符

必须设置为1

‘0’

1 bit

 

 

reserved

2 bit

 

 

section_length

12 bit

段长度

段总长度,包括CRC值在内

reserved

18 bit

节目号

一个单独节目的标识,在复合流中相关的音视频流要归在此标识下用以分流

version_number

5 bit

版本号

在1至32数值之间递增,当current_next_indicator为1 时是当前可用的,为0则代表当然无效,需要等待下一个PMT

current_next_indicator

1 bit

接续提示符

当current_next_indicator为1 时是当前可用的,为0则代表当然无效,需要等待下一个PMT

section_number

8 bit

段号

起始段号为0,随着段数加1

last_section_number

8 bit

最后段号

最大的段号

descriptor

 

 

 

CRC_32

32 bit

循环校验值

用于判断section段是否完整


2.6 PES包解析

        PES是一组ES包的集合,一个PES包内是一帧完整的视频或者音频数据。TS流的播放一般都会从关键帧所在的PES包起播。

 

字段名称

长度

描述

备注

packet_start_code_prefix

24 bit

Pes起始标识码

用于标识pes包起始,值为0x000001

stream_id

8 bit

流标识

用以区分ES的类型与序数

PES_packet_length

16 bit

包长度

PES包的总长度

'10'

2 bit

 

 

PES_scrambling_control

2 bit

扰流控制

用以指示PES包是否扰流模式

PES_priority

1 bit

优先级

值为1的包优先于值为0的包,合成器可据此判断包的先后

data_alignment_indicator

1 bit

数据排列指示符

值为1表示在PES包头之后紧跟着视频起始符或者音频同步位。

copyright

1 bit

版权标识

值为1表示PES包内容受版权保护

original_or_copy

8 bit

源或副本标识

值为1表示为源数据流,为0表示为副本

PTS_DTS_flags

2 bit

Pts与dts标志

值为01表示只有PTS,值为11表示同时有PTS与DTS

ESCR_flag

1 bit

Escr标志

值为1表示在PES头部有ESCR数据与其扩展字段

ES_rate_flag

1 bit

Es码率标志

值为1表示PES头部有es码率值

DSM_trick_mode_flag

1 bit

DSM伪装模式

值为1表示存在DSM伪装模式字段

additional_copy_info_flag

1 bit

附加复制信息标志

值为1表示存在附加复制信息字段

PES_CRC_flag

1 bit

循环校验标志

值为1表示存在PES包循环校验数据

PES_extension_flag

1 bit

扩展标志

值为1表示存在PES扩展数据

PES_header_data_length

8 bit

头部数据长度

除去以上字段之外接下来的数据长度

'0011'

4 bit

 

 

PTS [32..30]

3 bit

 

 

marker_bit

1 bit

标志位

值为1

PTS [29..15]

15 bit

 

 

marker_bit

1 bit

标志位

值为1

PTS [14..0]

15 bit

 

 

marker_bit

1 bit

标志位

值为1

'0001'

4 bit

 

 

DTS [32..30]

3 bit

 

 

marker_bit

1 bit

标志位

值为1

DTS [29..15]

15 bit

 

 

marker_bit

1 bit

标志位

值为1

DTS [14..0]

15 bit

 

 

marker_bit

1 bit

标志位

值为1

注意:PTS与DTS占30位,其分布规律为从最高位3位起,间隔一个marker,然后每15位一段。

 

三、参考文档

《ISO/IEC 13818-1》


显示全文