Windows Embedded Compact 7中的多媒体编程(下)

10.3摄像头捕捉示例

  10.3.1摄像头捕捉概述

  现在很多嵌入式电脑、智能手机上都配有内置摄像头,用户可以非常方便地使用摄像头进行监控视频、录像视频以及抓拍图片。微软提供了一套WDM视频采集流驱动标准,大多厂家也都遵循此标准,这样就使开发人员开发上端应用程序非常方便。封装成视频采集过滤器(Fiker),此Filter -般会包含最基本的捕捉Pin和静态捕捉Pin.还可以包含预览Piri,这样就可以使开发人员基于DSHOW技术非常方便地开发上端应用程序。如图10-10示的是视频过滤器连接图。

                  图10-10视频捕捉过滤器连接图

 DSHOW提供了一个辅助组件Capture Graph Builder,使用Capture Oraph Builder组件将会非常方便地创建视频捕捉过滤器,Capture Graph Builder组件在DSHOW中采用ICaptureGraphBuilder2接口实现。开发视频捕捉应用程序的第1步就是调用CoCreatelnstance创建Capture Graph Builder组件和Filter Graph Manager组件,如图10-11所示。

              图10-11创建Capture Graph Builder组件和Filter Graph Manager组件

    将Capture Oraph Builer组件和Filter Graph Manager组件关联起来,即初始化Capter GraphBuilder组件。调用ICaptureGraphBuilder2接口的SetFilterGraph方法,将Filter Graph Manager对象指针设置给它,具体示意如图10-12所示。

图 10-12初始化Capter Graph Builder组件

  下面将通过摄像头捕捉示例来详细介绍如何使用DSHOW技术来预览视频、录像视频文件以及拍照。

10.3.2摄像头捕捉示倒

 (1)建立新项目。使用VS2008 MFC智能设备应用程序向导创建一个基于对话框的应用程序CameraDemo,编译环境设置为yinchengOSSDK。

(2)新建CPropertyBag类,用于实现IPropertyBag接口。由于在后面会调用IPropertyBag接口来设置摄像头设备的相关属性,如指定视频捕捉设备名等,因此在这里要先实现IPropertyBag接口,本接口的实现完全参考Microsogt中的DEMO.CProperWBag类的定义如下所示。

#pragma once

struct VAR_LIST

{

VARIANT var;

VAR_LIST *pNext;

BSTR pBSTRName;

};

class CPropertyBag : public IPropertyBag

{  

public:

CPropertyBag();

~CPropertyBag();

HRESULT STDMETHODCALLTYPE

Read(

LPCOLESTR pszPropName, 

VARIANT *pVar, 

IErrorLog *pErrorLog

);

HRESULT STDMETHODCALLTYPE

Write(

LPCOLESTR pszPropName, 

VARIANT *pVar

);

ULONG STDMETHODCALLTYPE AddRef();        

ULONG STDMETHODCALLTYPE Release();        

HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);   

private:

ULONG _refCount;

VAR_LIST *pVar;

};

  

CPropertyBag类的实现如下所示。

#include "StdAfx.h"

#include "PropertyBag.h"

#include <Ocidl.h>

#include <oleauto.h>

//构造函数

CPropertyBag::CPropertyBag() : _refCount(1), pVar(0)

{       

}

//析构函数

CPropertyBag::~CPropertyBag()

{

VAR_LIST *pTemp = pVar;

HRESULT hr = S_OK;

while(pTemp)

{

VAR_LIST *pDel = pTemp;

VariantClear(&pTemp->var);

SysFreeString(pTemp->pBSTRName);

pTemp = pTemp->pNext;

delete pDel;

}

}

//属性读方法

HRESULT STDMETHODCALLTYPE

CPropertyBag::Read(LPCOLESTR pszPropName, 

   VARIANT *_pVar, 

   IErrorLog *pErrorLog)

