天天看点

基于vfw的摄像头视频浏览和捕获的程序

使用基于VFW的方式进行摄像头视频浏览和捕获,优点是编码简单,缺点是功能受限

方法: 新建一个基于对话框的工程,引用头文件<vfw.h> , 导入 vfw32.lib 库,库文件可以在vc 存在路径中找到; 如:D:/Program Files/Microsoft Visual Studio/VC98/Lib/vfw32.lib

在窗体上添加四个个按钮,修改ID 为IDC_VIDEO , IDC_CAPTURE , IDC_STOPVIDEO , IDC_STOPCAPTURE;

为按钮IDC_VIDEO 添加代码开始浏览视频 :

{

// create a window for captureWindow 

 CWnd  * mywnd = new  CWnd;

 mywnd -> Create(_T( " STATIC " ),  "" , WS_CHILD  |  WS_VISIBLE,CRect( 0 ,  0 ,  400 ,  400 ),  this ,  1234 );

 mywnd -> ShowWindow(SW_SHOW);

 CRect rect;

 mywnd -> GetWindowRect(rect);

// create capture window

 ghCapWnd = capCreateCaptureWindow(  " My Own Capture Window " ,WS_CHILD  |  WS_VISIBLE , 0 ,  0 , (rect.right - rect.left), (rect.bottom - rect.top), mywnd -> GetSafeHwnd(),  1235 );

// connect device

 capDriverConnect (ghCapWnd,  0 );

// get params

 CAPTUREPARMS CapParms;

 capCaptureGetSetup(ghCapWnd, & CapParms, sizeof  (CAPTUREPARMS));

// 设置桢速

 CapParms.dwRequestMicroSecPerFrame = 40000 ; 

// 有无时间限制 

 CapParms.fLimitEnabled  =  FALSE; 

// 是否捕捉音频

// CapParms.fCaptureAudio = FALSE; 

// MCI Device支持

 CapParms.fMCIControl  =  FALSE;  

// 设置窗口,如果为false,捕捉画面在桌面上              

 CapParms.fYield  =  TRUE;

// 停止捕捉键设置

 CapParms.vKeyAbort  =  VK_ESCAPE;

 CapParms.fAbortLeftMouse  =  FALSE;

 CapParms.fAbortRightMouse  =  FALSE;

 capCaptureSetSetup(ghCapWnd, & CapParms, sizeof  (CAPTUREPARMS));

// 设置预览时的比例

 capPreviewScale(ghCapWnd,  1 );

// 设置预览时的帧频率

 capPreviewRate(ghCapWnd, 66 );

// 是否支持比例变化

 capPreviewScale(ghCapWnd,FALSE);

// 打开预览

 capPreview(ghCapWnd,  1 );

}

为 IDC_CAPTURE 添加代码开始捕获视频 :

{

 capCaptureSequence(ghCapWnd);

}

为IDC_STOPCAPTURE添加代码停止捕捉:

{

 capCaptureAbort(ghCapWnd);

}

为IDC_STOPVIDEO添加代码断开连接:

{

 capDriverDisconnect(ghCapWnd);

}

补充:

一、捕获的帧频率

捕获的帧频率表示在一个捕获会话中,每秒要捕获多少帧。你通过WM_CAP_GET_SEQUENCE_SETUP 消息(capCaptureGetSetup宏)可以得到当前捕获的帧频率。当前的帧频率被保存在CAPTUREPARMS结构的dwRequestMicroSecPerFrame 成员中。你可以对该值进行修改,从而去改变帧频率。该值为捕获一帧要用的时间(单位是微秒 1/1000000秒),修改后,你可以发送WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup 宏)给你的捕获窗体,来刷新CAPTUREPARMS 结构。dwRequestMicroSecPerFrame 默认值是66667微秒,表示每秒15帧。(1000000/15=66667)

下例使用capCaptureGetSetup和capCaptureSetSetup宏来改变捕获速度,从默认值(15帧/秒)到10帧/秒。

基于vfw的摄像头视频浏览和捕获的程序

CAPTUREPARMS CaptureParms;

基于vfw的摄像头视频浏览和捕获的程序

