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