{

VAR_LIST *pTemp = pVar;

HRESULT hr = S_OK;

while(pTemp)

{

if(0 == wcscmp(pszPropName, pTemp->pBSTRName))

{

hr = VariantCopy(_pVar, &pTemp->var);

break;

}

pTemp = pTemp->pNext;

}

return hr;

}

//属性写方法

HRESULT STDMETHODCALLTYPE

CPropertyBag::Write(LPCOLESTR pszPropName, 

VARIANT *_pVar)

{

HRESULT hr = S_OK;

VAR_LIST *pTemp = new VAR_LIST();

ASSERT(pTemp);

if( !pTemp )

{

return E_OUTOFMEMORY;

}

VariantInit(&pTemp->var);

pTemp->pBSTRName = SysAllocString(pszPropName);

pTemp->pNext = pVar;

pVar = pTemp;

return VariantCopy(&pTemp->var, _pVar);

}

ULONG STDMETHODCALLTYPE 

CPropertyBag::AddRef() 

{

return InterlockedIncrement((LONG *)&_refCount);

}

ULONG STDMETHODCALLTYPE 

CPropertyBag::Release() 

{

ASSERT(_refCount != 0xFFFFFFFF);

ULONG ret = InterlockedDecrement((LONG *)&_refCount);    

if(!ret) 

delete this; 

return ret;

}

HRESULT STDMETHODCALLTYPE 

CPropertyBag::QueryInterface(REFIID riid, void** ppv) 

{

if(!ppv) 

return E_POINTER;

if(riid == IID_IPropertyBag) 

*ppv = static_cast<IPropertyBag*>(this);

else 

return *ppv = 0, E_NOINTERFACE;

return AddRef(), S_OK;

}

(3)新建CEricCamera类,用于封装摄像头视频操作。

CEricCamera类是一个通用c++类,无基类。其类图如图10-13所示。

                 图 10-13CEricCamera类是一个通用c++

 CEricCamera类中将提供6个共有方法。

·OetFirstCameraDriver方法用于获取系统中注册的第一个视频捕捉设备名,以便指定后面要预览、捕捉的是哪个摄像头。

·FreeDShow方法用于释放创建的DirectShow接口对象。

·PreviewCamera方法是最为重要的,此方法的直接效果是在窗体上预览视频。在此方法里还做了大量视频过滤器的创建以及相关接口的初始化、渲染工作,例如创建视频捕捉过滤器,并指定录像文件编码格式以及创建静态捕捉STILL PIN。这里需要注意的是,在进行录像、抓拍前,要确保先调用PreviewCamera方法,因为此方法还负责DirectShow接口的初始化工作。

·StartRecard方法和StopRecord方法分别用于开始录像和停止录像,这里录像采用的是WMV9 DMO Encoder编码方式。

·SnapPicture方法用于抓拍视频中的一幅图片,并保存到文件中,这里图像的文件格式为JPG

下面来介绍CEricCamera类的创建过程。

1)CEricCamera类添加DShow接口私有变量,这些接口将综合起来实现摄像头视频的预览、录像、抓拍等助能,具体定义如下:

   #pragma once

#include <streams.h>

#include <dmodshow.h>

#include <dmoreg.h>

#include <wmcodecids.h>

class CEricCamera

