刚刚做了一个利用VFW(Video For Windows)的视频采集程序,就想写出来,给需要的人分享一下。程序并不复杂,关键是在没人指导的情况下,学习是比较痛苦和漫长的过程,我经历了这个过程,如果大家想避免走弯路,直接看我下面的解释就好了。由于我仅仅作出了结果,对很多东西的理解也许并不完全正确或者是完全错误,愿请指教。提前说一句,我的程序是在Visual C++6.0平台下写的。下面我慢慢说,你也慢慢听。

1 什么是VFW
    VFW 是微软的一个软件包,至少可以用来开发视频采集程序,当然还有别的用处,但不是我想关心的。VFW提供了基于消息的接口,而这些接口,也可以利用它本省定义的宏来实现。
2 怎么使用VFW
    写之前提示一句,可以参照MSDN看下面的内容,一定会更好。
    (1)创建一个基于对话框的程序,工程名称Grasp
     因为要用VFW,所以要包含头文件
     可在GraspDlg.h中加入 #include<Vfw.h>,然后Project ->Settings,在link标签页的Object/library modules :里面加入Vfw32.lib

(2)在CGraspDlg类中添加一个窗口句柄HWND m_hVideo;
    (3)利用capCreateCaptureWindow函数创建窗口,并且得到返回的窗口句柄。
    m_hVideo=::capCreateCaptureWindow("Me",WS_CHILD | WS_VISIBLE,0,0,500,500,m_hWnd,0);

上面这个函数写在BOOL CGraspDlg::OnInitDialog()中。参数m_hWnd是你的工程中对话框的句柄,窗口类中都有这个成员变量,而对话框的类是窗口类的子类,记得?
    (4)用capSetCallbackOnFrame宏注册回调函数,也写在BOOL CGraspDlg::OnInitDialog()中。
    capSetCallbackOnFrame(m_hVideo, FrameCallbackProc);
    上面第二个参数是回调函数的地址,名字可以自己来定义,但是回调函数必须有如下参数和返回值。
    LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr);
    人家规定的,咱们也没办法,就照着写就好啦。
    解释一下,什么是回调函数呢,它有什么用处?
    回调函数,就是你自己写的函数,符合规定的参数和返回值类型,符合规定的调用约定,比如上面这个函数
就是回调函数,参数和返回值类型都是规定好的,调用约定为CALLBACK,CALLBACK其实是一个宏#define CALLBACK__stdcall满足一定条件时,此函数可以被系统自动调用,在回调函数当中,你可以写自己的代码完成一定功能。
    比如在这里,用capSetCallbackOnFrame(m_hVideo, FrameCallbackProc)注册后,当每得到一桢数据后,系统就调用函数FrameCallbackProc。
    (5)因为注册了回调函数,所以,当然要自己写出这个函数了。

在GraspDlg.cpp中,且在BOOL CGraspDlg::OnInitDialog()函数之前写下面代码:
     LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
    {
        if (!ghVideo)
            return FALSE;

return (LRESULT) TRUE ;
    }
    目前为止,该回调函数还没有什么作用,一会儿我们再来编写函数当中的代码,现在我就写的话,你也不见得看懂,不是么。一会儿写的话,你就可以轻松明白了。
    注意在这个函数中的ghVideo 了么?其实就和上面的m_hVideo一样,可是这里是全局函数,m_hVideo是对话框类的成员变量,
我写m_hVideo编译器是不认识的,对吧,所以,我又在GraspDlg.cpp当中定义了一个全局变量HWND ghVideo;并且,在m_hVideo=::capCreateCaptureWindow("Me",WS_CHILD | WS_VISIBLE,0,0,500,500,m_hWnd,0);之后加上一句ghVideo=m_hVideo; 这样就可以用ghVideo了。
    (6)在BOOL CGraspDlg::OnInitDialog()中继续添加如下代码:
    char szDeviceName[80];
    char szDeviceVersion[80];
    int wIndex;

for (wIndex = 0; wIndex < 10; wIndex++)
    {
        if (capGetDriverDescription (wIndex, szDeviceName,sizeof (szDeviceName),

szDeviceVersion,sizeof (szDeviceVersion)) )

{
            if(capDriverConnect(m_hVideo,wIndex))
            {

}
        }

}
    上面代码中,capGetDriverDescription是列举所有可用视频的驱动程序,如果列举成功,用capDriverConnect进行连接。其实,我的机器上就装了一个摄像头,所以,只有当wIndex=0的时候,列举成功,并且连接也成功。这段代码好像很奇怪,因为列举成功之后,不论是否连接上,都没有做任何事情。其实可以用下面代码代替:
    char szDeviceName[80];
    char szDeviceVersion[80];
    //Get Driver description and the code can also be deleted as you want.
    capGetDriverDescription (0 szDeviceName,sizeof (szDeviceName), szDeviceVersion,
        sizeof (szDeviceVersion));
    //connect window to driver
    capDriverConnect(m_hVideo,0);
    (7)到这里,再加下面两句话你就会有成就感了,在BOOL CGraspDlg::OnInitDialog()中继续添加如下代码:
    capPreviewRate(m_hVideo,40); //设置Preview模式的显示速率
    capPreview(m_hVideo,TRUE); //启动Preview模式
    如果到此为止,已经完成了视频采集的全过程,你运行一下,就可以看到摄像头拍摄的画面了,显示在你的对话框上。但是,我的目的还没有达到,我其实想在每一桢显示之前,能处理一下这一桢的数据,那么,去哪里找这桢数据存放的位置呢?
   (8)为了完成我的目标,我把步骤(7)中的两句代码先注释掉。在对话框上加一个按钮,并在对单击做出响应的响应函数中写下面代码:
    capGrabFrame(m_hVideo);
    这是一个宏,将鼠标移动到这段代码上,右键单击,选择Go To Definition of capGrabFrame,你会看到
