[轉]AVI文件格式及其應用研究

徐殿武 《現代電子技術》 2008年第02期

 

 

  摘 要:AVI文件是Windows操作系統下最常用的流媒體文件格式之一,瞭解AVI文件格式是正確使用AVI文件的基礎,以一個具體的AVI文件的二進制碼爲例,詳細解釋和研究AVI文件的各個字段的具體含義,並指出AVI-1文件與AVI-2文件格式的區別,在此基礎上,可以對AVI文件進行各種編程操作。給出使用VFW(Video For Windows)用Visual C++編程語言從AVI-2文件中獲取視頻幀,轉換爲BMP圖像,加以顯示並存儲爲位圖文件的編程方法。
  關鍵詞:流媒體文件;VC;AVI;VFW
  中圖分類號:TP311.1 文獻標識碼:A 文章編號:1004-373X(2008)02-119-04
  
  Study on AVI File Format and Its Application
  XU Dianwu
  (Mechano-Electronic College,China University of Petroleum,Beijing,102249,China)
  Abstract:Under Windows environment,AVI is a popular stream media format.To work with AVI file,it is the basic to know about AVI file format.In this paper,the example ofAVI file binary code is presented in binary code,to illustrate every chunk in the file.The format of AVI files,and especially the difference between AVI-1 and AVI-2 format is discussed.Programming method for pickup video frames from an AVI file and save it as BMP files in Visual C++ is presented.
  Keywords:stream medium file;VC;AVI;VFW
  
  1 引 言
  
  自微軟公司推出AVI文件格式以來,AVI逐漸成爲Windows 操作系統上最常用的流媒體文件格式之一[1]。AVI是視頻數據和音頻數據交叉編碼(Audio Video Interleaved)的一種RIFF文件,其多用於音視頻捕捉、編輯、播放等,其文件名後綴爲.avi。應用程序的開發者在編寫多媒體處理軟件時,除要對AVI文件進行播放、編輯、製作外,也經常需要從一個AVI文件中提取一視頻幀並存儲爲BMP圖像文件,這些都需要對AVI文件格式有深入瞭解,本文在對AVI文件格式進行解析的基礎上,給出了從AVI文件中獲取位圖的程序設計方法。這裏介紹的AVI文件格式不包括OpenDML AVI M-JPEG文件格式分委員會制定的內容以及nAVI(一種改進的ASF格式)的內容。
  
  2 RIFF文件格式簡介
  
  RIFF(Resource Interchange File Format)文件格式是一個信息交換框架[1],AVI文件格式是以RIFF爲基礎的,所以在很多文獻中,AVI文件又被稱爲AVI RIFF文件[2]。
  RIFF文件組成的基本單元叫作“塊”(chunk),使用FOURCC碼(Four Character Code,4字符碼,Windows中的數據類型爲FOURCC)來標識文件中的每個塊。FOURCC是由4個ASCII碼組成的一個DWORD型數據,高字節在後,如4字符abcd的FOURCC碼是0X64636261。RIFF就是一個FOURCC,表示這是一個RIFF塊。在一個RIFF文件中,除RIFF塊和LIST塊可以包含子塊(Sub Chunk)外,其他任何塊均不可以包含子塊。
  塊的格式分爲2種,可以包含子塊的塊(RIFF,LIST)的格式爲:FOURCC、塊長度(4字節,DWORD類型,長度不包括FOURCC和塊長度佔用的8個字節)、塊數據類型、塊數據。不可以包含子塊的塊的格式是:FOURCC、塊長度、塊數據,沒有塊數據類型部分。
  
  3 AVI文件格式
  
  AVI文件是一種最複雜的RIFF文件。現在常用的AVI文件有2種:AVI-1和AVI-2。在AVI-2文件中,通常包含2個流,一個視頻流和一個音頻流(被稱爲標準AVI格式),但只有一個視頻流或音頻流也是合法的。在AVI-1文件中只包含一個DV(digital Video)數據流(視頻採集設備的輸出數據,其中既有視頻信息也有音頻信息),在文件中以單個流的形式存在,其主要優點是佔用較少的存儲空間,對AVI-1的支持主要來自DirectShow中的DV Muxer和DV Splitter篩選器(Filter)[2]。雖然目前AVI-2仍然是最常使用的格式,但AVI-1由於其自身的優點和受到微軟最新技術的支持,將來可能會比AVI-2更流行。雖然這2種AVI文件不兼容,但他們都以RIFF格式爲基礎,除了實際的流數據格式不同以外,差別主要存在於文件的strh塊和strf塊。

  下面爲AVI文件的格式,左邊小括號處省略了4字節的文件大小或列表大小或塊大小,凡FOURCC都用4個字母表示,除RIFF和LIST外,所有的4字符碼都用單引號括起來,方括號表示可選:
  
  RIFF (′AVI◇′[JY]//RIFF文件頭,塊的數據類型是AVI,
  [JY]◇表示空格。
  LIST (′hdrl′[JY]//列表,列表中的數據類型是hdrl,
  [JY]下面緊跟avih子塊。
  ′avih′(AVI文件的全局信息,本行構成一個AVIMAINHEADER結構,長度爲64個字節)。
  LIST (′strl′[JY]//strl列表,表示本列表是一個流的列表,
  [JY]其後緊跟strh子塊。
  ′strh′([JY]//流的頭信息,本行構成一個AVISTREAMHEADER
  [JY]結構,長度爲64字節)
  ′strf′( [JY]//流的格式信息子塊,描述流中數據的格式。)
  [ ′strd′([JY]//附加的流頭數據,一般爲
  [JY]編解碼器驅動程序所定義) ]
  [ ′strn′(以0結束的字符串,流的名字) ]
  ...
   )
   ...
   )[JY]//hdrl列表塊到此結束
  LIST (′movi′[JY]//movi列表塊,包含了流的實際數據,
  [JY]數據可以是子塊,也可以將子塊組織成rec 列表,
  [JY]一個rec列表中的數據應該一次性地從磁盤讀出。
  {SubChunk | LIST (′rec ′
  SubChunk1
  SubChunk2
  ...
  )
  ...
  }
  ...
  )//movi列表塊到此結束
  [′idx1′ (索引塊) ]
  
本文原文
   )//RIFF塊到此結束,這就是一個完整的AVI RIFF文件
  從上面的格式可以看出,一個AVI RIFF文件由3大部分組成:RIFF文件頭;hdrl列表;movi列表。其中hdrl列表包含avih子塊和strl子列表,文件中有多少個流,hdrl列表中就有多少個strl子列表,strl子列表在hdrl中的次序就是流的序號(隱含)。
  strl子列表由strh子塊、strf子塊、strd子塊(可選)、strn子塊(可選)構成。movi列表中存儲的是流的實際數據,movi列表中數據子塊的種類有:##db,##dc,##pc,##wb,其中##表示數據所屬的流的序號,如00db,01dc。db表示未壓縮的視頻幀;dc表示壓縮的視頻幀;wb表示音頻數據;pc表示調色板變化,其後的數據是一個AVIPALCHANGE結構,此時strh中的dwFlages字段必須置爲AVISF_VIDEO_PALCHANGES。
  movi列表最後可以有一個可選的索引塊(idxl),他指出流的數據在文件中的位置,以便於對數據進行隨機訪問。一個AVI RIFF文件如果有索引塊,則將AVIMAINHEADER結構中的dwFlags字段置爲AVIF_HASINDEX。AVI文件中的JUNK塊爲數據對齊而存在,應用程序應該忽略JUNK塊的內容。
  AVI-1中只有一個流(DV data stream),其AVISTREAMHEADER(strh塊)中的fccType字段是4字符碼′iavs′,fccHandler字段是′dvsd′,′dvhd′,′dvsl′三者之一(分別對應3種DV格式),strl子列表中的strf塊是DVINFO結構(32字節)。AVI-2中一般有2個流,視頻流的AVISTREAMHEADER(strh塊)中的fccType字段是4字符碼′vids′(也可以是′dvsd′,′dvhd′,′dvsl′三者之一)[2], 音頻流的4字符碼是′auds′,其視頻流的strl子列表中的strf塊是BITMAPINFOHEADER結構(40字節),其後可以跟隨DVINFO結構。AVI-2中音頻流的strf塊是WAVEFORMATEX結構。
  AVI RIFF文件格式只規定了文件的組成方式,即各種數據如何在文件中排列等,對於文件中的數據並沒有做出編碼格式的約束,如MPEG-1、DivX等都可以作爲文件中數據的編碼格式。數據也可以未經壓縮。AVI文件可以看成是一個數據容器,AVI格式只規定了將數據裝入這個容器的方法,但對數據本身的編碼格式並不涉及。要操作一個AVI文件(播放、抓圖、編輯),必須在系統中安裝與該AVI文件中的編碼器對應的解碼器,才能進行正確的工作。

  4 AVI-2文件格式的例
  
  下面以AVI文件bfh.avi(風景介紹片)爲例,將該AVI文件打開,逐字節解釋其中的數據(見圖1):
  52494646是RIFF的ASCII碼;7E443400是文件長度,高位字節在後,(0034447E)16,(3425406)10;41564920是AVI◇的ASCII碼,◇表示空格;表示RIFF塊(文件)的數據類型是AVI。4C495354是LIST的ASCII碼,表示這是一個列表。10h開始的4字節表示本列表長度,(132)16,(306)10。接着6864726C是hdrl的ASCII碼,表明這是hdrl列表,61766968是avih的ASCII碼,表明這是hdrl列表中的avih塊,第二行最後4字節是16進制的38,十進制的56;表示avih塊的長度是56個字節(加上8正好是AVIMAINHEADER結構的長度),接下來的56個字節就是avih的內容,描述AVI文件的整體信息,AVIMAINHEADER結構中各個字段的內容不再分析,avih塊到057h結束。
  從0058h開始的4C495354是LIST的ASCII碼,其後4字節(74)16,即(116)10是本列表的大小。60h開始的7374726C是strl的ASCII碼,表示這是strl(流)列表,從64h到a3h的64個字節是一個AVISTREAMHEADER結構;64h開始的73747268是strh的ASCII碼,表示這是strl列表中strh塊(流的頭信息);下面的4字節是strh塊的大小(38)16,十進制的56,76696473是vids的ASCII碼,是流的類型,表示這是一個視頻流,從上面對AVI的2種格式的分析可知,這是一個AVI-2文件,如果是AVI-1文件,此處應該是iavs的ASCII碼。70h開始的4字節是′MSVC′(已經註冊的解碼器的4字符碼 )的ASCII碼4D535643,AVISTREAMHEADER結構其他字段不再羅列,90h這一行最後4個字節,表示顯示窗口左上角x,y,其值爲0,0。a0h開始的2字節是窗口顯示的右下角x座標,值爲十進制的128,以象素爲單位,再2字節是右下角y座標,十進制的112,至此,AVISTREAMHEADER結束。
  a4h開始的4字節是strf的ASCII碼73747266,後跟的4字節(28)16,(40)10是strf塊的長度,前面說過,在AVI-2中,如果是視頻流,strf就是一個BITMAPINFOHEADER結構,而該結構的長度是40字節,再後的4字節(28)16,就是BITMAPINFOHEADER的第一個字段,指明該結構的長度,所以有2個(28)16相連。從boh開始,就是BITMAPINFOHEADER其餘的內容,(80)16是圖像的寬度,120象素。(70)16是圖像的高度,112象素,這些都與前面的信息相符合。0001兩字節是位平面數,(0018)16是每象素比特數(24位)。接下來4字節44495633是′DIV3′(壓縮編碼格式的四字符碼)的ASCII碼,是BITMAPINFOHEADER的biCompression域的值,指壓縮方式,這是和普通的BMP文件不同的。後面的字段不再分析。值得指出的是,這裏可以後跟一個DVINFO結構(可選),如果是AVI-1文件,這裏用DVINFO結構取代BITMAPINFOHEADER結構。接下來的4C495344是LIST的ASCII碼,表明下面又是一個列表,列表大小是6Ah,doh行最後4字節是strl的ASCII碼,表明這是一個“流”列表。後面的數據不再分析。
  
  5 從AVI文件中提取位圖
  
  Windows提供的VFW和DirectShow[3]都可以處理和操作AVI文件,考慮到VFW爲大多數程序員所熟悉以及AVI-2仍然是最常使用的AVI文件格式,下面給出使用VFW從AVI-2文件中提取視頻幀加以顯示並存儲爲BMP位圖文件的程序。
  VFW 提供的AVIFile動態鏈接庫使用OLE技術實現,在AVIFile中的API函數將AVI文件中的數據當作“流”來處理,而不必逐一地尋找其中的塊(chunk)。使用該庫要首先調用函數AVIFileInit來初始化,使用完畢調用函數AVIFileExit後釋放。首先使用MFC AppWizard創建一個名爲avi的單文檔項目,然後重載CDocument類的虛函數OnOpenDocument,在此函數中打開AVI文件,讀出其中的視頻幀,存儲爲BMP文件並在屏幕上加以顯示(在VC++6.0中調試通過):

  BOOL CAviDoc::OnOpenDocument(LPCTSTR lpszPathName) 
  { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE;
  AVIFileInit(); [JY]//初始化
  AVIFileOpen(&pAviFile,lpszPathName,OF_SHARE_DENY_WRITE,0l);[JY]//打開AVI文件
  AVIFileGetStream(pAviFile,&pAviStream,streamtypeVIDEO,0L );[JY]//打開流
  AVIStreamInfo(pAviStream,&aviStrInfo,sizeof(AVISTREAMINFO));[JY]//獲取流的信息
  long lStreamSize;[JY]//流格式長度
  pBmpInfoH = new BITMAPINFOHEADER;[JY]//pBmpInfoH是文檔類的成員變量
  AVIStreamFormatSize(pAviStream,0,&lStreamSize);[JY]//獲取流的格式信息的長度
  AVIStreamReadFormat(pAviStream,0L,pBmpInfoH,&lStreamSize);
  PGETFRAME pgf;
  pgf = AVIStreamGetFrameOpen(pAviStream,NULL);[JY]//爲解壓幀做準備
  [JY]//解壓讀出第0幀,緊縮DIB的數據以返回值pData爲起始地址
  pData = (LPBYTE)AVIStreamGetFrame(pgf,0L);[JY]//文檔類的成員變量,類型爲LPBYTE
  pBmpInfoH->biCompression = 0;
  BITMAPFILEHEADER bmpFH;[JY]//位圖文件頭
  bmpFH.bfType = 0x4d42;
  bmpFH.bfSize = bmpInfoH.biWidth*bmpInfoH.biHeight*3 + 54;
  bmpFH.bfReserved1 = 0;bmpFH.bfReserved2 = 0;
  bmpFH.bfOffBits = 54;
  CFileDialog dlg(FALSE);[JY]//獲取用戶要存儲成的位圖文件名和路徑
  if(IDOK==dlg.DoModal ())str.Format ("%s",dlg.GetPathName() );
  CFile bmp(str,CFile::modeWrite|CFile::modeCreate);
  bmp.Write(&bmpFH,sizeof(BITMAPFILEHEADER));[JY]//寫入位圖文件頭
  bmp.WriteHuge(pData,bmpFH.bfSize-14);[JY]//寫入緊縮DIB
  bmp.Close(); AVIFileExit();
  UpdateAllViews(NULL);[JY]//更新視圖,在視圖類的OnDraw函數中顯示位圖
  return TRUE;
  }//程序中省略所有安全性檢查語句。位圖的顯示在視類的OnDraw函數(略)中。
  圖2是程序執行的結果:從bfh.avi中提取的第0幀轉換成的位圖的顯示。
  上面程序中pAviFile,pAviStream,aviStrInfo都是文檔類的成員變量,類型分別爲PAVIFILE,PAVISTREAM,AVISTREAMINFO。在文檔類的構造函數中將所有指針初始化爲NULL。還可以循環調用函數AVIStreamFindNextKey尋找所有的關鍵幀加以顯示並存儲爲BMP文件。需要注意,函數AVIStreamGetFrame返回的是一個“緊縮DIB”的地址,即以一個位圖的BITMAPINFOHEADER開始的地址,且所需的緩衝區由該函數自己開闢,不需應用程序動態申請。程序要加入#include,且在Project->Settings->Link中鍵入vfw32.lib。
  
  6 結 語
  
  由於Windows是很流行的操作系統,AVI是Microsoft公司大力支持的格式,因此在編寫基於Windows操作系統的流媒體圖像處理程序方面,AVI佔有不可替代的位置。準確理解AVI文件格式以及針對AVI文件的編程方法在工程實踐中具有重要的意義。AVI-1文件格式由於佔用存儲空間小,受到DirectShow的支持,其將來會成爲AVI文件中最流行的格式。
  
  參 考 文 獻
  [1]姜楠,王健.常用多媒體文件格式壓縮標準解析[M].北京:電子工業出版社,2005.
  [2]DirectX Documentation for C++[EB/OL].Microsoft Corporation,2005.
  [3]陸其明.DirectShow 開發指南[M].北京:清華大學出版社,2003.
  
  注:本文中所涉及到的圖表、註解、公式等內容請以PDF格式閱讀原文。

發佈了12 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章