织梦CMS - 轻松建站从此开始!

罗索

AVI文件格式及其应用研究

落鹤生 发布于 2010-04-02 14:44 点击:次 
AVI文件是Windows操作系统下最常用的流媒体文件格式之一,了解AVI文件格式是正确使用AVI文件的基础,以一个具体的AVI文件的二进制码为例,详细解释和研究AVI文件的各个字段的具体含义,并指出AVI-1文件与AVI-2文件格式的区别
TAG:

摘要:AVI文件是Windows操作系统下最常用的流媒体文件格式之一,了解AVI文件格式是正确使用AVI文件的基础,以一个具体的AVI文件的二进制码为例,详细解释和研究AVI文件的各个字段的具体含义,并指出AVI-1文件与AVI-2文件格式的区别,在此基础上,可以对AVI文件进行各种编程操作。给出使用VFW(VideoForWindows)用VisualC 编程语言从AVI-2文件中获取视频帧,转换为BMP图像,加以显示并存储为位图文件的编程方法。
  关键词:流媒体文件;VC;AVI;VFW
  中图分类号:TP311.1文献标识码:A文章编号:1004-373X(2008)02-119-04
  
  StudyonAVIFileFormatandItsApplication
  XUDianwu
  (Mechano-ElectronicCollege,ChinaUniversityofPetroleum,Beijing,102249,China)
  Abstract:UnderWindowsenvironment,AVIisapopularstreammediaformat.ToworkwithAVIfile,itisthebasictoknowaboutAVIfileformat.Inthispaper,theexampleofAVIfilebinarycodeispresentedinbinarycode,toillustrateeverychunkinthefile.TheformatofAVIfiles,andespeciallythedifferencebetweenAVI-1andAVI-2formatisdiscussed.ProgrammingmethodforpickupvideosfromanAVIfileandsaveitasBMPfilesinVisualC ispresented.
  Keywords:streammediumfile;VC;AVI;VFW
  
  1引言
  
  自微软公司推出AVI文件格式以来,AVI逐渐成为Windows操作系统上最常用的流媒体文件格式之一[1]。AVI是视频数据和音频数据交叉编码(AudioVideoInterleaved)的一种RIFF文件,其多用于音视频捕捉、编辑、播放等,其文件名后缀为.avi。应用程序的开发者在编写多媒体处理软件时,除要对AVI文件进行播放、编辑、制作外,也经常需要从一个AVI文件中提取一视频帧并存储为BMP图像文件,这些都需要对AVI文件格式有深入了解,本文在对AVI文件格式进行解析的基础上,给出了从AVI文件中获取位图的程序设计方法。这里介绍的AVI文件格式不包括OpenDMLAVIM-JPEG文件格式分委员会制定的内容以及nAVI(一种改进的ASF格式)的内容。
  
  2RIFF文件格式简介
  
  RIFFResourceInterchangeFileFormat)文件格式是一个信息交换框架[1],AVI文件格式是以RIFF为基础的,所以在很多文献中,AVI文件又被称为AVIRIFF文件[2]。
  RIFF文件组成的基本单元叫作“”(chunk),使用FOURCC码FourCharacterCode,4字符码,Windows中的数据类型为FOURCC)来标识文件中的每个块。FOURCC是由4个ASCII码组成的一个DWORD型数据,高字节在后,如4字符abcd的FOURCC码是0X64636261。RIFF就是一个FOURCC,表示这是一个RIFF块。在一个RIFF文件中,除RIFF块和LIST块可以包含子块(SubChunk)外,其他任何块均不可以包含子块。
  块的格式分为2种,可以包含子块的块(RIFF,LIST)的格式为:FOURCC、块长度(4字节,DWORD类型,长度不包括FOURCC和块长度占用的8个字节)、块数据类型、块数据。不可以包含子块的块的格式是:FOURCC、块长度、块数据,没有块数据类型部分。
  
  3AVI文件格式
  
  AVI文件是一种最复杂的RIFF文件。现在常用的AVI文件有2种:AVI-1AVI-2。在AVI-2文件中,通常包含2个流,一个视频流和一个音频流(被称为标准AVI格式),但只有一个视频流或音频流也是合法的。在AVI-1文件中只包含一个DV(digitalVideo)数据流(视频采集设备的输出数据,其中既有视频信息也有音频信息),在文件中以单个流的形式存在,其主要优点是占用较少的存储空间,对AVI-1的支持主要来自DirectShow中的DVMuxer和DVSplitter筛选器(Filter)[2]。虽然目前AVI-2仍然是最常使用的格式,但AVI-1由于其自身的优点和受到微软最新技术的支持,将来可能会比AVI-2更流行。虽然这2种AVI文件不兼容,但他们都以RIFF格式为基础,除了实际的流数据格式不同以外,差别主要存在于文件的strh块和strf块。
  下面为AVI文件的格式,左边小括号处省略了4字节的文件大小或列表大小或块大小,凡FOURCC都用4个字母表示,除RIFF和LIST外,所有的4字符码都用单引号括起来,方括号表示可选:
       /*   RIFF文件头 */  
  RIFF(′AVI◇′[JY]//RIFF文件头,块的数据类型是AVI,

      /* hdrl列表 */

  LIST(′hdrl′[JY]//列表,列表中的数据类型是hdrl,
  [JY]下面紧跟avih子块。
  ′avih′(AVI文件的全局信息,本行构成一个AVIMAINHEADER结构,长度为64个字节)。


       /* strl 列表 */

  LIST(′strl′[JY]//strl列表,表示本列表是一个流的列表,
  [JY]其后紧跟strh子块。
  ′strh′([JY]//流的头信息,本行构成一个AVISTREAMHEADER
  [JY]结构,长度为64字节)
  ′strf′([JY]//流的格式信息子块,描述流中数据的格式。)
  [′strd′([JY]//附加的流头数据,一般为
  [JY]编解码器驱动程序所定义)]
  [′strn′(以0结束的字符串,流的名字)]
  ...
  )
  ...
  )[JY]//hdrl列表块到此结束

  /* movi列表 */

       LIST(′movi′[JY]//movi列表块,包含了流的实际数据,
  [JY]数据可以是子块,也可以将子块组织成rec列表,
  [JY]一个rec列表中的数据应该一次性地从磁盘读出。
  {SubChunk|LIST(′rec′
  SubChunk1
  SubChunk2
  ...
  )
  ...
  }
  ...
  )//movi列表块到此结束
  [′idx1′(索引块)]
  [newpage]  )//RIFF块到此结束,这就是一个完整的AVIRIFF文件


  从上面的格式可以看出,一个AVIRIFF文件由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),他指出流的数据在文件中的位置,以便于对数据进行随机访问。一个AVIRIFF文件如果有索引块,则将AVIMAINHEADER结构中的dwFlags字段置为AVIF_HASINDEX。AVI文件中的JUNK块为数据对齐而存在,应用程序应该忽略JUNK块的内容。


  AVI-1中只有一个流(DVdatastream),其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结构。
  AVIRIFF文件格式只规定了文件的组成方式,即各种数据如何在文件中排列等,对于文件中的数据并没有做出编码格式的约束,如MPEG-1、DivX等都可以作为文件中数据的编码格式。数据也可以未经压缩。AVI文件可以看成是一个数据容器,AVI格式只规定了将数据装入这个容器的方法,但对数据本身的编码格式并不涉及。要操作一个AVI文件(播放、抓图、编辑),必须在系统中安装与该AVI文件中的编码器对应的解码器,才能进行正确的工作。
  
  4AVI-2文件格式的例
  
  下面以AVI文件bfh.avi(风景介绍片)为例,将该AVI文件打开,逐字节解释其中的数据(见图1):
  52494646RIFF的ASCII码;7E443400是文件长度,高位字节在后,(0034447E) 16,(3425406) 10;41564920是AVI◇的ASCII码,◇表示空格;表示RIFF块(文件)的数据类型是AVI。4C495354LIST的ASCII码,表示这是一个列表。10h开始的4字节表示本列表长度,(132) 16,(306) 10。接着6864726Chdrl的ASCII码,表明这是hdrl列表,61766968avih的ASCII码,表明这是hdrl列表中的avih块,第二行最后4字节是16进制的38,十进制的56;表示avih块的长度是56个字节(加上8正好是AVIMAINHEADER结构的长度),接下来的56个字节就是avih的内容,描述AVI文件的整体信息,AVIMAINHEADER结构中各个字段的内容不再分析,avih块到057h结束。
  从0058h开始的4C495354LIST的ASCII码,其后4字节(74) 16,即(116) 10是本列表的大小。60h开始的7374726Cstrl的ASCII码,表示这是strl(流)列表,从64h到a3h的64个字节是一个AVISTREAMHEADER结构;64h开始的73747268strh的ASCII码,表示这是strl列表中strh块(流的头信息);下面的4字节是strh块的大小(38) 16,十进制的56,76696473vids的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后释放。首先使用MFCAppWizard创建一个名为avi的单文档项目,然后重载CDocument类的虚函数OnOpenDocument,在此函数中打开AVI文件,读出其中的视频帧,存储为BMP文件并在屏幕上加以显示(在VC 6.0中调试通过):
  [newpage]  
  BOOLCAviDoc::OnOpenDocument(LPCTSTRlpszPathName)
  {if(!CDocument::OnOpenDocument(lpszPathName))returnFALSE;
  AVIFileInit();[JY]//初始化
  AVIFileOpen(&pAviFile,lpszPathName,OF_SHARE_DENY_WRITE,0l);[JY]//打开AVI文件
  AVIFileGetStream(pAviFile,&pAviStream,streamtypeVIDEO,0L);[JY]//打开流
  AVIStreamInfo(pAviStream,&aviStrInfo,sizeof(AVISTREAMINFO));[JY]//获取流的信息
  longlStreamSize;[JY]//流格式长度
  pBmpInfoH=newBITMAPINFOHEADER;[JY]//pBmpInfoH是文档类的成员变量
  AVIStreamFormatSize(pAviStream,0,&lStreamSize);[JY]//获取流的格式信息的长度
  AVIStreamReadFormat(pAviStream,0L,pBmpInfoH,&lStreamSize);
  PGETpgf;
  pgf=AVIStreamGetOpen(pAviStream,NULL);[JY]//为解压帧做准备
  [JY]//解压读出第0帧,紧缩DIB的数据以返回值pData为起始地址
  pData=(LPBYTE)AVIStreamGet(pgf,0L);[JY]//文档类的成员变量,类型为LPBYTE
  pBmpInfoH->biCompression=0;
  BITMAPFILEHEADERbmpFH;[JY]//位图文件头
  bmpFH.bfType=0x4d42;
  bmpFH.bfSize=bmpInfoH.biWidth*bmpInfoH.biHeight*3 54;
  bmpFH.bfReserved1=0;bmpFH.bfReserved2=0;
  bmpFH.bfOffBits=54;
  CFileDialogdlg(FALSE);[JY]//获取用户要存储成的位图文件名和路径
  if(IDOK==dlg.DoModal())str.Format("s",dlg.GetPathName());
  CFilebmp(str,C:modeWrite|C:modeCreate);
  bmp.Write(&bmpFH,sizeof(BITMAPFILEHEADER));[JY]//写入位图文件头
  bmp.WriteHuge(pData,bmpFH.bfSize-14);[JY]//写入紧缩DIB
  bmp.Close();AVIFileExit();
  UpdateAllViews(NULL);[JY]//更新视图,在视图类的OnDraw函数中显示位图
  returnTRUE;
  }//程序中省略所有安全性检查语句。位图的显示在视类的OnDraw函数(略)中。
  图2是程序执行的结果:从bfh.avi中提取的第0帧转换成的位图的显示。
  上面程序中pAviFile,pAviStream,aviStrInfo都是文档类的成员变量,类型分别为PAVIFILE,PAVISTREAM,AVISTREAMINFO。在文档类的构造函数中将所有指针初始化为NULL。还可以循环调用函数AVIStreamFindNextKey寻找所有的关键帧加以显示并存储为BMP文件。需要注意,函数AVIStreamGet返回的是一个“紧缩DIB”的地址,即以一个位图的BITMAPINFOHEADER开始的地址,且所需的缓冲区由该函数自己开辟,不需应用程序动态申请。程序要加入#i nclude,且在Project->Settings->Link中键入vfw32.lib。
  
  6结语
  
  由于Windows是很流行的操作系统,AVI是Microsoft公司大力支持的格式,因此在编写基于Windows操作系统的流媒体图像处理程序方面,AVI占有不可替代的位置。准确理解AVI文件格式以及针对AVI文件的编程方法在工程实践中具有重要的意义。AVI-1文件格式由于占用存储空间小,受到DirectShow的支持,其将来会成为AVI文件中最流行的格式。
  
  参考文献
  [1]姜楠,王健.常用多媒体文件格式压缩标准解析[M].北京:电子工业出版社,2005.
  [2]DirectXDocumentationforC [EB/OL].MicrosoftCorporation,2005.
  [3]陆其明.DirectShow开发指南[M].北京:清华大学出版社,2003.
  
  注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。
  (作者:徐殿武-字数:3302)

(徐殿武)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201004/8983.html]
本文出处:网络博客 作者:徐殿武
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容