float  FramesPerSec  =   10.0 ;

基于vfw的摄像头视频浏览和捕获的程序

capCaptureGetSetup(hWndC,  & CaptureParms,  sizeof (CAPTUREPARMS));

基于vfw的摄像头视频浏览和捕获的程序

CaptureParms.dwRequestMicroSecPerFrame  =  (DWORD) ( 1.0e6   /  FramesPerSec);

基于vfw的摄像头视频浏览和捕获的程序

capCaptureSetSetup(hWndC,  & CaptureParms,  sizeof  (CAPTUREPARMS)); 

基于vfw的摄像头视频浏览和捕获的程序

二、捕获窗体状态

通过发送WM_CAP_GET_STATUS消息(capGetStatus宏),可以获得当前捕获窗口的状态。这个消息得到一个CAPSTATUS结构体的拷贝,状态信息就在这个结构体的成员中。CAPSTATUS 结构体包含了图形尺寸大小、滚动位置(scroll position)、是否覆盖(overlay)或者预览(preview)等信息。因为在CAPSTATUS 中的信息是动态的,你的应用程序应该随时去刷新这个结构体中的内容。 改变捕获窗口的尺寸对实际的视频流的尺寸没有影响。视频捕获可以做这几个方面的工作:访问 视频源、显示选项、格式和压缩选项。音频捕获包括指定音频格式和选择压缩方式。

CAPSTATUS CapStatus;

capGetStatus(hWndC,  & CapStatus,  sizeof  (CAPSTATUS)); 

SetWindowPos(hWndC, NULL,  0 ,  0 , CapStatus.uiImageWidth, 

             CapStatus.uiImageHeight, SWP_NOZORDER  |  SWP_NOMOVE); 

三、捕获驱动性能

通过发送WM_CAP_DRIVER_GET_CAPS消息(capDriverGetCaps宏),可以获得当前连接的捕获设备的性能。发送该消息后,会返回一个CAPDRIVERCAPS 结构的对象。设备的性能信息,就在这个对象中。

基于vfw的摄像头视频浏览和捕获的程序

CAPDRIVERCAPS CapDrvCaps; 

基于vfw的摄像头视频浏览和捕获的程序

SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS, 

基于vfw的摄像头视频浏览和捕获的程序

     sizeof  (CAPDRIVERCAPS), (LONG) (LPVOID)  & CapDrvCaps); 

基于vfw的摄像头视频浏览和捕获的程序

//  或者,使用宏来获得驱动器的新能参数 

基于vfw的摄像头视频浏览和捕获的程序

//  capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS)); 

四、预览和覆盖模式 (Preview and Overlay )

一般,一个捕获驱动提供两种方式来观看输入的视频流:预览模式和覆盖模式。如果捕获驱动可以提供上面两种模式,那么用户就可以选择其中的模式来使用。

预览模式从捕获设备硬件传输数据帧到系统的内存中,并且在捕获窗口中使用GDI函数来显示这些数据帧。当捕获窗口的父窗体失去焦点的时候,在应用程序的视频预览的数据将变慢,如果父窗体获的焦点后,将对预览显示进行加速。因为预览处理的这种处理方式将大大提高整个系统的效率。

这里用3个消息用于控制预览操作。

l     WM_CAP_SET_PREVIEW消息(capPreview 宏)可以打开或者关闭预览模式。

l     WM_CAP_SET_PREVIEWRATE 消息(capPreviewRate 宏)可以设置预览模式下图像的帧速度。

l     WM_CAP_SET_SCALE 消息 (capPreviewScale 宏) 打开或者关闭预览视频的缩放比例。

当预览和缩放比例属性都打开后,那么视频将被缩放到和捕获窗口尺寸一样大。打开预览模式后,系统将自动关闭覆盖模式。

基于vfw的摄像头视频浏览和捕获的程序

capPreviewRate(hWndC,  66 );       //  速度,微秒

基于vfw的摄像头视频浏览和捕获的程序

capPreview(hWndC, TRUE);        //  开始预览 

基于vfw的摄像头视频浏览和捕获的程序

capPreview(hWnd, FALSE);         //  屏蔽预览 

