1. 程式人生 > >視訊檔案頭解析--mpeg-個人對mpg檔案結構的理解

視訊檔案頭解析--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