VC++_捕捉摄像头视频摘要:本文主要讲述用Directshow进行视频捕捉(捕捉静态图像)的编程思路,并提供针对摄像头编程的一个视频捕捉类CcaptureVideo和一个示例。前言DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。DirectShow为多媒体流的捕捉和回放提供了强有力的支持。用DirectShow开发应用程序,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。DirectShow是基于COM的,为了编写DirectShow应用程序,需要了解COM客户程序编写的基础知识。DirectShow提供了大量的接口,但在编程中发现还是不够方便,如果能构建一个视频捕捉类把常用的一些动作封装起来,那么就更方便了。编程思路为了更加容易建立视频捕捉应用程序,DirectShow提供了一个叫做CaptureGraphBuilder的对象,CaptureGraphBuilder提供IcaptureGraphBuilder2接口,该接口可以建立和控制CaptureGraph。建立视频捕捉程序,必须首先获取并初始化IcaptureGraphBuilder2接口,然后选择一个适当的视频捕捉设备。选择好设备后,为该设备创建Capturefilter,然后调用AddFilter把Capturefilter添加到FilterGraph。如果仅仅希望用摄像头来进行实时监控的话,只需要在上面的基础上调用ICaptureGraphBuilder2::RenderStream就可以了:ICaptureGraphBuilder2*pBuild;//CaptureGraphBuilder//省略初始化部分代码IBaseFilter*pCap;//Videocapturefilter.//省略初始化和添加到FilterGraph部分代码pBuild-RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,pCap,NULL,NULL);DirectShow提供了一个捕捉静态图像的方法:使用SampleGrabberfilter。依次按照以下三个步骤就可以了:第一步,定义一个类实现SampleGrabber的回调接口IsampleGrabberCB:classCSampleGrabberCB:publicISampleGrabberCB{//在后面提供的类中具体完成}CSampleGrabberCBmCB;第二步、调用RenderStream依次把Stillpin、SampleGrabber和系统默认RendererFilter连接起来。第三步、配置SampleGrabber以捕获数据。视频捕捉类CCaptureVideo的具体实现//CCaptureVideo视频捕捉类头文件/////////////////////////////////////////////////////////////////////#if!defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)#defineAFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_///////////////////////////////////////////////////////////////////////CaptureVideo.h:headerfile/////////////////////////////////////////////////////////////////////#if_MSC_VER1000#pragmaonce#endif//_MSC_VER1000#includeatlbase.h#includewindows.h#includedshow.h#ifndefSAFE_RELEASE#defineSAFE_RELEASE(x)\if(NULL!=x)\{\x-Release();\x=NULL;\}#endifclassCSampleGrabberCB;classCCaptureVideo:publicCWnd{friendclassCSampleGrabberCB;public:voidGrabOneFrame(BOOLbGrab);HRESULTInit(intiDeviceID,HWNDhWnd);intEnumDevices(HWNDhList);CCaptureVideo();virtual~CCaptureVideo();private:HWNDm_hWnd;IGraphBuilder*m_pGB;ICaptureGraphBuilder2*m_pCapture;IBaseFilter*m_pBF;IMediaControl*m_pMC;IVideoWindow*m_pVW;CComPtrISampleGrabberm_pGrabber;protected:voidFreeMediaType(AM_MEDIA_TYPE&mt);boolBindFilter(intdeviceId,IBaseFilter**pFilter);voidResizeVideoWindow();HRESULTSetupVideoWindow();HRESULTInitCaptureGraphBuilder();};#endif//!defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)//-------------------------------------------------------------------//CCaptureVideo视频捕捉类实现文件CaptureVideo.cpp//-------------------------------------------------------------------//CaptureVideo.cpp:implementationoftheCCaptureVideoclass.///////////////////////////////////////////////////////////////////////#includestdafx.h#includeCaptureVideo.h#ifdef_DEBUG#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#definenewDEBUG_NEW#endifBOOLbOneShot=FALSE;//全局变量classCSampleGrabberCB:publicISampleGrabberCB{public:longlWidth;longlHeight;TCHARm_szFileName[MAX_PATH];//位图文件名称CSampleGrabberCB(){strcpy(m_szFileName,c:\\donaldo.bmp);}STDMETHODIMP_(ULONG)AddRef(){return2;}STDMETHODIMP_(ULONG)Release(){return1;}STDMETHODIMPQueryInterface(REFIIDriid,void**ppv){if(riid==IID_ISampleGrabberCB||riid==IID_IUnknown){*ppv=(void*)static_castISampleGrabberCB*(this);returnNOERROR;}returnE_NOINTERFACE;}STDMETHODIMPSampleCB(doubleSampleTime,IMediaSample*pSample){return0;}STDMETHODIMPBufferCB(doubledblSampleTime,BYTE*pBuffer,longlBufferSize){if(!bOneShot)return0;if(!pBuffer)returnE_POINTER;SaveBitmap(pBuffer,lBufferSize);bOneShot=FALSE;return0;}//创建位图文件BOOLSaveBitmap(BYTE*pBuffer,longlBufferSize){HANDLEhf=CreateFile(m_szFileName,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,NULL,NULL);if(hf==INVALID_HANDLE_VALUE)return0;//写文件头BITMAPFILEHEADERbfh;memset(&bfh,0,sizeof(bfh));bfh.bfType=’MB’;bfh.bfSize=sizeof(bfh)+lBufferSize+sizeof(BITMAPINFOHEADER);bfh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);DWORDdwWritten=0;WriteFile(hf,&bfh,sizeof(bfh),&dwWritten,NULL);//写位图格式BITMAPINFOHEADERbih;memset(&bih,0,sizeof(bih));bih.biSize=sizeof(bih);bih.biWidth=lWidth;bih.biHeight=lHeight;bih.biPlanes=1;bih.biBitCount=24;WriteFile(hf,&bih,sizeof(bih),&dwWritten,NULL);//写位图数据WriteFile(hf,pBuffer,lBufferSize,&dwWritten,NULL);CloseHandle(hf);return0;}};CSampleGrabberCBmCB;////////////////////////////////////////////////////////////////////////Construction/Destruction//////////////////////////////////////////////////////////////////////CCaptureVideo::CCaptureVideo(){//COMLibraryIntializationif(FAILED(CoInitialize(NULL)))/*,COINIT_APARTMENTTHREADED)))*/{AfxMessageBox(CoInitializeFailed!\r\n);return;}m_hWnd=NULL;m_pVW=NULL;m_pMC=NULL;m_pGB=NULL;m_pCapture=NULL;}CCaptureVideo::~CCaptureVideo(){//Stopmediaplaybackif(m_pMC)m_pMC-Stop();if(m_pVW){m_pVW-put_Visible(OAFALSE);m_pVW-put_Owner(NULL);}SAFE_RELEASE(m_pCapture);SAFE_RELEASE(m_pMC);SAFE_RELEASE(m_pGB);SAFE_RELEASE(m_pBF);CoUninitialize();}intCCaptureVideo::EnumDevices(HWNDhList){if(!hList)retu