MPG(MPEG2 Program Stream)格式解析

本文详细介绍了MPG文件中MPEG2 Program Stream(PS)的结构,包括Pack层、System Header、PES Packet、Program Stream Map等组成部分,并探讨了码流的分层结构,如GOP、图像组、图像、宏块和块。通过对MPG格式的解析,有助于理解MPEG-2封装容器的工作原理。

参考自:MPEG2 Program Stream结构简单介绍
    MPEG-2 文件结构解析
    视频文件头解析–mpeg-个人对mpg文件结构的理解
    【Codecs系列】MPEG-2标准总结文档

1、MPG简介

mpg是一种常见的视频格式,mpeg标准主要有以下五个,MPEG-1、MPEG-2、MPEG-4、MPEG-7及MPEG-21等。mpg有可能是基于MPEG-1(VCD)或MPEG-2(DVD)中的任一压缩标准出现的,mpeg标准的视频压缩编码技术主要利用了具有运动补偿的帧间压缩编码技术以减小时间冗余度,利用DCT技术以减小图像的空间冗余度,利用熵编码则在信息表示方面减小了统计冗余度。这几种技术的综合运用,大大增强了压缩性能。

下面将以一个mpg封装的MPEG2 Program Stream为例详细介绍该封装格式的结构。
在这里插入图片描述

2、MPEG2 Program Stream

MPEG2 Program Stream,即MPEG2-PS,与MPEG2-TS对应。MPEG2-PS是一种多路复用数字音频、视频等的封装容器。其分为MPEG-1和MPEG-2两部分。Program Stream将一个或多个分组但有共同的时间基准的基本数据流 (PES)合并成一个整体流。它是为可靠稳定的储存媒介如光盘而设计的。据传输媒体的质量不同,MPEG-2中定义了两种复合信息流:传送流(TS:TransportStream)和节目流(PS:ProgramStream)。TS流与PS流的区别在于TS流的包结构是固定长度的,而PS流的包结构是可变长度的。

Program Stream由一个或者多个基本数据流组成,而基本数据流由访问单元(Access Unit)组成。基本数据流的数据保存在PES Packet中。PES Packet由Packet header和Packet data组成。PES Packet又被嵌入到Program Stream packs中。

PES Packet以一个32比特的start code开始,这个start code用于标识该packet属于哪个stream。PES packet header可能包含PTS和DTS,以及其他的fields。

在Program Stream中,PES Packet被组织成packs。一个pack以一个pack header开始,然后是0个或者多个PES Packets。Pack header开始于一个32比特的start code,Pack header用于保存时间和码率信息。

2.1、MPEG-2 Program Stream整体结构

一个完整的MPEG-2文件就是一个PS流文件。

MPEG-2文件的构造格式如下图:
在这里插入图片描述
在这里插入图片描述
自己找个mpg文件打开,可以看到文件以0x0000 01B9结束(有些文件不标准没有),即MPEG_Program_end_code,之前有很多个0x0000 00BA字段,即为program pack的开始标志。

2.2、Program Stream的Pack层结构

program pack包的构造如下:
在这里插入图片描述
在这里插入图片描述
可以看出program pack由3部分组成:pack_header+system_header+PES_packets,其中system_header当且仅当pack是第一个数据包时才存在。

第 5 个byte的前两个比特reserved中,01表示为 MPEG2,如果为00,则表示为MPEG1。

pack_header: 起始地址:0x0000 0000(这个地址有可能因为文件不一样而不一样)

标志:0x00 0x00 0x01 0xBA(4B)
在这里插入图片描述

  • pack_start_code: 标识一个pack的开始,比特流串为’0000 0000 0000 0000 0000 0001 1011 1010’ (0x000001BA)。
  • system_clock_reference_base与system_clock_reference_extension: System Clock Reference(SCR)是一个42比特的field,分为两个部分。第一个部分是system_clock_reference_base,一个33比特的field,由MPEG-1与MPEG-2兼容共用;第二部分是system_clock_reference_extension,一个9比特的field,由MPEG-2单独使用。SCR是为了解决压缩编码图像同步问题产生的。
  • program_mux_rate: 节目复合速率字段。
  • pack_stuffing_length: 表明stuffing_byte的个数。

例:在《陈明-情人的眼泪^思念是一种病【HD】(现场版)-国语-944010.mpg》码流中,pack_header为 00 00 01 BA 44 00 04 00 04 F7 02 66 37 F8

