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
对应的类型。
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
对应的类型。
相关文章推荐
- MPEG2 TS基本概念和数据结构(转)
- MPEG2 TS基本概念和数据结构(转)
- MPEG2 TS基本概念和数据结构
- MPEG2_TS流基本概念和数据结构
- TS基本概念和数据结构(转)
- MPEG2_TS流基本概念和数据结构 分类: ffmpeg-SDL-VLC-Live555 2015-04-02 15:44 401人阅读 评论(0) 收藏
- MPEG2_TS流基本概念和数据结构
- MPEG2_TS流基本概念和数据结构
- MPEG2_TS流基本概念和数据结构
- MPEG2_TS流基本概念和数据结构
- 数据结构_基本概念
- 数据结构基本概念和术语
- 数据结构基本概念
- PHP数据结构之八 树与二叉树基本概念
- 数据结构的基本概念
- 数据结构基本概念 - 学习笔记
- 数据结构的一些基本概念
- (一)数据结构基本概念和术语学习
- 第八话:补充数据结构基本概念的关系
- [数据结构和算法]算法基本概念