{

public:

CEricCamera(void);

~CEricCamera(void);

private:

//-----DSHOW接口-----------

//视频捕捉图形管理器接口

CComPtr<ICaptureGraphBuilder2> m_pCaptureGraphBuilder;

//图形管理器接口

CComPtr<IGraphBuilder> m_pGraphBuilder;

//视频捕捉过滤器

CComPtr<IBaseFilter> m_pVideoCaptureFilter;

//视频设备属性页

CComPtr<IPersistPropertyBag>    m_pPropertyBag ;

//静态捕捉PIN过滤器

CComPtr<IBaseFilter>         m_pImageSinkFilter;

//媒体播放控制器

CComPtr<IMediaControl> m_pMediaControl  ;

//视频窗口接口

CComPtr<IVideoWindow> m_pVideoWindow ;

//视频播放进度控制接口

CComPtr<IMediaSeeking> m_pMediaSeeking;

//媒体事件接口

CComPtr<IMediaEvent> m_pMediaEvent;

public:

//释放DSHOW接口

void FreeDShow();

public:

//查找第1个摄像头设备名

BOOL GetFirstCameraDriver( WCHAR *pwzName );

public:

//预览视频

BOOL PreviewCamera(HWND hVideoWnd /*视频显示窗口*/

,LPCTSTR strFileName /*录像文件名*/);

public:

//开始录像

BOOL StartRecord();

//停止录像

BOOL StopRecord();

public:

//抓拍

BOOL SnapPicture(LPCTSTR strFileName /*图象文件名,格式为JPG*/);

};

所以应包含如下DSHOW头文件

#include <wmcodecids.h>

另外,在工程中,应添加dmoguids.libstrmiids.lib两个静态库链接。具体操作为选择“CameraDemo属性页”一“链接器”一“输入”一“附加依赖项”,输入dmoguids.lib strmiids.lib。这里再定义CHKERR两个宏函数,用于DSHOW接口方法返回值的判断。这两个宏函数的定义如下:

    #define CHKtx) do{  if (FAILED(hResult - (x))){goto Cleanup;}}whileIFALSEl;

    #define ERR(x}do{ hResult -xj goto Cleanup;} while(FALSE);

    2)CEricCamera类添加FreeDShow私有方法,用于释放创建的DShow对象。该函数的定义如下;

    public

    //释放DSHOW接口

    void  FreeDShow()j

  FreeDShow方法的实现如程序清单10-14所示。

void CEricCamera::FreeDShow()

{

//释放IMediaControl接口

if (m_pMediaControl  != NULL)

{

m_pMediaControl->Stop();

m_pMediaControl.Release();

m_pMediaControl = NULL;

}

//释放IPropertyBag接口

if (m_pPropertyBag != NULL)

{

m_pPropertyBag.Release();

m_pPropertyBag = NULL;

}

//释放IVideoWindow接口

if (m_pVideoWindow != NULL)

{

//隐藏视频窗口

m_pVideoWindow->put_Visible(OAFALSE);

//设置视频播放窗口句柄为空

m_pVideoWindow->put_Owner(NULL);

m_pVideoWindow.Release();

m_pVideoWindow = NULL;

}

//释放IMediaSeeking接口

if (m_pMediaSeeking != NULL)

{

m_pMediaSeeking.Release();

m_pMediaSeeking = NULL;

}

//释放IMediaEvent接口

if (m_pMediaEvent != NULL)

{

m_pMediaEvent.Release();

m_pMediaEvent = NULL;

}

//释放IVideoCaptureFilter接口

if (m_pVideoCaptureFilter != NULL )

{

m_pVideoCaptureFilter.Release();

m_pVideoCaptureFilter = NULL;

}

//释放IImageSinkFilter接口

if (m_pImageSinkFilter != NULL )

{

m_pImageSinkFilter.Release();

m_pImageSinkFilter = NULL;

}

//释放IGraphBuilder接口

if (m_pGraphBuilder != NULL)

{

m_pGraphBuilder.Release();

m_pGraphBuilder = NULL;

}

//释放ICaptureGraphBuilder2接口

if (m_pCaptureGraphBuilder != NULL)

{

m_pCaptureGraphBuilder->SetFiltergraph(NULL);

m_pCaptureGraphBuilder.Release();

m_pCaptureGraphBuilder = NULL;

}

}

  3)实现CEricCamera类的构造函数和析构函数。在构造函数里初始化COM环境;在析构函数里释放COM接口,并释放COM环境。

  CEricCamera类构造函数和析构函数的实现如下所示。

  //构造函数

 CEricCamera::CEricCamera(void)

{

//初始化 COM 环境

CoInitialize(NULL); 

}

//析构函数

CEricCamera::~CEricCamera(void)