#define capGrabFrame(hwnd)((BOOL)AVICapSM(hwnd, WM_CAP_GRAB_FRAME, (WPARAM)0, (LPARAM)0L))
而继续察看AVICapSM宏你会看到其实是在调用SendMessage函数呢,对吧,其实就是在发送消息。至于消息谁处理了,我们就不去关心了,我们关心的是,发送消息后,系统会调用我们刚才注册的回调函数:
    LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr) ;
    (9)好了,如果你单击按钮,capGrabFrame(m_hVideo)就发送消息了,然后,我们就进入回调函数了,这太好了。看到回调函数传递的两个参数了么?我们更关心第二个参数,这个就是单击按钮我们捕捉到的一桢数据的入口啊!
    LPVIDEOHDR 是结构体VIDEOHDR的指针,而在MSDN中察看结构体VIDEOHDR,我们就可以找到桢数据的存贮位置指针了。
    VIDEOHDR定义如下:
    typedef struct videohdr_tag {
        LPBYTE lpData;
        DWORD dwBufferLength;
        DWORD dwBytesUsed;
        DWORD dwTimeCaptured;
        DWORD dwUser;
        DWORD dwFlags;
        DWORD_PTRdwReserved[4];
    } VIDEOHDR, NEAR *PVIDEOHDR, FAR * LPVIDEOHDR;
    看到结构体中第一个参数了么?这个就是我们想要的桢数据的指针!后面参数,包括缓冲区长度等。
    (10)终于得到了缓冲区的数据,可是,又一个问题出现了,缓冲区中的数据到底具体是啥含义啊?
    这桢图像多大啊?size 是多少乘多少的啊?就是我们想要的像素信息么?
    好的,我先告诉你,缓冲区中全部是像素信息,我们照着我的步骤这样做,其实是默认了一些参数,包括图像的长度,宽度,色彩数,等等,那么,这个默认的值是多少呢?
    (11)用一下capGetVideoFormat宏吧,你会得到想要的东西。
    在BOOL CGraspDlg::OnInitDialog()中继续添加如下代码:
    BITMAPINFO bmpInfo;
    capGetVideoFormat(m_hVideo,&bmpInfo,sizeof(BITMAPINFO));
    BITMAPINFO结构体内容自己看MSDN.定义如下
    typedef struct tagBITMAPINFO {
        BITMAPINFOHEADER bmiHeader;
        RGBQUAD bmiColors[1];
    } BITMAPINFO, *PBITMAPINFO;
    BITMAPINFOHEADER定义如下:
    typedef struct tagBITMAPINFOHEADER{
        DWORD biSize;
        LONG biWidth;
        LONG biHeight;
        WORD biPlanes;
        WORD biBitCount;
        DWORD biCompression;
        DWORD biSizeImage;
        LONG biXPelsPerMeter;
        LONG biYPelsPerMeter;
        DWORD biClrUsed;
        DWORD biClrImportant;
    } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
    加入步骤(11)的两句话,调试运行,我发现,bmpInfo.bmiHeader.biWidth为320,就是采集的图像宽度;
bmpInfo.bmiHeader.biHeight为240,就是采集的图像高度,这些都是默认值,也可以改变这些值,通过
capSetVideoFormat宏来实现。
    (12)那么,我们在步骤(9)中,回调函数第二个参数对应的结构体VIDEOHDR中,图像数据缓冲区的大小dwBufferLength是多少呢?我们可以在回调函数中加一个MessageBox函数,输出这个值,我们就可以发现,为230400,这个数很好,正好等于图像宽度X图像高度的3倍,也就是说,是图像像素数目的3倍,这就对了,每个像素用3个字节存储的嘛。好啦,我们知道了,桢缓冲区中,存储的完全是图像的像素信息,那么,具体哪个值对应哪个像素呢?
    存储顺序是这样的:先从图像最下面一行开始,从左向右,依次存储,每一个像素用连续的3个字节,分别为B(蓝色分量),G(绿色分量),R(红色分量)。然后存储倒数第二行,仍然按照图像从左向右存储,然后倒数第三行,倒数第四行。。。。。。等等,最后存储正数第一行。
    好啦,我所有想说的都说完啦,你明白了么?好累,现在是晚上,快10点钟了,我正好要去跑步去了。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/laolei1986/archive/2010/07/13/5733046.aspx

