Visual C++编程实现摄像头视频捕捉

Tags: vc
摘要 :本文主要讲述用Directshow进行视频捕捉(捕捉静态图像)的编程思路,并提供针对摄像头编程的一个视频捕捉类CcaptureVideo和一个示例。

   前言

DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。DirectShow为多媒体流的捕捉和回放提供了强有力的支持。用DirectShow开发应用程序,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。

  DirectShow是基于COM的,为了编写DirectShow应用程序,需要了解COM客户程序编写的基础知识。DirectShow提供了大量的接口,但在编程中发现还是不够方便,如果能构建一个视频捕捉类把常用的一些动作封装起来,那么就更方便了。

   编程思路

  为了更加容易建立视频捕捉应用程序,DirectShow提供了一个叫做Capture Graph Builder的对象,Capture Graph Builder提供IcaptureGraphBuilder2接口,该接口可以建立和控制Capture Graph。

  建立视频捕捉程序,必须首先获取并初始化IcaptureGraphBuilder2接口,然后选择一个适当的视频捕捉设备。选择好设备后,为该设备创建Capture filter,然后调用AddFilter把Capture filter添加到Filter Graph。

  如果仅仅希望用摄像头来进行实时监控的话,只需要在上面的基础上调用ICaptureGraphBuilder2::RenderStream就可以了:

ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder
//省略初始化部分代码
IBaseFilter *pCap; // Video capture filter.
//省略初始化和添加到Filter Graph部分代码
pBuild-> RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);

  DirectShow提供了一个捕捉静态图像的方法:使用Sample Grabber filter。依次按照以下三个步骤就可以了:

  第一步, 定义一个类实现Sample Grabber的回调接口IsampleGrabberCB:

class CSampleGrabberCB : public ISampleGrabberCB
{
  //在后面提供的类中具体完成
}
CSampleGrabberCB mCB;

  第二步、调用RenderStream依次把Still pin、Sample Grabber和系统默认Renderer Filter连接起来。

  第三步、配置Sample Grabber以捕获数据。

  视频捕捉类CCaptureVideo的具体实现

// CCaptureVideo视频捕捉类头文件
/////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_
/////////////////////////////////////////////////////////////////////
// CaptureVideo.h : header file
/////////////////////////////////////////////////////////////////////
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include
#include
#include
#ifndef SAFE_RELEASE
#define SAFE_RELEASE( x )
if ( NULL != x )
{
  x-> Release( );
  x = NULL;
}
#endif
class CSampleGrabberCB;
class CCaptureVideo : public CWnd
{
  friend class CSampleGrabberCB;
  public:
   void GrabOneFrame(BOOL bGrab);
   HRESULT Init(int iDeviceID,HWND hWnd);
   int EnumDevices(HWND hList);
   CCaptureVideo();
   virtual ~CCaptureVideo();
  private:
   HWND m_hWnd;
   IGraphBuilder *m_pGB;
   ICaptureGraphBuilder2* m_pCapture;
   IBaseFilter* m_pBF;
   IMediaControl* m_pMC;
   IVideoWindow* m_pVW;
   CComPtr m_pGrabber;
  protected:
   void FreeMediaType(AM_MEDIA_TYPE& mt);
   bool BindFilter(int deviceId, IBaseFilter **pFilter);
   void ResizeVideoWindow();
   HRESULT SetupVideoWindow();
   HRESULT InitCaptureGraphBuilder();
};
#endif // !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)
//-------------------------------------------------------------------
// CCaptureVideo视频捕捉类实现文件CaptureVideo.cpp
//-------------------------------------------------------------------
// CaptureVideo.cpp: implementation of the CCaptureVideo class.
//
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CaptureVideo.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
BOOL bOneShot=FALSE;//全局变量
class CSampleGrabberCB : public ISampleGrabberCB
{
  public:
   long lWidth;
   long lHeight;
   TCHAR m_szFileName[MAX_PATH];// 位图文件名称
   CSampleGrabberCB( ){
    strcpy(m_szFileName, "c:\donaldo.bmp");
   }
   STDMETHODIMP_(ULONG) AddRef() { return 2; }
   STDMETHODIMP_(ULONG) Release() { return 1; }
   STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){
   if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){
    *ppv = (void *) static_cast ( this );
    return NOERROR;
   }
   return E_NOINTERFACE;
  }
  STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ){
  return 0;
}
STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){
  if( !bOneShot )return 0;
 
  if (!pBuffer)return E_POINTER;
  SaveBitmap(pBuffer, lBufferSize);
  bOneShot = FALSE;
  return 0;
}
//创建位图文件
BOOL SaveBitmap(BYTE * pBuffer, long lBufferSize )
{
  HANDLE hf = CreateFile(
  m_szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
  CREATE_ALWAYS, NULL, NULL );
  if( hf == INVALID_HANDLE_VALUE )return 0;
   // 写文件头
   BITMAPFILEHEADER bfh;
   memset( &bfh, 0, sizeof( bfh ) );
   bfh.bfType = ’MB’;
   bfh.bfSize = sizeof( bfh ) + lBufferSize + sizeof( BITMAPINFOHEADER );
   bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
   DWORD dwWritten = 0;
   WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
   // 写位图格式
   BITMAPINFOHEADER bih;
   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 );
   return 0;
  }
};
CSampleGrabberCB mCB;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo()
{
  //COM Library Intialization
  if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
  {
   AfxMessageBox("CoInitialize Failed! ");
   return;
  }
  m_hWnd = NULL;
  m_pVW = NULL;
  m_pMC = NULL;
  m_pGB = NULL;
  m_pCapture = NULL;
}
CCaptureVideo::~CCaptureVideo()
{
  // Stop media playback
  if(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( );
}
int CCaptureVideo::EnumDevices(HWND hList)
{
  if (!hList)
   return -1;
  int id = 0;

  //枚举视频扑捉设备
  ICreateDevEnum *pCreateDevEnum;
  HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);

  if (hr != NOERROR)return -1;
  CComPtr pEm;
  hr = pCreateDevEnum-> CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);

  if (hr != NOERROR)return -1;
  pEm-> Reset();
  ULONG cFetched;
  IMon

本文链接:http://www.4byte.cn/learning/67561.html