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

2023-11-02

 

大家可以对比我的另一篇文章学习:    XP下基于DirectShow的摄像头采集

 转载自:

http://blog.csdn.net/northcan/article/details/7268745

 

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个,如下:

  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) 获取IMediaSeeking接口,用于对多媒体数据流的播放位置等属性进行控制。如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. }

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WinCE系统下基于DirectShow的摄像头应用编程 的相关文章

  • 当方法尝试使用可以为空的字段时抛出哪个异常? [复制]

    这个问题在这里已经有答案了 我实际上正在从事框架开发 这意味着需要非常强大的编码方法 我面临一个问题 我不知道需要抛出哪个 System Exception 派生类 基本上情况是 我有一个类 其中的字段可以由构造函数选择性地初始化 并且具有
  • 在 JMS 序列化器中排除 null 属性

    我使用的 XML API 可以选择仅检索部分响应 这导致生成的对象有很多NULL属性 如果使用此功能 有没有办法真正跳过NULL特性 我尝试实施排除策略 shouldSkipProperty PropertyMetadata propert
  • 在 IL 中对空引用调用实例方法

    在 IL 中可以对空引用调用实例方法是否正确 有没有例子可以证明这一点 是的 这是可能的 只要该方法不使用this因为 CLR 不会对以下内容进行空检查call指示 You would have to modify the IL by ha
  • WordPress 数据库 insert() 和 update() - 使用 NULL 值

    WordPress 附带wpdb处理 CRUD 操作的类 我感兴趣的这个类的两个方法是insert CRUD 中的 C 和update CRUD 中的 U 当我想将 NULL 插入 mysql 数据库列时出现问题 wpdb类将 PHP 空变
  • MySQL外键允许NULL吗?

    我正在拼凑一个图像网站 基本模式非常简单 MySQL 但我在尝试表示与图像关联的可能的管理标志 不适当 受版权保护 等 时遇到了一些麻烦 我目前的想法如下 tblImages imageID INT UNSIGNED NOT NULL AU
  • 仅当值既不为 null 也不未定义时才调用函数

    单击按钮时 我检查本地存储键中是否存在某些内容 如下所示 var a localStorage getItem foo if typeof a undefined Function 但如果该键根本不存在 则返回 null 我怎样才能打电话如
  • 如果字符串中间出现空字符怎么办?

    我知道字符串的结尾由空字符表示 但我无法理解以下代码的输出 include
  • Haskell 中的 undefined 和 Java 中的 null 有什么区别?

    两者的类型都是所有类型的交集 无人居住 两者都可以在代码中传递而不会失败 直到尝试评估它们为止 我能看到的唯一区别是 在 Java 中 有一个漏洞允许null仅针对一个操作进行评估 即引用相等比较 而在 Haskell 中undefined
  • 带有 NULL 的唯一键

    这个问题需要一些假设的背景 让我们考虑一个employee有列的表name date of birth title salary 使用 MySQL 作为 RDBMS 因为如果任何给定的人与另一个人具有相同的名字和出生日期 那么根据定义 他们
  • 从空整数到逗号列表中的指针的转换

    我知道在我们的现代世界中 NULL 和 0 并不是指针操作的最佳实践 根据 cppreference 指针转换 空指针常量 参见 NULL 可以是 转换为任意指针类型 结果为空指针 该类型的值 这种转换 称为空指针转换 允许作为单个转换转换
  • 字符串终止符'\0'如何与整数常量0具有相同的值?

    我有以下代码 include
  • 为什么 is.null 对于不存在的列表元素返回 false?

    我正在尝试测试列表是否包含对象 github源码 https raw github com PecanProject pecan 073235d9117faf8719038e095ba589bdaca1e402 settings R rea
  • Moshi/Kotlin - 如何将 NULL JSON 字符串序列化为空字符串?

    我正在尝试编写一个空安全字符串适配器来序列化此 JSON nullString null 进入这个 Model nullString 这样我希望是字符串的任何带有 null 值的 JSON 都将被替换为 假设存在这样的数据类 data cl
  • Java 中将对象与 null 进行比较

    我正在尝试验证一个对象是否是null或不 使用以下语法 void renderSearch Customer c System out println search customer rendering gt try if c equals
  • 函数不会在所有代码路径上返回值。使用结果时,运行时可能会发生空引用异常

    我收到此错误 函数 getkey 不会在所有代码路径上返回值 当结果为空引用异常时 可能会在运行时发生 用过的 到以下代码 Public Function getkey ByVal id As String Dim cmd As SqlCo
  • 使用 pymongo 查询空字段

    我想使用 python 查询 mongo 中的空字段 但是它很难处理单词 null 或 false 它要么给我错误 它们在 python 中未定义 要么在 mongo 中搜索字符串 null 和 false 这两种情况我都不希望发生 col
  • C 中的 NULL 是否需要/定义为零?

    在我的 GCC 测试程序中 NULL 似乎为零 但维基百科说NULL只需要指向不可寻址的内存 有编译器做吗NULL非零 我很好奇是否if ptr NULL 是比更好的练习if ptr NULL is guaranteed to be zer
  • PHP 构造函数返回 NULL

    我有这个代码 是否有可能User对象构造函数以某种方式失败 以便 this gt LoggedUser被分配了一个NULL构造函数返回后值和对象被释放吗 this gt LoggedUser NULL if SESSION verbiste
  • 检查多个变量java中的替换空值

    我试图找到一种简单的方法来在 Java 中的多个变量中执行多个 null 检查 替换 我有一个包含大约 20 个字符串变量的对象 在构造函数中 我想检查是否有任何变量值为空 如果它们为空 我想用空字符串替换它们 我可以执行一系列 if 语句
  • json_encode 返回 NULL?

    由于某种原因 项目 描述 返回NULL使用以下代码 这是我的数据库的架构 CREATE TABLE staff id int 11 NOT NULL AUTO INCREMENT name longtext COLL

