[C/C++] AVI Audio/Video Extractor

  • AVI Audio/Video Extractor
  • 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

  • RIFF
  • 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

  • AVI Main Header
  • 緊接著RIFF之後就是AVI結構裡第一個主LIST區塊(標頭定義區塊),在avih識別字之後會有一個AVI Main Header,在這個範例裡我們僅使用他來判別此檔案有多少個串流(dwStreams),詳細的結構資料你可以參考微軟的AVI Main Header

  • AVI Stream Header
  • 讀取完AVI Main Header之後緊接著是第一個子LIST,一個AVI檔通常會有2~4個sub-list,而Audio跟Video通常都在前兩個sub-list裡,而其餘的則是紀錄字幕或者一些保留資訊。在這個範例裡我們只藉由Stream Header來判斷目前此串流的格式(fccType),詳細結構你可以參考微軟的AVI Stream Headers

  • Bitmap Info Header
  • 每一個子LIST區塊都會有AVI Stream Header,紀錄著此串流的類型。以第一張的AVI架構圖來說,我們假設stream0為vids(也就是視訊串流),那這時就要讀取點陣圖的標頭檔,在這個範例裡我們只將此訊息儲存保留至視訊分離時使用,詳細結構請參考微軟的Bitmap Info Header

  • Wave FormatEx
  • 讀取完視頻的標頭資訊之後,stream1則是為音頻標頭資訊,範例裡我們使用標準的wave格式標頭檔WAVEFORMETEX來讀取,同樣的也是保留原始資訊作為之後分離音訊使用,詳細結構請參考微軟的WAVEFORMETEX

  • movi
  • 讀取完第一部份的主LIST,第二部份的LIST則是紀錄著音訊視訊的實體資料,以某一區塊的已壓縮視訊區塊為例,如下:

    第一個識別字00dc代表著stream0的已壓縮視訊資料,另外還有00db(stream0未壓縮視訊),以及01wb(stream1的音訊區塊),所以前面兩個字元00/01代表著串流的位置,二後兩個字元dc/db/wb則是串流的類型,詳細資料可以參考微軟的AVI RIFF File Reference

  • Index
  • Index在AVI格式裡是optional的,但是在這個範例程式裡必須仰賴有index的AVI才能正常處理,index內每一個entry定義如下:

    struct AVIOLDINDEX_ENTRY{
    DWORD dwChunkId;
    DWORD dwFlags;
    DWORD dwOffset;
    DWORD dwSize;
    };

    除了dwFlags在這個範例我們沒有用到之外,其餘的變數我們必須依照index的數據來搜尋實體資料。dwChunkId決定所紀錄區塊的串流類型,dwOffset則是紀錄此區塊的位置(不一定是絕對位置,所以在設計時必須自行修正這個問題),dwSize則是此區塊的大小,詳細資訊請參考微軟的AVIOLDINDEX

  • Demo
  • 使用GCC4.2.4在ubuntu8.04底下編譯之後會產生AviAVExtractor這個檔案,使用方式如下(以附件所附的imagine.avi檔案為例):

    處理完後音訊跟視訊的檔案分別為audio0.wav, video0.avi。

  • Discussion
  • 原始碼只有三個:

    AviDefinition.h : AVI and its related structure definition

    AviAVExtractor.h : header for AviAvExtractor.h

    AviAVExtractor.c : Main Program

    其中我將一些常用的AVI結構定義在AviDefinition.h裡面,為了程式設計方便,我所定義的結構可能會跟微軟上所列的有些出入。

    本程式僅是簡單展示如何做音訊視訊分離,仍有許多地方並未實做:

    1. 無index區塊的處理
    2. JUNK區塊對齊
    3. OpenDML標準格式支援
    4. 字幕處理
    5. 其他影音壓縮格式支援
    6. ....

    所以還有很多地方可以繼續補強,當然如果你是要做一些影音處理的專案,為了效率還是直接使用現成的API會比較快且穩定。

  • Reference
  • Microsoft MSDN - AVI RIFF File Reference

    OpenDML AVI File Format Extensions

No comments:

Post a Comment

Orange - data analysis tool

Installation pip install orange3 Run orange python -m Orange.canvas