注意:

  • 1、一个mpg文件可以只包含视频内容,那么文件开头以0x000001B3作为起始码;
  • 2、以0x000001BA 开头,就意味着同时包含音频数据和视频数据,如果没有音频数据,则以0x000001B3开头;
  • 3、一个mpg文件可以包含多个pack,每个pack的起始码都是0x000001BA ,pack没有结束码,一般遇到下一个0x000001BA 开头,就意味着此pack结束;
  • 4、Pack头一般应该是14字节,4字节的开始码或者叫起始标志位,以0x000001BA或者0x000001B3作为起始码,然后紧跟着10字节的pack header,即pack头信息。

2.3、Program Stream System Header结构

system_header构造如下:

在这里插入图片描述
system_header: 起始地址:0x0000 000e(这个地址有可能因为文件不一样而不一样)

标志(4B):0x00 0x00 0x01 0xBB
在这里插入图片描述

  • system_header_start_code: 标识system header的开始,比特流串为’0000 0000 0000 0000 0000 0001 1011 1011’ (0x000001BB)。

例:在《陈明-情人的眼泪^思念是一种病【HD】(现场版)-国语-944010.mpg》码流中,system_header为 00 00 01 BB 00 0F 81 33 1B 08 E1 7F E0 E3 61 C0 C0 20 C1 C0 20

2.4、Program Stream PES Packet结构

PES_packets构造如下:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • packet_start_code_prefix: packet_start_code_prefix与stream_id一起构成了一个start code,用于标识packet的开始。packet_start_code_prefix的比特流串为’0000 0000 0000 0000 0000 0001’ (0x000001)。
  • PTS_DTS_flags: 如果PTS_DTS_flags设置为‘10’,在PES packet header中仅仅包含PTS;如果设置为‘11’,那么在PES packet header中既包含PTS,也包含DTS;如果设置为‘00’,PTS和DTS都不包含。
    在这里插入图片描述

例:
在这里插入图片描述
PES packet 起始地址: 0x0000 0023(这个地址有可能因为文件不一样而不一样)
标志位(3B): 0x 00 00 01
stream_id(1B): 0xBE(BE为Padding stream)
PES_packet_length(2B): 0x07 D7,跳过该长度的填充字节,刚好为下一个pack的起始标志0x000001BA;
在这里插入图片描述
从0x0800地址开始为第二个pack包,该包的构造格式为pack_header+PES,分析如下:
pack_header 起始地址: 0x0000 0800(这个地址有可能因为文件不一样而不一样)
(此包上面已经讲到,这里不再赘述)
PES packet 起始地址: 0x0000 080e(这个地址有可能因为文件不一样而不一样)
标志位(3B): 0x 00 00 01
stream_id(1B): 0xE0(视频)

注意:

1、PES_packets的结构:

  • a) 4字节的起始码,一般是3字节包头起始码前缀的0x000001+1字节的数据流识别stream_id。
  • b) 2字节的pes包长
  • c) 紧接着是不定长的基本流特有信息,其中包含:1)2字节的pes包头识别标志,或者叫控制标志位,主要内容是pes加扰控制、优先级、版权以及PTS\DTS标志等(有否PTS/DTS标志,是解决视音频同步显示、防止解码器输入缓存器上溢或下溢的关键所在)。2)1字节的PES扩展数据长度,即pes包头长。3)0-46B的信息区。4)最多256字节的填充字节。
  • d) 最大长度为65526(2^16-1-6-3)字节的包数据。

2、根据PES_packets结构中的前4字节的起始码,可以判断当前pes包里面的数据的具体内容是什么。比如:

  • a) 0x000001E0 - 0x000001EF: Video PES start code();
  • b) 0x000001C0 - 0x000001DF: Audio PES start code(ISO/IEC 13818-3 or 11172-3);
  • c) 0x000001BD: Private Stream(AC3)

