转自:http://blog.youkuaiyun.com/laolei1986/archive/2010/07/13/5730241.aspx
一、基于VFW的摄像头视频捕捉程序
#include <vfw.h>
#pragma comment(lib, "Vfw32.lib")
初始化操作
1、创建捕获窗口
函数 capCreateCaptureWindow() 返回视频捕获窗口,它是所有捕获工作及设置的基础,其主要功能包括:
① 动态地同视频和音频输入器连接或断开;
② 设置视频捕获速率;
③ 提供视频源、视频格式以及是否采用视频压缩的对话框;
④ 设置视频采集的显示模式为Overlay或为Preview;
⑤ 实时获取每一帧视频数据;
⑥ 将一视频流和音频流捕获并保存到一个AVI文件中;
⑦ 捕获某一帧数字视频数据,并将单帧图像以DIB格式保存;
⑧ 指定捕获数据的文件名,并能将捕获的内容拷贝到另一文件。
HWND m_hCapWnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);
2、关联窗体到本程序实例
capSetUserData(m_hCapWnd, this);
m_hCapWnd窗口句柄相当于vfw捕获活动的基础,他就代表了这个捕获。
3、登记回调函数
登记回调函数用来实现用户的一些特殊需要。在以一些实时监控系统或视频会议系统中,需要将数据流在写入磁盘以前就必须加以处理,达到实时功效。应用程序可用捕获窗来登记回调函数,以便及时处理以下情况:捕获窗状态改变、出错、使用视频或音频缓存、放弃控制权等,相应的回调函数分别为 capStatusCallback(), capErrorCallback(), capVideoStreamCallback(), capWaveStreamCallback(),capYieldCallback()。
例如,设置回调函数:
capSetCallbackOnVideoStream(m_hCapWnd, OnCaptureVideo);
4、获得安装的捕获驱动程序的名称和版本
capGetDriverDescription(iIndex, szDevName, MAX_PATH, szDevVersion, MAX_PATH);
szDevName和szDevVersion返回当前第iIndex个设备的设备名称和版本。
5、连接捕获窗口与视频捕获卡
capDriverConnect(m_hCapWnd, iIndex);
6、获取捕获窗口的缺省参数
CAPTUREPARMS CapParms = {0};
capCaptureGetSetup(m_hCapWnd, &CapParms, sizeof(CapParms));
7、修改刚刚获得的参数
CapParms.fAbortLeftMouse = FALSE; // 退出鼠标设置
CapParms.fAbortRightMouse = FALSE; // ...
CapParms.fYield = TRUE; // 使用背景作业
CapParms.fCaptureAudio = FALSE; // 不获取声音
CapParms.wPercentDropForError = 50; // 允许遗失的百分比
8、设置捕获窗口的相关参数
capCaptureSetSetup(m_hCapWnd, &CapParms, sizeof(CapParms));
9、获得视频的格式、大小
capGetVideoFormat(m_hCapWnd, &m_BmpInfo, sizeof(m_BmpInfo));
10、更改视频的尺寸
m_BmpInfo.bmiHeader.biWidth = 176;
m_BmpInfo.bmiHeader.biHeight = 144;
11、设置新的视频属性
capSetVideoFormat(m_hCapWnd, &m_BmpInfo, sizeof(m_BmpInfo))
(不更改视频尺寸或者设置属性不正确运行时会出错!)
开始捕获(不使用磁盘存储的捕获)
12、初始化Dib
HDRAWDIB m_hDib = ::DrawDibOpen();
13、开始绘制Dib
::DrawDibBegin(m_hDib,
m_hDC,
-1, // don't stretch
-1, // don't stretch
&m_BmpInfo.bmiHeader,
IMAGE_WIDTH, // width of image
IMAGE_HEIGHT, // height of image
0);
14、开始捕获
capCaptureSequenceNoFile(m_hCapWnd);
结束退出
15、结束绘制Dib,关闭Dib:
::DrawDibEnd(m_hDib);
::DrawDibClose(m_hDib);
清除采集过程
16、停止采集过程
capCaptureAbort(m_hCapWnd);
17、使回调函数无效
capSetCallbackOnVideoStream(m_hCapWnd, NULL);
18、断开与设备的连接
capDriverDisconnect(m_hCapWnd);
在回调函数中的操作
19、关联数据到一个捕获窗体
CVideoCapture *vidcap=(CVideoCapture *)capGetUserData(hwnd);
注意其返回一个当前实例指针!因为其参数是通过回调函数参数传递而来的m_hCapWnd。
20、回放
::DrawDibDraw(m_hDib,
m_hDC,
m_szLocalOffset.cx, // dest : left pos
m_szLocalOffset.cy, // dest : top pos
m_szLocalView.cx, // don't zoom x
m_szLocalView.cy, // don't zoom y
&m_BmpInfo.bmiHeader, // bmp header info
data, // bmp data
0, // src :left
0, // src :top
IMAGE_WIDTH, // src : width
IMAGE_HEIGHT, // src : height
DDF_SAME_DRAW); // use prev params....
没用到的:
获取采集设备的功能和状态:
通过宏capDriverGetCaps(hWndCap,&m_CapDrvCap,sizeof(CAPDRIVERCAPS))来获取视频设备的能力,通过宏capGetStatus(hWndCap,&m_CapStatus,sizeof(m_CapStatus))来获取视频设备的状态。
示例程序代码:http://download.youkuaiyun.com/source/2940975
VFW的详细使用说明请参考:
谈谈使用VFW在windows下编程控制摄像头http://blog.youkuaiyun.com/suntaoznz/archive/2005/08/06/447067.aspx
二、AVICap回调函数
回调函数示例: LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr) {...}
LPVIDEOHDR 是结构体VIDEOHDR的指针,而在MSDN中察看结构体VIDEOHDR,我们就可以找到桢数据的存贮位置指针了。
VIDEOHDR定义如下:
typedef struct videohdr_tag {
LPBYTE lpData;
DWORD dwBufferLength;
DWORD dwBytesUsed;
DWORD dwTimeCaptured;
DWORD dwUser;
DWORD dwFlags;
DWORD_PTR dwReserved[4];
} VIDEOHDR, NEAR *PVIDEOHDR, FAR * LPVIDEOHDR;
看到结构体中第一个参数了么?这个就是我们想要的桢数据的指针!后面参数,包括缓冲区长度等。
你的应用程序可以为一个捕获窗口注册一些回调函数,它们可以告诉你的应用程序一些变化。比如捕获状态发生变化了,或者有错误发生了,音视频缓存区可使用了。下面的消息设置回调函数。
消 息
说 明
WM_CAP_SET_CALLBACK_CAPCONTROL
CapSetCallbackOnCapControl 宏
在应用程序中指定回调函数用于控制捕获的开始和结束。
WM_CAP_SET_CALLBACK_ERROR
CapSetCallbackOnError 宏
在应用程序中指定回调函数,当出错的时候就调用它。
WM_CAP_SET_CALLBACK_FRAME
CapSetCallbackOnFrame 宏
在应用程序中指定回调函数,当预览图像帧被捕获了的时候就调用它。
WM_CAP_SET_CALLBACK_STATUS
CapSetCallbackOnStatus 宏
在应用程序中指定回调函数,当状态(status)改变的时候就调用它。
WM_CAP_SET_CALLBACK_VIDEOSTREAM
CapSetCallbackOnVideoStream 宏
在应用程序中指定回调函数,在流捕获期间,当一个新的视频缓存区可用的时候就调用它。
WM_CAP_SET_CALLBACK_WAVESTREAM
CapSetCallbackOnWaveStream 宏
在应用程序中指定回调函数,在流捕获期间,当一个新的音频缓存区可用的时候就调用它。
WM_CAP_SET_CALLBACK_YIELD
CapSetCallbackOnYield 宏
在应用程序中指定回调函数,在流捕获期间Yielding(产生?)
三、预览模式的流程:
m_hVideo=::capCreateCaptureWindow("Me",WS_CHILD | WS_VISIBLE,
0,0,500,500,m_hWnd,0); //参数m_hWnd是你的工程中对话框的句柄,窗口类中都有这个成员变量,而对话框的类是窗口类的子类
//capSetCallbackOnFrame(m_hVideo, FrameCallbackProc); //回调函数
capDriverConnect(m_hVideo,0); //连接设备0
capPreviewRate(m_hVideo, 40); // 设置Preview模式的显示速率
capPreview(m_hVideo, TRUE); //启动Preview模式
capPreview(hVideo, FALSE); // 屏蔽预览
capDriverDisconnect(hVideo);//将捕获窗同驱动器断开
四、保存为文件
下例使用capFileSetCaptureFile宏来指定一个要命名的文件名(mycap.avi),使用capFileAlloc宏去预分配5MB的文件。
char szCaptureFile[] = "MYCAP.AVI";
capFileSetCaptureFile( m_capwnd, szCaptureFile);
capFileAlloc( m_capwnd, (1024L * 1024L * 5));*/
或者使用capCaptureSequence宏开始视频捕获,使用capFileSaveAs宏从捕获文件拷贝数据到其他文件NEWFILE.AVI中。
char szNewName[] = "NEWFILE.AVI";
// Set up the capture operation.
capCaptureSequence(hWndC);
// Capture.
capFileSaveAs(hWndC, szNewName);
Powered by Zoundry Raven