男主角死了的动漫:.VC++关于的VFW视频采集方案

来源:百度文库 编辑:中财网 时间:2024/04/27 21:58:58

2.2  VFW视频采集方案

VFW是Microsoft于1992年推出的数字视频软件包,它不依赖于专用的硬件设备,提供了通用的数字视频开发方案。VFW主要由AVICap.dll、MSVideo.dll、MCIAvi.drv、AVIFile.dll、vfw32.lib等库文件组成,这些库提供了相关视频、音频、AVI文件的函数,本节将介绍如何利用这些函数进行视频采集。

2.2.1  开发流程分析

VFW使用的视频函数被封装在vfw32.lib库文件中,该库文件默认情况下没有被连接到MFC工程中,因此使用VFW进行视频开发的第一步是导入vfw32.lib库文件。方法如下:

(1)引用vfw.h头文件。

#include "vfw.h"

(2)导入vfw32.lib库文件。

#pragma comment (lib,"vfw32")

步骤2也可以在通过工程选项窗口的连接选项卡进行设置。如图2.1所示。

 

连接vfw32.lib库文件

 

 

图2.1  工程选项窗口

在导入vfw32.lib库文件后便可以使用视频函数了。首先调用capCreateCaptureWindow函数创建具有WS_POPUP风格的视频捕捉窗口。然后调用capDriverConnect函数连接驱动程序,设置视频捕捉窗口的大小、显示位置。最后调用capPreviewRate函数设置预览速率,调用capPreview函数进行视频预览。

总结上述流程分析,VFW视频捕捉开发流程具体步骤如下:

(1)引用“vfw.h”头文件并导入vfw32.lib库。

(2)创建一个线程,在线程函数中调用capCreateCaptureWindow创建视频捕捉窗口。

(3)调用capDriverConnect连接驱动程序,设置视频捕捉窗口风格、大小及父窗口。

(4)调用capPreviewRate函数设置预览速度,调用capPreview函数开始预览。

2.2.2  视频窗口创建

在进行视频程序开发时,第一步需要创建一个视频预览窗口。在程序中可以使用capCreateCaptureWindow函数来创建视频预览窗口,该函数语法如下:

HWND VFWAPI capCreateCaptureWindow(LPCSTR lpszWindowName, DWORD dwStyle, int x,                  

int y, int nWidth, int nHeight, HWND hWnd, int nID);

参数说明:

lpszWindowName:表示视频捕捉窗口的名称。

dwStyle:表示视频捕获窗口的风格,一般包含有WS_CHILD 和 WS_VISIBLE风格。

x、y:表示视频捕捉窗口的左上角坐标。

nWidth、nHeight:表示视频捕捉窗口的宽度和高度。

hWnd:表示视频捕捉窗口父窗口的句柄。

nID:表示视频捕捉窗口标识。

在创建视频捕捉窗口之后,需要将其显示在对话框中的适当位置。可以在对话框中预先放置一个静态文本控件,调整其大小和位置,然后将视频捕捉窗口放置在该控件的位置处就可以了。例如:

m_Captured = FALSE;

m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,1,1,10,10,m_hWnd,0);

::SetParent(m_hWndVideo,*this);

::SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);

CRect wndRC;

m_Panel.GetClientRect(wndRC);

m_Panel.MapWindowPoints(this,wndRC);

wndRC.DeflateRect(1,1,1,1);

::SetWindowPos(m_hWndVideo,NULL,wndRC.left,wndRC.top,wndRC.Width(),

wndRC.Height(),SWP_NOZORDER);

::ShowWindow(m_hWndVideo,SW_SHOW);

2.2.3  视频预览实现

在开发视频应用程序时,第一步需要实现的功能便是视频预览。在2.2.1节中笔者曾分析了视频预览的实现过程,下面以一个具体实例来说明VFW视频预览的实现过程。效果如图2.2所示。

 

图2.2  视频预览实现

程序设计步骤如下:

  实例位置光盘\mr\2\2.2\2.2.3\01

(1)创建一个基于对话框的工程,在对话框中添加Picture控件,如图2.3所示。

 

图2.3  视频预览设计窗口

(2)在类向导的“Member Variables”选项卡中为Picture控件命名,如图2.4所示。

 

图2.4  类向导窗口

