|
次測試MPEG4和H264的時候,由于要進行分幀輸入解碼器測試,因此進行了MPEG4和H264碼流的簡單分析,MPEG4碼流的分析見上次記錄的那篇文章。
目前又要開始測試MPEG1和MPEG2碼流的解碼了,同樣,對這兩種碼流也進行一下簡單的分析,通過搜集資料和查看兩種標準的協(xié)議13818-2和11172-2,了解這兩種碼流格式的一些基本結(jié)構(gòu),今天把它們也在此做一個簡單的整理和記錄,也便于以后的翻看和大家的參考: 由于MPEG1與MPEG2的結(jié)構(gòu)類似,這里就主要以MPEG2來進行說明: 首先來給一張MPEG2 video Sequence的一個結(jié)構(gòu)圖:
與采用Elecard Stream Analyer分析出的結(jié)果基本一致:
有了上面的圖后,大家就可以清晰的看出MPEG2 video Sequence的一個大體結(jié)構(gòu)了。 下面我們來以例子來進行碼流結(jié)構(gòu)的簡單分析和說明: 比如: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幀的哦。當(dāng)出現(xiàn)0x0000100,是就表示已經(jīng)到了圖象層,再越過10位(Temporal_reference占10位),就到了Picture_coding_type(3位),如果Picture_coding_type為001(二進制)就是I幀,為010是P幀,011則就是B幀;截取一下段兒13828-2的6.3.2節(jié)中對于picture_header的描述:也可看出Picture_coding_type(占3位)
vbv_delay(16):001 1000 1001 1 extra_bit_picture(1):0
再以下的Slice、MicroBlock、Block中的信息就不再往下分析了。有興趣的話可以繼續(xù)參考標準哦,里面很是詳細; 小結(jié)一下,其實對于各種start Code,在標準中亦有清楚地說明,見: Table 6-1 — Start code values
其實,對于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幀
最后再小記另一個問題,就是對于I P B幀進行判定的時候,要進行Picture_coding_type的二進制位的判斷,如何僅對某些相應(yīng)的位(Picture_coding_type的三位)進行判斷呢?這里采用按位與&的方法。 由于進行判斷幀類型的Picture_coding_type位于Picture Header后的第11位~13位,因此應(yīng)該在其start code后的第二個字節(jié)中。舉個例子:00 00 01 00 00 0F,那么00 0F字節(jié)轉(zhuǎn)換為為二進制后是:00000000 00001111,其中第11~13位為001,因此判定此幀為I幀; 要取某個數(shù)中的某些指定位,就讓其與相應(yīng)位為1的數(shù)按位與&即可,我們現(xiàn)在要取start code后的第二個字節(jié)(即上面例子中的0F)的第3~5位,就讓其與00111000(0x38)按位與&即可,如果是I幀,按位與后該字節(jié)數(shù)為00001000=0x08;如果是P幀,按位與后該字節(jié)數(shù)為00010000=0x10;如果是B幀,按位與后該字節(jié)數(shù)為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++);
|
|||||||||||||||||||||||||||||||||||||||||||
|
|