Visual C++编程实现摄像头视频捕捉.docx
- 文档编号:11164948
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:13
- 大小:21.75KB
Visual C++编程实现摄像头视频捕捉.docx
《Visual C++编程实现摄像头视频捕捉.docx》由会员分享,可在线阅读,更多相关《Visual C++编程实现摄像头视频捕捉.docx(13页珍藏版)》请在冰豆网上搜索。
VisualC++编程实现摄像头视频捕捉
VisualC++编程实现摄像头视频捕捉
摘要:
本文主要讲述用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_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
#include
#include
#include
#ifndefSAFE_RELEASE
#defineSAFE_RELEASE(x)\
if(NULL!
=x)\
{\
x->Release();\
x=NULL;\
}
#endif
classCSampleGrabberCB;
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;
CComPtrm_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.
//
/////////////////////////////////////////////////////////////////////
#include"stdafx.h"
#include"CaptureVideo.h"
#ifdef_DEBUG
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#definenewDEBUG_NEW
#endif
BOOLbOneShot=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_cast(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()
{
//COMLibraryIntialization
if(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()
{
//Stopmediaplayback
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();
}
intCCaptureVideo:
:
EnumDevices(HWNDhList)
{
if(!
hList)
return-1;
intid=0;
//枚举视频扑捉设备
ICreateDevEnum*pCreateDevEnum;
HRESULThr=CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,(void**)&pCreateDevEnum);
if(hr!
=NOERROR)return-1;
CComPtrpEm;
hr=pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm,0);
if(hr!
=NOERROR)return-1;
pEm->Reset();
ULONGcFetched;
IMoniker*pM;
while(hr=pEm->Next(1,&pM,&cFetched),hr==S_OK)
{
IPropertyBag*pBag;
hr=pM->BindToStorage(0,0,IID_IPropertyBag,(void**)&pBag);
if(SUCCEEDED(hr))
{
VARIANTvar;
var.vt=VT_BSTR;
hr=pBag->Read(L"FriendlyName",&var,NULL);
if(hr==NOERROR)
{
TCHARstr[2048];
id++;
WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,str,2048,NULL,NULL);
:
:
SendMessage(hList,CB_ADDSTRING,0,(LPARAM)str);
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
}
returnid;
}
HRESULTCCaptureVideo:
:
Init(intiDeviceID,HWNDhWnd)
{
HRESULThr;
hr=InitCaptureGraphBuilder();
if(FAILED(hr)){
AfxMessageBox("Failedtogetvideointerfaces!
");
returnhr;
}
//BindDeviceFilter.Weknowthedevicebecausetheidwaspassedin
if(!
BindFilter(iDeviceID,&m_pBF))returnS_FALSE;
hr=m_pGB->AddFilter(m_pBF,L"CaptureFilter");
//hr=m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,
//m_pBF,NULL,NULL);
//createasamplegrabber
hr=m_pGrabber.CoCreateInstance(CLSID_SampleGrabber);
if(!
m_pGrabber){
AfxMessageBox("FailtocreateSampleGrabber,maybeqedit.dllisnotregistered?
");
returnhr;
}
CComQIPtr
//设置视频格式
AM_MEDIA_TYPEmt;
ZeroMemory(&mt,sizeof(AM_MEDIA_TYPE));
mt.majortype=MEDIATYPE_Video;
mt.subtype=MEDIASUBTYPE_RGB24;
hr=m_pGrabber->SetMediaType(&mt);
if(FAILED(hr)){
AfxMessageBox("Failtosetmediatype!
");
returnhr;
}
hr=m_pGB->AddFilter(pGrabBase,L"Grabber");
if(FAILED(hr)){
AfxMessageBox("Failtoputsamplegrabberingraph");
returnhr;
}
//trytorenderpreview/capturepin
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’tbuildthegraph");
returnhr;
}
hr=m_pGrabber->GetConnectedMediaType(&mt);
if(FAILED(hr)){
AfxMessageBox("Failttoreadtheconnectedmediatype");
returnhr;
}
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;
SetupVideoWindow();
hr=m_pMC->Run();//开始视频捕捉
if(FAILED(hr)){AfxMessageBox("Couldn’trunthegraph!
");returnhr;}
returnS_OK;
}
boolCCaptureVideo:
:
BindFilter(intdeviceId,IBaseFilter**pFilter)
{
if(deviceId<0)
returnfalse;
//enumerateallvideocapturedevices
CComPtrpCreateDevEnum;
HRESULThr=CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum,(void**)&pCreateDevEnum);
if(hr!
=NOERROR)
{
returnfalse;
}
CComPtrpEm;
hr=pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm,0);
if(hr!
=NOERROR)
{
returnfalse;
}
pEm->Reset();
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Visual C+编程实现摄像头视频捕捉 C+ 编程 实现 摄像头 视频 捕捉