(3)在对话框的头文件中引用“vfw.h”头文件,然后链接“vfw32.lib”库文件。

#include "vfw.h"

#pragma comment (lib,"vfw32")

(4)在对话框中定义一个视频预览窗口的句柄。

HWND   m_hWndVideo; //视频显示窗口

(5)在对话框初始化时创建视频预览窗口,连接视频驱动程序,设置预览帧率,开始视频预览。

BOOL CVideoPreviewDlg::OnInitDialog()

{

   CDialog::OnInitDialog();

   ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

   ASSERT(IDM_ABOUTBOX < 0xF000);

   CMenu* pSysMenu = GetSystemMenu(FALSE);

   if (pSysMenu != NULL)

   {

       CString strAboutMenu;

       strAboutMenu.LoadString(IDS_ABOUTBOX);

       if (!strAboutMenu.IsEmpty())

       {

              pSysMenu->AppendMenu(MF_SEPARATOR);

              pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

       }

   }

   SetIcon(m_hIcon, TRUE);   

   SetIcon(m_hIcon, FALSE);

   //创建预览窗口

   m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,1,1,10,10,m_hWnd,0);

   //连接驱动程序

   if (capDriverConnect(m_hWndVideo,0))

  

       ::SetParent(m_hWndVideo,*this);

       ::SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);

       CRect wndRC;

       m_Panel.GetClientRect(wndRC);

       m_Panel.MapWindowPoints(this,wndRC);

       wndRC.DeflateRect(1,1,1,1);

       ::SetWindowPos(m_hWndVideo,NULL,wndRC.left,

wndRC.top,wndRC.Width(),wndRC.Height(),SWP_NOZORDER);

       ::ShowWindow(m_hWndVideo,SW_SHOW);

       capPreviewRate(m_hWndVideo,30);

       capPreview(m_hWndVideo,TRUE);

  

   return TRUE;

}

(6)在对话框关闭时断开视频驱动程序。

void CVideoPreviewDlg::OnCancel()

{

   //断开驱动程序连接

   capDriverDisconnect(m_hWndVideo);

   CDialog::OnCancel();

}

2.2.4  捕捉参数设置

在进行视频捕捉时,通常需要设置视频捕捉参数。VFW提供了capCaptureSetSetup函数用于设置视频捕捉参数,该函数语法如下:

BOOL capCaptureSetSetup(HWND hwnd, LPCAPTUREPARMS  psCapParms,UINT wSize );

参数说明:

hwnd:表示视频捕捉窗口句柄。

psCapParms:表示视频捕捉参数,该参数是CAPTUREPARMS结构指针。CAPTUREPARMS结构成员描述如表2.1所示。

表2.1  CAPTUREPARMS结构成员描述

成员名称

成员类型

描述

dwRequestMicroSecPerFrame

DWORD

以毫秒为单位设置捕捉帧率,默认值为66667,即每秒15帧

fMakeUserHitOKToCapture

BOOL

如果为TRUE,将显示一个对话框帮助用户快速地进行捕捉设置

wPerentDropForError

UINT

在捕捉过程中允许弃帧的最大百分比

fYield

BOOL

如果为TRUE,将产生一个后台线程来进行视频捕捉

dwIndexSize

DWORD

表示AVI文件最大的索引入口数

wChunkGranularity

UINT

以字节为单位表示AVI文件的大小

fUsingDOSMemory

BOOL

未使用

wNumVideoRequested

UINT

分配视频缓冲区的最大数量

fCaptureAudio

BOOL

为TRUE,表示音频被捕捉,默认值依赖于安装的音频设备

wNumAudioRequested

UINT

表示分配的音频缓冲区的最大数量

vKeyAbort

UINT

表示终止捕捉的虚拟键

fAbortLeftMouse

BOOL

为TRUE,表示单击鼠标左键停止捕捉

fAbortRightMouse

BOOL

为TRUE,表示单击鼠标右键停止捕捉

fLimitEnabled

BOOL

为TRUE,表示设置捕捉时间限制

wTimeLimit

UINT

以秒为单位设置捕捉的超时时间

fMCIControl

BOOL

为TRUE,控制MCI(媒体设备接口)兼容的视频源

fStepMCIDevice

BOOL

为TRUE,使用MCI设备使用步进帧进行捕捉,为FALSE,使用MCI设备进行时时捕捉,如果fMCIControl成员为FALSE,该成员被忽略

