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

avi文件格式解析

2017-06-05 6页 doc 72KB 19阅读

用户头像

is_591137

暂无简介

举报
avi文件格式解析AVI格式解析   2008-10-13 19:31:40|  分类: 视频文件格式 |  标签: |字号大中小 订阅 AVI是音频视频交错(Audio Video Interleaved)的英文缩写,它是Microsoft公司开发的一种符合RIFF文件规范的数字音频与视频文件格式,原先用于Microsoft Video for Windows (简称VFW)环境,现在已被Windows 95/98、OS/2等多数操作系统直接支持。AVI格式允许视频和音频交错在一起同步播放,支持256色和RLE压缩,但AVI文件并未限定压缩...
avi文件格式解析
AVI格式解析   2008-10-13 19:31:40|  分类: 视频文件格式 |  标签: |字号大中小 订阅 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; //子块长度 }; ********************************************************************************************************************************************* 首先声明:本文的内容都是我从开发过程中总结出来的,以我的理解在尽可能短的篇幅里对 DV AVI 文件的分析作介绍。真要作开发还需要参考原始的文档。 AVI 文件总是以 12 个字节开始的,就是 'RIFF' + size + 'AVI '。这里 size 是一个 4 字节的整数,声明其后的字节数(包括'AVI '这4个字节数) 现在问就出来了,这样的格式就是限定了 size 的最大取值只能是 4G,后来人们就扩展了 AVI 的结构——当分析到声明的字节数后,如果后面是扩展格式,那么就继续分析。 扩展部分类似 AVI 的格式,只不过从 'AVI ' 变成了 'AVIX',而且可能有多个扩展部分。因此这一部分的分析代码就是: head = struct.unpack('<4sI4s', avifile.read(12)) if head[0] != 'RIFF' or head[2] != 'AVI ': return None while True: xread = readChunk(avifile, head[1]-4, 0) # 分析剩余的数据 s = avifile.read(12) if 0 == len(s): # 如果没有什么可读的了,自然是分析完了 break head = struct.unpack('<4sI4s', s) if head[0] != 'RIFF' or head[2] != 'AVIX': break 由于 AVI 内部嵌套的数据块的格式也类似 4bytes info + size + data 这样的结构,因此 readChunk 被设计成一个递归函数,返回值为 0 或 -1,中途解析失败就返回 -1,根据此返回值退出嵌套调用。(回过头来看这样一段程序,递归调用分析的可读性很糟糕,主要是因为开始编程的时候对 Python 没有太多的认识所致) 可能是为了便于编程,各个数据块被设计成 4 字节对齐的,但 data 的大小未必是 4 的整数倍,从文件中读出来的 size 只是表示 data 的长度,有时候必须计算对齐。下面两行语句就是作这个的: page = (head[1] - 1)/4 chunksize = (page + 1) * 4 为了便于播放器去 seek 一个特定的位置,比如从文件的第 12 分 32 秒开始播放,需要一个索引可以快速定位到相应的数据。这就是 'idx1' chunk 里面定义的东东。但传统的定义里面偏移量最大只能为 4G,因此扩展格式里面增加了 super index,或者说 index 的 index,里面可以放 longlong 的 64 位整数来避免这种寻址困境,估计在我有生之年都不会有这么大个的数据文件问世。 readChunk 函数的主要功能就是生成一个 index 列表,然后从这个列表的最前面和最后面分别 seek 到相应的数据存储区域,找出时间码。如果发现 AVI 里面有 super index,就在 readChunk 返回后,再根据 super index 生成 index 列表。程序里面这个列表变量名为 offset 分析 DV 格式获取时间的函数是 readtime。DV 可能是每次记录 12000 字节数据(类似磁盘扇区的概念??),因此在每 12000 字节数据里面都会存储一个时间码。我的当时参考的代码里面在每个 index 指向的数据块里循环了 15 次还是 10 次,但我发现我这里只能循环 12 次就碰到了数据的尽头,后来估计是 PAL/NTSC 的差异,也就没有继续追究下去。
/
本文档为【avi文件格式解析】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索