开发环境: Win7 + VS2008 + VFW
一. 最基础的调用
1.1 初始化
BOOL CMyDlg::Init()
{
// HWND m_hWndVideo;
// 创建捕捉窗口
m_hWndVideo = capCreateCaptureWindow(
_T("abcd"), // 窗口名称
WS_POPUP, // Windows窗口的属性
1, 1, 10, 10, // 窗口的位置和大小
0, // 父窗口
0 // 我这里使用0, 如果是非0, 就创建失败, 不知为什么.
);
// 连接设备.
// 在Win7下, capDriverConnect有时会调用失败, 所以需要使用一个循环来知道调用成功为止.
// 当然, 最好加上挑除循环的判断, 否则在没有插入摄像头时, 会死循环.
while(FALSE == (capDriverConnect(m_hWndVideo, 0)))
{
Sleep(10);
}
m_bCapture=TRUE;
// 设置视频窗口的一些属性, 这些都是Windows窗口的一些属性
// 不设置也可以, 看你的需求.
::SetParent(m_hWndVideo, *this);
::SetWindowLong(m_hWndVideo, GWL_STYLE,WS_CHILD);
// 设置位置
CRect m_rect;
m_panel.GetClientRect(m_rect);
m_panel.MapWindowPoints(this,m_rect);
m_rect.DeflateRect(1,1,1,1);
::SetWindowPos(m_hWndVideo,NULL,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height(),SWP_NOZORDER);
// 显示窗口
::ShowWindow(m_hWndVideo, SW_SHOW);
return true;
}
1.2 播放视频
void CMyDlg::OnBtnPreview()
{
// TODO: Add your control notification handler code here
if(m_bCapture)
{
// 播放前, 一定要设置帧率, 否则不能播放
capPreviewRate(m_hWndVideo, 15); // 设置预览帧频率 每15ms播放一帧
capPreviewScale(m_hWndVideo, TRUE); // 预览帧缩放有效,视频大小缩放至显示窗口大小
capPreview(m_hWndVideo, TRUE);
}
else
{
MessageBox("设备链接失败,无法预览");
}
}
1.3 停止播放
void CMyDlg::OnCancel()
{
m_bCapture = FALSE;
capPreview(m_hWndVideo, TRUE);
capCaptureStop(m_hWndVideo);
capDriverDisconnect(m_hWndVideo);
CDialog::OnCancel();
}
二. 使用回调模式
在”一最基础的调用”中, 我们只能看到视频, 但通常我们需要对视频帧进行处理, 此时需要使用回调方式, 回调方式就是每一帧会触发我们定义的回调函数, 对帧或者其他做一些处理. 我没有很深入的研究VFW的回调方式, 反正使用下面的方式是实现了, 可能不是最好的方式.
2.1 设置帧回调函数
static LRESULT __stdcall FrameCallBackFun(HWND hWnd, LPVIDEOHDR lpVHdr)
{
int i = 0;
return 0;
}
BOOL CMyDlg::Init()
{
<span style="white-space:pre"> </span>......
<span style="white-space:pre"> </span>capSetCallbackOnFrame(m_hWndVideo, FrameCallBackFun);
}
A. VIDEOHDR保存了帧的数据.
三. 遇到的困难
3.1 在Win7下, capDriverConnect有时调用成功, 有时调用失败, 所以加了一个循环来连接设备, 直到连接成功.
3.2 在Win7下, VFW枚举设备, 只枚举到一个, 如果插入两个摄像头, 不知怎么做.
3.3 在帧回调函数中返回的帧数据是YUV2的格式, 通常我们需要把YUV2格式转成RGB格式.
BITMAPINFO bitmapInfo;
memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
nT = capGetVideoFormatSize(hWndVideo);
capGetVideoFormat(hWndVideo, &bitmapInfo, sizeof(BITMAPINFO));
返回的bitmapInfo.bmiHeader.biCompression值就是844715353, 这就是YUV2格式(844715353就是字符"YUV2")
3.4 帧回调函数返回的帧数据格式, 不知道是不是与摄像头有关还是回调中总是返回YUV2格式.
VFW控制摄像头代码:
http://download.csdn.net/detail/cay22/8631271
YUV2转RGB24文章:
引用:
http://www.xuebuyuan.com/1852220.html
http://www.cnblogs.com/lidabo/p/3701954.html
http://www.cnblogs.com/kangwang1988/archive/2011/03/19/1989066.html
http://blog.sina.com.cn/s/blog_48f198e901000ajo.html
http://blog.csdn.net/wangqing008/article/details/12127103