dwMCIStartTime

DWORD

以毫秒为单位标识MCI设备视频捕捉序列的起始位置,如果fMCIControl成员为FALSE,该成员被忽略

dwMCIStopTime

DWORD

以毫秒为单位标识MCI设备视频捕捉序列的停止位置,如果fMCIControl成员为FALSE,该成员被忽略

fStepCaptureAt2x

BOOL

为TRUE,捕捉的视频帧使用两个分辨率,它可以使用软件在某个分辨率的基础上改写像素,将其该为高清晰度的图像

wStepCaptureAverageFrames

UINT

在捕捉时每帧图像使用的时间大小

dwAudioBufferSize

DWORD

音频缓冲区大小

fDisableWriteCache

BOOL

未使用

AVStreamMaster

UINT

确定在写入AVI文件时,音频流是否控制时钟

wSize:表示psCapParms参数的大小。

在进行视频捕捉时,通常会根据实际需要设置捕捉参数。例如,在视频录像时,通常会将fYield成员设置为TRUE,启动后台线程来进行视频录像,这样,前台用户依然可以进行其他界面有关操作。

2.2.5  回调函数设计

在开发视频应用程序时,可以为视频捕捉窗口设计一些回调函数,这样,当视频应用程序的某些状态改变时,可以在回调函数中进行处理。VFW提供了如下的函数进行回调函数注册。

(1)capSetCallbackOnCapControl

该函数提供了视频捕捉时精确地控制捕捉开始和结束的时间。语法如下:

BOOL capSetCallbackOnCapControl(HWND hwnd,  CAPCONTROLCALLBACK fpProc );

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示视频捕捉回调函数指针,其定义如下:

typedef LRESULT (CALLBACK* CAPCONTROLCALLBACK)(HWND hWnd, int nState);

其中,hWnd表示视频捕捉窗口句柄,nState参数如果设置为CONTROLCALLBACK_PREROLL,表示将要开启视频源,为CONTROLCALLBACK_CAPTURING,表示应用程序允许通过返回FALSE去结束视频捕捉。

(2)capSetCallbackOnError

该函数用于为客户端应用程序设置错误处理的回调函数。语法如下:

BOOL capSetCallbackOnError(HWND hwnd, CAPERRORCALLBACKA  fpProc);

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示错误处理的回调函数指针,其定义如下:

typedef LRESULT (CALLBACK* CAPERRORCALLBACKA)  (HWND hWnd, int nID, LPCSTR lpsz);

其中,hWnd表示视频捕捉窗口句柄,nID表示消息ID,lpsz表示消息文本描述。

(3)capSetCallbackOnFrame

该函数用于设置预览回调函数,回调函数在预览帧之前调用。语法如下:

BOOL capSetCallbackOnFrame(HWND hwnd, CAPVIDEOCALLBACK  fpProc );

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示预览回调函数指针,其定义如下:

typedef LRESULT (CALLBACK* CAPVIDEOCALLBACK)  (HWND hWnd, LPVIDEOHDR lpVHdr);

其中, hWnd表示视频捕捉窗口句柄,lpVHdr是一个VIDEOHDR结构指针,表示视频数据头。

(4)capSetCallbackOnStatus

该函数用于在程序中设置一个状态回调函数。语法如下:

BOOL capSetCallbackOnStatus(HWND hwnd,  CAPSTATUSCALLBACKA fpProc );

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,当应用程序的状态改变时将调用该函数。其定义如下:

typedef LRESULT (CALLBACK* CAPSTATUSCALLBACKA) (HWND hWnd, int nID, LPCSTR lpsz);

其中, hWnd表示视频捕捉窗口句柄,nID表示状态码,lpsz表示状态文本描述。

(5)capSetCallbackOnVideoStream

该函数用于注册一个回调函数,使得视频缓冲区被填充时调用回调函数。语法如下:

BOOL capSetCallbackOnVideoStream(HWND hwnd, CAPVIDEOCALLBACK fpProc );

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,当视频缓冲区被填充时调用回调函数,其定义与capSetCallbackOnFrame函数的fpProc参数相同。

(6)capSetCallbackOnWaveStream

该函数用于注册一个回调函数,使得音频缓冲区被填充时调用回调函数。语法如下:

