AVI結構解析 結構體

AVI文件規範

本文主要參考瞭如下資料:

http://blog.csdn.net/sunshine1314/archive/2007/10/14/1824432.aspx 格式規範

http://blogold.chinaunix.net/u2/69656/showart_1110871.html  格式規範

http://blog.csdn.net/njuitjf/archive/2010/06/19/5680632.aspx  格式解析

http://blog.csdn.net/happydeer/archive/2004/04/16/8775.aspx  AVI文件格式----摘自《DirectShow實務精選》 作者:陸其明


一、AVI文件簡介

AVI的英文全稱爲Audio Video Interleaved,即音頻視頻交錯格式,是將語音和影像同步組合在一起的文件格式。AVI於1992年被Microsoft公司推出,隨 Windows3.1一起被人們所認識和熟知。AVI文件格式多用於音視頻捕捉、編輯、回放等應用程序中。通常情況下,一個AVI文件可以包含多個不同類 型的媒體流(典型的情況下有一個音頻流和一個視頻流),不過含有單一音頻流或單一視頻流的AVI文件也是合法的。AVI可以算是Windows操作系統上 最基本的、也是最常用的一種媒體文件格式。

Note: 本文介紹的是基本的AVI文件格式規範,至於newAVI等一些AVI擴展格式,請關注筆者後續文章。

 

二、RIFF文件規範

AVI文件屬於一種RIFF(Resource Interchange File Format的縮寫)文件格式,與此同類的還有常見的WAV文件。RIFF是Microsoft提出的一種多媒體文件的存儲方式,不同編碼的音頻、視頻文 件,可以按照它定義的存儲規則保存、記錄各自不同的數據。如果讀者不熟悉RIFF文件規範,閱讀下面章節前,建議先閱讀《RIFF文件規範》這篇文章:http://blog.csdn.net/sunshine1314/archive/2007/10/10/1817991.aspx

 

三、AVI文件結構實例分析

1、AVI文件的展開結構大致如下: 

RIFF (‘AVI ’
      LIST (‘hdrl’
            ‘avih’(主AVI信息頭數據)
            LIST (‘strl’
                  ‘strh’ (流的頭信息數據)
                  ‘strf’ (流的格式信息數據)
                  [‘strd’ (可選的額外的頭信息數據) ]
                  [‘strn’ (可選的流的名字) ]
                  ...
                 )
             ...
           )
      LIST (‘movi’
            { SubChunk | LIST (‘rec ’
                              SubChunk1
                              SubChunk2
                              ...
                             )
               ...
            }
            ...
           )
      [‘idx1’ (可選的AVI索引塊數據) ]
     )

 

 

2、AVI文件全局結構說明

       整個AVI文件的結構爲:一個RIFF頭 + 兩個列表(一個用於描述媒體流格式、一個用於保存媒體流數據) + 一個可選的索引塊 + 一個JUNK塊。

首先,RIFF (‘AVI ’…)表徵了AVI文件類型。然後就是AVI文件必需的第一個列表——‘hdrl’列表,用於描述AVI文件中各個流的格式信息(AVI文件中的每一路媒 體數據都稱爲一個流)。‘hdrl’列表嵌套了一系列塊和子列表——首先是一個‘avih’塊,用於記錄AVI文件的全局信息。然後,就是一個或多個 ‘strl’子列表。文件中有多少個流,這裏就對應有多少個‘strl’子列表,示例clock.avi文件有兩路流,既音頻流和視頻流。

當AVI文件中的所有流都使用一個‘strl’子列表說明了以後(注意:‘strl’子列表出現的順序與媒體流的編號是對應的,比如第一個 ‘strl’子列表說明的是第一個流(Stream 0),第二個‘strl’子列表說明的是第二個流(Stream 1),以此類推),‘hdrl’列表的任務也就完成了,隨後跟着的就是AVI文件必需的第二個列表——‘movi’列表,用於保存真正的媒體流數據(視頻 圖像幀數據或音頻採樣數據等)。

最後,緊跟在‘hdrl’列表和‘movi’列表之後的,就是AVI文件可選的索引塊。這個索引塊爲AVI文件中每一個媒體數據塊進行索引,並且記錄它們在文件中的偏移(可能相對於‘movi’列表,也可能相對於AVI文件開頭)。