{

//释放DSHOW接口

FreeDShow();

//释放COM 环境

CoUninitialize();

}

  4)添加GetFirstCameraDriver方法,用于获取第一个视频采集设备名。在嵌入式电脑中,一般默认只会有1个注册的视频采集设备,默认名一般为CAMI:。但是有些嵌入式电脑中,也可能注册多个视频采集设备。这些注册的视频采集设备可以是实际的摄像头.也可以是虚拟的摄像头。GetFirstCameraDriver方法用于获取系统中注册的第一个视频采集设备名,定义如下:

  public:

    //查找第一个摄像头设备名

    BOOL GetFirstCameraDriver( WCHAR *pwzName );

    GetFirstCameraDriver方法的实现如下所示。

/*

*函数介绍: 查找第1个摄像头设备

*入口参数: pwzName : 存储摄像头设备名称,应提前分配好内存

*出口参数:pwzName :存储摄像头设备名称

*返回值:TRUE:成功;FALSE:失败

*/

BOOL CEricCamera::GetFirstCameraDriver( WCHAR *pwzName )

{

HRESULT hr = S_OK;

HANDLE handle = NULL;

DEVMGR_DEVICE_INFORMATION di;

GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 };

if( pwzName == NULL )

{

return FALSE;

}

di.dwSize = sizeof(di);

//查到第1个摄像头设备

handle = FindFirstDevice( DeviceSearchByGuid, &guidCamera, &di );

if(( handle == NULL ) || ( di.hDevice == NULL ))

{

FindClose( handle );

return FALSE;

}

//复制设备名

StringCchCopy( pwzName, MAX_PATH, di.szLegacyName );

//关闭查找设备

FindClose( handle );

return TRUE;

}

    5)添加PreviewCamera方法,用于初始化和预览视频。在PreviewCamera方法中建立了整个视频捕捉链图,包括预览视频过滤器、捕捉视频过滤器以及抓拍静态图过滤器。此方法是CEricCamera类的核心,理解了此方法,也就大概了解了视频捕捉程序的流程。

  在实现此函数之前,先添加对CPropertyBag类的引用。

  tinclude”PropertyBag.h”

  PreviewCamera方法的定义如下:

  public

    //预览视频

    BOOL PreviewCamera(HWND hVideoWnd ,LPCTSTR strFileName /*录像文件名*/)

PreviewCamera方法的实现如下所示。

/*

*函数介绍: 初始化DSHOW接口,并预览视频

*入口参数: hVideoWnd : 显示视频的窗口句柄

strFileName :录像文件名

*出口参数:()

*返回值:TRUE:成功;FALSE:失败

*/

BOOL CEricCamera::PreviewCamera(HWND hVideoWnd /*视频显示窗口*/

,LPCTSTR strFileName /*录像文件名*/)

{

HRESULT hResult = S_FALSE;

LONGLONG dwStart = 0, dwEnd = 0;

WORD     wStartCookie = 1, wEndCookie = 2;

CRect rectVideo;  //视频窗口尺寸

CComVariant   varCamName;  //定义摄像头设备名称

WCHAR       wzDeviceName[ MAX_PATH + 1 ]; //摄像头设备名称

CPropertyBag  PropBag;  //摄像头属性页

//--定义录像用到的编码、写文件等FILTER

CComPtr<IBaseFilter>            pVideoEncoder;

CComPtr<IBaseFilter>            pASFMultiplexer;

CComPtr<IFileSinkFilter>        pFileSinkFilter;

CComPtr<IDMOWrapperFilter>      pWrapperFilter;

//默认先释放DSHOW接口

FreeDShow();

//1,创建ICaptureGraphBuilder2接口,用于管理媒体捕捉对象

CHK(m_pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder));

//2,创建IGraphBuilder接口

CHK(m_pGraphBuilder.CoCreateInstance(CLSID_FilterGraph));

//3,

CHK(m_pCaptureGraphBuilder->SetFiltergraph(m_pGraphBuilder ));

