您的位置:首页 > 理论基础 > 数据结构算法

MPEG2 TS基本概念和数据结构

2011-06-21 14:14 281 查看
(1)ES-
Elementary Streams (
原始流
)
,对视频、音频信号及其他数据进行编码压缩后的数据流称为原始流。原始流包括访问单元,比如视频原始流的访问单元就是一副图像的编码数据。

(2) PES- Packetized Elementary Streams (
分组的原始流
)
,原始流形成的分组称为
PES
分组,是用来传递原始流的一种数据结构

(3)
节目是节目元素的集合。节目元素可能是原始流,这些原始流有共同的时间基点,用来做同步显示。

(4)
传输流和节目流
TS-Transport Stream
翻译为

传输流
”PS-Program
Stream
翻译为

节目流
”PS
用来传输和保存一道节目的编码数据或其他数据。
PS
的组成单位是
PES
分组。
TS
用来传输和保存多道节目的编码数据或其他数据,
TS
的组成单位是节目。
PS
适用于不容易发生错误的环境,以及涉及到软件处理的应用,典型应用如
DVD
光盘的文件存储
TS
适用于容易发生错误的环境,典型应用就是数字电视信号的传输。
TS

PS
是可以互相转换的,比如从
TS
中抽取一道节目的内容并产生有效的
PS
是可能。

(5)
传输流分组和
PES
分组原始流分成很多
PES
分组,保持串行顺序,一个
PES
分组只包含一个原始流的编码数据。
PES
分组长度很大,最大可为
64K
字节。
PES
分组分为

分组首部
(header)”


有效负载
(payload)”


有效负载

指跟随在首部字节之后的字节。首部的前
4
个字节构成分组的起始码,标识了该分组所属原始流的类型和
ID
号。
TS
分组也就是传输流数据形成的数据包。每个
TS
分组长度为
188
字节,包括

分组首部



有效负载,前
4
个字节是分组首部,包含了这个分组的一些信息。有些情况下需要更多的信息时,需在后面添加

调整字段
(adaption field)”
。两者之间的关系
:PES
分组是插入到
TS
分组中的,每个
PES
分组首部的第一字节就是
TS
分组有效负载的第一字节。一个
PID
值的
TS
分组只带有来自一个原始流的数据。

(6)PSI
全称
Program Specific
Information
,意为节目专用信息。传输流中是多路节目复用的,那么,怎么知道这些节目在传输流中的位置,区分属于不同节目呢?所以就还需要一些附加信息,这就是
PSI

PSI
也是插入到
TS
分组中的,它们的
PID
是特定值。
MPEG-2
中规定了
4

PSI
,包括
PAT(
节目关联表
)

CAT(
条件访问表
)

PMT(
节目映射表
)

NIT(
网络信息表
)
,这些
PSI
包含了进行多路解调和显示节目的必要的和足够的信息。应用中可能包括更多的信息,比如
DVB-T
中定义了
SDT(
服务描述表
),EIT(
环境信息表
),BAT(
节目组相关表
),TDT(
时间日期表
)
等,统称为
DVB-SI(
服务信息
)

PSI

PID
是特定的,含
PSI
的数据包必须周期性的出现在传输流中。

PMT (Program Map Table
)

节目映射表

PMT
所在分组的
PID

PAT
指定,所以要先解出
PAT
,再解
PMT

PMT
中包含了属于同一节目的视频、音频和数据原始流的
PID
。找到了
PMT
,解多路复用器就可找到一道节目对应的每个原始流的
PID
,再根据原始流
PID
,去获取原始流。

PAT (Program Association

Table
)

节目关联表

PAT
所在分组的
PID=0 PAT
中列出了传输流中存在的节目流
PAT
指定了传输流中每个节目对应
PMT
所在分组的
PIDPAT
的第一条数据指定了
NIT
所在分组的
PID
,其他数据指定了
PMT
所在分组的
PID


CAT (Conditional Access Table

)

条件访问表

CAT
所在分组的
PID=1CAT
中列出了条件控制信息
(ECM)
和条件管理信息
(EMM)
所在分组的
PID

CAT
用于节目的加密和解密
NIT( Network
Information Table)
网络信息表
NIT

所在分组的

PID



PAT

指定

NIT
提供一组传输流的相关信息,以及于网络自身特性相关的信息,比如网络名称,传输参数
(
如频率
,
调制方式等
)

NIT
一般是解码器内部使用的数据,当然也可以做为
EPG
的一个显示数据提供给用户做为参考。几种
PSI
之间的关系,如下图所示:首先
PAT
中指定了传输流中所存在的节目,及每个节目对应的
PMT

PID
号。
比如
Program 1
对应的
PMT

PID=22,
然后找到
PID=22

TS
分组,解出
PMT
,得到这个节目中包含的原始流的
PID
,再根据原始流的
PID
去找相应的
TS
分组,获取原始流的数据,然后就可以送入解码器解码了。

数据结构(

1



TS

分组

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

transport_packet(){

sync_byte
//8

transport_error_indicator
//1

payload_unit_start_indicator
//1

transport_priority
// 1

PID
//13

transport_scrambling_control
// 2

adaptation_field_control
//2

continuity_counter
//4

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

adaptation_field()

}

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

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

data_byte

}

}

}

前面
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
,或一些自定义的数据。



2



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
校验码

上面
program_number

network_PID

program_map_PID
是循环出现的。
program_number
等于
0
时对应
network_PID

program_number
等于其它值时对应
program_map_PID


(3)PMT
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_indicator

section_length


version_number


current_next_indicator

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

section_number

last_section_number

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

program_number

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

PCR_PID

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

program_info_length

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

stream_type

指示了
PID

elementary_PID

PES
分组中原始流的类型,比如视频流,音频流等,见后面的表

elementary_PID

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

ES_info_length

该节目相关原始流的描述符的信息长度。
stream_type
对应的类型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: