上次测试MPEG4和H264的时候,由于要进行分帧输入解码器测试,因此进行了MPEG4和H264码流的简单分析,
MPEG4码流的分析见上次记录的那篇文章。
目前又要开始测试MPEG1和MPEG2码流的解码了,同样,对这两种码流也进行一下简单的分析,通过搜集资料和查看两种标准的
协议13818-2和11172-2,了解这两种码流格式的一些基本结构,今天把它们也在此做一个简单的整理和记录,也便于以后的翻看和大家的参考:
由于MPEG1与MPEG2的结构类似,这里就主要以MPEG2来进行说明:
首先来给一张MPEG2 video Sequence的一个结构图:
![MPEG-2 video Sequence](http://www.rosoo.net/Files/allimg/120306/15522Q635-0.jpg)
与采用Elecard Stream Analyer分析出的结果基本一致:
![Elecard分析出的MPEG2码流](http://www.rosoo.net/Files/allimg/120306/15522T2b-1.jpg)
有了上面的图后,大家就可以清晰的看出MPEG2 video Sequence的一个大体结构了。
下面我们来以例子来进行码流结构的简单分析和说明:
比如:Test.m2v
00 00 01 B3 08 00 80 23 00 FA 20 30 00 00 01 B5
以视频系列头Sequence Header开始,Start code values: 00 00 01 B3 为起始码;
horizontal_size_value(12 bits):08 0 = 128
vertical_size_value(12 bits):0 80 = 128
aspect_ratio_information(4 bits) = 2
frame_rate_code (4 bits) = 3
bit_rate_value(18 bits) = 00 FA 2>>2 = 0000 0000 1111 1010 00 = 1000
marker_bit(1 bit) = 1
vbv_buffer_size_value(10 bits) = 0 0000 0011 0 = 6
constrained_parameters_flag(1 bit) = 0
load_intra_quantiser_matrix( 1bit) = 0
load_non_intra_quantiser_matrix(1bit) = 0
00 00 01 B5 extension_start_code
00 00 01 B5 14 82 00 01 00 00 00 00 01 B5 23 05 05 05 02 02 04 00 00 00 00 01 B2
extension_start_code_identifier(4 bits) = 1
profile_and_level_indication(8 bit) = 48
progressive_sequence( 1 bit) = 0
chroma_format(2 bits) = 01
horizontal_size_extension(2bit) = 0
vertical_size_extension(2 bit) = 0
bit_rate_extension(12 bit) = 0 0000 0000 000
marker_bit(1 bit) = 1
vbv_buffer_size_extension(8 bits) = 00
low_delay(1 bit) = 0
frame_rate_extension_n(2 bit) = 00
frame_rate_extension_d(5 bit) = 00000
接着,下组是Extension& user data,又是一个00 00 01 B5 extension_start_code,所以接下来是extension_data( i ),
extension_start_code_identifier(4bit) = 2, Sequence Display Extension ID
video_format((3 bit) = 001
colour_description(1bit)=1
colour_primaries(8) = 05
transfer_characteristics(8)=05
matrix_coefficients(8) = 05
display_horizontal_size(14) = 0000 0010 0000 00
marker_bit(1 bit) = 1
display_vertical_size(14) = 0 0000 0100 0000 0
还剩余了3bit 000
接下来又是00 00 01 b2 user_data_start_code,user_data(),忽略它,因为他是用户自定义的,就不多说了
00 00 01 B2 4D 50 45 47 2D32 20 56 65 72 69 66 69 63 61 74 69 6F5E20 53 65 71 75 65 6E 63 65 0A 00 00 01 B8
接下来是图象组头Group of picture Header Start code values: 00 00 01 B8为起始码;
00 00 01 B8 5F BF 6C 40
time_code(25): 0101 1111 1011 1111 0110 1100 0 = 49022
closed_gop(1): 1
broken_link(1):0
剩余5bit 0 0000
下面终于到图象头 Picture Header,Start code values : 00 00 01 00为起始码;
00 00 01 00 00 0A 58 58 00 00 01 B5
00 00 01 00, picture_start_code, picture_header
temporal_reference(10): 0000 0000 00
picture_coding_type(3): 00 1
注:就是在这里的值判定是I帧,P帧还是B帧的哦。当出现0x0000100,是就表示已经到了图象层,再越过10位(Temporal_reference占10位),就到了Picture_coding_type(3位),如果Picture_coding_type为001(二进制)就是I帧,为010是P帧,011则就是B帧;截取一下段儿13828-2的6.3.2节中对于picture_header的描述:也可看出Picture_coding_type(占3位)
picture_header() {
|
No. of bits
|
Mnemonic
|
picture_start_code
|
32
|
bslbf
|
temporal_reference
|
10
|
uimsbf
|
picture_coding_type
|
3
|
uimsbf
|
vbv_delay
|
16
|
uimsbf
|
vbv_delay(16):001 1000 1001 1
extra_bit_picture(1):0
再以下的Slice、MicroBlock、Block中的信息就不再往下分析了。有兴趣的话可以继续参考标准哦,里面很是详细;
小结一下,其实对于各种start Code,在标准中亦有清楚地说明,见:
Table 6-1 — Start code values
Name
|
start code value
(hexadecimal)
|
picture_start_code
|
00
|
Slice_start_code
|
01 through AF
|
Reserved
|
B0
|
Reserved
|
B1
|
User_data_start_code
|
B2
|
sequence_header_code
|
B3
|
sequence_error_code
|
B4
|
extension_start_code
|
B5
|
Reserved
|
B6
|
Sequence_end_code
|
B7
|
group_start_code
|
B8
|
system start codes (see note)
|
B9 through FF
|
NOTE - system start codes are defined in Part 1 of this specification
|
其实,
对于MPEG1来说,格式与MPEG2很是类似,只是没有Extension部分,由视频头以视频系列头Sequence Header开始,00 00 01 B3 为起始码;接下来是图象组头
Group of Picture Header 00 00 01 B8 为起始码,然后是图象头
Picture Header 00 00 01 00 为起始码;分析起来亦是一样,视频系列头起始码是:0x00001b3,图象组头的起始码是:0x00001b8,图象头的起始码是:0x0000100;对一段视频流,越过了视频系列头就到了图象组层,越过了图象组头就到了图象,再越过10位(Picture_start_code占32位,Temporal_reference占10位),就到了Picture_coding_type(3位),如果Picture_coding_type为001(二进制)就是I帧,为010是P帧,011则就是B帧
![Elecard分析出的MPEG1码流](http://www.rosoo.net/Files/allimg/120306/15522S910-2.jpg)
最后再小记另一个问题,就是对于I P B帧进行判定的时候,要进行Picture_coding_type的二进制位的判断,如何仅对某些相应的位(Picture_coding_type的三位)进行判断呢?这里采用
按位与&的方法。
由于进行判断帧类型的Picture_coding_type位于Picture Header后的第11位~13位,因此应该在其start code后的第二个字节中。举个例子:00 00 01 00 00 0F,那么00 0F字节转换为为二进制后是:00000000 00
001111,其中第11~13位为001,因此判定此帧为I帧;
要取某个数中的某些指定位,就让其与相应位为1的数按位与&即可,我们现在要取start code后的第二个字节(即上面例子中的0F)的第3~5位,就让其与00111000(0x38)按位与&即可,如果是I帧,按位与后该字节数为00001000=0x08;如果是P帧,按位与后该字节数为00010000=0x10;如果是B帧,按位与后该字节数为00011000=0x18;:代码如下:
if ((*p & 0x38)==0x08) printf("picture header-I frame # %d,/n ", frames++);
else if ((*p & 0x38)==0x10) printf("picture header-P frame # %d,/n ", frames++);
else if ((*p & 0x38)==0x18) printf("picture header-B frame # %d,/n ", frames++);
MPEG1和MPEG2的码流结构和简单分析先记录到此,测试工作中如再遇到问题,我会继续在此添加,希望高手们予以指正,另外,上次测试中H264的码流NALU结构分析的我还没来得及写在这里,以后有时间了将H264的码流分析也补上~~~