//4,得到IMediaControl接口,用于控制流播放

CHK(m_pGraphBuilder.QueryInterface(&m_pMediaControl)); 

//5,得到IMediaSeeking接口,用于设置播放位置

CHK(m_pGraphBuilder.QueryInterface(&m_pMediaSeeking)); 

//6,得到m_pMediaEvent接口,用于获取媒体事件

CHK(m_pGraphBuilder.QueryInterface(&m_pMediaEvent)); 

//7,创建视频捕捉Filter

CHK(m_pVideoCaptureFilter.CoCreateInstance(CLSID_VideoCapture));

//8,得到视频捕捉属性页接口

CHK(m_pVideoCaptureFilter->QueryInterface(&m_pPropertyBag ));

//9,选择视频捕捉设备

//得到第1个视频捕捉设备名。

if (!GetFirstCameraDriver( wzDeviceName ))

{

goto Cleanup;

}

varCamName = wzDeviceName;

if(( varCamName.vt == VT_BSTR ) == NULL ) {

return FALSE;

}

//设置视频捕捉为第1个捕捉设备

PropBag.Write( L"VCapName", &varCamName );   

CHK(m_pPropertyBag->Load( &PropBag, NULL ));

//10,将视频捕捉FILTER添加到FILTER图中。

CHK(m_pGraphBuilder->AddFilter( m_pVideoCaptureFilter, L"Video capture source" ));

//11,创建IDMOWrapperFilter接口

CHK(pVideoEncoder.CoCreateInstance( CLSID_DMOWrapperFilter ));

CHK(pVideoEncoder.QueryInterface( &pWrapperFilter ));

//12,加载WMV9 DMO

CHK(pWrapperFilter->Init( CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER ));

// 13,将编码器FILTER加入到过滤器图中

CHK(m_pGraphBuilder->AddFilter( pVideoEncoder, L"WMV9 DMO Encoder" ));

//14,创建ASF多路(复用)器,并加入到过滤器图中

CHK(m_pCaptureGraphBuilder->SetOutputFileName( &MEDIASUBTYPE_Asf,strFileName, &pASFMultiplexer, &pFileSinkFilter ));

//15,渲染预览视频PIN

CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_PREVIEW,

&MEDIATYPE_Video, m_pVideoCaptureFilter,

NULL, NULL ));

//16,设置视频预览窗口

CHK(m_pGraphBuilder.QueryInterface(&m_pVideoWindow));

设置视频播放的WINDOWS窗口

m_pVideoWindow->put_Owner((OAHWND)hVideoWnd);

m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);

//设置视频尺寸

GetClientRect(hVideoWnd,&rectVideo);

m_pVideoWindow->SetWindowPosition(0,0,rectVideo.Width(),rectVideo.Height());

m_pVideoWindow->put_Visible(OATRUE);

//17,渲染捕捉PIN, 用于录像

CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pVideoEncoder, pASFMultiplexer ));

//18,创建Still Pin,用于抓图

CHK(m_pImageSinkFilter.CoCreateInstance(CLSID_IMGSinkFilter));

CHK(m_pGraphBuilder->AddFilter(m_pImageSinkFilter, L"Still image filter" ));

CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_STILL, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, m_pImageSinkFilter ));

//19,设置捕捉流暂停

CHK(m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, 0, 0 ,0,0 ));

//20,预览视频

CHK(m_pMediaControl->Run());

Sleep(1000);

Cleanup:

//释放接口

if (pVideoEncoder != NULL)

{

pVideoEncoder.Release();

pVideoEncoder = NULL;

}

if (pASFMultiplexer != NULL)

{

pASFMultiplexer.Release();

pASFMultiplexer = NULL;

}

if (pFileSinkFilter != NULL)

{

pFileSinkFilter.Release();

pFileSinkFilter = NULL;

}

if (pWrapperFilter != NULL)

{

pWrapperFilter.Release();

pWrapperFilter = NULL;

}

