1.引言
视频的采集和压缩是进行视频传输、监控等视频应用开发时必须采取的步骤。
关于视频采集,本文探讨了一种基于Windows平台的简单而实用的方法,利用微软提供的VFW(Video For Windows)软件包来实现,只需要有一般的USB摄像头,就可以方便地对视频进行采集和保存。
视频压缩方面,本文探讨了如何利用现阶段压缩率最大、传输可靠性最高的一种编码标准—H.264标准的开源编码器(T264)来实现对采集到的视频文件进行压缩的方法,利用VFW 所采集到的视频格式是没有进行任何压缩的AVI 格式,首先对AVI 格式进行转换,再利用T264源码对转换后的视频流文件进行压缩编码,这样就极大地压缩了视频文件,方便视频的传输。
2.视频信息的采集
由于利用VFW软件包能够方便地实现视频、音频数据流到AVI文件的存储,在Visual C++中将VFW软件包的函数封装成为AVICAP窗口类函数,利用AVICAP窗口类函数,程序员能够通过发送消息或设置属性来捕获、播放和编辑视频剪辑,能灵活地实现从模拟视频源采集数字视频信号,并将捕捉的视频流存储到磁盘或者直接对视频缓存进行处理。
本文所述的方法是在Viusal C++ 6.0 软件平台上实现的,而软件实现的具体步骤如下:
1)在采集视频前必须先创建一个视频采集的窗口,以及添加一些具体的操作按钮,窗口利用函数capCreateCaptureWindow 来创建,如果窗口创建成功,返回窗口的句柄(程序中hwndV),如果创建不成功,则返回NULL 值。具体的创建程序及注释如下:
hwndV=capCreateCaptureWindow(
(LPSTR) "My Capture Window", //捕捉窗口名称
WS_CHILD | WS_VISIBLE, //窗口风格样式
150, 150, 300, 280, //窗口位置和大小
(HWND) hwndMain, //父窗口句柄
(int) 1); //窗口标识
2)采集开始前,要将采集窗口与视频设备相关联,VFW接口采用capDriverConnect (hWndCap,,nIndex)这个函数,式中:hWndCap所建立的视频捕捉窗口的句柄;nIndex为查询得到的视频卡驱动程序的索引号。接下来,获取视频采集设备的能力及状态信息,VFW中采用函数capDriverGetCaps(hwnd,psCaps,wsize)来得到采集设备的能力,而采用capGetStatus (hwnd,s,size)函数来得到采集设备的状态信息。
3)启动显示模式并设置其模式参数,AVICAP 窗口类采用两个函数来实现,具体程序和注释如下:
capPreviewRate( hwndVideo, 66); //设置预览播放速率
capreview( hwndVideo, TRUE); //启动预览模式
4)采集视频流并保存,并终止视频采集并断开与采集设备的连接,在程序的开头定义一个结构体OPENFN,用于初始化一个对话框,而这个对话框是用来保存视频的对话框。
具体程序如下:
if (!isRecordFileOpen)
{
OPENFN ofname; //打开文件结构体
ZeroMemory(&ofname, sizeof(OPENFN)); //初始化结构体
ofname.lStructSize = sizeof(OPENFN); //结构体的大小
ofname.hwndOwner = hwndMain; //主窗口句柄
ofname.lpstrFile = recordFile; //保存的文件指针
ofname.nMaxFile = sizeof(recordFile); //保存文件的大小
ofname.lpstrFilter = "Video\0*.avi"; //保存文件的后缀
ofname.nFilterIndex = 1; //文件索引号
ofname.lpstrFileTitle = NULL; //文件名指针
ofname.nMaxFileTitle = 0;
ofname.lpstrInitialDir = NULL;
ofname.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
if(GetSaveFileName(&ofn) == TRUE) //显示保存文件的对话框
{
strcpy(recordFile, ofn.lpstrFile);
strcat(recordFile, ".avi");
isRecordFileOpen = true;
}
}
设置好保存文件以后,需用函数CreateThread来创建一个录像的线程在其中采集视频流,并利用函数capDriverDisconnect 来终止视频采集并断开与采集设备的连接,录像线程的具体代码如下:
DWORD id; //创建一个录像线程
SECURITY_ATTRIBUTES ma;
ma.nLength = sizeof(SECURITY_ATTRIBUTES);
ma.lpSecurityDescriptor = NULL;
ma.bInheritHandle = TRUE;
hVideoThread = (&ma, (ULONG)0,
videoThreadProc, (LPVOID)(ULONG)0, (ULONG)0, &id);
3.视频格式的转换
本文所采用的是基于H.264编码标准的视频压缩方法,所利用的源码是由中国视频编码自由组织联合开发的t264编×××,在使用本源码前,编码器要求进行压缩的文件格式应为YUV 格式视频文件,而VFW采集到的视频文件是最原始的AVI 格式,因而要进行格式的转换 。
从AVI格式到YUV 格式的转换,并没有直接的公式,而AVI视频文件流的每一帧对应一个BMP(RGB)文件,则可以利用公式转换成YUV 文件,转换的公式如下:
Y = 0.299R + 0.587G + 0.114B
Cb = 0.564(B - Y )
Cr = 0.713(R -Y )
其中,Cb 对应U,Cr 对应V,分别表示构成彩色的两个分量,而在程序中,则通过以下的程序来实现(按4:2:0 采样格式):
void RGB2YUV ( uint8 R, uint8 G, uint8 B, uint8 *y, uint8 *u, uint8 *v )
{
*y = Clip ( ( ( 66 * int(R) + 129 * int(G) + 25 * int(B) + 128) >> 8) + 16 );
*u = Clip ( ( ( -38 * int(R) - 74 * int(G) + 112 * int(B) + 128) >> 8) + 128 );
*v = Clip ( ( ( 112 * int(R) - 94 * int(G) - 18 * int(B) + 128) >> 8) + 128 );
}
4.利用编码器进行压缩编码
由中国视频编码自由组织联合开发的编码器在基于VisualC++平台上创建了一个console程序,而前述的视频采集程序因为有窗口、按钮等视图窗口,故是一个windows程序,在Visual C++平台中,要将console 程序和windows 程序很好地结合在一起使用,是个很复杂的过程,因此,可以在前面视频采集程序里面运用一个C++函数ShellExecute 来调用编码器函数。
具体实现的步骤如下:
1)首先针对采集后经格式转换生成的YUV文件,得到它的帧数目,在配置文件enconfig.txt修改编码帧的数目,例如如果帧数目为100,将enconfig.txt 文件中的第6、7、8 行:
300 # total frame number
300 # i intervals
300 # idr intervals
改为 :
100 # total frame number
100 # i intervals
100 # idr intervals
帧数目修改以后,文件生成的路径也应该改为最终exe 文件生成的路径,在enconfig.txt的最后三行进行修改。
1)编译编码器,是采用的CONSOLE 程序,一般是在命令行中来执行exe 程序,而本文中的方法是利用入口函数main(int argc, char* argv[])的特征,其中,argc 表示参数的个数,而argv[]数组用于保存参数的指针,在程序中就对参数进行赋值,省去了进入命令行进行执行的繁琐过程,从而生成一个可以直接拿来运用的exe 程序。具体赋值语句如下:
argv[0]="T264.exe";
argv[1]="-e";
argv[2]="enconfig.txt";
2)设置t264.exe 文件路径,上述的过程中已经生成一个可执行的t264.exe 文件,如果将YUV文件放在与之相同的目录下,在调试运行这个程序的时候就可以生成264码流文件,达到编码的目的。但本文是需要将采集、压缩编码在同一个程序中完成,因而把生成的t264.exe文件复制到采集程序的调试目录下面。
3)上述的工作都做好以后,可以在采集程序里面调用编码器程序了,这时用一个函数来实现,具体代码是:
ShellExecute(NULL,"open","t264.exe",
"T264.exe –e enconfig.txt",NULL,SW_SHOWNORMAL);
其中,SW_SHOWNORMAL 指的是一种程序运行风格,此时代表正常运行,在调用时可以看到程序运行的全部过程(DOS命令窗口显示),如果需要程序透明执行,不可见,则可以用SW_HIDE 来代替它。
至此,整个视频采集、格式转换与编码压缩的过程就全部完成了,本文中所采集的AVI文件大小为4.075M,经格式转换后的YUV 文件大小为5.458M,而最终生成的264 码流大小只有27k,压缩率达到了150.9倍。
5.总结
本文所探讨的从视频采集、格式转换到压缩编码的整个过程,可以简单方便地完成,可以直接应用在视频监控或者视频的网络传输等的前期开发。佰锐科技已为视频监控音视频即时通讯提供了解决方案。http://www.bairuitech.com
对于本博客有任何问题的朋友可加Q:992139738