MPEG2学习笔记.docx
《MPEG2学习笔记.docx》由会员分享,可在线阅读,更多相关《MPEG2学习笔记.docx(13页珍藏版)》请在冰豆网上搜索。
![MPEG2学习笔记.docx](https://file1.bdocx.com/fileroot1/2023-1/24/c33cd2f7-fb20-47e0-8ef5-6b60badef2f5/c33cd2f7-fb20-47e0-8ef5-6b60badef2f51.gif)
MPEG2学习笔记
MPEG-2学习笔记
(一)(转载)
2008-08-2813:
00
最近有点时间,看了一部分MPEG-2的规范,看后想总结点东西,算是做了点作业,另外希望能和大家讨论讨论,请大家指点。
中文版很多概念翻译得很模糊,不易理解,但总体来说还算是不错,适合像我这种入门级别的看,不过建议和英文版对照看,对一些概念能比较准确的理解。
整个规范包括三部分:
系统,视频编码,音频编码。
对应的标准号分别为ISO/IEC13818-1,ISO/IEC13818-2,ISO/IEC13818-3,在规范中经常可以看到这几个字符串。
第一部分“系统”和我们现在的工作关系较紧密,我也主要学习了第一部分。
后面两部分主要是讲解编码过程,编码部分看了实在让人犯晕,先偷一下懒吧,把第一部分搞清楚了再看去啃难啃的骨头吧。
下面进入正题了。
一、概念
规范中讲述的概念很多,容易让人糊涂,所以先把一些概念理清,弄清楚它们之间的关系,再看后面的就可提高很多的效率。
(1)ES-ElementaryStreams(原始流),对视频、音频信号及其他数据进行编码压缩后
的数据流称为原始流。
原始流包括访问单元,比如视频原始流的访问单元就是一副图像的编
码数据。
(2)PES-PacketizedElementaryStreams(分组的原始流),原始流形成的分组称为PES分组,是用来传递原始流的一种数据结构
(3)节目是节目元素的集合。
节目元素可能是原始流,这些原始流有共同的时间基点,用来做同步显示。
(4)传输流和节目流
TS-TransportStream翻译为“传输流”
PS-ProgramStream翻译为“节目流”
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个字节是分组首部,包含了这个分组的一些信息。
有些情况下需要更多的信息时,需在后面添加“调整字段(adaptionfield)”。
两者之间的关系:
PES分组是插入到TS分组中的,每个PES分组首部的第一字节就是TS分组有效负载的第一字节。
一个PID值的TS分组只带有来自一个原始流的数据。
(5)PSI
全称ProgramSpecificInformation,意为节目专用信息。
传输流中是多路节目复用的,那么,怎么知道这些节目在传输流中的位置,区分属于不同节目呢?
所以就还需要一些附加信息,这就是PSI。
PSI也是插入到TS分组中的,它们的PID是特定值。
MPEG-2中规定了4个PSI,包括PAT(节目关联表),CAT(条件访问表),PMT(节目映射表),
NIT(网络信息表),这些PSI包含了进行多路解调和显示节目的必要的和足够的信
息。
具体的应用中可能包括更多的信息,比如DVB-T中定义了SDT(服务描述表),EIT(环境信息表),BAT(节目组相关表),TDT(时间日期表)等,统称为DVB-SI(服务信息)。
l PSI的PID是特定的,含PSI的数据包必须周期性的出现在传输流中。
MPEG-2学习笔记
(二)
2008-08-2813:
01
PMT(ProgramMapTable)节目映射表
PMT所在分组的PID由PAT指定,所以要先解出PAT,再解PMT
PMT中包含了属于同一节目的视频、音频和数据原始流的PID。
找到了PMT,解多路复用器就可找到一道节目对应的每个原始流的PID,再根据原始流
PID,去获取原始流。
如下图:
PID1和PID2分别对应某道节目的视频原始流和音频原始流
的PID。
l PAT(ProgramAssociationTable)节目关联表
l PAT所在分组的PID=0
PAT中列出了传输流中存在的节目流
l
l PAT指定了传输流中每个节目对应PMT所在分组的PID
l PAT的第一条数据指定了NIT所在分组的PID,其他数据指定了PMT所在分组的PID,如下图所示:
lCAT(ConditionalAccessTable)条件访问表
lCAT所在分组的PID=1
lCAT中列出了条件控制信息(ECM)和条件管理信息(EMM)所在分组的PID。
lCAT用于节目的加密和解密
lNIT(NetworkInformationTable)网络信息表
lNIT所在分组的PID由PAT指定
lNIT提供一组传输流的相关信息,以及于网络自身特性相关的信息,比如网络名称,传输参数(如频率,调制方式等)。
lNIT一般是解码器内部使用的数据,当然也可以做为EPG的一个显示数据提供给用户做为参考。
几种PSI之间的关系,如下图所示:
首先PAT中指定了传输流中所存在的节目,及每个节目对应的PMT的PID号。
比如Program1对应的PMT的PID=22,然后找到PID=22的TS分组,解出PMT,得到这个节目中包含的原始流的PID,再根据原始流的PID去找相应的TS分组,获取原始流的数据,然后就可以送入解码器解码了。
MPEG-2学习笔记(三)
2008-08-2813:
02
二、数据结构
(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 data_byte //8
}
}
}
前面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,或一些自定义的数
MPEG-2学习笔记(四)
2008-08-2813:
03
(2)PAT
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 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。
举个例子,下述流为带PAT的TS分组:
4740001c0000b01513f6e700000000e0100001e0200002e0211a34b477ff…………..ff
其中红色的四个字节是TS分组头部,用数据结构解出首部,得到PID=0x00,表示为该分组的有效负载是PAT。
蓝色的00称为“指针域”----Pointerfield,表示了一个偏移量,即从后面第几个字节开始是PAT部分。
为00表示后面紧接着的就是PAT:
00b01513f6e700000000e0100001e0200002e0211a34b477
再利用PAT的数据结构解出PAT,得到如下信息:
---------------PATInformation-------------
table_id:
00
section_syntax_indicator:
01
section_length:
0015
transport_stream_id:
13f6
version_number:
13
current_next_indicator:
01
section_number:
00
last_section_number:
00
program_number:
0000
network_PID:
0010
program_number:
0001
program_map_PID:
0020
program_number:
0002
program_map_PID:
0021
CRC_32:
1a34b477
可以看出,此PAT只有一段,包含了三个节目,节目号0000对应于network_PID=0010,节目号0001对应于program_map_PID=0020,节目号0002对应于program_map_PID=0021,从实际的角度,我们应该把这三个节目号理解为三个频道,第一个频道中的内容是网络信息,第二、三个频道包含了节目信息。
在数字电视中,一个频道即对应于一个频点,如498MHZ,一个频道上可以有多个节目,后面的PMT即是告诉了我们某个频道中所有节目对应的PID。
于是现在就搜寻PID=0x0020的TS分组,即是频道2对应的PMT信息。
MPEG-2学习笔记(五)
2008-08-2813:
04
(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
reserved4
program_info_length //12
for(i=0;i descriptor()
}
for(i=0;i stream_type //8
reserved //3
elementary_PID //13
reserved //4
ES_info_length //12
for(i=0;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