if( FAILED( hResult ))

{

return FALSE;

}

else

{

return TRUE;

}

}

StartRecordStopRecord方法的实现如下所示。

/*

*函数介绍:开始录像

*入口参数: ()

*出口参数:()

*返回值:TRUE:成功;FALSE:失败

*/

BOOL CEricCamera::StartRecord()

{

LONGLONG dwStart = 0, dwEnd = 0;

WORD     wStartCookie = 1, wEndCookie = 2;

HRESULT hResult = 0;

    if( m_pCaptureGraphBuilder == NULL )

    {

       return FALSE;

    }

//开始录制

dwStart=0;

dwEnd=MAXLONGLONG;

hResult = m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, NULL, &dwStart, &dwEnd, wStartCookie, wEndCookie );

TRACE(L"开始录制\n");

if( FAILED( hResult ))

{

return FALSE;

}

else

{

return TRUE;

}

}

/*

*函数介绍:停止录像

*入口参数: ()

*出口参数:()

*返回值:TRUE:成功;FALSE:失败

*/

BOOL CEricCamera::StopRecord()

{

HRESULT   hResult = S_OK;

LONGLONG  dwStart = 0, dwEnd = 0;

WORD      wStartCookie = 1, wEndCookie = 2;

LONG lEventCode = 0;

LONG lParam1 = 0;

LONG lParam2 = 0;

    if( m_pCaptureGraphBuilder == NULL )

    {

       return FALSE;

    }

//停止视频捕捉流,并存入到文件中

dwStart = 0;

hResult = m_pMediaSeeking->GetCurrentPosition( &dwEnd );

hResult = m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, NULL, &dwStart, &dwEnd, wStartCookie, wEndCookie );

//检测录像文件生成结束

while (true)

{

m_pMediaEvent->GetEvent( &lEventCode, &lParam1, &lParam2, INFINITE );

m_pMediaEvent->FreeEventParams( lEventCode, lParam1, lParam2 );

if( lEventCode == EC_STREAM_CONTROL_STOPPED ) {

TRACE(L"录像停止\n");

break;

}

}

//

if( FAILED( hResult ))

{

return FALSE;

}

else

{

return TRUE;

}

}

7)掭加SnapPicture方法,用于拍照并保存为JPG图像文件。SnapPicture方法的定义如下。

    public

    //抓拍

BOOL CEricCamera::SnapPicture(LPCTSTR strFileName /*图象文件名,格式为JPG*/)

 SnapPicture方法实现如下所示。

/*

*函数介绍:抓拍

*入口参数: strFileName:抓拍保存的文件名,图象格式为JPG.

*出口参数:()

*返回值:TRUE:成功;FALSE:失败

*/

BOOL CEricCamera::SnapPicture(LPCTSTR strFileName /*图象文件名,格式为JPG*/)

{

HRESULT hResult = S_FALSE;

CComPtr<IFileSinkFilter> pFileSink;

CComPtr<IUnknown>  pUnkCaptureFilter;

CComPtr<IPin>  pStillPin;

CComPtr<IAMVideoControl> pVideoControl;

    if( m_pCaptureGraphBuilder == NULL )

    {

       goto Cleanup;

    }

//得到IFileSinkFilter接口

CHK( m_pImageSinkFilter.QueryInterface( &pFileSink ));

//设置抓拍保存的图象文件名

CHK( pFileSink->SetFileName( strFileName, NULL ));

//得到StillPin

CHK( m_pVideoCaptureFilter.QueryInterface( &pUnkCaptureFilter ));

CHK( m_pCaptureGraphBuilder->FindPin( pUnkCaptureFilter, PINDIR_OUTPUT, &PIN_CATEGORY_STILL, &MEDIATYPE_Video, FALSE, 0, &pStillPin ));

//设置抓拍动作

CHK( m_pVideoCaptureFilter.QueryInterface( &pVideoControl ));

CHK( pVideoControl->SetMode( pStillPin, VideoControlFlag_Trigger ));

Cleanup:

//释放DSHOW接口

if (pFileSink != NULL)

{

pFileSink.Release();

pFileSink = NULL;

}

if (!pUnkCaptureFilter != NULL)

{

pUnkCaptureFilter.Release();

pUnkCaptureFilter = NULL;

}

if (pStillPin != NULL)

{

pStillPin.Release();

pStillPin = NULL;

}

if (pVideoControl != NULL)

{

pVideoControl.Release();

pVideoControl = NULL;

}

if( FAILED( hResult ))

{

return FALSE;

}

else

{

return TRUE;

}

}

    至此,CEricCamera类就实现完毕了。下面可以非常方便地基于此类来演示如何预览摄像头视频、录像、抓拍等操作。