随机推荐

  • JavaScript -- Set数据结构

    文章目录 什么是Set Set实例的属性和方法 add has delete clear forEach size属性 Set构造函数 数组 字符串 arguments DOM Set 注意事项 判断重复的方式 Set应用 Set转数组 数
  • flask 导入一个模板

    from flask import Flask redirect url for render template app Flask name app route def index return render template login
  • neo4j图数据入门(二)数据的插入和删除 图形界面操作 图文并茂

    点击下图中的按钮 点击下图中按钮 上图中的代码 CREATE p1 Person name 胡兴炯 born 1991 interest mac ios 旅游 goodat java swift objectiveC p2 Person n
  • Java - 多态之向上转型与向下转型

    Java 多态之向上转型与向下转型 代码示例 父类 public class Father int f 100 public void name System out println father public void tel Syste
  • Premiere Pro 2022 for Mac(pr2022)中文版

    Mac版Premiere Pro 2022更新了 最新版的pr2022不仅可以帮助用户对各种视频进行剪辑 旋转 分割 合并 字幕添加 背景音乐等基础的处理 还能帮助用户进行视频颜色校正 颜色分级 稳定镜头 调整层 更改片段的持续时间和速度
  • hover调试小技巧(无需修改代码)

    某块内容是hover后才能显示的 但此时我们想要调试hover态的时候 通常的办法是以下几种 改代码 修改代码让它默认处于hover态 但是这样麻烦不说 还只应用于本地环境 每次改代码都需要进行热更新 用Chrome开发工具让DOM处于ho
  • cache write back

    1 问题阐述 在ITE的SDK上编译 选择了CPU write back cache enable CPU WB 之后 显示画面总是出现有错乱 通过设置断点 发现当停在解析的数据后 在运行就不会出现错乱现象 问了大神才知道 只是cache没
  • qt开发的程序 为何一个主窗口关闭了,程序不退出,而是到等到所有窗口关闭了,才退出呢?

    这种行为是由Qt框架中的事件循环 Event Loop 机制引起的 Qt应用程序在执行时 会进入一个事件循环 该循环负责处理用户输入 事件和信号 并相应地调用相应的槽函数或处理程序 当你关闭一个Qt应用程序的主窗口时 主窗口会发出一个关闭事
  • 二进制模2除法(CRC校验)

    二进制模2除法与二进制除法不同 模2运算 加法不进位 减法不借位 二进制除法 带借位的二进制除法 根据余数减除数够减与否 确定商1还是商0 若够减则商1 否则商0 二进制模2除法 采用模2减法 不带借位的二进制减法 因此考虑余数够减除数与否
  • 制作论文中双Y轴散点图

    import pandas as pd import matplotlib pyplot as plt from matplotlib dates import AutoDateLocator DateFormatter from date
  • Unity开发优化----删除多余的MeshCollider和Animation组件

    手游项目做碰撞的时候 有关一切物理的东西Unity对手机支持的并不好 多余的MeshCollider 和Animation 空的组件 这俩东西很占效率的 比如下图这样的组件 还有场景的材质最好用Mobile Diffuse 它会比Diffu
  • SQL注入联合注入

    SQL注入定义 SQL是操作数据库数据的结构化查询语言 网页的应用数据和后台数据库中的数据进行交互时会采用SQL SQL注入是指将Web页面的原URL 表单域或数据包输入的参数 修改拼接成SQL语句 传递给Web服务器 进而传给数据库服务器
  • fopen与fopen_s的区别

    在定义FILE fp 之后 fopen的用法是 fp fopen filename w 而对于fopen s来说 还得定义另外一个变量errno t err 然后err fopen s fp filename w 返回值的话 对于fopen
  • 中国移动智能家庭网关(类型二)默认账号和密码

    超级账号 CMCCAdmin 超级密码 aDm8H MdA 超级用户名 telecomadmin 超级密码 nE7jA 5m 用户名 telecomadmin 密码 admintelecom 超级用户名 fiberhomehg2 0 超级密
  • Win10更新后开机变得很慢怎么办?Win10更新后开机变得很慢解决方法

    Win10更新后开机变得很慢怎么办 尽管Win10提供了许多强大的功能和改进 但有些用户在系统升级后可能会遇到开机变慢的问题 让用户们感到困扰 因为开机速度直接关系到使用计算机的效率和便捷性 以下小编将给用户们介绍Win10更新后开机变得很
  • Ancona虚拟环境创建失败

    anaconda虚拟环境创建失败 报错信息如最下 参考了这篇解决方法 先输入conda clean i 再创建虚拟环境就成功了 conda clean i Solving environment failed gt gt gt gt gt
  • 七位高僧大德的临终开示,非大福报者不得见

    http www xuefo net nr article47 465546 html 一 印光大师 印光大师临终时当晚对身边的弟子说 净土法门 别无奇特 只要恳切至诚 没有不蒙佛接引 带业往生 此后精神逐渐疲惫 体温降低 夜里一时半 大师
  • 仿函数(functors)

    functor 仿函数 或者称之为function object 函数对象 是STL的四大组件之一 什么是仿函数呢 一个函数对象是封装在类中 从而看起来更像是一个对象 这个类只有一个成员函数 即重载了 括号 的运算符 它没有任何数据 该类被
  • 工频干扰频谱测量_经验分享

    正文 2219 字 丨 7 分钟阅读 导读 本文的内容是关于转动设备常见振动故障频谱特征及案例分析 非常实用的经验总结 希望对你的工作和学习有所帮助 一 不平衡 转子不平衡是由于转子部件质量偏心或转子部件出现缺损造成的故障 它是旋转机械最常
  • WinCE系统下基于DirectShow的摄像头应用编程

    大家可以对比我的另一篇文章学习 XP下基于DirectShow的摄像头采集 转载自 http blog csdn net northcan article details 7268745 在WinCE设备上使用摄像头时 一般都是向厂家索要驱