您的位置:首页 > 编程语言

WinCE系统下基于DirectShow的摄像头应用编程

2012-04-19 09:33 387 查看
大家可以对比我的另一篇文章学习:
XP下基于DirectShow的摄像头采集

转载自:

/article/1872895.html



在WinCE设备上使用摄像头时,一般都是向厂家索要驱动。对于摄像头设备,WinCE会有一个标准的流驱动框架,大多数厂商就会按照这个标准完成WinCE系统下的摄像头驱动程序。

这样程序员通过Pin连接的Filter Graph来完成摄像头的视频采集应用。前提是视频采集设备被封装成Filter,并包含相应的Pin(比如Capture Pin、Preview Pin)。并注册到了系统里,所以我们能通过

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

找到此设备。

关于{ 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 };

一般大家可以在WCE的BSP包中的cesysgen\oak\inc\camera.h里找到。



这里以汪兵老师封装的CEricCamera为例,简单学习一下。

(a) 首先本例中使用到的DirectShow接口一共有9个,如下:

[cpp]
view plaincopyprint?

//视频捕捉图形管理器接口
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;

(b) 下面是利用这些DirectShow接口及其方法,完成摄像头视频采集的基本流程。

(1) 创建Capture Gpaph Builder组件,而该组件由ICaptureGraphBuilder2接口实现,所以首先创建ICaptureGraphBuilder2接口。

[cpp]
view plaincopyprint?

m_pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder);

(2) 创建IGraphBuilder接口。

[cpp]
view plaincopyprint?

m_pGraphBuilder.CoCreateInstance(CLSID_FilterGraph);

(3)将ICaptureGraphBuilder2接口与IGraphBuilder接口连接起来,即调用ICaptureGraphBuilder2接口的SetFilterGraph方法,并将IGraphBuilder接口对象指针传递给它。以便后面将Capture到的数据通过Filter Graph构造成视频数据。

[cpp]
view plaincopyprint?

m_pCaptureGraphBuilder->SetFiltergraph(m_pGraphBuilder );

(4) 获取IMediaControl接口,后面将通过该接口的Run,Pause,Stop方法控制视频流的播放。

[cpp]
view plaincopyprint?

m_pGraphBuilder.QueryInterface(&m_pMediaControl);

(5) 获取IMediaSeeking接口,用于对多媒体数据流的播放位置等属性进行控制。如GetCurrentPositions获得当前播放位置。

[cpp]
view plaincopyprint?

m_pGraphBuilder.QueryInterface(&m_pMediaSeeking);

(6) 获取m_pMediaEvent接口,用于获取Filter Graph产生的事件。

[cpp]
view plaincopyprint?

m_pGraphBuilder.QueryInterface(&m_pMediaEvent);

(7) 创建视频捕捉过滤器(Filter)。

[cpp]
view plaincopyprint?

m_pVideoCaptureFilter.CoCreateInstance(CLSID_VideoCapture)

(8) 通过(7)中创建的视频捕捉过滤器,获取视频捕捉属性页接口(IPersistPropertyBag)。

[cpp]
view plaincopyprint?

m_pVideoCaptureFilter->QueryInterface(&m_pPropertyBag);

(9) 得到视频捕捉设备名。

[cpp]
view plaincopyprint?

GetFirstCameraDriver(wzDeviceName );
varCamName = wzDeviceName;

(10) 初始化(8)中获取的视频捕捉属性页接口m_pPropertyBag,设置视频捕捉设备名。

[cpp]
view plaincopyprint?

PropBag.Write(TEXT("VCapName"), &varCamName);
m_pPropertyBag->Load(&PropBag, NULL);

[cpp] 
view plaincopyprint?

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

  (12) 创建IDMOWrapperFilter接口。

[cpp] 
view plaincopyprint?

CComPtr<IBaseFilter> pVideoEncoder;  
pVideoEncoder.CoCreateInstance(CLSID_DMOWrapperFilter);  
CComPtr<IDMOWrapperFilter> pWrapperFilter;  
pVideoEncoder.QueryInterface(&pWrapperFilter);  

  (13) 利用(12)中创建的IDMOWrapperFilter接口pWrapperFilter,加载WMV9 DMO Encoder(WMV格式的编码器),因为我们将使用该编码器将摄像头采集到的视频数据编码为WMV格式的视频文件。

[cpp] 
view plaincopyprint?

pWrapperFilter->Init(CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER);    

  (14) 将WMV9编码器添加到Filter Graph(过滤器图)中。

[cpp] 
view plaincopyprint?

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

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

[cpp] 
view plaincopyprint?

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

  (16) 渲染预览视频Pin。

[cpp] 
view plaincopyprint?

m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, NULL);    

  (17) 获取IVideoWindow接口,用于设置多媒体播放窗口的属性。如put_Owner指定视频播放窗口,put_WindowStyle设置视频窗口风格属性。

[cpp] 
view plaincopyprint?

m_pGraphBuilder.QueryInterface(&m_pVideoWindow);    

  (18) 设置视频播放窗口及窗口风格。

[cpp] 
view plaincopyprint?

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);  

  (19) 渲染捕捉Pin用于录像。

[cpp] 
view plaincopyprint?

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

  (20) 创建Still Pin(静态Pin)用于抓图。下面的代码首先创建静态捕捉Pin过滤器接口m_pImageSinkFilter,然后将其添加到Filter Graph(过滤器图)中,最后渲染Still Pin(静态Pin)。

[cpp] 
view plaincopyprint?

