// CaptureVideo.h: interface for the CCaptureVideo class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <atlbase.h>
#include <windows.h>
#include <dshow.h>
#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);
void ImageProcess(BOOL bImage);
HRESULT Init(int iDeviceID,HWND hWnd);
CCaptureVideo();
virtual ~CCaptureVideo();
BOOL bIsVideoOpen;
void SwitchImageProcess(BOOL bprocess);
void ImageProcessing(unsigned char*m_pDibBits,int m_height, int m_width);
private:
HWND m_hWnd;
IGraphBuilder *m_pGB;
ICaptureGraphBuilder2* m_pCapture;
IBaseFilter* m_pBF;
IMediaControl* m_pMC;
IVideoWindow* m_pVW;
CComPtr <ISampleGrabber> m_pGrabber;
protected:
void FreeMediaType(AM_MEDIA_TYPE& mt);
bool BindFilter(int deviceId, IBaseFilter **pFilter);
HRESULT InitCaptureGraphBuilder();
};
#endif // !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <atlbase.h>
#include <windows.h>
#include <dshow.h>
#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);
void ImageProcess(BOOL bImage);
HRESULT Init(int iDeviceID,HWND hWnd);
CCaptureVideo();
virtual ~CCaptureVideo();
BOOL bIsVideoOpen;
void SwitchImageProcess(BOOL bprocess);
void ImageProcessing(unsigned char*m_pDibBits,int m_height, int m_width);
private:
HWND m_hWnd;
IGraphBuilder *m_pGB;
ICaptureGraphBuilder2* m_pCapture;
IBaseFilter* m_pBF;
IMediaControl* m_pMC;
IVideoWindow* m_pVW;
CComPtr <ISampleGrabber> m_pGrabber;
protected:
void FreeMediaType(AM_MEDIA_TYPE& mt);
bool BindFilter(int deviceId, IBaseFilter **pFilter);
HRESULT InitCaptureGraphBuilder();
};
#endif // !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)
// CaptureVideo.cpp: implementation of the CCaptureVideo class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CaptureVideo.h"
#include "ImageProcess.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////声明全局变量//////////////////////////////////////
BOOL bIsSavePic = FALSE;
BOOL bIsImageProcess = FALSE;
//////////////////////////////////////////////////////////////////////
class CSampleGrabberCB:public ISampleGrabberCB
{
public:
long lWidth;
long lHeight;
CCaptureVideo dlg;
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<ISampleGrabberCB*> ( this );
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
{
return 0;
}
//回调函数
STDMETHODIMP BufferCB( double dblSampleTime, unsigned char* pBuffer, long lBufferSize )
{
if (!pBuffer) return E_POINTER;
if (bIsImageProcess)
{//如果条件为真则进行数字图像处理
dlg.ImageProcessing(pBuffer, lHeight, lWidth);
}
return 0;
}
};
CSampleGrabberCB mCB;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo()
{
//COM Library Intialization
if(FAILED(CoInitialize(NULL)))
{
AfxMessageBox("CoInitialize Failed!\r\n");
return;
}
m_hWnd = NULL;
m_pVW = NULL;
m_pMC = NULL;
m_pGB = NULL;
m_pCapture = NULL;
bIsVideoOpen = FALSE;
}
CCaptureVideo::~CCaptureVideo()
{
if (bIsVideoOpen)
{
// 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( );
}
}
///////////////////////////////////////////////////////////////////////////
////
//// DirectShow核心代码
////
///////////////////////////////////////////////////////////////////////////
HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
{
HRESULT hr;
hr = InitCaptureGraphBuilder();
if (FAILED(hr))
{
AfxMessageBox("Failed to get video interfaces!");
return hr;
}
// Bind Device Filter. We know the device because the id was passed in
if(!BindFilter(iDeviceID, &m_pBF))
{
AfxMessageBox("未找到USB摄像头!\n请检查设备后重试!");
PostQuitMessage(0);
return S_FALSE;
}
hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");
// hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, // m_pBF, NULL, NULL);
// create a sample grabber
hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !m_pGrabber )
{
AfxMessageBox("Fail to create SampleGrabber, maybe qedit.dll is not registered?");
return hr;
}
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase(m_pGrabber);
//**********设置视频格式**********//
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24; //抓取24位位图
hr = m_pGrabber->SetMediaType(&mt);
if( FAILED( hr ) )
{
AfxMessageBox("Fail to set media type!");
return hr;
}
hr = m_pGB->AddFilter( pGrabBase, L"Grabber" );
if( FAILED( hr ) )
{
AfxMessageBox("Fail to put sample grabber in graph");
return hr;
}
// try to render preview/capture pin
hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
{
AfxMessageBox("Can't build the graph");
return hr;
}
hr = m_pGrabber->GetConnectedMediaType( &mt );
if ( FAILED( hr) )
{
AfxMessageBox("Failt to read the connected media type");
return hr;
}
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
mCB.lWidth = vih->bmiHeader.biWidth;
mCB.lHeight = vih->bmiHeader.biHeight;
FreeMediaType(mt);
hr = m_pGrabber->SetBufferSamples( FALSE );
hr = m_pGrabber->SetOneShot( FALSE );
hr = m_pGrabber->SetCallback( &mCB, 1 );
//*********设置视频捕捉窗口********//
m_hWnd = hWnd ; //picture控件的句柄
hr = m_pVW->put_Owner((OAHWND)m_hWnd);
if (FAILED(hr)) return hr;
hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
if (FAILED(hr)) return hr;
if (m_pVW)
{
CRect rc;
::GetClientRect(m_hWnd,&rc);
m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);//让图像充满整个窗口
}
hr = m_pVW->put_Visible(OATRUE);
//*********开始视频捕捉********//
hr = m_pMC->Run();
if(FAILED(hr))
{
AfxMessageBox("Couldn't run the graph!");
return hr;
}
bIsVideoOpen = TRUE;
return S_OK;
}
HRESULT CCaptureVideo::InitCaptureGraphBuilder()
{
HRESULT hr;
// 创建IGraphBuilder接口
hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
// 创建ICaptureGraphBuilder2接口
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
if (FAILED(hr)) return hr;
m_pCapture->SetFiltergraph(m_pGB);
hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
if (FAILED(hr)) return hr;
hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW);
if (FAILED(hr)) return hr;
return hr;
}
bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter)
{
if (deviceId < 0) return false;
// enumerate all video capture devices
CComPtr<ICreateDevEnum> pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
{
return false;
}
CComPtr<IEnumMoniker> pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
if (hr != NOERROR)
{
return false;
}
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
int index = 0;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
if (index == deviceId)
{
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
}
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
index++;
}
return true;
}
void CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
// Strictly unnecessary but tidier
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
void CCaptureVideo::SwitchImageProcess(BOOL bprocess)
{
bIsImageProcess = bprocess;
}
//////////////////////////////////////////////////////////////////////////////
/////////
///////// 数字图像处理
////////
///////////////////////////////////////////////////////////////////////////////
void CCaptureVideo::ImageProcessing(unsigned char*m_pDibBits, int m_height, int m_width)
{
CImageProcess::ColorToGray(m_pDibBits,m_height, m_width); //彩色转灰度
CImageProcess::ConvertGrayToWhiteBlack(m_pDibBits, m_height, m_width, 120); //二值化
}
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CaptureVideo.h"
#include "ImageProcess.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////声明全局变量//////////////////////////////////////
BOOL bIsSavePic = FALSE;
BOOL bIsImageProcess = FALSE;
//////////////////////////////////////////////////////////////////////
class CSampleGrabberCB:public ISampleGrabberCB
{
public:
long lWidth;
long lHeight;
CCaptureVideo dlg;
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<ISampleGrabberCB*> ( this );
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
{
return 0;
}
//回调函数
STDMETHODIMP BufferCB( double dblSampleTime, unsigned char* pBuffer, long lBufferSize )
{
if (!pBuffer) return E_POINTER;
if (bIsImageProcess)
{//如果条件为真则进行数字图像处理
dlg.ImageProcessing(pBuffer, lHeight, lWidth);
}
return 0;
}
};
CSampleGrabberCB mCB;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo()
{
//COM Library Intialization
if(FAILED(CoInitialize(NULL)))
{
AfxMessageBox("CoInitialize Failed!\r\n");
return;
}
m_hWnd = NULL;
m_pVW = NULL;
m_pMC = NULL;
m_pGB = NULL;
m_pCapture = NULL;
bIsVideoOpen = FALSE;
}
CCaptureVideo::~CCaptureVideo()
{
if (bIsVideoOpen)
{
// 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( );
}
}
///////////////////////////////////////////////////////////////////////////
////
//// DirectShow核心代码
////
///////////////////////////////////////////////////////////////////////////
HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
{
HRESULT hr;
hr = InitCaptureGraphBuilder();
if (FAILED(hr))
{
AfxMessageBox("Failed to get video interfaces!");
return hr;
}
// Bind Device Filter. We know the device because the id was passed in
if(!BindFilter(iDeviceID, &m_pBF))
{
AfxMessageBox("未找到USB摄像头!\n请检查设备后重试!");
PostQuitMessage(0);
return S_FALSE;
}
hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");
// hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, // m_pBF, NULL, NULL);
// create a sample grabber
hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !m_pGrabber )
{
AfxMessageBox("Fail to create SampleGrabber, maybe qedit.dll is not registered?");
return hr;
}
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase(m_pGrabber);
//**********设置视频格式**********//
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24; //抓取24位位图
hr = m_pGrabber->SetMediaType(&mt);
if( FAILED( hr ) )
{
AfxMessageBox("Fail to set media type!");
return hr;
}
hr = m_pGB->AddFilter( pGrabBase, L"Grabber" );
if( FAILED( hr ) )
{
AfxMessageBox("Fail to put sample grabber in graph");
return hr;
}
// try to render preview/capture pin
hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
{
AfxMessageBox("Can't build the graph");
return hr;
}
hr = m_pGrabber->GetConnectedMediaType( &mt );
if ( FAILED( hr) )
{
AfxMessageBox("Failt to read the connected media type");
return hr;
}
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
mCB.lWidth = vih->bmiHeader.biWidth;
mCB.lHeight = vih->bmiHeader.biHeight;
FreeMediaType(mt);
hr = m_pGrabber->SetBufferSamples( FALSE );
hr = m_pGrabber->SetOneShot( FALSE );
hr = m_pGrabber->SetCallback( &mCB, 1 );
//*********设置视频捕捉窗口********//
m_hWnd = hWnd ; //picture控件的句柄
hr = m_pVW->put_Owner((OAHWND)m_hWnd);
if (FAILED(hr)) return hr;
hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
if (FAILED(hr)) return hr;
if (m_pVW)
{
CRect rc;
::GetClientRect(m_hWnd,&rc);
m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);//让图像充满整个窗口
}
hr = m_pVW->put_Visible(OATRUE);
//*********开始视频捕捉********//
hr = m_pMC->Run();
if(FAILED(hr))
{
AfxMessageBox("Couldn't run the graph!");
return hr;
}
bIsVideoOpen = TRUE;
return S_OK;
}
HRESULT CCaptureVideo::InitCaptureGraphBuilder()
{
HRESULT hr;
// 创建IGraphBuilder接口
hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
// 创建ICaptureGraphBuilder2接口
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
if (FAILED(hr)) return hr;
m_pCapture->SetFiltergraph(m_pGB);
hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
if (FAILED(hr)) return hr;
hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW);
if (FAILED(hr)) return hr;
return hr;
}
bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter)
{
if (deviceId < 0) return false;
// enumerate all video capture devices
CComPtr<ICreateDevEnum> pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
{
return false;
}
CComPtr<IEnumMoniker> pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
if (hr != NOERROR)
{
return false;
}
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
int index = 0;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
if (index == deviceId)
{
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
}
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
index++;
}
return true;
}
void CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
// Strictly unnecessary but tidier
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
void CCaptureVideo::SwitchImageProcess(BOOL bprocess)
{
bIsImageProcess = bprocess;
}
//////////////////////////////////////////////////////////////////////////////
/////////
///////// 数字图像处理
////////
///////////////////////////////////////////////////////////////////////////////
void CCaptureVideo::ImageProcessing(unsigned char*m_pDibBits, int m_height, int m_width)
{
CImageProcess::ColorToGray(m_pDibBits,m_height, m_width); //彩色转灰度
CImageProcess::ConvertGrayToWhiteBlack(m_pDibBits, m_height, m_width, 120); //二值化
}
主程序
#ifdef _DEBUG
#pragma comment(lib,"strmbasd.lib")
#else
#pragma comment(lib,"STRMBASE.lib")
#endif
#pragma comment(lib,"strmiids.lib")
#pragma comment(lib,"quartz.lib")
void CUSBShowDlg::OnBUTTONOpenVideo() //打开摄像头
{
HWND hWnd = m_StaticShow.GetSafeHwnd();
HRESULT hr = m_cap.Init(0,hWnd); //DirectShow初始化
}
void CUSBShowDlg::OnBUTTONImageProcess() //启动数字图像处理开关
{
m_cap.SwitchImageProcess(TRUE);
}
#ifdef _DEBUG
#pragma comment(lib,"strmbasd.lib")
#else
#pragma comment(lib,"STRMBASE.lib")
#endif
#pragma comment(lib,"strmiids.lib")
#pragma comment(lib,"quartz.lib")
void CUSBShowDlg::OnBUTTONOpenVideo() //打开摄像头
{
HWND hWnd = m_StaticShow.GetSafeHwnd();
HRESULT hr = m_cap.Init(0,hWnd); //DirectShow初始化
}
void CUSBShowDlg::OnBUTTONImageProcess() //启动数字图像处理开关
{
m_cap.SwitchImageProcess(TRUE);
}