圖1中還有一種特殊的數據塊,用一個四字符碼‘JUNK’來表徵,它用於內部數據的隊齊(填充),應用程序應該忽略這些數據塊的實際意義。

 

3、’avih’塊

‘avih’塊,用於記錄AVI文件的全局信息,比如流的數量、視頻圖像的寬和高等,可以使用一個AVIMAINHEADER數據結構來操作:

typedef struct _avimainheader {
    FOURCC fcc;   // 必須爲‘avih’
    DWORD  cb;    // 本數據結構的大小,不包括最初的8個字節(fcc和cb兩個域)
    DWORD  dwMicroSecPerFrame;   // 視頻幀間隔時間(以毫秒爲單位)
    DWORD  dwMaxBytesPerSec;     // 這個AVI文件的最大數據率
    DWORD  dwPaddingGranularity; // 數據填充的粒度
    DWORD  dwFlags;         // AVI文件的全局標記,比如是否含有索引塊等
    DWORD  dwTotalFrames;   // 總幀數
    DWORD  dwInitialFrames; // 爲交互格式指定初始幀數(非交互格式應該指定爲0)
    DWORD  dwStreams;       // 本文件包含的流的個數
    DWORD  dwSuggestedBufferSize; // 建議讀取本文件的緩存大小(應能容納最大的塊)
    DWORD  dwWidth;         // 視頻圖像的寬(以像素爲單位)
    DWORD  dwHeight;        // 視頻圖像的高(以像素爲單位)
    DWORD  dwReserved[4];   // 保留
} AVIMAINHEADER;

 

4、’strl’子列表

每個‘strl’子列表至少包含一個‘strh’塊和一個‘strf’塊,而‘strd’塊(保存編解碼器需要的一些配置信息)和‘strn’塊 (保存流的名字)是可選的。首先是‘strh’塊,用於說明這個流的頭信息,可以使用一個AVISTREAMHEADER數據結構來操作:

typedef struct _avistreamheader {
     FOURCC fcc;  // 必須爲‘strh’
     DWORD  cb;   // 本數據結構的大小,不包括最初的8個字節(fcc和cb兩個域)
     FOURCC fccType;    // 流的類型:‘auds’(音頻流)、‘vids’(視頻流)、
                   //‘mids’(MIDI流)、‘txts’(文字流)
     FOURCC fccHandler; // 指定流的處理者,對於音視頻來說就是解碼器
     DWORD  dwFlags;    // 標記:是否允許這個流輸出?調色板是否變化?
     WORD   wPriority;  // 流的優先級(當有多個相同類型的流時優先級最高的爲默認流)
     WORD   wLanguage;
     DWORD  dwInitialFrames; // 爲交互格式指定初始幀數
     DWORD  dwScale;   // 這個流使用的時間尺度
     DWORD  dwRate;
     DWORD  dwStart;   // 流的開始時間
     DWORD  dwLength;  // 流的長度(單位與dwScale和dwRate的定義有關)
     DWORD  dwSuggestedBufferSize; // 讀取這個流數據建議使用的緩存大小
     DWORD  dwQuality;    // 流數據的質量指標(0 ~ 10,000)
     DWORD  dwSampleSize; // Sample的大小
     struct {
         short int left;
         short int top;
         short int right;
         short int bottom;
}  rcFrame;  // 指定這個流(視頻流或文字流)在視頻主窗口中的顯示位置
             // 視頻主窗口由AVIMAINHEADER結構中的dwWidth和dwHeight決定
} AVISTREAMHEADER;

 

然後是‘strf’塊,用於說明流的具體格式。如果是視頻流,則使用一個BITMAPINFO數據結構來描述;如果是音頻流,則使用一個WAVEFORMATEX數據結構來描述。

 

5、‘movi’列表

‘movi’列表保存的是真正的媒體流數據,其數據組織方式有兩種。可以將數據塊直接嵌在‘movi’列表裏面,也可以將幾個數據塊分組成一個‘rec ’列表後再編排進‘movi’列表。