m_pImageSinkFilter.CoCreateInstance(CLSID_IMGSinkFilter);  
m_pGraphBuilder->AddFilter(m_pImageSinkFilter, TEXT("Still image filter"));  
m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_STILL, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, m_pImageSinkFilter);  

  (21) 设置捕捉流暂停。

[cpp] 
view plaincopyprint?

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

  (22) 预览视频

[cpp] 
view plaincopyprint?

m_pMediaControl->Run();    

(c) 下面是汪兵老师封装的CEricCamera类完整源代码,该类主要导出4个公共接口:PreviewCamera预览视频,StartRecord开始录像,StopRecord停止录像,SnapPicture抓拍。

  (1) PropertyBag.h

[cpp] 
view plaincopyprint?

#pragma once   
  
struct VAR_LIST  
{  
    VARIANT var;  
    VAR_LIST *pNext;  
    BSTR pBSTRName;  
};  
  
class CPropertyBag : public IPropertyBag  
{    
public:  
    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);     
    CPropertyBag();  
    ~CPropertyBag();  
private:  
    ULONG _refCount;  
    VAR_LIST *pVar;  
};  

#pragma once

struct VAR_LIST
{
    VARIANT var;
    VAR_LIST *pNext;
    BSTR pBSTRName;
};

class CPropertyBag : public IPropertyBag
{  
public:
    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);   
    CPropertyBag();
    ~CPropertyBag();
private:
    ULONG _refCount;
    VAR_LIST *pVar;
};

(2) PropertyBag.cpp

[cpp]
view plaincopyprint?

#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;
}

[cpp] 
view plaincopyprint?

/*----------------------------------------- 
* Copyright (c) 2008 Eric Wong 
* 本版紧供读者参考,不得用于任何商业行为 
* 
* 文件名称:EricCamera.h 
* 文件标识: 
* 摘要:用于封装DSHOW 摄像头预览、录像、抓拍功能 
* 
* 当前版本:1.0 
* 作者:汪兵Eric Wong 
* 完成日期:2008年月日 
* 
* 取代版本: 
* 原作者: 
* 完成日期: 
----------------------------------------*/  
  
#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();  
  
    //查找第个摄像头设备名   
    BOOL GetFirstCameraDriver(WCHAR *pwzName);  
  
    //预览视频   
    BOOL PreviewCamera(HWND hVideoWnd /*视频显示窗口*/, LPCTSTR strFileName /*录像文件名*/);  
  
    //开始录像   
    BOOL StartRecord();  
  
    //停止录像   
    BOOL StopRecord();  
  
    //抓拍   
    BOOL SnapPicture(LPCTSTR strFileName /*图象文件名,格式为JPG*/);  
  
};  

/*-----------------------------------------
* Copyright (c) 2008 Eric Wong
* 本版紧供读者参考,不得用于任何商业行为
*
* 文件名称:EricCamera.h
* 文件标识:
* 摘要:用于封装DSHOW 摄像头预览、录像、抓拍功能
*
* 当前版本:1.0
* 作者:汪兵Eric Wong
* 完成日期:2008年月日
*
* 取代版本:
* 原作者:
* 完成日期:
----------------------------------------*/

#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();

    //查找第个摄像头设备名
    BOOL GetFirstCameraDriver(WCHAR *pwzName);

    //预览视频
    BOOL PreviewCamera(HWND hVideoWnd /*视频显示窗口*/, LPCTSTR strFileName /*录像文件名*/);

    //开始录像
    BOOL StartRecord();

    //停止录像
    BOOL StopRecord();

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

};

(4) EricCamera.cpp

[cpp]
view plaincopyprint?

/*-----------------------------------------
* Copyright (c) 2008 Eric Wong
* 本版紧供读者参考,不得用于任何商业行为
*
* 文件名称:EricCamera.cpp
* 文件标识:
* 摘要:用于封装DSHOW 摄像头预览、录像、抓拍功能
*
* 当前版本:1.0
* 作者:汪兵Eric Wong
* 完成日期:2008年月日
*
* 取代版本:
* 原作者:
* 完成日期:
----------------------------------------*/

#include "StdAfx.h"
#include "EricCamera.h"

#include "PropertyBag.h"

#define CHK( x ) do{ if( FAILED( hResult = ( x ))) { goto Cleanup; }} while( FALSE );
#define ERR( x ) do{ hResult = x; goto Cleanup; } while( FALSE );

//构造函数
CEricCamera::CEricCamera(void)
{
//初始化COM 环境
CoInitialize(NULL);
}

//析构函数
CEricCamera::~CEricCamera(void)
{
//释放DSHOW接口
FreeDShow();
//释放COM 环境
CoUninitialize();
}

/*
*函数介绍:释放DSHOW接口
*入口参数:(无)
*出口参数:(无)
*返回值:TRUE:成功;FALSE:失败
*/
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;
}
}

/*
*函数介绍:查找第个摄像头设备
*入口参数: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);

//查到第个摄像头设备
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;
}

/*
*函数介绍:初始化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,选择视频捕捉设备
//得到第个视频捕捉设备名。
if (!GetFirstCameraDriver( wzDeviceName ))
{
goto Cleanup;
}

varCamName = wzDeviceName;
if(( varCamName.vt == VT_BSTR ) == NULL ) {
return FALSE;
}

//设置视频捕捉为第个捕捉设备
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;
}
}

/*
*函数介绍:开始录像
*入口参数:(无)
*出口参数:(无)
*返回值: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;
}
}

/*
*函数介绍:抓拍
*入口参数: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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: