- AVI Audio/Video Extractor
- RIFF
- AVI Main Header
- AVI Stream Header
- Bitmap Info Header
- Wave FormatEx
- movi
- Index
- Demo
- Discussion
- 無index區塊的處理
- JUNK區塊對齊
- OpenDML標準格式支援
- 字幕處理
- 其他影音壓縮格式支援
- ....
- Reference
Download: AviAVExtractor.zip
AVI Audio/Video Extractor是兩年前為了了解基本的影音架構處理而撰寫的小程式,最近終於有時間將這個小程式做些微的修正發佈出來。整個程式演算沒有什麼難度,只是大量的使用結構與檔案的輸入輸出的處理。基本的AVI結構圖如下:
上面這張概略圖已經不是最原始的AVI架構,我參照了OpenDML標準定義所混和繪製的。
本範例程式最原先版本是參照微軟的AVI RIFF File Reference文件定義所撰寫的,網址如下;
http://msdn.microsoft.com/en-us/library/ms779636(VS.85).aspx
AVI屬於RIFF(Resource Interchange File Format)標準定義內的格式,所以在圖上你可以看到一開始會有12bytes為RIFF的資訊(如右圖),每一個區塊佔用4bytes,第一個區塊紀錄著RIFF這四個字元,第二個區塊則是紀錄這整個檔案的大小,例如圖中的16進位數值轉為10進位就是13044728 bytes,會比實際檔案大小少於8 bytes,因為13044728是不包含檔案前8個bytes。第三個區塊則是紀錄著此檔案的類型。同樣的紀錄方式應用在WAVE檔也是如此。RIFF是由Microsfot跟IBM所定義的,詳細訊息可以參考wikipedia - Resource Interchange File Format
緊接著RIFF之後就是AVI結構裡第一個主LIST區塊(標頭定義區塊),在avih識別字之後會有一個AVI Main Header,在這個範例裡我們僅使用他來判別此檔案有多少個串流(dwStreams),詳細的結構資料你可以參考微軟的AVI Main Header。
讀取完AVI Main Header之後緊接著是第一個子LIST,一個AVI檔通常會有2~4個sub-list,而Audio跟Video通常都在前兩個sub-list裡,而其餘的則是紀錄字幕或者一些保留資訊。在這個範例裡我們只藉由Stream Header來判斷目前此串流的格式(fccType),詳細結構你可以參考微軟的AVI Stream Headers。
每一個子LIST區塊都會有AVI Stream Header,紀錄著此串流的類型。以第一張的AVI架構圖來說,我們假設stream0為vids(也就是視訊串流),那這時就要讀取點陣圖的標頭檔,在這個範例裡我們只將此訊息儲存保留至視訊分離時使用,詳細結構請參考微軟的Bitmap Info Header。
讀取完視頻的標頭資訊之後,stream1則是為音頻標頭資訊,範例裡我們使用標準的wave格式標頭檔WAVEFORMETEX來讀取,同樣的也是保留原始資訊作為之後分離音訊使用,詳細結構請參考微軟的WAVEFORMETEX
讀取完第一部份的主LIST,第二部份的LIST則是紀錄著音訊視訊的實體資料,以某一區塊的已壓縮視訊區塊為例,如下:
第一個識別字00dc代表著stream0的已壓縮視訊資料,另外還有00db(stream0未壓縮視訊),以及01wb(stream1的音訊區塊),所以前面兩個字元00/01代表著串流的位置,二後兩個字元dc/db/wb則是串流的類型,詳細資料可以參考微軟的AVI RIFF File Reference
Index在AVI格式裡是optional的,但是在這個範例程式裡必須仰賴有index的AVI才能正常處理,index內每一個entry定義如下:
struct AVIOLDINDEX_ENTRY{
DWORD dwChunkId;
DWORD dwFlags;
DWORD dwOffset;
DWORD dwSize;
};
除了dwFlags在這個範例我們沒有用到之外,其餘的變數我們必須依照index的數據來搜尋實體資料。dwChunkId決定所紀錄區塊的串流類型,dwOffset則是紀錄此區塊的位置(不一定是絕對位置,所以在設計時必須自行修正這個問題),dwSize則是此區塊的大小,詳細資訊請參考微軟的AVIOLDINDEX
使用GCC4.2.4在ubuntu8.04底下編譯之後會產生AviAVExtractor這個檔案,使用方式如下(以附件所附的imagine.avi檔案為例):
處理完後音訊跟視訊的檔案分別為audio0.wav, video0.avi。
原始碼只有三個:
AviDefinition.h : AVI and its related structure definition
AviAVExtractor.h : header for AviAvExtractor.h
AviAVExtractor.c : Main Program
其中我將一些常用的AVI結構定義在AviDefinition.h裡面,為了程式設計方便,我所定義的結構可能會跟微軟上所列的有些出入。
本程式僅是簡單展示如何做音訊視訊分離,仍有許多地方並未實做:
所以還有很多地方可以繼續補強,當然如果你是要做一些影音處理的專案,為了效率還是直接使用現成的API會比較快且穩定。
No comments:
Post a Comment