基于vfw的摄像头视频浏览和捕获的程序

覆盖模式,将不占用CPU的处理资源,直接在显示器上显示视频内容。所用的处理是有捕获设备硬件来完成。发送WM_CAP_SET_OVERLAY消息(或capOverlay 宏)给捕获窗口,可以打开覆盖模式。打开覆盖模式后,将自动关闭预览格式。

基于vfw的摄像头视频浏览和捕获的程序

CAPDRIVERCAPS CapDrvCaps; 

基于vfw的摄像头视频浏览和捕获的程序

capDriverGetCaps(hWndC,  & CapDrvCaps,  sizeof  (CAPDRIVERCAPS)); 

基于vfw的摄像头视频浏览和捕获的程序

if  (CapDrvCaps.fHasOverlay) 

基于vfw的摄像头视频浏览和捕获的程序

    capOverlay(hWndC, TRUE);

无论是预览模式还是覆盖模式,都可以通过发送WM_CAP_SETSCROLL消息(capSetScroollPos 宏),可以设置图像的在整个视频帧的滚动位置(scroll position)。

五、捕获变化

除了对基于持续时间间隔的流捕获外,AVICap还支持如下的捕获:

l     手控制帧捕获

l     Still-image 捕获

l     不使用磁盘存储的捕获

l     从一个MCI设备的流捕获(real-time and step-frame)

手动帧捕获

如果你向指定捕获视频流中个别帧,你可以通过WM_CAP_SINGLE_FRAME_OPEN消息、WM_CAP_SINGLE_FRAME消息、WM_CAP_SINGLE_FRMAE_CLOSE消息来控制帧序列(capCaptureSingleFrameOpen 、/capCaptureSingleFrame 、capCaptureSigleFrameClose )。

 典型应用是,这些消息用于向捕获文件添加单独的帧来创建一个动画, WM_CAP_SINGLE_FRAME_OPEN 为手动捕获操作打开一个文件,WM_CAP_SINGLE_FRAME用于捕获一个单独的帧放在文件中。

WM_CAP_SINGLE_FRMAE_CLOSE用于关闭这个捕获文件。

注:  该操作支持音视频同时捕获。

Still-Image 捕获

如果要捕获一个单独的帧作为一个静态图像,你可以使用WM_CAP_GRAB_FRAME_NOSTOP或者 WM_CAP_GRAB_FRAME 消息 (

或 宏) 在一个帧缓存区中捕获一个图像。你可以通过使用下面的消息来抓获当前显示的图形WM_CAP_GRAB_FRAME ,否则,使用WM_CAP_GRAB_FRAME_NOSTOP。

一旦开始捕获,你可以拷贝图像给其他应用程序。你可以从帧缓存区拷贝一个图像到剪贴板(使用WM_CAP_EDIT_COPY 消息或capEditCopy 宏)。你还可以使用如下的消息,将缓存区的一张图像拷贝到一个DIB位图中(WM_CAP_FILE_SAVEDIB消息或capFileSaveDIB 宏)。

不使用磁盘存储的捕获

使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile 宏),可以不向磁盘文件写入数据。该消息仅在配合回调函数时有用,它允许你的应用程序直接使用音视频数据。例如,在视频会议中,应用程序使用该消息区获得视频流。回调函数将传输捕获的图像传送给远程的计算机。

基于vfw的摄像头视频浏览和捕获的程序

capCaptureSequenceNoFile(m_hWndCapture);  //  默认开始视频

获取内存中图像位置指针的方法:

基于vfw的摄像头视频浏览和捕获的程序

LRESULT CALLBACK FrameCallbackProc(HWND ghWnd,LPVIDEOHDR lpVData)

     unsigned  char *  data;

    data = lpVData -> lpData; // 获得视频数据首址并将数据存入data数组中以便处理

     return  (LRESULT) TRUE;

}

基于vfw的摄像头视频浏览和捕获的程序

// 在捉图的时候调用

基于vfw的摄像头视频浏览和捕获的程序

capSetCallbackOnVideoStream(hCapWnd,capVideoStreamCallback);

基于vfw的摄像头视频浏览和捕获的程序