VFW-MFC视频采集相关推荐

  1. 使用VFW开发视频采集软件

    VFW是Video For Windows的缩写,使用VFW可以快速开发Windows视频采集软件.VFW开发的资源可以参考MSDN中的Video Capture一节的内容,当然也可以参考网上一些翻译 ...

  2. Window 下 VFW 视频采集与显示

    引言 经过几天的努力终于将VFW视频采集与显示功能完整实现了,不得不说网上对这方面完整的详细讲解文章是在太少了.所以就要本人来好好总结一下让后来者不再像我一样折腾好久.在本文中我将详细讲解VFW视频采 ...

  3. .VC++关于的VFW视频采集方案【转 360doc】

    2.2  VFW视频采集方案 VFW是Microsoft于1992年推出的数字视频软件包,它不依赖于专用的硬件设备,提供了通用的数字视频开发方案.VFW主要由AVICap.dll.MSVideo.dl ...

  4. VFW视频采集方案(Captureparms参数详细)

    2.2 VFW视频采集方案 VFW是Microsoft于1992年推出的数字视频软件包,它不依赖于专用的硬件设备,提供了通用的数字视频开发方 案.VFW主要由AVICap.dll.MSVideo.dl ...

  5. 音视频采集—Windows平台VFW

    因为Windows开发相对方便一些,所以将VFW作为入门篇进行分享. VFW(Video for Windows)是Microsoft推出的关于数字视频的一个软件开发包. 我们在这里主要分享:核心AP ...

  6. VC++实现视频聊天:VFW视频采集+FFmpeg编码

    上次介绍了视频聊天软件的界面.文字聊天.文件传输部分,这此介绍视频聊天功能,这算是音视频领域一个很广的应用.首先视频聊天的双方需要有一个USB摄像头(或者笔记本摄像头),在windows系统下,一个完 ...

  7. (转载)视频采集学习笔记

    视频采集学习笔记 第一节.视频采集   一.二者的不同点: 说起视频捕捉问题,我们先要来看一下视频捕捉卡.根据使用的驱动程序的不同来分类,目前市场上大致有两种捕捉卡:VFW (Video for Wi ...

  8. FFMPEG Qt录屏软件开发之视频采集

    前面讲解了视频播放器的开发,初步掌握了使用FFMPEG解码音视频. 现在我们就接着讲解使用FFMPEG来编码音视频,主要是实现一个录屏软件的制作. 一个录屏软件的流程基本就是: 图像采集 图像编码 将 ...

  9. VFW连接视频驱动不成功问题解决

    使用VFW进行视频捕获时,使用capdriverconnect宏连接视频驱动时, 一般方法是 if(capDriverConnect(m_hwnd,0){  //连接视频驱动成功后进行的动作 } el ...

  10. 流媒体之DirectShow——视频采集

    文章目录 一:介绍 二:设备枚举 三:Video Graph 3.1 视频预览 3.2 录制视频到AVI文件 3.3 录制视频到Windows Media File(ASF) 3.4 录制视频到其他文 ...

最新文章

  1. Python函数16道入门练习题
  2. 【Splay】【块状链表】bzoj3223 Tyvj 1729 文艺平衡树
  3. 为什么在子类中不重写超类的实例变量
  4. android 闪存软件测试,手机为什么这么卡:闪存I/O测试AndroBench
  5. 服务器间传文件$d,基于OpenSSH+WinSCP完成Windows服务器之间的文件传输
  6. mysql syncmasterinfo_sync_master_info的一些说明
  7. 【转】MySQL索引和查询优化
  8. php base64_decode 图片,php读取和保存base64编码图片
  9. 妨碍编译器优化的因素
  10. 电动牙刷C语言程序,电动牙刷的日常维护
  11. 量产软件测试培训,U盘量产及在虚拟机中测试
  12. (Linux)简单电子通讯录
  13. throw Exception
  14. 分形理论在地理信息科学研究中的应用
  15. 图片没有透明效果html,为什么png不是透明底
  16. PHP 合成图片并在图片上加文字
  17. 统计软件与数据分析—Lesson2
  18. 接口显示返回值正常,但是拿到的值却是undefined?
  19. Corrective feedback
  20. 未来五年最赚钱的不是股市、房地产,而是......

热门文章

  1. HTML DOM 事件 —— 鼠标事件 JS鼠标事件
  2. 浅论计算机基础课程远程教学系统的设计和实现
  3. QQ好友列表名片点赞全自动脚本,使用autojs开发的免root运行
  4. 手机屏幕常见故障_【最新推荐】手机触摸屏常见问题及解决方法-范文模板 (3页)...
  5. 硬件设计基础----二极管
  6. 模电1.2 半导体二极管
  7. BIT2023 智慧社区综合管理系统-二周目
  8. KubeVela 1.4:让应用交付更安全、上手更简单、过程更透明
  9. Matlab:提取或分配日期时间数组的日期时间分量
  10. away3d学习笔记 转载