BOOL capSetCallbackOnWaveStream (HWND hwnd, CAPWAVECALLBACK fpProc );

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,当音频缓冲区被填充时调用回调函数。其定义如下:

typedef LRESULT (CALLBACK* CAPWAVECALLBACK)   (HWND hWnd, LPWAVEHDR lpWHdr);

其中, hWnd表示视频捕捉窗口句柄,lpWHdr是一个WAVEHDR结构指针,表示音频数据头。

(7)capSetCallbackOnYield

该函数用于注册一个回调函数,使得在每一次捕捉视频帧时调用一次回调函数。语法如下:

BOOL capSetCallbackOnYield(HWND hwnd,  fpProc );

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,其定义如下:

typedef LRESULT (CALLBACK* CAPYIELDCALLBACK)  (HWND hWnd);

其中, hWnd表示视频捕捉窗口句柄。通常,该函数由消息循环构成。

VFW的回调函数在视频预览、视频录像、视频压缩等多个地方被广泛使用。下面以统计预览帧数为例介绍VFW回调函数的使用。效果如图2.5所示。

 

统计预览帧数

 

 

图2.5  回调函数设计

程序设计步骤如下:

  实例位置光盘\mr\2\2.2\2.2.5\01

(1)创建一个基于对话框的工程,在对话框中添加静态文本、图像等控件,如图2.6所示。

 

图2.6  回调函数设计窗口

(2)利用类向导为图像、静态文本控件命令,如图2.7所示。

 

图2.7  MFC类向导窗口

(3)在对话框的头文件中引用“vfw.h”头文件,并导入“vfw32.lib”库文件。

#include "vfw.h"

#pragma comment (lib,"vfw32")

(4)向对话框中添加成员变量m_hWndVideo,作为预览窗口的句柄。

HWND   m_hWndVideo; //视频显示窗口

(5)定义一个全局变量,记录当前的预览帧数。

long num = 0;

(6)定义一个全局函数,作为视频预览的回调函数。

LRESULT CALLBACK  PreviewCallback (HWND hWnd)

{

   num++;

   return 0;

}

(7)处理对话框的WM_TIMER消息,将num数值显示在界面中。

void CCallbackDesigendDlg::OnTimer(UINT nIDEvent)

{

   CString str;

   str.Format("%i",num);

   m_FrameNum.SetWindowText(str);

   CDialog::OnTimer(nIDEvent);

}

(8)在对话框初始化时创建视频预览窗口,设置预览回调函数,开始视频预览。

BOOL CCallbackDesigendDlg::OnInitDialog()

{

   CDialog::OnInitDialog();

   ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

   ASSERT(IDM_ABOUTBOX < 0xF000);

   CMenu* pSysMenu = GetSystemMenu(FALSE);

   if (pSysMenu != NULL)

   {

       CString strAboutMenu;

       strAboutMenu.LoadString(IDS_ABOUTBOX);

       if (!strAboutMenu.IsEmpty())

       {

              pSysMenu->AppendMenu(MF_SEPARATOR);

              pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

       }

   }

   SetIcon(m_hIcon, TRUE);   

   SetIcon(m_hIcon, FALSE);

  

   //创建预览窗口

   m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,1,1,10,10,m_hWnd,0);

   //连接驱动程序

   if (capDriverConnect(m_hWndVideo,0))

  

       ::SetParent(m_hWndVideo,*this);

       ::SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);

       CRect wndRC;

       m_Panel.GetClientRect(wndRC);

       m_Panel.MapWindowPoints(this,wndRC);

       wndRC.DeflateRect(1,1,1,1);

       ::SetWindowPos(m_hWndVideo,NULL,wndRC.left,

       wndRC.top,wndRC.Width(),wndRC.Height(),SWP_NOZORDER);

       ::ShowWindow(m_hWndVideo,SW_SHOW);

       capSetCallbackOnFrame(m_hWndVideo,PreviewCallback);

       capPreviewRate(m_hWndVideo,30);

       capPreview(m_hWndVideo,TRUE);

  

  

   SetTimer(1,800,NULL);

  

(9)在对话框关闭时断开视频驱动程序。

void CCallbackDesigendDlg::OnCancel()

{

   //断开驱动程序连接

   capDriverDisconnect(m_hWndVideo);

   CDialog::OnCancel();

}