3、关于video_pid、音、视频编码方式和文件类型:

  • a)如果起始码是0x000001B3,那么那么后面的pes数据是视频且为原始流,video_pid=0x01;video_codec=0x02;file_type=ES( Elementary Streams (原始流),对视频、音频信号及其他数据进行编码压缩后的数据流称为原始流).参看mpeg2标准13818-2视频部分文档。

  • b)如果起始码是0x000001E0-0x000001EF,即(stream_id>=0xe0)&&(stream_id<=0xef),那么后面的pes数据是视频,video_pid=stream_id;video_codec=0x02;file_type=mpg。

  • c)如果起始码是0x000001C0-0x000001DF,即((stream_id>=0xc0)&&(stream_id<=0xdf)),那么后面的pes数据为音频数据,audio_pid =stream_id;audio_codec= 0x04;file_type=MPG;参看mpeg2标准13818-3音频部分文档。

  • d)如果起始码是0x000001BD,即stream_id == 0xbd,那么后面的pes数据为AC3音频数据。解析AC3的数据的时候有些特别,主要步骤如下:

    • (1)跳过了2字节的pes封包长度,也叫pespacket长度,直接到达2字节的控制标志位,获取stream_flag,然后判断pes加扰控制位是否存在((stream_flag & 0xC0) !=0X80),因为pes加扰控制位总是设置为10,所以如果与出来的结果不为0x80,则表明此段流为不标准的,不解析。
    • (2)如果是标准流,再增加1字节,到达pes扩展数据长度,解析出标志pts_flag(pts_flag = psBuf[pos] & 0xC0),获取pes_packet包里面的PTS和DTS标志位,这两个位不可以为01,所以与上0xc0的结果只可能为0x00/0x80/0xc0.
    • (3)如果pts_flag为0x00/0x80/0xc0其中之一,那么可以获取之后数据(pes扩展数据)的长度。如果不是,跳出,继续解析下一个packet的数据。
      if((pts_flag == 0x00) ||(pts_flag == 0x80) || (pts_flag == 0xc0))
      
      {
      
      pos++;//指针后移一字节,获取pes头数据长度,也就是pts的长度
      
      pts_length = psBuf[pos];
      
      pos++;//指针后移1字节,然后再后移pts数据长度,解析音频信息
      
      pos +=pts_length;
      
      stream_id = psBuf[pos];
      
      pos++;//pos加1字节,准备做下一个packet的解析
      
      }
      

4、关于audio_pid和音频编码方式何有文件类型:

  • a) 如果(stream_id >= 0x80&& stream_id <= 0x87),表明后面的音频流是AC3,那么audio_pid=(stream_id<<8)|0xbd; audio_codec=0x81 /* DolbyDigital AC3 audio */;file_type=mpg;
  • b) 如果(stream_id >= 0x88&& stream_id <= 0x8F),表明后面的音频流是DTS,那么audio_pid=(stream_id<<8)|0xbd; audio_codec=0x82 /* DigitalDigital Surround sound. */;file_type=mpg;
  • C) 如果(stream_id>= 0xA0 && stream_id <= 0xA7),表明后面的音频流是PCM,那么audio_pid=(stream_id<<8)|0xbd; audio_codec=0x88/* LPCM, DVDmode */;file_type=vob /*用于DVD,audio为lpcm格式*/;

2.5、Program Stream Map结构

PSM提供了一个对PS中的基本码流的描述以及他们之间的关系。PSM以PES Packet的形式存在,它的stream_id为0xBC。需要注意一点的是PSM虽然以PES Packet的形式存在,但是他的句法又不同于PES Packet的句法。
在这里插入图片描述

  • packet_start_code_prefix: packet_start_code_prefix与map_stream_id一起构成了一个start code,用于标识packet的开始。packet_start_code_prefix的比特流串为’0000 0000 0000 0000 0000 0001’ (0x000001)。
  • map_stream_id: 固定值为0xBC。
  • program_stream_map_length: program_stream_map_length表明了在program_stream_map中该field之后的总字节数。该field的最大值为1018(0x3FA)。
  • program_stream_info_length: program_stream_info_length表明了该field之后的descriptors的总长度。
  • elementary_stream_map_length: elementary_stream_map_length指明了在该PSM中所有的elementary stream information的总长度,包括stream_type,elementary_stream_id和elementary_stream_info_length这三个fileds。

2.6、Program Stream Directory Packet结构

在这里插入图片描述

3、码流的分层结构

编码的视频数据由称作layer的比特流序列组成。如果仅有一层,那么这个视频流就是不可分级的视频比特流。如果有两层或多层,则称为分级的视频比特流。
MPEG-2的编码码流共分为六个层次。为更好地表示编码数据,MPEG-2用句法Syntax规定了一个层次性结构。它共分为六层,自上到下分别是:图像序列层(Video Sequence)、图像组层(GOP)、图像层(Picture)、宏块条层(Slice)、宏块层(MacroBlock)和块层(Block)。

3.1、码流的分层结构