capCaptureSequenceNoFile(hwndCap); 

基于vfw的摄像头视频浏览和捕获的程序

// 调用完成后关闭

基于vfw的摄像头视频浏览和捕获的程序

capSetCallbackOnVideoStream(hwndCap,NULL); 

从MCI 设备进行流捕获

MCI设备加强了实时捕获和步进帧(step-frame)捕获的处理操作。你可以指定一个MCI设备,比如一张影碟或者一盘录像带(VCR)来充当视频源。通过发送消息并指定你要选定的MCI设备的名称。消息:WM_CAP_SET_MCI_DEVICE (capSetMCIDeviceName 宏)。获得当前使用的设备可以使用WM_CAP_GET_MCI_DEVICE(capGetMCIDeviceName )消息。

控制MCI设备的规格信息保存在CAPTRUEPARMS 数据结构体的数据成员中。MCI兼容的视频源包括录像机(VCR)和光碟。如果fMCIControl 数据成员为TRUE,捕获窗口采用MCI操作。捕获窗口使用dwMCIStartTime 和dwMCIStopTime 来获得开始和结束位置(毫秒)。 如果fMCIControl 数据成员的值为FALSE, dwMCIStartTime 和dwMCIStopTime 的值将被忽略不见。

你可以使用Media Player 去快速检查MCI设备是否正确地连接到了你的系统上,如果在视频显示显示了图像,就表示这个视频源正确连接到了捕获硬件上。

步进帧(step-frame)捕获控制的规格信息保存在CAPTRUEPARMS 数据结构体的数据成员中。步进帧(step-frame)捕获除了使用视频捕获要用的数据成员外,还使用其他的数据成员:fStepMCIDevice , fStepCaptureAt2x , 和 wStepCaptureAverageFrames 。如果数据成员fStepMCIDevice 的值为TRUE,捕获窗口采用步进帧(step-frame)捕获。捕获窗口将使用这两个参数来指定捕获的开始和结束位置(dwMCIStartTime 和dwMCIStopTime 毫秒)。捕获窗口使用fStepCaptureAt2x 来决定捕获硬件捕获的视频帧使用两个普通的分辨率。使用 wStepCaptureAverageFrames 来指定捕获时每帧图像使用的时间大小。

    如果在一个步进帧(step-frame)捕获中,指定fStepCaptureAt2x 为TRUE,那么捕获硬件将使用两个指定的解析度来进行捕获(高和宽的解析度都是双倍的)。它使用软件,在指定的解析度的基础上改写图像的象素,让其成为更高解析度的图像。如果硬件不支持基于硬件的批量处理,你也可以使用该选项。并且捕获为RGB格式。

注意:  如果你的硬件步支持基于硬件的批量处理(hardware-based decimation), it can capture samples at a higher rate than specified and use these additional samples to obtain color definitions that are more consistent with the original image. The additional samples are discarded after they are used, and the hardware passes samples to the capture driver at the specified rate。

如果指定了步进帧捕获, wStepCaptureAverageFrames 成员用于指定捕获一帧图像要使用的时间,它是一个采样的标准时间。以后捕获图像捕获平均时间都会基于这个时间。采用这种机制,降会减少在一个图像帧的随机数字化噪音。这个数据成员的标准值是5。

关于MCI的信息可以查看MSDN上的信息。

六、高级捕获选项

这节描述在一个捕获操作中,你还可以进行的其他选择。

l     测量视频质量

l     用户初始化捕获

l     和调色板一起工作

l     在AVI文件中的嵌入信息块

l     用户数据消息(Messages)

测量视频质量

测量视频质量的一个方法是去限定在一个捕获操作期间丢掉的捕获图像帧的数字。当流捕获完成后,质量 = 丢掉的帧 / 所有的帧。如果这个数(百分数)大于wPercentDropForError 的值,AVICap将发一个错误信息给错误回调函数。WPercentDropForError 是CAPTUREPARMS 数据结构体的一个数据成员。

通过WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureGetSetup 宏)可以得到当前设定的丢掉帧的限定值。同样对wPercentDropForError 进行修改,再把修改后的数据结构体发送给捕获窗体就可以完成对限定值的修改。WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureSetSetup ), wPercentDropForErrorm 默认值10 (10%)。

