为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

avi文件格式

2012-10-19 20页 doc 175KB 108阅读

用户头像

is_916688

暂无简介

举报
avi文件格式1. 从(00000000-000007F3)为一个WindowsAVI文件的信息区部分。 它是文件的第一个LIST块。在它的内部记录着整个文件的系统构成,如告诉播放软件“我是一个AVI文件”“在我的体内有几个数据流”“每个数据流包含着什么数据类型——图像、声音或其他”“如果是图像数据流,那么它的大小、颜色、压缩方式、播放速度等,等是怎样规定的”“如果是声音数据流,那么它的压缩方式、播放效果等等又将有何规定”......在信息区中还有多个附属的LIST块,也就是我们前面提到的“子块”,它们用来记录每个数据流的全部信息。而这些附...
avi文件格式
1. 从(00000000-000007F3)为一个WindowsAVI文件的信息区部分。 它是文件的第一个LIST块。在它的内部记录着整个文件的系统构成,如告诉播放软件“我是一个AVI文件”“在我的体内有几个数据流”“每个数据流包含着什么数据类型——图像、声音或其他”“如果是图像数据流,那么它的大小、颜色、压缩方式、播放速度等,等是怎样规定的”“如果是声音数据流,那么它的压缩方式、播放效果等等又将有何规定”......在信息区中还有多个附属的LIST块,也就是我们前面提到的“子块”,它们用来记录每个数据流的全部信息。而这些附间LIST块与数据流之间保持着—一对应的关系,即 第一个附属LIST块对应于00号数据流第二个附属LIST块对应于01号数据流......要想解释数据流,我们必须先了解AVI文件中数据块是什么。在AVI文件中,数据块是被放置在数据区中的一个有起始标志(由“数据流识别码”和“数据块存储方式识别码"组成,请参见对数据区部分的说明),并指明大小和数据内容的数据段.那么,数据流就是那些相互之间具有联系的同种数据类型的数据块集合. 00000000-00000003多媒体文件识别码:RIFF 00000004-00000007文件大小(10EDICh字节)-8字节 00000008-0000000BAVI文件识别码 0000000C-0000000F第一个LIST块识别码 00000010-00000013第一个LIST块的大小(168h字节) 00000014-00000017hdrl部分识别码,以下数据记录着此文件的格式 00000018-0000001Bhdrl部分所包含的avih块识别码,此模块记录着本文件的初始化信息 0000001C-0000001Favih块大小(38h字节) 00000020-00000023每帧画面显示所维持多少个百万分之一秒,本例为1046Bh,即66667百万分之一秒,约0.07秒。所以在播放此文件时,你看到的画面约每秒15帧 小知识:AVI文件格式----摘自《DirectShow实务精选》 作者:陆其明   AVI(Audio Video Interleaved的缩写)是一种RIFF(Resource Interchange File Format的缩写)文件格式,多用于音视频捕捉、编辑、回放等应用程序中。通常情况下,一个AVI文件可以包含多个不同类型的媒体流(典型的情况下有一个音频流和一个视频流),不过含有单一音频流或单一视频流的AVI文件也是合法的。AVI可以算是Windows操作系统上最基本的、也是最常用的一种媒体文件格式。 先来介绍RIFF文件格式。RIFF文件使用四字符码FOURCC(four-character code)来征数据类型,比如‘RIFF’、‘AVI ’、‘LIST’等。注意,Windows操作系统使用的字节顺序是little-endian,因此一个四字符码‘abcd’实际的DWORD值应为0x64636261。另外,四字符码中像‘AVI ’一样含有空格也是合法的。 RIFF文件首先含有一个如图3.31的文件头结构。 图3.31 RIFF文件结构   最开始的4个字节是一个四字符码‘RIFF’,表示这是一个RIFF文件;紧跟着后面用4个字节表示此RIFF文件的大小;然后又是一个四字符码说明文件的具体类型(比如AVI、WAVE等);最后就是实际的数据。注意文件大小值的计算方法为:实际数据长度 + 4(文件类型域的大小);也就是说,文件大小的值不包括‘RIFF’域和“文件大小”域本身的大小。 RIFF文件的实际数据中,通常还使用了列表(List)和块(Chunk)的形式来组织。列表可以嵌套子列表和块。其中,列表的结构为:‘LIST’ listSize listType listData ——‘LIST’是一个四字符码,表示这是一个列表;listSize占用4字节,记录了整个列表的大小;listType也是一个四字符码,表示本列表的具体类型;listData就是实际的列表数据。注意listSize值的计算方法为:实际的列表数据长度 + 4(listType域的大小);也就是说listSize值不包括‘LIST’域和listSize域本身的大小。再来看块的结构:ckID ckSize ckData ——ckID是一个表示块类型的四字符码;ckSize占用4字节,记录了整个块的大小;ckData为实际的块数据。注意ckSize值指的是实际的块数据长度,而不包括ckID域和ckSize域本身的大小。(注意:在下面的内容中,将以LIST ( listType ( listData ) )的形式来表示一个列表,以ckID ( ckData )的形式来表示一个块,如[ optional element ]中括号中的元素表示为可选项。) 接下来介绍AVI文件格式。AVI文件类型用一个四字符码‘AVI ’来表示。整个AVI文件的结构为:一个RIFF头 + 两个列表(一个用于描述媒体流格式、一个用于保存媒体流数据) + 一个可选的索引块。AVI文件的展开结构大致如下:   RIFF (‘AVI ’       LIST (‘hdrl’             ‘avih’(主AVI信息头数据)             LIST (‘strl’                   ‘strh’ (流的头信息数据)                   ‘strf’ (流的格式信息数据)                   [‘strd’ (可选的额外的头信息数据) ]                   [‘strn’ (可选的流的名字) ]                   ...                  )              ...            )       LIST (‘movi’             { SubChunk | LIST (‘rec ’                               SubChunk1                               SubChunk2                               ...                              )                ...             }             ...            )       [‘idx1’ (可选的AVI索引块数据) ]      )   首先,RIFF (‘AVI ’…)表征了AVI文件类型。然后就是AVI文件必需的第一个列表——‘hdrl’列表,用于描述AVI文件中各个流的格式信息(AVI文件中的每一路媒体数据都称为一个流)。‘hdrl’列表嵌套了一系列块和子列表——首先是一个‘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;   然后,就是一个或多个‘strl’子列表。(文件中有多少个流,这里就对应有多少个‘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数据结构来描述。 当AVI文件中的所有流都使用一个‘strl’子列表说明了以后(注意:‘strl’子列表出现的顺序与媒体流的编号是对应的,比如第一个‘strl’子列表说明的是第一个流(Stream 0),第二个‘strl’子列表说明的是第二个流(Stream 1),以此类推),‘hdrl’列表的任务也就完成了,随后跟着的就是AVI文件必需的第二个列表——‘movi’列表,用于保存真正的媒体流数据(视频图像帧数据或音频采样数据等)。那么,怎么来组织这些数据呢?可以将数据块直接嵌在‘movi’列表里面,也可以将几个数据块分组成一个‘rec ’列表后再编排进‘movi’列表。(注意:在读取AVI文件内容时,建议将一个‘rec ’列表中的所有数据块一次性读出。)但是,当AVI文件中包含有多个流的时候,数据块与数据块之间如何来区别呢?于是数据块使用了一个四字符码来表征它的类型,这个四字符码由2个字节的类型码和2个字节的流编号组成。标准的类型码定义如下:‘db’(非压缩视频帧)、‘dc’(压缩视频帧)、‘pc’(改用新的调色板)、‘wb’(音缩视频)。比如第一个流(Stream 0)是音频,则表征音频数据块的四字符码为‘00wb’;第二个流(Stream 1)是视频,则表征视频数据块的四字符码为‘00db’或‘00dc’。对于视频数据来说,在AVI数据序列中间还可以定义一个新的调色板,每个改变的调色板数据块用‘xxpc’来表征,新的调色板使用一个数据结构AVIPALCHANGE来定义。(注意:如果一个流的调色办中途可能改变,则应在这个流格式的描述中,也就是AVISTREAMHEADER结构的dwFlags中包含一个AVISF_VIDEO_PALCHANGES标记。)另外,文字流数据块可以使用随意的类型码表征。 最后,紧跟在‘hdrl’列表和‘movi’列表之后的,就是AVI文件可选的索引块。这个索引块为AVI文件中每一个媒体数据块进行索引,并且记录它们在文件中的偏移(可能相对于‘movi’列表,也可能相对于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标记。 还有一种特殊的数据块,用一个四字符码‘JUNK’来表征,它用于内部数据的队齐(填充),应用程序应该忽略这些数据块的实际意义。 利用VC++实现AVI文件的合成和分解 摘要:本文详细的解析了AVI文件的存储结构,介绍了微软提供的用来操作AVI文件的一组API使用方法,并通过例子代码,演示了如何将一组静态Bmp图片合成一个avi视频文件以及如何将一个avi视频文件解析保存为一系列的bmp图像文件。   关键词:avi文件 bmp图像 vc   AVI是音频视频交错(Audio Video Interleaved)的英文缩写,它是Microsoft公司开发的一种符合RIFF文件规范的数字音频与视频文件格式,原先用于Microsoft Video for Windows (简称VFW)环境,现在已被Windows 95/98、OS/2等多数操作系统直接支持。AVI格式允许视频和音频交错在一起同步播放,支持256色和RLE压缩,但AVI文件并未限定压缩标准,因此,AVI文件格式只是作为控制界面上的标准,不具有兼容性,用不同压缩算法生成的AVI文件,必须使用相应的解压缩算法才能播放出来。常用的AVI播放驱动程序,主要是Microsoft Video for Windows或Windows 95/98中的Video 1,以及Intel公司的Indeo Video。   在介绍AVI文件前,我们要先来看看RIFF文件结构。AVI文件采用的是RIFF文件结构方式,RIFF(Resource Interchange File Format,资源互换文件格式)是微软公司定义的一种用于管理windows环境中多媒体数据的文件格式,波形音频wave,MIDI和数字视频AVI都采用这种格式存储。构造RIFF文件的基本单元叫做数据块(Chunk),每个数据块包含3个部分,   1、4字节的数据块标记(或者叫做数据块的ID)   2、数据块的大小   3、数据   整个RIFF文件可以看成一个数据块,其数据块ID为RIFF,称为RIFF块。一个RIFF文件中只允许存在一个RIFF块。RIFF块中包含一系列的子块,其中有一种字块的ID为"LIST",称为LIST,LIST块中可以再包含一系列的子块,但除了LIST块外的其他所有的子块都不能再包含子块。   RIFF和LIST块分别比普通的数据块多一个被称为形式类型(Form Type)和列表类型(List Type)的数据域,其组成如下:   1、4字节的数据块标记(Chunk ID)   2、数据块的大小   3、4字节的形式类型或者列表类型   4、数据   下面我们看看AVI文件的结构。AVI文件是目前使用的最复杂的RIFF文件,它能同时存储同步表现的音频视频数据。AVI的RIFF块的形式类型是AVI,它包含3个子块,如下所述:   1、信息块,一个ID为"hdrl"的LIST块,定义AVI文件的数据格式。   2、数据块,一个ID为 "movi"的LIST块,包含AVI的音视频序列数据。   3、索引块,ID为 "idxl"的子块,定义 "movi"LIST块的索引数据,是可选块。   AVI文件的结构如下图所示,下面将具体介绍AVI文件的各子块构造。   1、信息块,信息块包含两个子块,即一个ID为 avih 的子块和一个ID 为 strl 的LIST块。   "avih"子块的内容可由如下的结构定义: typedef struct {  DWORD dwMicroSecPerFrame ; //显示每桢所需的时间ns,定义avi的显示速率  DWORD dwMaxBytesPerSec; // 最大的数据传输率  DWORD dwPaddingGranularity; //记录块的长度需为此值的倍数,通常是2048  DWORD dwFlages; //AVI文件的特殊属性,如是否包含索引块,音视频数据是否交叉存储  DWORD dwTotalFrame; //文件中的总桢数  DWORD dwInitialFrames; //说明在开始播放前需要多少桢  DWORD dwStreams; //文件中包含的数据流种类  DWORD dwSuggestedBufferSize; //建议使用的缓冲区的大小,  //通常为存储一桢图像以及同步声音所需要的数据之和  DWORD dwWidth; //图像宽  DWORD dwHeight; //图像高  DWORD dwReserved[4]; //保留值 }MainAVIHeader;   "strl" LIST块用于记录AVI数据流,每一种数据流都在该LIST块中占有3个子块,他们的ID分别是"strh","strf", "strd"; "strh"子块由如下结构定义。 typedef struct {  FOURCC fccType; //4字节,表示数据流的种类 vids 表示视频数据流  //auds 音频数据流  FOURCC fccHandler;//4字节 ,表示数据流解压缩的驱动程序代号  DWORD dwFlags; //数据流属性  WORD wPriority; //此数据流的播放优先级  WORD wLanguage; //音频的语言代号  DWORD dwInitalFrames;//说明在开始播放前需要多少桢  DWORD dwScale; //数据量,视频每桢的大小或者音频的采样大小  DWORD dwRate; //dwScale /dwRate = 每秒的采样数  DWORD dwStart; //数据流开始播放的位置,以dwScale为单位  DWORD dwLength; //数据流的数据量,以dwScale为单位  DWORD dwSuggestedBufferSize; //建议缓冲区的大小  DWORD dwQuality; //解压缩质量参数,值越大,质量越好  DWORD dwSampleSize; //音频的采样大小  RECT rcFrame; //视频图像所占的矩形 }AVIStreamHeader;   "strf"子块紧跟在"strh"子块之后,其结构视"strh"子块的类型而定,如下所述;如果 strh子块是视频数据流,则 strf子块的内容是一个与windows设备无关位图的BIMAPINFO结构,如下: typedef struct tagBITMAPINFO {  BITMAPINFOHEADER bmiHeader;  RGBQUAD bmiColors[1]; //颜色表 }BITMAPINFO; typedef struct tagBITMAPINFOHEADER {  DWORD biSize;  LONG biWidth;  LONG biHeight;  WORD biPlanes;  WORD biBitCount;  DWORD biCompression;  DWORD biSizeImage;  LONG biXPelsPerMeter;  LONG biYPelsPerMeter;  DWORD biClrUsed;  DWORD biClrImportant; }BITMAPINFOHEADER;   如果 strh子块是音频数据流,则strf子块的内容是一个WAVEFORMAT结构,如下: typedef struct {  WORD wFormatTag;  WORD nChannels; //声道数  DWORD nSamplesPerSec; //采样率  DWORD nAvgBytesPerSec; //WAVE声音中每秒的数据量  WORD nBlockAlign; //数据块的对齐标志  WORD biSize; //此结构的大小 }WAVEFORMAT   "strd"子块紧跟在strf子块后,存储供压缩驱动程序使用的参数,不一定存在,也没有固定的结构。   "strl" LIST块定义的AVI数据流依次将 "hdrl " LIST 块中的数据流头结构与"movi" LIST块中的数据联系在一起,第一个数据流头结构用于数据流0,第二个用于数据流1,依次类推。   数据块中存储视频和音频数据流,数据可直接存于 "movi" LIST块中。数据块中音视频数据按不同的字块存放,其结构如下所述,   音频字块     "##wb"     Wave 数据流   视频子块中存储DIB数据,又分为压缩或者未压缩DIB,     "##db"     RGB数据流     "##dc"   压缩的图像数据流   看到了吧,avi文件的图像数据可以是压缩的,和非压缩格式的。对于压缩格式来说,也可采用不同的编码,也许你曾经遇到有些avi没法识别,就是因为编码方式不一样,如果没有相应的解码,你就没法识别视频数据。AVI的编码方式有很多种,比较常见的有 mpeg2,mpeg4,divx等。 索引块,索引快包含数据块在文件中的位置索引,能提高avi文件的读写速度,其中存放着一组AVIINDEXENTRY结构数据。如下,这个块并不是必需的,也许不存在。 typedef struct {  DWORD ckid; //记录数据块中子块的标记  DWORD dwFlags; //表示chid所指子块的属性  DWORD dwChunkOffset; //子块的相对位置  DWORD dwChunkLength; //子块长度 };   现在我相信你肯定会对AVI的文件结构已经很清楚了,在介绍完了AVI文件结构后,我们就来看看如何对avi文件进行读写了,为了对avi进行读写,微软提供了一套API,总共50个函数,他们的用途主要有两类,一个是avi文件的操作,一类是数据流streams的操作。   1、打开和关闭文件   AVIFileOpen ,AVIFileAddRef, AVIFileRelease   2、从文件中读取文件信息   通过AVIFileInfo可以获取avi文件的一些信息,这个函数返回一个AVIFILEINFO结构,通过AVIFileReadData可以用来获取AVIFileInfo函数得不到的信息。这些信息也许不包含在文件的头部,比如拥有file的公司和个人的名称。   3、写入文件信息   可以通过AVIFileWriteData函数来写入文件的一些额外信息。   4、打开和关闭一个流   打开一个数据流就跟打开文件一样,你可以通过 AVIFileGetStream函数来打开一个数据流,这个函数创建了一个流的接口,然后在该接口中保存了一个句柄。   如果你想操作文件的某一个单独的流,你可以采用AVIStreamOpenFromFile函数,这个函数综合了AVIFileOpen和AVIFileGetStream函数。   如果你想操作文件中的多个数据流,你就要首先AVIFileOpen,然后AVIFileGetStream。   可以通过AVIStreamAddRef来增加stream接口的引用。   通过AVIStreamRelease函数来关闭数据流。这个函数用来减少streams的引用计数,当计数减少为0时,删除。   5、从流中读取数据和信息   AVIStreamInfo函数可以获取数据的一些信息,该函数返回一个AVISTREAMINFO结构,该结构包含了数据的类型压缩方法,建议的buffersize,回放的rate,以及一些description。   如果数据流还有一些其它的额外的信息,你可以通过AVIStreamReadData函数来获取。应用程序分配一个内存,传递给这个函数,然后这个函数会通过这个内存返回数据流的信息,额外的信息可能包括数据流的压缩和解压缩的方法,你可以通过AVIStreamDataSize宏来回去需要申请内存块的大小。   可以通过AVIStreamReadFormat函数获取数据流的格式信息。这个函数通过指定的内存返回数据流的格式信息,比如对于视频流,这个buffer包含了一个BIMAPINFO结构,对于音频流,内存块包含了WAVEFORMATEX或者PCMAVEFORMAT结构。你可以通过给AVIStreamReadFormat传递一个空buffer就可以获取buffer的大小。也可以通过AVIStreamFormatSize宏。   可以通过AVIStreamRead函数来返回多媒体的数据。这个函数将数据复制到应用程序提供的内存中,对于视频流,这个函数返回图像祯,对于音频流,这个函数返回音频的sample数据。可以通过给AVIStreamRead传递一个NULL的buffer来获取需要的buffer的大小。也可以通过AVIStreamSampleSize宏来获取buffer的大小。   有些AVI数据流句柄可能需要在启动数据流的前要做一下准备工作,此时,我们可以调用AVIStreamBeginStreaming函数来告知AVI数据流handle来申请分配它需要的一些资源。在完毕后,调用AVIStreamEndStreamming函数来释放资源。   6、操作压缩的视频数据   如果你要演示一祯或者几祯压缩视频图像时,你可以调用AVIStreamRead函数,将获取的数据传递给DrawDib函数来显示图像。这些函数可以显示压缩和未压缩的图像。   AVIFile也提供了一个函数AVIStreamGetFrameOpen,来获取未压缩的视频祯,这个函数创建了内存来获取未压缩的数据。也可以通过AVIStreamGetFrame函数来解压缩一个单独的视频祯。这个函数可以解压缩某一祯图像,然后将数据以一个BIMAPINFOHEADER结构返回。当你调用完AVIStreamGetFrame函数后,要调用AVIStreamGetFrameClose函数释放上一个函数申请的资源。   7、根据已存在的数据流创建文件   创建一个包含多个数据流的文件的方法就是整合多个数据流,将其写入一个新文件。这些数据流可以是内存中的数据,也可以是存在于另一个文件中。   我们可以用AVISave这个函数来build一个文件。这个函数可以创建一个文件,并且将指定的多个数据流按照指定的顺序写入文件,你也可以通过AVISaveV函数来创建一个新的文件,这个函数的功能和AVISave的功能一样,主要区别是AVISaveV采用的数据流数组,而AVISave是单个的数据流,多次保存。   我们可以调用AVISaveOptions函数来显示一个对话框,可以让用户来选择压缩方式。   我们可以在调用AVISave和AVISaveV函数时指定一个回调函数,用来显示avi文件的生成进度,可以让用户随时地取消生成avi文件。   我们可以调用GetSaveFileNamePreview函数来显示保存的对话框让用户选择保存的文件名。   通过AVIMakeFileFromStreams函数我们可以创建一个虚拟的文件句柄,其他的avi函数可以通过这个虚拟的文件句柄来操作文件中的数据流,操作完毕要记得调用AVIFileRelease释放。 8、向文件写入一个数据流   我们可以通过AVIFileCreateStream函数来在一个新文件或者已经存在的文件中创建一个数据流。这个函数根据AVISTREAMINFO结构定义了新的数据流,并为新的数据流创建一个接口,返回接口的指针。   在写入新的数据前,一定要指定流的格式信息,通过AVIStreamSetFormat函数,当设置一个视频流的时候,一定要使用BIMAPINFO结构来设置,音频就用WAVEFORMAT。   然后我们就可以通过AVIStreamWrite函数将我们的多媒体数据写入数据流了。这个函数将应用程序提供的内存数据复制到指定的流。缺省的avi handler将数据写入流的最后。   如果你有其他额外的信息需要写入流,你可以调用AVIFileWriteData或者AVIStreamWriteData,最后记得在完成数据写入后,要调用AVIStreamRelease。   9、数据流中的祯的位置   寻找起始祯:   可以通过AVIStreamStart函数来获取第一祯包含的sample number。也可以通过AVIStreamInfo函数来获取这个信息,这个函数的AVISTREAMINFO结构中包含了dwStart,可以通过AVIStreamStartTime宏来获取第一个sample。   可以通过AVIStreamLength函数来获取流的长度。这个函数返回流中的sample的数目。也可以通过AVIStreamInfo函数来获取这些信息,可以通过AVIStreamLengthTime宏来获取流的长度,毫秒。   在视频流中,一个sample对应着一祯图像,所以,有时这些sample中没有视频数据,如果你调用AVIStreamRead函数来数据,可能返回NULL,也可以通过AVIStreamFindSample通过指定FIND_ANY标志来查找指定的sample。   查找关键祯   通过AVIStreamFindSample函数查找符合要寻找的sample,然后可以通过下面的宏判断是否关键祯。   在time和sample间互相切换。   AVIStreamSampleToTime这个函数可以将smaple转换成毫秒。对于视频,这个值代表的是这个祯开始播放的时间。   在了解了上面的知识后,我们对avi的文件结构以及如何操作avi文件心里就明白了,下面我们可以开始我们的编程了。我们要做两件事情:   1、如何将一组静态的bmp位图合成一个avi的视频文件;   2、如何将一个未压缩的avi文件解析成一幅幅位图。   示例程序界面如下:   下面的函数演示了如何将一个文件夹下面的所有bmp文件都保存为一个avi文件,函数的第一个参数是要生成的AVI的文件名,第二个参数是存放bmp文件的文件夹名,这个函数会枚举该文件夹下的所有bmp文件,合成一个AVI文件。 void Cbmp2aviDlg::AVItoBmp(CString strAVIFileName, CString strBmpDir) {  // TODO: 在此添加控件通知处理程序代码  AVIFileInit();  PAVIFILE avi;  int res=AVIFileOpen(&avi, strAVIFileName, OF_READ, NULL);  int n = GetLastError();  if (res!=AVIERR_OK)  {   //an error occures   if (avi!=NULL)    AVIFileRelease(avi);   return ;  }  AVIFILEINFO avi_info;  AVIFileInfo(avi, &avi_info, sizeof(AVIFILEINFO));  PAVISTREAM pStream;  res=AVIFileGetStream(avi, &pStream, streamtypeVIDEO /*video stream*/,    0 /*first stream*/);  if (res!=AVIERR_OK)  {   if (pStream!=NULL)    AVIStreamRelease(pStream);    AVIFileExit();   return ;  }  //do some task with the stream  int iNumFrames;  int iFirstFrame;  iFirstFrame=AVIStreamStart(pStream);  if (iFirstFrame==-1)  {   //Error getteing the frame inside the stream   if (pStream!=NULL)    AVIStreamRelease(pStream);   AVIFileExit();   return ;  }  iNumFrames=AVIStreamLength(pStream);  if (iNumFrames==-1)  {   //Error getteing the number of frames inside the stream   if (pStream!=NULL)    AVIStreamRelease(pStream);   AVIFileExit();   return ;  }  //getting bitmap from frame  BITMAPINFOHEADER bih;  ZeroMemory(&bih, sizeof(BITMAPINFOHEADER));  bih.biBitCount=24; //24 bit per pixel  bih.biClrImportant=0;  bih.biClrUsed = 0;  bih.biCompression = BI_RGB;  bih.biPlanes = 1;  bih.biSize = 40;  bih.biXPelsPerMeter = 0;  bih.biYPelsPerMeter = 0;  //calculate total size of RGBQUAD scanlines (DWORD aligned)  bih.biSizeImage = (((bih.biWidth * 3) + 3) & 0xFFFC) * bih.biHeight ;  PGETFRAME pFrame;  pFrame=AVIStreamGetFrameOpen(pStream, NULL );  AVISTREAMINFO streaminfo;  AVIStreamInfo(pStream,&streaminfo,sizeof(AVISTREAMINFO));  //Get the first frame  BITMAPINFOHEADER bih2;  long lsize = sizeof(bih2);  int index=0;  for (int i=iFirstFrame; i
/
本文档为【avi文件格式】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索