視訊檔案頭解析--mpeg-個人對mpg檔案結構的理解
1、一個mpg檔案可以只包含視訊內容,那麼檔案開頭以0x000001B3作為起始碼
2、以0x000001BA 開頭,就意味著同時包含音訊資料和視訊資料,如果沒有音訊資料,則以0x000001B3開頭
3、一個mpg檔案可以包含多個pack,每個pack的起始碼都是0x000001BA ,pack沒有結束碼,一般遇到下一個0x000001BA 開頭,就意味著此pack結束。
4、Pack頭一般應該是14位元組,4位元組的開始碼或者叫起始標誌位,以0x000001BA或者0x000001B3作為起始碼.然後緊跟著10位元組的pack header,即pack頭資訊,這個頭資訊一般沒有太多有用的內容,不解析。(Pack的具體組成件附件1,pack具體格式)
5、Pack由3部分組成pack_header、system_header(具體長度為head_length+4(起始碼4B)+2(head_length 2B))、PES_packets(多個)。其中system_header當且僅當pack是第一個資料包是才存在。
6、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)位元組的包資料。
7、根據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)
8、關於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),表明後面的音訊流是DTS,那麼audio_pid=(stream_id<<8)|0xbd; audio_codec=0x88/* LPCM, DVDmode */;file_type=vob /*用於DVD,audio為lpcm格式*/;
Mpg包結構(pes基本包)
將MPEG-2壓縮編碼的視訊基本流(ES-Elementary Stream)資料分組為包長度可變的資料包,稱為打包基本流(PES-Packetized Elementary Stream)。廣而言之,PES為打包了的專用視訊、音訊、資料、同步、識別資訊資料通道。所謂ES,是指只包含1個信源編碼器的資料流。即ES是編碼的視訊資料流,或編碼的音訊資料流,或其它編碼資料流的統稱。每個ES都由若干個存取單元(AU-Access Unit)組成,每個視訊AU或音訊AU都是由頭部和編碼資料兩部分組成的。將幀順序為I1P4B2B3P7B5B6 的編碼ES,通過打包,就將ES變成僅含有1種性質ES的PES包,如僅含視訊ES的PES包,僅含音訊ES的PES包,僅含其它ES的PES包.
PES包的組成見圖2。
由圖2可見,1個PES包是由包頭、ES特有資訊和包資料3個部分組成。由於包頭和ES特有資訊二者可合成1個數據頭,所以可認為1個PES包是由資料頭和包資料(有效載荷)兩個部分組成的。
包頭由起始碼字首、資料流識別及PES包長資訊3部分構成。包起始碼字首是用23個連續“0”和1個“1”構成的,用於表示有用資訊種類的資料流識別,是1個8 bit的整數。由二者合成1個專用的包起始碼,可用於識別資料包所屬資料流(視訊,音訊,或其它)的性質及序號.
PES包長用於包長識別,表明在此欄位後的位元組數。如,PES包長識別為2 B ,即2×8 = 16 bit字寬,包總長為2^16-1=65535 B,分給資料頭9 B(包頭6 B + ES特有資訊3B ),可變長度的包資料最大容量為65526 B。儘管PES包最大長度可達(2^16 -1)=65535 B(Byte),但在通常的情況下是組成ES的若干個AU中的由頭部和編碼資料兩部分組成的1個AU長度。1個AU相當於編碼的1幅視訊影象或1個音訊幀,參見圖2右上角從ES到PES的示意圖。也可以說,每個AU實際上是編碼資料流的顯示單元,即相當於解碼的1幅視訊影象或1個音訊幀的取樣。
ES特有資訊是由PES包頭識別標誌、PES包頭長資訊、資訊區和用於調整資訊區可變包長的填充位元組4部分組成的PES包控制資訊。其中,PES包頭識別標誌由12個部分組成:PES加擾控制資訊、PES優先級別指示、資料適配定位指示符、有否版權指示、原版或拷貝指示、有否顯示時間標記(PTS-PresentationTime Stamp)/解碼時間標記(DTS-DecodeTime Stamp)標誌、PES包頭有否基本流時鐘基準(ESCR-ElementaryStream Clock Reference)資訊標誌、PES包頭有否基本流速率資訊標誌、有否數字儲存媒體(DSM)特技方式資訊標誌、有否附加的拷貝資訊標誌、PES包頭有否迴圈冗餘校驗(CRC-Cyclic Redundancy Check)資訊標誌、有否PES擴充套件標誌。有擴充套件標誌,表明還存在其它資訊。如,在有傳輸誤碼時,通過資料包計數器,使接收端能以準確的資料恢復資料流,或藉助計數器狀態,識別出傳輸時是否有資料包丟失。
其中,有否PTS/DTS標誌,是解決視音訊同步顯示、防止解碼器輸入快取器上溢或下溢的關鍵所在。因為,PTS表明顯示單元出現在系統目標解碼器(STD-System TargetDecoder)的時間, DTS表明將存取單元全部位元組從STD的ES解碼快取器移走的時刻。視訊編碼影象幀次序為I1P4B2B3P7B5B6I10B8B9的ES,加入PTS/DTS後,打包成一個個視訊PES包。每個PES包都有一個包頭,用於定義PES內的資料內容,提供定時資料。每個I、P、B幀的包頭都有一個PTS和DTS,但PTS與DTS對B幀都是一樣的,無須標出B幀的DTS。對I幀和P幀,顯示前一定要儲存於視訊解碼器的重新排序快取器中,經過延遲(重新排序)後再顯示,一定要分別標明PTS和DTS。例如,解碼器輸入的影象幀次序為I1P4B2B3P7B5B6I10B8B9,依解碼器輸出的幀次序,應該P4比B2、B3在先,但顯示時P4一定要比B2、B3在後,即P4要在提前插入資料流中的時間標誌指引下,經過快取器重新排序,以重建編碼前視訊幀次序I1B2B3P4B5B6P7B8B9I10。顯然,PTS/DTS標誌表明對確定事件或確定資訊解碼的專用時標的存在,依靠專用時標解碼器,可知道該確定事件或確定資訊開始解碼或顯示的時刻。例如,PTS/DTS標誌可用於確定編碼、多路複用、解碼、重建的時間。
7、圖
6、對照檔案內容,各欄位值如下:
pack_header: 起始地址:0x0000 0000
Packet_start_code(4B):0x0000 01BA
'01'
SCR_base[32...30](3b):000
marker:1
SCR_base[29...15](15b):00 0000 0000 0010 1
marker:1
SCR_base[14...0](15b):00 0100 1000 0101 1
marker:1
SCR_externsion(9b):00 1111 101
marker:1
mutiplex_rate(22b):0000 0000 0101 0101 0001 01
marker:1
marker:1
reserved(5b):1111 1
stuffing_length(3b):000
system_header: 起始地址:0x0000 000e
system_head_start_code(4B):0x0000 01BB
head_length(2B):0x000C
marker:1
rate_bound(22b):000 0000 0010 1010 1000 101
marker:1
audio_bound(6b):0000 01
fixed_flag(1b):0
CSPS_flag(1b):0
system_audio_local_flag(1b):0
system_video_local_flag(1b):0
marker:1
video_bound(5b):0 0001
packet_rate_restriction_flag(1b):0
reserved(7b):111 1111
stream_id(1B):0xE0(E0~EF為視訊ID)
'11'
P-STD_buffer_bound_scale(1b):1
P-STD_buffer_size_bound(13b):0 0000 0000 0001
stream_id(1B):0xC0(C0~DF為音訊ID)
'11'
P-STD_buffer_bound_scale(1b):0
P-STD_buffer_size_bound(13b):0 0000 0100 1000
PES packet:起始地址:0x0000 0020
packet_start_code_prefix(3B):0x 00 00 01
stream_id(1B):0xBE(BE為Padding stream)
PES_packet_length(2B):0x07 DA,跳過該長度的填充位元組,剛好為下一個pack的起始標誌:
0x000001BA
從0x0800地址開始為第二個pack包,該包的構造格式為pack_header+PES,分析如下:
pack_header: 起始地址:0x0000 0800
Packet_start_code(4B):0x0000 01BA
'01'
program_clock_reference_base(3b):000
marker:1
SCR_base(15b):00 0000 0000 0000 0
marker:1
SCR_base(15b):00 0001 1001 1001 1
marker:1
SCR_externsion(9b):00 0111 100
marker:1
mutiplex_rate(22b):0000 0000 0100 0110 0101 00
marker:1
marker:1
reserved(5b):1111 1
stuffing_length(3b):000
PES packet:起始地址:0x0000 080e
packet_start_code_prefix(3B):0x 00 00 01
stream_id(1B):0xE0(視訊)
PES_packet_length(2B):0x07 EC,跳過該長度,到達0x1000地址單元,為下一個pack的起始標誌:
0x000001BA
'10'
scrambling_control(2b):00
priority(1b):0
alignment(1b):0
copyright(1b):0
original(1b):0
PTS_DTS_flag(2b):11,該標誌不能為01
ESCR_flag(1b):0
ES_rate_flag(1b):0
DSM_trick_mode_flag(1b):0
additional_copy_info_flag(1b):0
CRC_flag(1b):0
extension_flag(1b):0
PES_header_data_length(1B):0x0A
'0011'
PTS[32...30](3b):000,PTS全稱為presentationtime stamp
marker:1
PTS[29...15](15b):0000 0000 0000 000
marker:1
PTS[14...0](15b):1010 1001 1111 001
marker:1
'0001'
DTS[32...30](3b):000,DTS全稱為dedodingtime stamp
marker:1
DTS[29...15](15b):0000 0000 0000 000
marker:1
DTS[14...0](15b):1000 1100 1010 000
marker:1
因為除了PTS_DTS_flag為11外,其餘6個標誌都為0,所以直接進入視訊序列:Video Sequence,其結構定義如下:
對各欄位分析如下:
sequence header:起始地址:0x0000 0821
sequence_header_code(4B):0x 0000 01B3
horizontal_size(12b):0010 0100 0000
vertical_size(12b):0001 1110 0000
aspect_ratio_info(4b):0010
frame_rate(4b):0001
bit_rate(18b):0001 0110 1111 0011 00
marker:1
VBV_buffer_size(10b):0 0011 1000 0
constrained(1b):0
load_intra_Q_matrix(1b):0
sequence extension:起始地址:0x0000 082d;如果有這一項說明是MPEG-2檔案,否則為MPEG-1文
件
extension_start_code(4B):0x0000 01B5
start_code_identifer(4b):0001
profile_level_escape(1b):0
profile_level(7b):100 1000
progressive(1b):1
chroma(2b):01
horiz_extension(2b):00
vertical_extension(2b):00
接下來的資料是0x0000 01B8,說明該序列中沒有extension&user data[i](extension data的開始符為0x0000
01B5,user data的開始符為0x0000 01B2),接下來的內容為Group of pictures header。
link(1b):0
extension & user data[1]:無
picture header: 起始地址:0x0000 083F
picture_start_code(4B):0x0000 0100
temporal_reference(10b):0000 0000 0000 00
picture_coding_type(3b):00 1
vbv_delay(16b):111 1111 1111 1111 1
extra_bit_picture(1b):0
picture coding extension:起始地址:0x0000 0847
extension_start_code(4B):0x0000 01B5
extension_start_code_identifier(4b):1000
f_code[0][0](4b):1111,forward horizontal
f_code[0][1](4b):1111,forward vertical
f_code[1][0](4b):1111,backward horizontal
f_code[1][1](4b):1111,backward vertical
intra_dc_presison(2b):00
picture_structure(2b):11
top_field_first(1b):0
frame_pred_frame_dct(1b):1
concealment_motion_vectors(1b):0
q_scale_type(1b):0
intra_vlc_format(1b):0
alternate_scan(1b):0
repeat_first_field(1b):0
chroma_420_type(1b):1
progressive_frame(1b):1
composite_display_flag(1b):0
extension & user data[2]:無
picture data: 起始地址:0x0000 0850,picture data分為多個slice片,而每個slice又分為多個
Microblock,Microblock繼續分為Block塊。
13818-2中定義的picture_data()如下:
picture_data(){
do {
slice()
} while (nextbits() == slice_start_code )
next_start_code()
}
Slice
slice() {
slice_start_code32
if (vertical_size> 2800)
slice_vertical_position_extension3
if(<sequence_scalable_extension() is present in the bitstream>) {
if(scalable_mode == “data partitioning” )
priority_breakpoint7
}
quantiser_scale_code5
if (nextbits() == ‘1’ ) {
intra_slice_flag 1
intra_slice 1
reserved_bits7
while (nextbits() == ‘1’ ) {
extra_bit_slice/* with the value ‘1*/ 1
extra_information_slice8
}
}
extra_bit_slice/* with the value ‘0’ */ 1
do {
macroblock()
} while (nextbits() != ‘000 0000 0000 0000 0000 0000’ )
next_start_code()
}
從檔案內容分析,從0x0000 0850單元為第一個slice(0000 0101),共有7個slice,第7個slice的起始單元為0x0000 fe04,緊接著開始下一個packe,直到0x0000 3000才開始第一個音訊pack包,後面的資料視訊pack和音訊資料成交叉狀態。檔案結尾標誌為0x0000 01B9