LVF转换AVI经验谈
这几天的时间都花在了研究LVF和AVI文件格式的细节,并自己做了一个LVF文件转换AVI文件的小程序。界面比较丑,主要是为了实现功能。

在做格式转换的时候,比较好的通用的做法应该是将源文件的数据流依次取出,然后配置目标文件。然而,由于本次学习的目的在于熟悉LVF和AVI的文件结构,所以降低了这方面的要求,而是通过读取LVF文件信息进行AVI信息的部分填充。当然,为了更好的了解这两种文件格式,我在实现的过程中完全没有参考任何现有的借口或者代码。而是通过,两个简单介绍文件格式的文档,以及一个LVF文件和一个AVI文件完成了目标。
文件格式介绍的文档能够帮助我对文件大致的结构进行认识,以及一些必要的STRUCT进行说明。然而,仅靠文档说明是不能对细节进行了解的,从而LVF和AVI文件的作用则是帮助我确定具体结构的偏移地址,并帮助理解一些结构的参数是如何来配置的。
关于AVI文件格式
AVI文件的介绍我找了许多文档,下面就推荐一篇我认为还不错的文章。http://wenku.baidu.com/view/63fdd12d2af90242a895e5f1.html这篇文档已经非常详细了,所以这里不做累述。不过我需要补充的是,也是我在做的过程中遇到的一些问题:
1.
大家在现有的avi文件中可能可以看到一些JUNK信息,而且JUNK一般出现在信息块和数据块之间,对于应用程序来说不用理会JUNK,它是一段垃圾数据。所以,我们在自己写avi文件的时候,可以数据块紧跟信息块,JUNK并不是必须的。当然,JUNK在某些场合也是有用的,比如在这里可以放一些旧的数据信息。
2.
在我作为参照的AVI文件中,BITMAPINFO结构中并没有颜色表属性,从而我在写自己的AVI文件的时候也没有写颜色表,而是直接使用了BITMAPINFOHEADER代替BITMAPINFO。从而我怀疑颜色表可能是针对文中所介绍的bmp图片而所需的属性,而在做这种视频数据的时候可以忽略甚至缩减这个结构。
3.
这篇文章分为“AVI文件格式”和“利用VC++实现AVI文件的合成和分解”读者可以发现这两部分在结构上有细小的区别。比如第一部分的AVIMAINHEADER和第二部分中的MainAVIHeader,后者少了FOURCC
fcc; DWORD cb;这两个属性。其实如第一部分所说,它将块封装为:ckID ckSize
ckData ;那么显然第二部分其实只是将块分为ckHead和ckData两个部分,ckHead = {ckID,
ckSize},而ckData在例子中就是MainAVIHeader了。所以在使用MainAVIHeader、BITMAPINFO或者WAVEFORMAT的时候记得在这些结构前面需要添加ckHead。
关于AVI的参数
知道使用Windows的AVI接口的话,有许多参数可以缺省由其自动生成,然而对于我这种“傻瓜式”的fwrite方法来说,就需要对一些参数有具体的了解。那么下面就挑几个我认为可能会带来困难的参数来介绍一下,同者在调试过程中发现可以缺省的参数以简化初学者的参数配置:
1.
结构MainAVIHeader的参数:
DWORD
dwMicroSecPerFrame
//
=1000000/帧率
DWORD
dwMaxBytesPerSec;
// 可以缺省为0
DWORD
dwPaddingGranularity; //
可以缺省为0
DWORD
dwSuggestedBufferSize; // 可以缺省为0
2.
结构AVIStreamHeader的参数:
FOURCC
fccHandler; // 对于视频流为’x264’,音频流可为空
WORD
wLanguage; // 可以缺省为0
DWORD
dwLength; // 流的总数/ dwScale
3.
结构WAVEFORMAT的参数
WORD
wFormatTag;
// = WAVE_FORMAT_PCM = 0x11
4.
数据块的四字符码
大家都知道表征音频数据块的四字符码为‘##wb’,表征视频数据块的四字符码为‘##db’或
‘##dc’。然而在LVF文件中只有‘##dc’,那么对于I帧写入AVI的时候需要将其定义为‘##db’,
其他仍然为‘##dc’。
5.
索引的偏移地址
对于刚接触视频文件格式的人来说,大家一开始肯定都认为数据块的偏移地址是相对于文件头的。
但是当我读取一个现有AVI文件的索引后,惊奇得发现,偏移地址是从‘movi’开始计算的,也即第
一个数据块的偏移地址是4。
关于LVF文件格式
由于LVF文件格式大多使用在视频摄像领域,在这里不做详细介绍。
大致体系框架如下:
|
lvf_chunk_header_t ={ ‘LVFF’, sizeof( lvf_main_header_t) }
|
|
lvf_main_header_t
|
有多少个流就有多少个 lvf_stream_header_t
lvf_stream_info_t
占用1KB
|
|
lvf_stream_header_t
|
|
lvf_stream_info_t
|
|
lvf_stream_header_t
|
|
lvf_stream_info_t
|
|
…
|
|
stream_format ‘##fm’
|
视频:chunk+ lvf_bitmap_header_t
音频:chunk+ lvf_wave_format_t
占用1KB
|
|
stream_format ‘##fm’
|
|
….
|
|
Stream_data ‘##wb’
|
chunk+ frame_head_t+流数据
视频:‘##dc’
音频:‘##wb’
|
|
stream_data ‘##dc’
|
|
…
|
|
index_data ‘##ix’
|
与AVI只有一个索引并且记录每一帧不同
LVF给每一个流都创建了一个索引
而且索引中只记录关键帧的信息
|
|
index_data ‘##ix’
|
|
…
|
-----------------------------------------------------------------------------------------------
Write By Jacky Zhou
2010 - 8 - 10
加载中,请稍候......