编码的比特流中的最高语法结构就是视频序列。一个视频序列以一个序列头开始,后面可选地跟着一组图像头和一个或多个编码帧。视频序列以一个sequence_end_code终止。序列头、图像组头和图像头在视频序列中可能是重复出现的,通过重复第一个序列头的数据单元,从而使得对视频序列的随机访问成为可能。
在这里插入图片描述
图中sequence_header,sequence entension等子内容定义如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

例:
在这里插入图片描述
00 00 01 E0: Video PES start code
00 00 01 B3: Sequence header code
00 00 01 B5: Sequence extension start code,如果有这一项说明是MPEG-2文件,否则为MPEG-1文件
接下来如果为extension&user data[i](extension data的开始符为0x0000 01B5,user data的开始符为0x0000 01B2),Group of pictures header 是0x0000 01B8。
00 00 01 B8: Group start code,说明该序列中没有extension&user data[i]。
extension & user data[1]:无
00 00 01 00: Picture start code
00 00 01 B5: Extension start code, picture coding extension
extension & user data[2]:无
接下来是picture data,picture data分为多个slice片,而每个slice又分为多个Microblock,Microblock继续分为Block块。
00 00 01 01: Slice start code

3.2、Group of Pictures(GOP) 图像组

图像组是由一系列的编码图像组成。在编码比特流中,图像组头后面的第一个编码帧是I帧。

3.3、逐行序列和隔行序列

MPEG-2标准支持逐行编码和隔行编码。

3.4、Picture 图像

一个重构图可以通过对一个编码图的解码获得。一个编码图是由一个图像头、紧跟后面的可选扩展以及图像数据组成。一个编码图可以是一个帧图或一个场图。一个重构图可以是一个重构帧,或是一个重构帧的一个场。

MPEG-2支持三种图像类型:

  • I 图 : 只使用当前帧的编码信息。
  • P 图: 利用前面的I图或P图使用运动补偿预测进行编码的图。
  • B 图: 利用前面的或后面的I图或P图使用运动补偿预测进行编码的图。

3.5、Slice 条带(块组)

Slice是由一系列任意数目的连续宏块组成。Slice的第一个和最后一个宏块不能是Skip块。一个Slice中至少要包含一个宏块。Slice之间不能重叠。Slice的第一个和最后一个宏块要在同一宏块水平行上。 Slice可以独立编解码,Slice的设计是为了错误恢复。

注意:Slice的句法元素最早是在MPEG-1标准中引入的,MPEG-1标准中Slice的第一个宏块和最后
一个宏块可以不在同一个宏块水平行上。但是这种设计不利于错误恢复。

3.6、Macroblock 宏块

宏块包含亮度分离和对应的色度分量。MPEG-2支持3种色度格式:4:2:0,4:2:2和4:4:4。对于4:2:0格式的图像,亮度宏块的大小为16x16,色度块的大小为8x8。一个宏块是由6个块组成的,分别是4个亮度块和2个色度块。
对于隔行扫描的图像,亮度块有2种组织方式:
(1)帧DCT编码中,每个块由两场的行交替组成;
(2)场DCT编码中,每个块仅由两场中之一个场的行组成。
所以对场DCT编码的图像中,一个亮度块解码之后,要按照隔行的方式去存放,才能恢复出原来的图像。

3.7、Block 块

块是视频编码中处理的最小单元。一般来说,DCT变换和量化的基本单元就是8x8的块。
这里块既可以指源图像数据和重构图像数据,也可以指DCT系数或相应的编码数据单元。

4、视频比特流的语法

4.1、 起始码

起始码是不会在视频中另外出现的特定位模式。
每个起始码由一个起始码前缀和跟在后面的一个起始码值组成。起始码前缀是由一串23个零值和跟在后面的一位1值组成,即“0000 0000 0000 0000 0000 00001”。
起始码值是个8bit整数,表明了起始码的类型。大部分起始码类型只有一个起始码值,而slice_start_code由许多起始码值表示,在这种情况下slice的起始码值是slice_vertical_position。

表1. MPEG-2标准定义的起始码值
在这里插入图片描述

4.2、 Sytax of Video Sequence

包括了Sequence header、Extension and user data、Sequence extension、Sequence display extension、Sequence scalable extension和Group of pictures header的句法。略

4.3、Sytax of Picture header

包括了Picture coding extension、Quant matrix extension、Picture display extension和Picture temporal scalable extension、Copyright extension等句法。略

4.4、Sytax of Picture data

4.5、Sytax of Slice

4.6、Sytax of Macroblock

4.7、Sytax of Block

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值