AVI视频的合成和分解方法VC++实现Word文件下载.docx
- 文档编号:21721892
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:16
- 大小:58.39KB
AVI视频的合成和分解方法VC++实现Word文件下载.docx
《AVI视频的合成和分解方法VC++实现Word文件下载.docx》由会员分享,可在线阅读,更多相关《AVI视频的合成和分解方法VC++实现Word文件下载.docx(16页珍藏版)》请在冰豆网上搜索。
的LIST块,包含AVI的音视频序列数据。
3、索引块,ID为"
idxl"
的子块,定义"
LIST块的索引数据,是可选块。
AVI文件的结构如下图所示,下面将具体介绍AVI文件的各子块构造。
1、信息块,信息块包含两个子块,即一个ID为avih的子块和一个ID为strl的LIST块。
信息块
"
avih"
子块的内容可由如下的结构定义:
typedefstruct
{
DWORDdwMicroSecPerFrame;
//显示每桢所需的时间ns,定义avi的显示速率
DWORDdwMaxBytesPerSec;
//最大的数据传输率
DWORDdwPaddingGranularity;
//记录块的长度需为此值的倍数,通常是2048
DWORDdwFlages;
//AVI文件的特殊属性,如是否包含索引块,音视频数据是否交叉存储
DWORDdwTotalFrame;
//文件中的总桢数
DWORDdwInitialFrames;
//说明在开始播放前需要多少桢
DWORDdwStreams;
//文件中包含的数据流种类
DWORDdwSuggestedBufferSize;
//建议使用的缓冲区的大小,
//通常为存储一桢图像以及同步声音所需要的数据之和
DWORDdwWidth;
//图像宽
DWORDdwHeight;
//图像高
DWORDdwReserved[4];
//保留值
}MainAVIHeader;
strl"
LIST块用于记录AVI数据流,每一种数据流都在该LIST块中占有3个子块,他们的ID分别是"
strh"
"
strf"
"
strd"
;
"
子块由如下结构定义。
FOURCCfccType;
//4字节,表示数据流的种类vids表示视频数据流
//auds音频数据流
FOURCCfccHandler;
//4字节,表示数据流解压缩的驱动程序代号
DWORDdwFlags;
//数据流属性
WORDwPriority;
//此数据流的播放优先级
WORDwLanguage;
//音频的语言代号
DWORDdwInitalFrames;
//说明在开始播放前需要多少桢
DWORDdwScale;
//数据量,视频每桢的大小或者音频的采样大小
DWORDdwRate;
//dwScale/dwRate=每秒的采样数
DWORDdwStart;
//数据流开始播放的位置,以dwScale为单位
DWORDdwLength;
//数据流的数据量,以dwScale为单位
//建议缓冲区的大小
DWORDdwQuality;
//解压缩质量参数,值越大,质量越好
DWORDdwSampleSize;
//音频的采样大小
RECTrcFrame;
//视频图像所占的矩形
}AVIStreamHeader;
子块紧跟在"
子块之后,其结构视"
子块的类型而定,如下所述;
如果strh子块是视频数据流,则strf子块的内容是一个与windows设备无关位图的BIMAPINFO结构,如下:
typedefstructtagBITMAPINFO
BITMAPINFOHEADERbmiHeader;
RGBQUADbmiColors[1];
//颜色表
}BITMAPINFO;
typedefstructtagBITMAPINFOHEADER
DWORDbiSize;
LONGbiWidth;
LONGbiHeight;
WORDbiPlanes;
WORDbiBitCount;
DWORDbiCompression;
DWORDbiSizeImage;
LONGbiXPelsPerMeter;
LONGbiYPelsPerMeter;
DWORDbiClrUsed;
DWORDbiClrImportant;
}BITMAPINFOHEADER;
如果strh子块是音频数据流,则strf子块的内容是一个WAVEFORMAT结构,如下:
WORDwFormatTag;
WORDnChannels;
//声道数
DWORDnSamplesPerSec;
//采样率
DWORDnAvgBytesPerSec;
//WAVE声音中每秒的数据量
WORDnBlockAlign;
//数据块的对齐标志
WORDbiSize;
//此结构的大小
}WAVEFORMAT
子块紧跟在strf子块后,存储供压缩驱动程序使用的参数,不一定存在,也没有固定的结构。
LIST块定义的AVI数据流依次将"
hdrl"
LIST块中的数据流头结构与"
LIST块中的数据联系在一起,第一个数据流头结构用于数据流0,第二个用于数据流1,依次类推。
数据块中存储视频和音频数据流,数据可直接存于"
LIST块中。
数据块中音视频数据按不同的字块存放,其结构如下所述,
音频字块
"
##wb"
Wave数据流
视频子块中存储DIB数据,又分为压缩或者未压缩DIB,
##db"
RGB数据流
"
##dc"
压缩的图像数据流
看到了吧,avi文件的图像数据可以是压缩的,和非压缩格式的。
对于压缩格式来说,也可采用不同的编码,也许你曾经遇到有些avi没法识别,就是因为编码方式不一样,如果没有相应的解码,你就没法识别视频数据。
AVI的编码方式有很多种,比较常见的有mpeg2,mpeg4,divx等。
索引块,索引快包含数据块在文件中的位置索引,能提高avi文件的读写速度,其中存放着一组AVIINDEXENTRY结构数据。
如下,这个块并不是必需的,也许不存在。
DWORDckid;
//记录数据块中子块的标记
//表示chid所指子块的属性
DWORDdwChunkOffset;
//子块的相对位置
DWORDdwChunkLength;
//子块长度
};
现在我相信你肯定会对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函数将我们的多媒体数据写入数据流了。
这个函数将应用程序提供的内存数据复制到指定的流。
缺省的avihandler将数据写入流的最后。
如果你有其他额外的信息需要写入流,你可以调用AVIFileWriteData或者AVIStreamWriteData,最后记得在完成数据写入后,要调用AVIStreamRelease。
9、数据流中的祯的位置
寻找起始祯:
可以通过AVIStreamStart函数来获取第一祯包含的samplenumber。
也可以通过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文件。
voidCbmp2aviDlg:
:
AVItoBmp(CStringstrAVIFileName,CStringstrBmpDir)
//TODO:
在此添加控件通知处理程序代码
AVIFileInit();
PAVIFILEavi;
intres="
AVIFileOpen"
(&
avi,strAVIFileName,OF_READ,NULL);
intn=GetLastError();
if(res!
=AVIERR_OK)
{
//anerroroccures
if(avi!
=NULL)
AVIFileRelease(avi);
return;
}
AVIFILEINFOavi_info;
AVIFileInfo(avi,&
avi_info,sizeof(AVIFILEINFO));
PAVISTREAMpStream;
res=AVIFileGetStream(avi,&
pStream,streamtypeVIDEO/*videostream*/,
0/*firststream*/);
if(pStream!
AVIStreamRelease(pStream);
AVIFileExit();
//dosometaskwiththestream
intiNumFrames;
intiFirstFrame;
iFirstFrame=AVIStreamStart(pStream);
if(iFirstFrame==-1)
//Errorgetteingtheframeinsidethestream
AVIFileExit();
iNumFrames=AVIStreamLength(pStream);
if(iNumFrames==-1)
//Errorgetteingthenumberofframesinsidethestream
//gettingbitmapfromframe
BITMAPINFOHEADERbih;
ZeroMemory(&
bih,sizeof(BITMAPINFOHEADER));
bih.biBitCount=24;
//24bitperpixel
bih.biClrImportant=0;
bih.biClrUsed=0;
bih.biCompression=BI_RGB;
bih.biPlanes=1;
bih.biSize=40;
bih.biXPelsPerMeter=0;
bih.biYPelsPerMeter=0;
//calculatetotalsizeofRGBQUADscanlines(DWORDaligned)
bih.biSizeImage=(((bih.biWidth*3)+3)&
0xFFFC)*bih.biHeight;
PGETFRAMEpFrame;
pFrame=AVIStreamGetFrameOpen(pStream,NULL);
AVISTREAMINFOstreaminfo;
AVIStreamInfo(pStream,&
streaminfo,sizeof(AVISTREAMINFO));
//Getthefirstframe
BITMAPINFOHEADERbih2;
longlsize=sizeof(bih2);
intindex="
0"
;
for(inti="
iFirstFrame"
i<
iNumFrames;
i++)
index=i-iFirstFrame;
BYTE*pDIB=(BYTE*)AVIStreamGetFrame(pFrame,index);
//
AVIStreamReadFormat(pStream,index,&
bih2,&
lsize);
BITMAPFILEHEADERstFileHdr;
BYTE*Bits="
new"
BYTE[bih2.biSizeImage];
AVIStreamRead(pStream,index,1,Bits,bih2.biSizeImage,NULL,NULL);
//RtlMoveMemory(Bits,pDIB+sizeof(BITMAPINFOHEADER),bih2.biSizeImage);
bih2.biClrUsed=0;
stFileHdr.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
stFileHdr.b
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AVI 视频 合成 分解 方法 VC 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)