摘 要:提出并实现了使用AVI文件存储XVID压缩视频流的方案,网络视频监控服务器将采集的视频图像利用XVID进行视频编码,存储系统将压缩视频流以通用AVI文件格式存储,以便检索和查询。
关键词:AVI;XVID视频编解码器;视频存储;视频播放
How to Design Recording System in Network Camera Video Server Based on AVI
Li Qunlin
(College of Electrical and Information Engineering of Hunan University, Changsha 410082)
Abstract: A Rcording System in a Network Camera Video Server which is designed with AVI files, The Video Server uses the XVID MPEG-4 Video Codec to compress image data, Then the Recording System saves the compressed video data in AVI files for query later.
Keywords: AVI;XVID MPEG-4 Video Codec;Video Record;Video Play
1. 网络视频监控系统介绍
随着Internet和宽带网络技术的日益发展,具有视频和音频的多媒体内容服务即将成为主流。同时,各种高效压缩解压算法的提出,为多媒体信息在网络上进行传输提供了可能。网络视频监控以直观、方便、信息内容丰富等特点被广泛应用于许多场合。
图1 网络视频监控系统结构图
网络视频监控系统是一个基于客户机/服务器模型的系统,由视频服务器端和客户端组成。视频服务器是一个由SAA7113、PNX1301、RTL8139等组成的嵌入式系统,SAA7113实现视频的采集; PNX1301是系统的核心,对视频数据进行处理,如视频编码、报警检测、云镜控制等;RTL8139负责数据传输,数据通过网络与客户端交互。
客户端是一台通用计算机,客户端有选择性地连接单个或者多个服务器,经过身份验证后可以向监控服务器发送命令,从监控服务器获取压缩视频流和其他测量数据,从而实现远程视频监控。
系统采用XVID视频编解码器对图像数据进行压缩,因为XVID开放源码,可以将它移植到PNX1301的PSOS操作系统中,对图像数据进行编码;客户端计算机从网络接收压缩的视频数据,使用相同版本的XVID解码器解码,即可得到图像数据。
2. XVID视频压缩格式
2.1. XVID的特点
XVID支持多种编码模式,除了最原始单重估定码流压缩(1-pass CBR)之外,XVID提供了包括:单重质量模式动态码流压缩、单重量化(Quantization)模式动态码流压缩、和包括外部控制和内部控制的两种双重(2-pass)动态码流压缩模式。
XVID的运动侦测(Motion Search)特性,为需要高码流的运动画面可以分配更多空间、更高的码流、更低的量化幅度来保持画面的细节;而对于不包含太多运动信息的静态画面,则消减分配预算。这是XVID做为第二代MPEG4编码的核心内容。
XVID支持动态关键帧距(I-frame interval)和B帧,即双向预测帧。此外还支持心理视觉亮度修正、演员表选项。画面优化解码等。
2.2. XVID的编解码实现方法
XVID源码有三部分构成:xvidcore、vfw、dshow,可以用Microsoft Visual C++和NASM编译。本文使用Microsoft Visual C++ 2003.net和NASM-0.98.39编译成功,其中编译dshow项目还需要安装DirectX 9.0 SDK。
xvidcore工程生成XVID编解码器的API函数库:xvidcore.dll;vfw工程生成XVID编解码器在Windows下的安装文件:xvidvfw.dll和xvid.inf;dshow生成XVID在Windows下注册文件:xvid.ax。
图2 XVID库函数的调用过程
由于本文的XVID编码部分在PNX1301中实现,在此只介绍XVID的解码部分。
1) 加载xvidcore.dll库函数
使用XVID的API函数需要加载xvidcore.dll库,并包含vfw.h和xvid.h头文件,调用API函数的方法如下:
HINSTANCE m_hdll = LoadLibrary("xvidcore.dll");
xvid_global_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_global");
xvid_decore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_decore");
2) 初始化编解码器
xvid_global_func(0, XVID_GBL_INIT, &init, NULL);
3) 创建解码器
int length = xvid_decore_func(0, XVID_DEC_CREATE, &create, NULL);
4) 结果输出设置
xvid_dec_frame_t结构是解码的主要参数,其中输出部分需要设置输出缓冲区、步长和输出类型,在颜色深度是24位的情况下,RGB格式的数据步长为图像宽度的3倍。
frame.output.plane[0] = ostream;
frame.output.stride[0] = CALC_BI_STRIDE(width, 24);
frame.output.csp = XVID_CSP_VFLIP | XVID_CSP_BGR;
5) 解码
int length = xvid_decore_func(dhandle, XVID_DEC_DECODE, &frame, &stats);
3. 利用AVI格式存储视频
AVI(Audio Video Interleaved的缩写)是一种RIFF(Resource Interchange File Format的缩写)文件格式,用于音视频捕捉、编辑、回放等应用程序中。通常情况下,一个AVI文件可以包含多个不同类型的媒体流(典型的情况下有一个音频流和一个视频流),不过含有单一音频流或单一视频流的AVI文件也是合法的。AVI可以算是Windows操作系统上最基本的、也是最常用的一种媒体文件格式。
3.1. AVI视频文件结构
图3 AVI文件结构
'avih':文件信息(AVIFILEINFO格式),'strh' :数据流信息(AVISTREAMINFO格式),'strf' :格式化信息(BITMAPINFO格式)。
3.2. 安装XVID编解码器
在Windows下使用XVID编解码器,需要安装XVID编解码器。安装需要前面提到xvidcore 和vfw项目生成的三个文件xvidcore.dll 、xvidvfw.dll和xvid.inf,使用方法是右键点击xvid.inf文件选择“安装”命令即可。
3.3. 存储AVI视频文件
微软提供了一套API对AVI文件进行读写,使用这些库函数需要在程序中加载vfw32.lib库和vfw.h头文件。本文的对AVI文件的操作都使用此库中的函数。
如果要对数据流进行压缩,可以使用AVISaveOptions和AVIMakeCompressedStream函数,选择操作系统中已经安装的视频编解码器。由于本文从视频服务器得到的是已经编码的XVID格式数据流,所以不需要这个步骤。
图4 AVI读写过程
3.3.1. 获取原始数据
首先获取帧数据的长度,然后获取文件中的原始数据。
AVIStreamRead(pVideoStream, lFrames, AVISTREAMREAD_CONVENIENT, NULL, 0, &lSize, NULL);
AVIStreamRead(pVideoStream, lFrames, AVISTREAMREAD_CONVENIENT, pBuffer, lSize, NULL, NULL);
原始数据为压缩数据,可以直接调用XVID的API函数对其进行解码得到图像数据。
3.3.2. 获得RGB格式的数据
使用AVI的API函数可以直接自动调用XVID解码器,获得RGB格式的数据。
1) 获取格式化信息
先获取格式的大小,可由此判断数据流是视频流还是音频流。
AVIStreamReadFormat(pVideoStream, AVIStreamStart(pVideoStream), NULL, &lSize) ;
获取格式化信息内容,如果是视频流则转化为BITMAPINFO格式,即可获取格式化的具体信息,如图像的大小,压缩方式,颜色深度,缓冲区大小等。
AVIStreamReadFormat(pVideoStream, AVIStreamStart(pVideoStream), pChunk, &lSize) ;
LPBITMAPINFO pInfo = (LPBITMAPINFO)pChunk;
2) 设置结果的信息头
这里我们想得到RGB格式的数据流,原始数据格式为XVID格式,这里我们只需要改变原始格式的压缩方式和缓冲区大小就可以了。缓冲区的大小计算公式如下,它的大小和相同大小的BMP图像数据大小是相等的。
LPBITMAPINFOHEADER pBmpih = GetStreamFormat();
pBmpih->biCompression = BI_RGB;
pBmpih->biSizeImage = ((pBmpih->biWidth * pBmpih->biBitCount + 31)/32 * 4) * pBmpih->biHeight;
3) 获取RGB格式化数据流,如果pBmpih为空,将到原始数据
PGETFRAME pVideoFrame = AVIStreamGetFrameOpen(pVideoStream, pBmpih);
4) 获取RGB数据,获得的RGB数据包括40字节的图像格式信息
LPBYTE pImage = (LPBYTE)AVIStreamGetFrame(pVideoFrame, lFrames);
pImage = pImage + sizeof(BITMAPINFOHEADER);
3.4. AVI视频播放
如果操作系统没有安装XVID编解码器,播放器无法识别XVID格式的AVI文件。解决的方发是使用如上文的安装方法,或者使用dshow生成的xvid.ax注册文件。
注册方法是在命令行输入:
“<path to Windows>/system/regsvr32 <path to xvid.ax>/xvid.ax”
例如:“C:/windows/system/regsvr32 C:/Program Files/xvid.ax”,然后复制xvidcore.dll到“<path to Windows>/system32”,如:“C:/ windows /system32”。测试是否安装成功的方法是播放一段XVID片断,看播放器是否正常工作。
本文使用三种方法对播放XVID视频进行测试,都工作正常。一是利用xvidcore.dll 、xvidvfw.dll和xvid.inf,然后安装xvid.inf,使用Windows Media Player播放;二是xvidcore.dll和xvid.ax,注册xvid.ax,使用Windows Media Player播放;三是安装暴风影音,使用暴风影音的XVID编解码器,用暴风影音播放。
4. 结论
利用AVI文件存储XVID格式视频流完全可行,由于大部分播放器支持AVI格式,安装XVID编解码器后,用户可以选用自己喜欢的播放器播放视频监控系统的存储记录,运行稳定,使用方便。
源代码:http://download1.csdn.net/down3/20070618/18111759279.rar
参考文献
1. http://www.xvid.org/
2. How to Compile XviD with Microsoft Visual C++ 6.0, David Carroll, 11-23-2003, http://www.discdude.net/xvid/compile.html
3. Working With AVI files, Jonathan Nix, http://www.gamedev.net/reference/programming/features/avifile/
4. Microsoft Visual C++.NET 技术内幕(第6版),(美)谢菲德(Shepherd G.) 潘爱民译,清华大学出版社
作者介绍
姓名:李群林
性别:男
职称:研究生
研究方向:测试计量技术与仪器
邮政编码:410082
地址:湖南大学电气与信息工程学院
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gooseli/archive/2006/08/28/1131210.aspx