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

WinCE系统下基于DirectShow的摄像头应用编程 by斜风细雨QQ:253786989    2012-02-17

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

  一般情况下,视频采集设备被封装成Filter,并包含相应的Pin(比如Capture Pin、Preview Pin)。这样程序员就可以通过Pin连接的Filter Graph来完成摄像头的视频采集应用,这里以汪兵老师封装的CEricCamera为例,简单学习一下。

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

  1. //视频捕捉图形管理器接口  
  2. CComPtr<ICaptureGraphBuilder2> m_pCaptureGraphBuilder;  
  3.   
  4. //图形管理器接口  
  5. CComPtr<IGraphBuilder> m_pGraphBuilder;  
  6.   
  7. //视频捕捉过滤器  
  8. CComPtr<IBaseFilter> m_pVideoCaptureFilter;  
  9.   
  10. //视频设备属性页  
  11. CComPtr<IPersistPropertyBag> m_pPropertyBag ;  
  12.   
  13. //静态捕捉PIN过滤器  
  14. CComPtr<IBaseFilter> m_pImageSinkFilter;  
  15.   
  16. //媒体播放控制器  
  17. CComPtr<IMediaControl> m_pMediaControl  ;  
  18.   
  19. //视频窗口接口  
  20. CComPtr<IVideoWindow> m_pVideoWindow ;  
  21.   
  22. //视频播放进度控制接口  
  23. CComPtr<IMediaSeeking> m_pMediaSeeking;  
  24.   
  25. //媒体事件接口  
  26. CComPtr<IMediaEvent> m_pMediaEvent;  

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

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

  1. m_pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder);  

  (2) 创建IGraphBuilder接口。

  1. m_pGraphBuilder.CoCreateInstance(CLSID_FilterGraph);  

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

  1. m_pCaptureGraphBuilder->SetFiltergraph(m_pGraphBuilder );  

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

  1. m_pGraphBuilder.QueryInterface(&m_pMediaControl);  

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

  1. m_pGraphBuilder.QueryInterface(&m_pMediaSeeking);  

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

  1. m_pGraphBuilder.QueryInterface(&m_pMediaEvent);   

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

  1. m_pVideoCaptureFilter.CoCreateInstance(CLSID_VideoCapture)    

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

  1. m_pVideoCaptureFilter->QueryInterface(&m_pPropertyBag);    

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

  1. GetFirstCameraDriver(wzDeviceName );  
  2. varCamName = wzDeviceName;  

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

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

  (11) 将(7)中创建的视频捕捉过滤器接口m_pVideoCaptureFilter添加到Filter Graph(过滤器图)中。

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

  (12) 创建IDMOWrapperFilter接口。

  1. CComPtr<IBaseFilter> pVideoEncoder;  
  2. pVideoEncoder.CoCreateInstance(CLSID_DMOWrapperFilter);  
  3. CComPtr<IDMOWrapperFilter> pWrapperFilter;  
  4. pVideoEncoder.QueryInterface(&pWrapperFilter);  

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

  1. pWrapperFilter->Init(CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER);    

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

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

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

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

  (16) 渲染预览视频Pin

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

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

  1. m_pGraphBuilder.QueryInterface(&m_pVideoWindow);    

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

  1. m_pVideoWindow->put_Owner((OAHWND)hVideoWnd);  
  2. m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);  
  3. GetClientRect(hVideoWnd,&rectVideo);  
  4. m_pVideoWindow->SetWindowPosition(0,0,rectVideo.Width(),rectVideo.Height());  
  5. m_pVideoWindow->put_Visible(OATRUE);  

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

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

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

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

  (21) 设置捕捉流暂停。

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

  (22) 预览视频

  1. m_pMediaControl->Run();    

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

  (1) PropertyBag.h

  1. #pragma once  
  2.   
  3. struct VAR_LIST  
  4. {  
  5.     VARIANT var;  
  6.     VAR_LIST *pNext;  
  7.     BSTR pBSTRName;  
  8. };  
  9.   
  10. class CPropertyBag : public IPropertyBag  
  11. {    
  12. public:  
  13.     HRESULT STDMETHODCALLTYPE Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog);  
  14.     HRESULT STDMETHODCALLTYPE Write(LPCOLESTR pszPropName, VARIANT *pVar);  
  15.     ULONG   STDMETHODCALLTYPE AddRef();          
  16.     ULONG   STDMETHODCALLTYPE Release();          
  17.     HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);     
  18.     CPropertyBag();  
  19.     ~CPropertyBag();  
  20. private:  
  21.     ULONG _refCount;  
  22.     VAR_LIST *pVar;  
  23. };  

  (2) PropertyBag.cpp

  1. #include "StdAfx.h"  
  2. #include "PropertyBag.h"  
  3. #include <Ocidl.h>  
  4. #include <oleauto.h>  
  5.   
  6. //构造函数  
  7. CPropertyBag::CPropertyBag() : _refCount(1), pVar(0)  
  8. {}  
  9.   
  10. //析构函数  
  11. CPropertyBag::~CPropertyBag()  
  12. {  
  13.     VAR_LIST *pTemp = pVar;  
  14.     HRESULT hr = S_OK;  
  15.     while(pTemp)  
  16.     {  
  17.         VAR_LIST *pDel = pTemp;  
  18.         VariantClear(&pTemp->var);  
  19.         SysFreeString(pTemp->pBSTRName);  
  20.         pTemp = pTemp->pNext;  
  21.         delete pDel;  
  22.     }  
  23. }  
  24.   
  25. //属性读方法  
  26. HRESULT STDMETHODCALLTYPE CPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *_pVar, IErrorLog *pErrorLog)  
  27. {  
  28.     VAR_LIST *pTemp = pVar;  
  29.     HRESULT hr = S_OK;  
  30.     while(pTemp)  
  31.     {  
  32.         if(0 == wcscmp(pszPropName, pTemp->pBSTRName))  
  33.         {  
  34.             hr = VariantCopy(_pVar, &pTemp->var);  
  35.             break;  
  36.         }  
  37.     pTemp = pTemp->pNext;  
  38.     }  
  39.   
  40.     return hr;  
  41. }  
  42.   
  43. //属性写方法  
  44. HRESULT STDMETHODCALLTYPE CPropertyBag::Write(LPCOLESTR pszPropName, VARIANT *_pVar)  
  45. {  
  46.     HRESULT hr = S_OK;  
  47.     VAR_LIST *pTemp = new VAR_LIST();  
  48.     ASSERT(pTemp);  
  49.     if(!pTemp)  
  50.     {  
  51.         return E_OUTOFMEMORY;  
  52.     }  
  53.   
  54.     VariantInit(&pTemp->var);  
  55.     pTemp->pBSTRName = SysAllocString(pszPropName);  
  56.     pTemp->pNext = pVar;  
  57.     pVar = pTemp;  
  58.     return VariantCopy(&pTemp->var, _pVar);  
  59. }  
  60.   
  61. ULONG STDMETHODCALLTYPE CPropertyBag::AddRef()   
  62. {  
  63.     return InterlockedIncrement((LONG *)&_refCount);  
  64. }  
  65.   
  66. ULONG STDMETHODCALLTYPE CPropertyBag::Release()   
  67. {  
  68.     ASSERT(_refCount != 0xFFFFFFFF);  
  69.     ULONG ret = InterlockedDecrement((LONG *)&_refCount);      
  70.     if(!ret)   
  71.     {  
  72.         delete this;   
  73.     }  
  74.   
  75.     return ret;  
  76. }  
  77.   
  78. HRESULT STDMETHODCALLTYPE CPropertyBag::QueryInterface(REFIID riid, void** ppv)   
  79. {  
  80.     if(!ppv)   
  81.     {  
  82.         return E_POINTER;  
  83.     }  
  84.   
  85.     if(riid == IID_IPropertyBag)   
  86.     {  
  87.         *ppv = static_cast<IPropertyBag*>(this);   
  88.     }  
  89.     else   
  90.     {  
  91.         return *ppv = 0, E_NOINTERFACE;  
  92.     }  
  93.   
  94.     return AddRef(), S_OK;   
  95. }  

  (3)  EricCamera.h

  1. /*----------------------------------------- 
  2. * Copyright (c) 2008 Eric Wong 
  3. * 本版紧供读者参考,不得用于任何商业行为 
  4. * 
  5. * 文件名称:EricCamera.h 
  6. * 文件标识: 
  7. * 摘要:用于封装DSHOW 摄像头预览、录像、抓拍功能 
  8. * 
  9. * 当前版本:1.0 
  10. * 作者:汪兵Eric Wong 
  11. * 完成日期:2008年月日 
  12. * 
  13. * 取代版本: 
  14. * 原作者: 
  15. * 完成日期: 
  16. ----------------------------------------*/  
  17.   
  18. #pragma once  
  19. #include <streams.h>  
  20. #include <dmodshow.h>  
  21. #include <dmoreg.h>  
  22. #include <wmcodecids.h>  
  23.   
  24. class CEricCamera  
  25. {  
  26. public:  
  27.     CEricCamera(void);  
  28.     ~CEricCamera(void);  
  29. private:  
  30.   
  31.     //-----DSHOW接口-----------  
  32.     //视频捕捉图形管理器接口  
  33.     CComPtr<ICaptureGraphBuilder2> m_pCaptureGraphBuilder;  
  34.   
  35.     //图形管理器接口  
  36.     CComPtr<IGraphBuilder> m_pGraphBuilder;  
  37.   
  38.     //视频捕捉过滤器  
  39.     CComPtr<IBaseFilter> m_pVideoCaptureFilter;  
  40.   
  41.     //视频设备属性页  
  42.     CComPtr<IPersistPropertyBag> m_pPropertyBag ;  
  43.   
  44.     //静态捕捉PIN过滤器  
  45.     CComPtr<IBaseFilter> m_pImageSinkFilter;  
  46.   
  47.     //媒体播放控制器  
  48.     CComPtr<IMediaControl> m_pMediaControl  ;  
  49.   
  50.     //视频窗口接口  
  51.     CComPtr<IVideoWindow> m_pVideoWindow ;  
  52.   
  53.     //视频播放进度控制接口  
  54.     CComPtr<IMediaSeeking> m_pMediaSeeking;  
  55.   
  56.     //媒体事件接口  
  57.     CComPtr<IMediaEvent> m_pMediaEvent;  
  58.   
  59. public:  
  60.     //释放DSHOW接口  
  61.     void FreeDShow();  
  62.   
  63.     //查找第个摄像头设备名  
  64.     BOOL GetFirstCameraDriver(WCHAR *pwzName);  
  65.   
  66.     //预览视频  
  67.     BOOL PreviewCamera(HWND hVideoWnd /*视频显示窗口*/LPCTSTR strFileName /*录像文件名*/);  
  68.   
  69.     //开始录像  
  70.     BOOL StartRecord();  
  71.   
  72.     //停止录像  
  73.     BOOL StopRecord();  
  74.   
  75.     //抓拍  
  76.     BOOL SnapPicture(LPCTSTR strFileName /*图象文件名,格式为JPG*/);  
  77.   
  78. };  

  (4) EricCamera.cpp

  1. /*----------------------------------------- 
  2. * Copyright (c) 2008 Eric Wong 
  3. * 本版紧供读者参考,不得用于任何商业行为 
  4. * 
  5. * 文件名称:EricCamera.cpp 
  6. * 文件标识: 
  7. * 摘要:用于封装DSHOW 摄像头预览、录像、抓拍功能 
  8. * 
  9. * 当前版本:1.0 
  10. * 作者:汪兵Eric Wong 
  11. * 完成日期:2008年月日 
  12. * 
  13. * 取代版本: 
  14. * 原作者: 
  15. * 完成日期: 
  16. ----------------------------------------*/  
  17.   
  18. #include "StdAfx.h"  
  19. #include "EricCamera.h"  
  20. #include "PropertyBag.h"  
  21.   
  22. #define CHK( x ) do{ if( FAILED( hResult = ( x ))) { goto Cleanup; }} while( FALSE );  
  23. #define ERR( x ) do{ hResult = x; goto Cleanup; } while( FALSE );  
  24.   
  25. //构造函数  
  26. CEricCamera::CEricCamera(void)  
  27. {  
  28.     //初始化COM 环境  
  29.     CoInitialize(NULL);   
  30. }  
  31.   
  32. //析构函数  
  33. CEricCamera::~CEricCamera(void)  
  34. {  
  35.     //释放DSHOW接口  
  36.     FreeDShow();  
  37.     //释放COM 环境  
  38.     CoUninitialize();  
  39. }  
  40.   
  41. /* 
  42. *函数介绍:释放DSHOW接口 
  43. *入口参数:(无) 
  44. *出口参数:(无) 
  45. *返回值:TRUE:成功;FALSE:失败 
  46. */  
  47. void CEricCamera::FreeDShow()  
  48. {  
  49.     //释放IMediaControl接口  
  50.     if (m_pMediaControl  != NULL)  
  51.     {  
  52.         m_pMediaControl->Stop();  
  53.         m_pMediaControl.Release();  
  54.         m_pMediaControl = NULL;  
  55.     }  
  56.     //释放IPropertyBag接口  
  57.     if (m_pPropertyBag != NULL)  
  58.     {  
  59.         m_pPropertyBag.Release();  
  60.         m_pPropertyBag = NULL;  
  61.     }  
  62.     //释放IVideoWindow接口  
  63.     if (m_pVideoWindow != NULL)  
  64.     {  
  65.         //隐藏视频窗口  
  66.         m_pVideoWindow->put_Visible(OAFALSE);  
  67.         //设置视频播放窗口句柄为空  
  68.         m_pVideoWindow->put_Owner(NULL);  
  69.        m_pVideoWindow.Release();  
  70.        m_pVideoWindow = NULL;  
  71.     }  
  72.     //释放IMediaSeeking接口  
  73.     if (m_pMediaSeeking != NULL)  
  74.     {  
  75.         m_pMediaSeeking.Release();  
  76.         m_pMediaSeeking = NULL;  
  77.     }  
  78.     //释放IMediaEvent接口  
  79.     if (m_pMediaEvent != NULL)  
  80.     {  
  81.         m_pMediaEvent.Release();  
  82.     m_pMediaEvent = NULL;  
  83.     }  
  84.     //释放IVideoCaptureFilter接口  
  85.     if (m_pVideoCaptureFilter != NULL )  
  86.     {  
  87.     m_pVideoCaptureFilter.Release();  
  88.     m_pVideoCaptureFilter = NULL;  
  89.     }  
  90.     //释放IImageSinkFilter接口  
  91.     if (m_pImageSinkFilter != NULL )  
  92.     {  
  93.     m_pImageSinkFilter.Release();  
  94.     m_pImageSinkFilter = NULL;  
  95.     }  
  96.     //释放IGraphBuilder接口  
  97.     if (m_pGraphBuilder != NULL)  
  98.     {  
  99.     m_pGraphBuilder.Release();  
  100.     m_pGraphBuilder = NULL;  
  101.     }  
  102.     //释放ICaptureGraphBuilder2接口  
  103.     if (m_pCaptureGraphBuilder != NULL)  
  104.     {  
  105.     m_pCaptureGraphBuilder->SetFiltergraph(NULL);  
  106.     m_pCaptureGraphBuilder.Release();  
  107.     m_pCaptureGraphBuilder = NULL;  
  108.     }  
  109. }  
  110.   
  111. /* 
  112. *函数介绍:查找第个摄像头设备 
  113. *入口参数:pwzName : 存储摄像头设备名称,应提前分配好内存 
  114. *出口参数:pwzName :存储摄像头设备名称 
  115. *返回值:TRUE:成功;FALSE:失败 
  116. */  
  117. BOOL CEricCamera::GetFirstCameraDriver( WCHAR *pwzName )  
  118. {  
  119.     HRESULT hr = S_OK;  
  120.     HANDLE handle = NULL;  
  121.     DEVMGR_DEVICE_INFORMATION di;  
  122.     GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 };  
  123.     if( pwzName == NULL )  
  124.     {  
  125.     return FALSE;  
  126.     }  
  127.   
  128.     di.dwSize = sizeof(di);  
  129.   
  130.     //查到第个摄像头设备  
  131.     handle = FindFirstDevice( DeviceSearchByGuid, &guidCamera, &di );  
  132.     if(( handle == NULL ) || ( di.hDevice == NULL ))  
  133.     {  
  134.     FindClose( handle );  
  135.     return FALSE;  
  136.     }  
  137.   
  138.     //复制设备名  
  139.     StringCchCopy( pwzName, MAX_PATH, di.szLegacyName );  
  140.   
  141.     //关闭查找设备  
  142.     FindClose( handle );  
  143.   
  144.     return TRUE;  
  145. }  
  146.   
  147. /* 
  148. *函数介绍:初始化DSHOW接口,并预览视频 
  149. *入口参数:hVideoWnd : 显示视频的窗口句柄 
  150. strFileName :录像文件名 
  151. *出口参数:(无) 
  152. *返回值:TRUE:成功;FALSE:失败 
  153. */  
  154. BOOL CEricCamera::PreviewCamera(HWND hVideoWnd /*视频显示窗口*/LPCTSTR strFileName /*录像文件名*/)  
  155. {  
  156.     HRESULT hResult = S_FALSE;  
  157.     LONGLONG dwStart = 0, dwEnd = 0;  
  158.     WORD wStartCookie = 1, wEndCookie = 2;  
  159.     CRect rectVideo;                    //视频窗口尺寸  
  160.     CComVariant varCamName;             //定义摄像头设备名称  
  161.     WCHAR wzDeviceName[ MAX_PATH + 1 ]; //摄像头设备名称  
  162.     CPropertyBag PropBag;               //摄像头属性页  
  163.   
  164.     //--定义录像用到的编码、写文件等FILTER  
  165.     CComPtr<IBaseFilter>            pVideoEncoder;  
  166.     CComPtr<IBaseFilter>            pASFMultiplexer;  
  167.     CComPtr<IFileSinkFilter>        pFileSinkFilter;  
  168.     CComPtr<IDMOWrapperFilter>      pWrapperFilter;  
  169.   
  170.     //默认先释放DSHOW接口  
  171.     FreeDShow();  
  172.   
  173.     //1,创建ICaptureGraphBuilder2接口,用于管理媒体捕捉对象  
  174.     CHK(m_pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder));  
  175.   
  176.     //2,创建IGraphBuilder接口  
  177.     CHK(m_pGraphBuilder.CoCreateInstance(CLSID_FilterGraph));  
  178.   
  179.     //3,  
  180.     CHK(m_pCaptureGraphBuilder->SetFiltergraph(m_pGraphBuilder ));  
  181.   
  182.     //4,得到IMediaControl接口,用于控制流播放  
  183.     CHK(m_pGraphBuilder.QueryInterface(&m_pMediaControl));   
  184.   
  185.     //5,得到IMediaSeeking接口,用于设置播放位置  
  186.     CHK(m_pGraphBuilder.QueryInterface(&m_pMediaSeeking));   
  187.   
  188.     //6,得到m_pMediaEvent接口,用于获取媒体事件  
  189.     CHK(m_pGraphBuilder.QueryInterface(&m_pMediaEvent));   
  190.   
  191.     //7,创建视频捕捉Filter  
  192.     CHK(m_pVideoCaptureFilter.CoCreateInstance(CLSID_VideoCapture));  
  193.   
  194.     //8,得到视频捕捉属性页接口  
  195.     CHK(m_pVideoCaptureFilter->QueryInterface(&m_pPropertyBag));  
  196.   
  197.     //9,选择视频捕捉设备  
  198.     //得到第个视频捕捉设备名。  
  199.     if (!GetFirstCameraDriver( wzDeviceName ))  
  200.     {  
  201.         goto Cleanup;  
  202.     }  
  203.   
  204.     varCamName = wzDeviceName;  
  205.     if(( varCamName.vt == VT_BSTR ) == NULL ) {  
  206.     return FALSE;  
  207.     }  
  208.   
  209.     //设置视频捕捉为第个捕捉设备  
  210.     PropBag.Write( L"VCapName", &varCamName);     
  211.     CHK(m_pPropertyBag->Load( &PropBag, NULL));  
  212.   
  213.     //10,将视频捕捉FILTER添加到FILTER图中。  
  214.     CHK(m_pGraphBuilder->AddFilter( m_pVideoCaptureFilter, L"Video capture source" ));  
  215.   
  216.     //11,创建IDMOWrapperFilter接口  
  217.     CHK(pVideoEncoder.CoCreateInstance( CLSID_DMOWrapperFilter ));  
  218.     CHK(pVideoEncoder.QueryInterface( &pWrapperFilter ));  
  219.   
  220.     //12,加载WMV9 DMO  
  221.     CHK(pWrapperFilter->Init( CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER ));  
  222.   
  223.     // 13,将编码器FILTER加入到过滤器图中  
  224.     CHK(m_pGraphBuilder->AddFilter( pVideoEncoder, L"WMV9 DMO Encoder" ));  
  225.   
  226.     //14,创建ASF多路(复用)器,并加入到过滤器图中  
  227.     CHK(m_pCaptureGraphBuilder->SetOutputFileName( &MEDIASUBTYPE_Asf,strFileName, &pASFMultiplexer, &pFileSinkFilter ));  
  228.   
  229.     //15,渲染预览视频PIN  
  230.     CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video, m_pVideoCaptureFilter,NULL, NULL));  
  231.   
  232.     //16,设置视频预览窗口  
  233.     CHK(m_pGraphBuilder.QueryInterface(&m_pVideoWindow));  
  234.   
  235.     //设置视频播放的WINDOWS窗口  
  236.     m_pVideoWindow->put_Owner((OAHWND)hVideoWnd);  
  237.     m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);  
  238.   
  239.     //设置视频尺寸  
  240.     GetClientRect(hVideoWnd,&rectVideo);  
  241.     m_pVideoWindow->SetWindowPosition(0,0,rectVideo.Width(),rectVideo.Height());  
  242.     m_pVideoWindow->put_Visible(OATRUE);  
  243.   
  244.     //17,渲染捕捉PIN,用于录像  
  245.     CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pVideoEncoder, pASFMultiplexer ));  
  246.   
  247.     //18,创建Still Pin,用于抓图  
  248.     CHK(m_pImageSinkFilter.CoCreateInstance(CLSID_IMGSinkFilter));  
  249.     CHK(m_pGraphBuilder->AddFilter(m_pImageSinkFilter, L"Still image filter" ));  
  250.     CHK(m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_STILL, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, m_pImageSinkFilter ));  
  251.   
  252.     //19,设置捕捉流暂停  
  253.     CHK(m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, 0, 0 ,0,0 ));  
  254.   
  255.     //20,预览视频  
  256.     CHK(m_pMediaControl->Run());  
  257.     Sleep(1000);  
  258.   
  259. Cleanup:  
  260.   
  261.     //释放接口  
  262.     if (pVideoEncoder != NULL)  
  263.     {  
  264.     pVideoEncoder.Release();  
  265.     pVideoEncoder = NULL;  
  266.     }  
  267.   
  268.     if (pASFMultiplexer != NULL)  
  269.     {  
  270.     pASFMultiplexer.Release();  
  271.     pASFMultiplexer = NULL;  
  272.     }  
  273.   
  274.     if (pFileSinkFilter != NULL)  
  275.     {  
  276.     pFileSinkFilter.Release();  
  277.     pFileSinkFilter = NULL;  
  278.     }  
  279.   
  280.     if (pWrapperFilter != NULL)  
  281.     {  
  282.     pWrapperFilter.Release();  
  283.     pWrapperFilter = NULL;  
  284.     }  
  285.   
  286.     if( FAILED( hResult ))  
  287.     {  
  288.     return FALSE;  
  289.     }  
  290.     else  
  291.     {  
  292.     return TRUE;  
  293.     }  
  294. }  
  295.   
  296. /* 
  297. *函数介绍:开始录像 
  298. *入口参数:(无) 
  299. *出口参数:(无) 
  300. *返回值:TRUE:成功;FALSE:失败 
  301. */  
  302. BOOL CEricCamera::StartRecord()  
  303. {  
  304.     LONGLONG dwStart = 0, dwEnd = 0;  
  305.     WORD wStartCookie = 1, wEndCookie = 2;  
  306.     HRESULT hResult = 0;  
  307.     if( m_pCaptureGraphBuilder == NULL )  
  308.     {  
  309.        return FALSE;  
  310.     }  
  311.   
  312.     //开始录制  
  313.     dwStart = 0;  
  314.     dwEnd = MAXLONGLONG;  
  315.     hResult = m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, NULL, &dwStart, &dwEnd, wStartCookie, wEndCookie );  
  316.     TRACE(L"开始录制\n");  
  317.     if( FAILED( hResult ))  
  318.     {  
  319.     return FALSE;  
  320.     }  
  321.     else  
  322.     {  
  323.     return TRUE;  
  324.     }  
  325. }  
  326.   
  327. /* 
  328. *函数介绍:停止录像 
  329. *入口参数:(无) 
  330. *出口参数:(无) 
  331. *返回值:TRUE:成功;FALSE:失败 
  332. */  
  333. BOOL CEricCamera::StopRecord()  
  334. {  
  335.     HRESULT hResult = S_OK;  
  336.     LONGLONG dwStart = 0, dwEnd = 0;  
  337.     WORD wStartCookie = 1, wEndCookie = 2;  
  338.     LONG lEventCode = 0;  
  339.     LONG lParam1 = 0;  
  340.     LONG lParam2 = 0;  
  341.   
  342.     if( m_pCaptureGraphBuilder == NULL )  
  343.     {  
  344.        return FALSE;  
  345.     }  
  346.   
  347.     //停止视频捕捉流,并存入到文件中  
  348.     dwStart = 0;  
  349.     hResult = m_pMediaSeeking->GetCurrentPosition( &dwEnd );  
  350.     hResult = m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, NULL, &dwStart, &dwEnd, wStartCookie, wEndCookie );  
  351.   
  352.     //检测录像文件生成结束  
  353.     while (true)  
  354.     {  
  355.     m_pMediaEvent->GetEvent( &lEventCode, &lParam1, &lParam2, INFINITE );  
  356.     m_pMediaEvent->FreeEventParams( lEventCode, lParam1, lParam2 );  
  357.     if( lEventCode == EC_STREAM_CONTROL_STOPPED ) {  
  358.             TRACE(L"录像停止\n");  
  359.         break;  
  360.         }  
  361.     }  
  362.   
  363.     //  
  364.     if( FAILED( hResult ))  
  365.     {  
  366.         return FALSE;  
  367.     }  
  368.     else  
  369.     {  
  370.         return TRUE;  
  371.     }  
  372. }  
  373.   
  374. /* 
  375. *函数介绍:抓拍 
  376. *入口参数:strFileName:抓拍保存的文件名,图象格式为JPG. 
  377. *出口参数:(无) 
  378. *返回值:TRUE:成功;FALSE:失败 
  379. */  
  380. BOOL CEricCamera::SnapPicture(LPCTSTR strFileName /*图象文件名,格式为JPG*/)  
  381. {  
  382.     HRESULT hResult = S_FALSE;  
  383.     CComPtr<IFileSinkFilter> pFileSink;  
  384.     CComPtr<IUnknown>  pUnkCaptureFilter;  
  385.     CComPtr<IPin>  pStillPin;  
  386.     CComPtr<IAMVideoControl> pVideoControl;  
  387.   
  388.     if( m_pCaptureGraphBuilder == NULL )  
  389.     {  
  390.        goto Cleanup;  
  391.     }  
  392.   
  393.     //得到IFileSinkFilter接口  
  394.     CHK( m_pImageSinkFilter.QueryInterface( &pFileSink ));  
  395.   
  396.     //设置抓拍保存的图象文件名  
  397.     CHK( pFileSink->SetFileName( strFileName, NULL ));  
  398.   
  399.     //得到StillPin  
  400.     CHK( m_pVideoCaptureFilter.QueryInterface( &pUnkCaptureFilter ));  
  401.     CHK( m_pCaptureGraphBuilder->FindPin( pUnkCaptureFilter, PINDIR_OUTPUT, &PIN_CATEGORY_STILL, &MEDIATYPE_Video, FALSE, 0, &pStillPin ));  
  402.   
  403.     //设置抓拍动作  
  404.     CHK( m_pVideoCaptureFilter.QueryInterface( &pVideoControl ));  
  405.     CHK( pVideoControl->SetMode( pStillPin, VideoControlFlag_Trigger ));  
  406.   
  407. Cleanup:  
  408.     //释放DSHOW接口  
  409.     if (pFileSink != NULL)  
  410.     {  
  411.         pFileSink.Release();  
  412.         pFileSink = NULL;  
  413.     }  
  414.   
  415.     if (!pUnkCaptureFilter != NULL)  
  416.     {  
  417.     pUnkCaptureFilter.Release();  
  418.     pUnkCaptureFilter = NULL;  
  419.     }  
  420.   
  421.     if (pStillPin != NULL)  
  422.     {  
  423.     pStillPin.Release();  
  424.     pStillPin = NULL;  
  425.     }  
  426.   
  427.     if (pVideoControl != NULL)  
  428.     {  
  429.         pVideoControl.Release();  
  430.         pVideoControl = NULL;  
  431.     }  
  432.   
  433.     if( FAILED( hResult ))  
  434.     {  
  435.         return FALSE;  
  436.     }  
  437.     else  
  438.     {  
  439.         return TRUE;  
  440.     }  
  441. }<span style="FONT-SIZE: 16px; FONT-FAMILY: KaiTi_GB2312"><span style="FONT-FAMILY: KaiTi_GB2312"><span style="FONT-SIZE: 16px; FONT-FAMILY: KaiTi_GB2312"><span style="font-family:KaiTi_GB2312;font-size:16px;"><span style="font-family:KaiTi_GB2312;"><strong><span style="font-size:24px;color:#333333;"><em>  
  442. </em></span></strong></span></span></span></span></span>  

WinCE系统下基于DirectShow的摄像头应用编程 by斜风细雨QQ:253786989    2012-02-17


发布了14 篇原创文章 · 获赞 5 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/laoyouji/article/details/8130365