當AVI文件中包含有多個流的時候,數據塊與數據塊之間如何來區別呢?數據塊使用了一個四字符碼來表徵它的類型,這個四字符碼由2個字節的類型碼和 2個字節的流編號組成。標準的類型碼定義如下:‘db’(非壓縮視頻幀)、‘dc’(壓縮視頻幀)、‘pc’(改用新的調色板)、‘wb’(音縮視頻)。 比如第一個流(Stream 0)是音頻,則表徵音頻數據塊的四字符碼爲‘00wb’;第二個流(Stream 1)是視頻,則表徵視頻數據塊的四字符碼爲‘00db’或‘00dc’。對於視頻數據來說,在AVI數據序列中間還可以定義一個新的調色板,每個改變的調 色板數據塊用‘xxpc’來表徵,新的調色板使用一個數據結構AVIPALCHANGE來定義。(注意:如果一個流的調色板中途可能改變,則應在這個流格 式的描述中,也就是AVISTREAMHEADER結構的dwFlags中包含一個AVISF_VIDEO_PALCHANGES標記)。另外,文字流數 據塊可以使用隨意的類型碼錶徵。

 

6、AVI索引塊

索引塊使用一個四字符碼‘idx1’來表徵,索引信息使用一個數據結構來AVIOLDINDEX定義。

typedef struct _avioldindex {
   FOURCC  fcc;  // 必須爲‘idx1’
   DWORD   cb;   // 本數據結構的大小,不包括最初的8個字節(fcc和cb兩個域)
   struct _avioldindex_entry {
      DWORD   dwChunkId;   // 表徵本數據塊的四字符碼
      DWORD   dwFlags;     // 說明本數據塊是不是關鍵幀、是不是‘rec ’列表等信息
      DWORD   dwOffset;    // 本數據塊在文件中的偏移量
      DWORD   dwSize;      // 本數據塊的大小
  } aIndex[]; // 這是一個數組!爲每個媒體數據塊都定義一個索引信息
} AVIOLDINDEX;

 注意:如果一個AVI文件包含有索引塊,則應在主AVI信息頭的描述中,也就是AVIMAINHEADER結構的dwFlags中包含一個AVIF_HASINDEX標記。

 

四、後記

       大家應該都聽過“AVI文件不適合用於流媒體傳輸”這樣的說法,通過本文對AVI文件結構的解析,相信大家對這種說法有更清晰的驗證,因爲AVI文件結構中置於文件尾部的索引塊、頭部信息中規定的文件長度等過多的選項都是不適合流媒體應用的。

     提示:上述關於AVI文件格式的介紹,並不包括OpenDML AVI M-JPEG文件格式小組制定的OpenDML AVI文件格式擴展部分的內容。想對該擴展部分有更多瞭解的讀者,請另行參考“OpenDML AVI File Format Extensions”一文(此文可在Internet上搜索獲得)。提示:上述關於AVI文件格式的介紹,並不包括OpenDML AVI M-JPEG文件格式小組制定的OpenDML AVI文件格式擴展部分的內容。想對該擴展部分有更多瞭解的讀者,請另行參考“OpenDML AVI File Format Extensions”一文(此文可在Internet上搜索獲得)。

 

五、二進制 格式解析

