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
?
圖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