1)设计主窗口,演示摄像头视频预览、录像、抓拍功能。

2)CCameraDemoDlg类添加m_Camera成员变量,类型为之前创建的CEricCamera类。

定义如下:

    private

    CEricCamera m_Camera; //摄像头控制类

    备注:由于引用了CEricCamera类,因此要在CameraDemoDlg.h文中件添加对CEricCamera类定义文件的引用。

    tlnclude "EricCamera.h”

3)实现“预览”按钮单击事件,用于初始化摄像头,并预览视频。具体代码清单如下所示。

    //预览视频

void CCameraDemoDlg::OnBnClickedBtnPreview()

{

CWnd *pVideoWnd = (CWnd*)GetDlgItem(IDC_WND_VIDEO);

m_Camera.PreviewCamera(pVideoWnd->m_hWnd,L"\\EricVideo.asf");

}

4)实现“抓拍”按钮单击事件,用于将视频中的一帧图片抓拍并保存到文件中。具体代码如程序清单如下所示。

//抓拍图片

void CCameraDemoDlg::OnBnClickedBtnSnap()

{

//定义媒体播放文件名

CString strFileName;

TCHAR szFilters[]= _T("Image File (*.jpg)|*.jpg||");

CFileDialog fileDlg (FALSE, _T("Save Image files"), _T("\\My   Documents\\"),

OFN_OVERWRITEPROMPT , szFilters, this);

//打开文件选择对话框

if( fileDlg.DoModal () !=IDOK )

{

return;

}

//得到要保存的图象文件名

strFileName = fileDlg.GetPathName();

//抓拍

m_Camera.SnapPicture(strFileName);

}

  5)实现“录像”按钮单击事件。在“录像”按钮单击事件中,首先开始录制视频,然后启用定时器,5秒后,停止录像。因此这里只录制了5秒的视频。“录像”按钮单击事件的实现如下所示.

//录像

void CCameraDemoDlg::OnBnClickedBtnRecord()

{

if (m_Camera.StartRecord())

{

//启动定时器,录制5秒视频

SetTimer(1,5000,NULL);

}

}

这里启用了定时器来终止录像,因此要先实现WINDOWS定时器WM_TIMER函数。定时器函数的实现如下所示。

//5秒后停止录像

void CCameraDemoDlg::OnTimer(UINT_PTR nIDEvent)

{

KillTimer(1);

if (m_Camera.StopRecord())

{

AfxMessageBox(L"录像完毕");

}

else

{

AfxMessageBox(L"录像失败");

}

CDialog::OnTimer(nIDEvent);

}

  至此,摄像头示例就实现完毕了。

将该程序编译成可执行文件,启动Windows Embedded Compact 7虚拟机,复制到共享目录,执行之。如图10-14

10-14选择运行程序运行之

效果如图10-15

10-15程序效果图

在虚拟机上共享USB串口,挂接一个摄像头,截取个美女的照片,如下图10-16

所示

10-16程序效果图

           

10.4小节

本章主要讲解了多媒体播放与视频捕获的多媒体开发,读者需要认真实践工程代码案例,以便在自己开发应用程序的时候能够得心应手。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡耀文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值