52 49 46 46 -> FORCC碼'RIFF'的ASCII值,說明是一個RIFF文件。RIFF( resource interchange file format ) 。
84 CF 4A 00 -> 表示文件大小的4個字節,由於windows是小頭的,所以文件大小爲0x004ACF84,即4902788字節,由於該size不包含開頭的8字節,所以文件總大小爲4902796字節
41 56 49 20 -> FOURCC碼'AVI '的ASCII碼,文件類型,說明是一個avi文件。AVI(AudioVideoInterleaved)。
        4C 49 53 54 -> FOURCC碼'LIST'的ASCII碼,說明是一個list
        7C 02 00 00 -> 表示list大小的4個字節。該list size爲0x0000027C,即636字節,整個list的大小爲:636 + 8 = 644 字節
        68 64 72 6C -> FOURCC碼'hdrl'的ASCII碼,list類型,說明這是一個頭信息列表(header list)。
                61 76 69 68 -> FOURCC碼'avih'的ASCII碼,表示該chunk的ID(ckID),說明這是一個主avi頭(main avi header)。是結構體AVIMAINHEADER中的fcc成員
                38 00 00 00 -> 表示chunk大小的4個字節。該chunk的size爲0x00000038,即56字節,整個chunk的大小爲:56 + 8 = 64 字節。是結構體AVIMAINHEADER中的cb成員
                56 82 00 00 -> 是結構體AVIMAINHEADER中的dwMicroSecPerFrame成員,表示幀之間的微秒數。爲0x00008256,即33366微秒。 
                EF AF 0A 00 -> 是結構體AVIMAINHEADER中的dwMaxBytesPerSec成員,表示文件的近似最大速率。爲0x000AAFEF,即700399字節/秒。
                01 00 00 00 -> 是結構體AVIMAINHEADER中的dwPaddingGranularity成員,表示以多少字節對齊。爲0x000001,即1字節,說明文件以1字節對齊。
                10 08 00 00 -> 是結構體AVIMAINHEADER中的dwFlags成員。爲0x00000810,HasIndex(+);MustUseIndex;IsInterleaved;WasCaptureFile;Copyrighted;TrustCKType(+)
                DD 00 00 00 -> 是結構體AVIMAINHEADER中的dwTotalFrames成員。表示文件中總共有多少幀。爲:0x000000DD,即221幀。dwTotalFrames * dwMicroSecPerFrame = 文件總時長。221 * 33366 = 7373886 微秒。即文件總時長爲7.373886秒。
                00 00 00 00 -> 是結構體AVIMAINHEADER中的dwInitialFrames成員。表示交錯幀中的初始幀,非交錯文件,該值爲0。從dwFlags可知,該文件爲非交錯文件,所以該值爲0。 
                01 00 00 00 -> 是結構體AVIMAINHEADER中的dwStreams成員,表示文件中所包含的流的數量。該文件中只包含一中流,所以該值爲1。 
                A8 62 00 00 -> 是結構體AVIMAINHEADER中的dwSuggestedBufferSize成員,表示讀該文件時,建議的緩存大小。爲0x000062A8,即25256字節。查看數據chunk可知,最大的數據chunk的size就是25256。
                60 01 00 00 -> 是結構體AVIMAINHEADER中的dwWidth成員,表示AVI文件的寬,以像素爲單位。爲0x00000160,即352像素。
                F0 00 00 00 -> 是結構體AVIMAINHEADER中的dwHeight成員,表示AVI文件的高,以像素爲單位。爲0x000000F0,即240像素。
                00 00 00 00 -> 是結構體AVIMAINHEADER中的dwReserved[0]成員,保留。
                00 00 00 00 -> 是結構體AVIMAINHEADER中的dwReserved[1]成員,保留。
                00 00 00 00 -> 是結構體AVIMAINHEADER中的dwReserved[2]成員,保留。
                00 00 00 00 -> 是結構體AVIMAINHEADER中的dwReserved[3]成員,保留。
                4C 49 53 54 -> FOURCC碼'LIST'的ASCII碼,說明是一個list
                24 01 00 00 -> 表示list大小的4個字節。該list size爲0x00000124,即292字節,整個list的大小爲:292 + 8 = 300 字節
                73 74 72 6C -> FOURCC碼'strl'的ASCII碼,list類型,說明這是一個流信息的list。
                        73 74 72 68 -> FOURCC碼'strh'的ASCII碼,說明這是一個流的頭信息chunk,其內容是一個AVISTREAMHEADER結構體。該值是AVISTREAMHEADER結構體的fcc成員。
                        38 00 00 00 -> 表示chunk大小的4個字節。該chunk的size爲0x00000038,即56字節,整個chunk的大小爲:56 + 8 = 64 字節。是結構體AVISTREAMHEADER的cb成員。
                        76 69 64 73 -> FOURCC碼'vids'的ASCII碼,說明這是一個視頻流。是結構體AVISTREAMHEADER的fccType成員。
                        63 76 69 64 -> FOURCC碼'cvid'的ASCII碼,標識解碼該流時使用的編解碼器。是結構體AVISTREAMHEADER的fccHandler成員。
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的dwFlags成員。整個數據流的標誌。Disabled;VideoPaletteChanges。
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的wPriority成員和wLanguage成員。
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的dwInitialFrames成員。表示交錯幀中的初始幀,非交錯文件,該值爲0。
                        E9 03 00 00 -> 是結構體AVISTREAMHEADER的dwScale成員。爲0x000003E9,即1001。與 dwRate 一起,決定該流所要使用的時間尺度。對於視頻流來說,dwRate / dwScale = 幀率(fram rate )。
                        30 75 00 00 -> 是結構體AVISTREAMHEADER的dwRate成員。爲0x00007530,即3000。該視頻流的幀率爲:3000 / 1001 = 29.97 (fps)
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的dwStart成員。這個流的開始時間。此處爲0。即文件開始時,流即開始。
                        DD 00 00 00 -> 是結構體AVISTREAMHEADER的dwLength成員。表示流的長度。爲0x000000DD,即221。對於視頻流,這其實就是總幀數,用dwLength除以幀率,即得到流的總時長。
                        A8 62 00 00 -> 是結構體AVISTREAMHEADER的dwSuggestedBufferSize成員。表示讀該流時,建議的緩存大小。爲0x000062A8,即25256字節。查看數據chunk可知,該流最大的數據chunk的size就是25256。
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的dwQuality成員。表示該流的質量指標,此處爲0。 
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的dwSampleSize成員。表示一個數據樣本的大小。如果樣本大小可變,此值爲0。視頻流中,該值一般爲0。此處爲0。
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的rcFrame成員的left和top成員。rcFrame指定一個由主頭文件中的wWidth 成員和dwHeight 成員文本流或視頻流的目標矩形。此處,left和top都爲0。
                        00 00 00 00 -> 是結構體AVISTREAMHEADER的rcFrame成員的right和bottom成員。此處爲0。
                        73 74 72 66 -> FOURCC碼'strf'的ASCII碼,說明這是一個流的格式信息chunk。如果是視頻流,其數據是一個BITMAPINFO結構體,對於音頻流,其數據是一個WAVEFORMATEX結構體。
                        28 00 00 00 -> 格式信息chunk的大小,不包括最初的8個字節。爲0x00000028,即40字節。整個chunk的大小爲:40 + 8 = 48 字節。
                        28 00 00 00 -> 是結構體BITMAPINFO的成員BITMAPINFOHEADER的biSize成員,表示結構體BITMAPINFOHEADER的大小。爲0x00000028,即40字節。這說明本chunk中,BITMAPINFO只包含一個成員,即BITMAPINFOHEADER結構體(因爲biBitCount爲24,所以結構體BITMAPINFO不包含顏色表)。
                        60 01 00 00 -> 是結構體BITMAPINFOHEADER的biWidth成員,位圖的寬,以像素爲單位。爲0x00000160,即352像素。
                        F0 00 00 00 -> 是結構體BITMAPINFOHEADER的biHeight成員,位圖的高,以像素爲單位。爲0x000000F0,即240像素。
                        01 00 18 00 -> 是結構體BITMAPINFOHEADER的biPlanes成員和biBitCount成員。其中biPlanes表示目標設備平面層的個數,其值爲1。biBitCount表示一個像素所佔的位數,其值爲0x0018,即一個像素佔24位。
                        63 76 69 64 -> 'cvid'的ASCII碼,是結構體BITMAPINFOHEADER的biCompression成員,表示了壓縮的類型。
                        FC 7B 00 00 -> 是結構體BITMAPINFOHEADER的biSizeImage成員,表明image的大小。爲0x00007BFC,即31740字節。
                        00 00 00 00 -> 是結構體BITMAPINFOHEADER的biXPelsPerMeter成員,水平分辨率,此處爲0。 
                        00 00 00 00 -> 是結構體BITMAPINFOHEADER的biYPelsPerMeter成員,垂直分辨率,此處爲0。
                        00 00 00 00 -> 是結構體BITMAPINFOHEADER的biClrUsed成員,此處爲0。表明此處使用與對於biCompression指定的壓縮模式的biBitCount值所對應的最大值。
                        00 00 00 00 -> 是結構體BITMAPINFOHEADER的biClrImportant成員,此處爲0。表明所有的顏色都是重要的。
                        ------------------------------------------------------------------------------------------------
                        是一個AVI 2.0的索引結構體。由於此次只使用old index,暫不對此進行研究。
                        ------------------------------------------------------------------------------------------------
                --------------------------------------------------------------------------------------------------------
                一個AVI OpenDML 1.02 Header List,包含一個AVI ODML Header。暫不研究。
                --------------------------------------------------------------------------------------------------------
        4C 49 53 54 -> FOURCC碼'LIST'的ASCII碼,說明是一個list
        0C BF 4A 00 -> 表示list大小的4個字節。該list size爲0x004ABF0C,即4898572字節,整個list的大小爲:4898572 + 8 = 4898580 字節
        6D 6F 76 69 -> FOURCC碼'movi'的ASCII碼,list類型,說明這是一個數據list。
                --------------------------------------------------------------------------------------------------------
                一個AVI Standard Index Chunk,暫不研究
                --------------------------------------------------------------------------------------------------------
                30 30 64 62 -> FOURCC碼'00db'的ASCII碼,說明這是第一個流(視頻流)的數據,爲未壓縮幀。
                08 62 00 00 -> 表示chunk大小的4個字節。該chunk的size爲0x00006208,即25096字節,整個chunk的大小爲:25096 + 8 = 25104 字節。
                --------------------------------------------------------------------------------------------------------
                chunk 的數據。
                --------------------------------------------------------------------------------------------------------
                30 30 64 63 -> FOURCC碼'00dc'的ASCII碼,說明這是第一個流(視頻流)的數據,爲壓縮幀。
                DA 5A 00 00 -> 表示chunk大小的4個字節。該chunk的size爲0x00005ADA,即23258字節,整個chunk的大小爲:23258 + 8 = 23266 字節。
                --------------------------------------------------------------------------------------------------------
                chunk 的數據。
                --------------------------------------------------------------------------------------------------------
                --------------------------------------------------------------------------------------------------------
                連續的chunk 的數據。
                --------------------------------------------------------------------------------------------------------
        64 69 78 31 -> FOURCC碼'idx1'的ASCII碼,chunk 類型,說明這是一個old index chunk。
        E0 0D 00 00 -> 表示chunk大小的4個字節。該chunk的size爲0x00000DE0,即3552字節,整個chunk的大小爲:3552 + 8 = 3560 字節。每條索引信息有4個DWORD類型構成,即佔16個字節,所以該index chunk中包含的索引項的個數爲:3552 / 16 = 222。由此可以推知,movi list中含有222個數據chunk。
                37 46 78 78 -> '7Fxx'的ASCII碼,chunk ID,這應該是用戶自定義的chunk的索引。
                00 00 00 00 -> 標誌。'LIST'-chunk;KeyFrame;Midpart;Firstpart;Lastpart;NoTime
                9C 02 00 00 -> 偏移量。爲0x0000029C,即668字節。
                00 00 00 00 -> 該數據chunk的大小。根據給chunk的偏移量,沒有找到該chunk。該chunk的數據大小又爲0,推斷這是一處錯誤數據。
                30 30 64 62 -> '00db'的ASCII碼,chunk ID,說明是第一個流的非壓縮幀。
                10 00 00 00 -> 標誌。'LIST'-chunk;KeyFrame(+);Midpart;Firstpart;Lastpart;NoTime
                FC 08 00 00 -> 偏移量。爲0x000008FC,即2300字節。該文件中用的是從文件開始處的偏移量。
                08 62 00 00 -> 該數據chunk的大小。爲0x00006208,即25096字節。
                30 30 64 63 -> '00dc'的ASCII碼,chunk ID,說明是第一個流的壓縮幀。
                00 00 00 00 -> 標誌。'LIST'-chunk;KeyFrame;Midpart;Firstpart;Lastpart;NoTime
                0C 6B 00 00 -> 偏移量。爲0x00006B0C,即27404字節。該文件中用的是從文件開始處的偏移量。
                DA 5A 00 00 -> 該數據chunk的大小。爲0x00005ADA,即23258字節。
                --------------------------------------------------------------------------------------------------------
                下面依次是index成員,直到文件結束。
                --------------------------------------------------------------------------------------------------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章