用户初始化捕获

   通过WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureGetSetup 宏)可以得到当前用户初始化捕获的状态值。该值存放在fMakeUserHitOKToCapture 中。在开始一个捕获会话前,设置该值为TRUE,可以为用户提供精确的控制。系统为所有的音视频分配好数据缓存区后,AVICap会显示一个对话框。它让用户清除因为软件初始化导致的捕获延迟。如果你的应用程序为视频数据分配的数据缓存区很小,那么这个对话框可能就没的必要了。该值的默认值是FALSE。

和调色板一起工作

    最初,如果视频捕获格式需要一个调色板,那么捕获窗口将使用捕获驱动提供的调色板来代替。这个调色板可能由灰度值,或者可选的彩色值组成。使用WM_CAP_PAL_PASTE或者WM_CAP_PAL_OPEN消息(capPalettePaste 或capPaletteOpen )可以获得一个现存的调色板去替换默认的调色板。你还可以创建一个自定义的调色板去替换默认的调色板,你要使用WM_CAP_PAL_AUTOCREATE 或者 WM_CAP_PAL_MANUALCREATE消息 ( capPaletteAuto 或 capPaletteManual )。当你替换了调色板后,捕获窗体和驱动程序将使用替换后的调色板,直到你创建或打开其他的调色板为止。

WM_CAP_PAL_AUTOCREATE 或者 WM_CAP_PAL_MANUALCREATE 消息将创建一个基于当前视频输入最优化的调色板。这个自定义的调色板将为视频提供一个最好的颜色逼真度,因为这个调色板的颜色是基于这个视频的。捕获窗口创建一个采样颜色的3维柱状图。它会减小真实颜色和渐近色间的值。

在发送WM_CAP_PAL_AUTOCREATE消息时, 你必须指定AVICap采样的帧数以及调色板的颜色尺寸。在指定帧数时,要保证帧数足够大以保证所有的视频颜色可以被采样收集到。

   使用WM_CAP_PAL_MANUALCREATE消息可以对当前帧进行采样。通过该消息,进行几次手动选择帧采样操作,你可以创建自己的调色板,它包含了你想要的颜色信息。

一个调色板可以包含256种颜色。如果你要合并调色板,或者在视频队列中同时在显示其他视频或图像。你可以去使用一个小的颜色集合,这样不同图像或视频的颜色就可以共存了。

使用WM_CAP_PAL_SAVE消息(capPaletteSave ),可以保促一个新的调色板。通过WM_CAP_PAL_OPEN消息还可以得到当前的调色板。你可以在调色板处理前保存一个调色板,或者为其他应用程序使用去保存一个调色板。

使用WM_CAP_PAL_PASTE可以把剪贴板中的调色板粘贴到捕获窗口中。捕获窗口通过这个调色板到捕获驱动。其他程序可以拷贝调色板到剪贴板中。你也可以把调色板粘贴到剪贴板中。使用WM_CAP_ENDIT_COPY消息(capEditCopy )。它将拷贝视频缓存区(包括调色板)到剪贴区。

在AVI 文件中的嵌入信息块

你可以在一个AVI文件中插入信息块,比如文本或者自定义的数据。通过使用下面的消息:WM_CAP_FILE_SET_INFOCHUNK(capFileSetInfoChunk )。可以使用这个消息还可以清除掉一个AVI文件中的信息块。

用户数据消息

    通过使用WM_CAP_GET_USER_DATA和WM_CAP_SET_USER_DATA消息可以关联数据到一个捕获窗体。(capGetUserData 和 capSetUserData 宏)。使用…Get…消息可以得到一个LONG数据值,可以通过_Set_消息去设置该值。

七、AVICap回调函数

    你的应用程序可以为一个捕获窗口注册一些回调函数,它们可以告诉你的应用程序一些变化。比如捕获状态发生变化了,或者有错误发生了,音视频缓存区可使用了。下面的消息设置回调函数。

消      息 说      明

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(产生?)

转自blog.csdn.net/suntaoznz  

继续阅读