天天看點

AVI檔案規範

AVI檔案規範

PeterLee 2007-10-14

一、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檔案結構示例

       圖1所示為windows系統目錄下的clock.avi的檔案結構圖,其結構是用RIFFspot程式解析得到的,關于RIFFspot程式,感興趣的讀者可以到下面的網址中下載下傳:http://blog.csdn.net/sunshine1314/archive/2007/09/22/1795739.aspx

AVI檔案規範

圖1 clock.avi檔案結構

2、AVI檔案全局結構說明

       如圖1所示,整個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檔案結構中置于檔案尾部的索引塊、頭部資訊中規定的檔案長度等過多的選項都是不适合流媒體應用的。

Note: 本文内容節選自 AVI檔案格式----摘自《DirectShow實務精選》 作者:陸其明, 并作了整理。

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/sunshine1314/archive/2007/10/14/1824432.aspx

繼續閱讀