📄 capturevideo.cpp
字号:
//-------------------------------------------------------------------
// CCaptureVideo视频捕捉类实现文件CaptureVideo.cpp
//-------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CaptureVideo.h"
#include <windows.h>
#include <io.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//CSampleGrabberCB mCB;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo()
{
//COM Library Intialization
if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
{
AfxMessageBox("COM初始化失败!\r\n");
return;
}
m_hPreviewWnd = NULL;
m_pVW = NULL;
m_pMC = NULL;
m_pGB = NULL;
m_pCapture = NULL;
m_bCapStatus = false;
m_strVideoFile.Format(".\\video.avi");
char *pbuff=new char[255];
GetCurrentDirectory(255,pbuff);
m_strBaseDir = pbuff;
delete []pbuff;
pbuff = NULL;
}
CCaptureVideo::~CCaptureVideo()
{
//停止回放
if(m_pMC)m_pMC->Stop();
if(m_pVW)
{
m_pVW->put_Visible(OAFALSE);
m_pVW->put_Owner(NULL);
}
if(!m_bCapStatus)
return;
if (NULL!=m_pCapture)
{
m_pCapture->Release();
m_pCapture = NULL;
}
if (NULL!=m_pMC)
{
m_pMC->Release();
m_pMC = NULL;
}
if (NULL!=m_pGB)
{
m_pGB->Release();
m_pGB = NULL;
}
if (NULL!=m_pBF)
{
m_pBF->Release();
m_pBF = NULL;
}
//CoUninitialize();
}
//枚举摄像设备,并将名称添加到list框里
int CCaptureVideo::EnumDevices(HWND hList)
{
if(!hList)
return -1;
int id = 0;
//枚举视频扑捉设备(这次枚举是为了往list框里添加名称,后边使用时得再次枚举)
ICreateDevEnum *pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
return -1;
CComPtr<IEnumMoniker> pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
if (hr != NOERROR)
return -1;
pEm->Reset();
ULONG cFetched;
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))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
TCHAR str[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();
}
return id;
}
HRESULT CCaptureVideo::Create(int iDeviceID, CStatic* inpPrev , int nMode)
{
if (inpPrev != NULL)
{
m_hPreviewWnd = inpPrev->GetSafeHwnd();
}
if (nMode == 1)
{
SetCurrentDirectory(m_strBaseDir);
SetCurrentDirectory(m_strCurDir);
//确定视频捕捉文件名
char FileBuf[20];
for(int i=0;i<65535;i++)
{ //试探是否已存在捕捉文件
sprintf(FileBuf,"Video%05d.AVI",i);
if((access(FileBuf,0)) == -1)
break;
}
m_strVideoFile = FileBuf;
}
//使用m_bCapStatus标记防止重复初始化出错,true表示曾经初始化
if(m_bCapStatus)
return NULL;
//初始化CaptureGraph
HRESULT hr;
hr = InitCaptureGraphBuilder();
if (FAILED(hr))
{
AfxMessageBox("获取视频捕捉接口失败!");
return hr;
}
//将m_pBF绑定到摄像头设备上,添加到graph里
if(!BindFilter(iDeviceID, &m_pBF))
{
AfxMessageBox("绑定视频设备失败!");
return S_FALSE;
}
hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");
if (FAILED(hr))
{
AfxMessageBox("Capture Filter添加失败!");
}
//创建一个sample grabber
hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !m_pGrabber )
{
AfxMessageBox("创建SampleGrabber Filter失败,请确认qedit.dll是否已注册");
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;
//将媒体格式设置到m_pGrabber
hr = m_pGrabber->SetMediaType(&mt);
if( FAILED( hr ) )
{
AfxMessageBox("设置媒体类型失败");
return hr;
}
//往graph添加grabberfilter,截图
hr = m_pGB->AddFilter( pGrabBase, L"Grabber" );
if( FAILED( hr ) )
{
AfxMessageBox("尝试将grabberfilter加入Graph失败!");
return hr;
}
/*/枚举系统中的压缩编码filter
CComPtr <IBaseFilter> pCompFilter;
GetCompFilter(&pCompFilter);
if (!pCompFilter)
return false;
//向graph中添加压缩编码filter
hr = m_pGB->AddFilter( pCompFilter, L"Compress" );
if( FAILED( hr ) )
{
return false;
}*/
//AVI文件filter
CComPtr< IBaseFilter > pMux;
CComPtr< IFileSinkFilter > pSink;
USES_CONVERSION;
if (nMode)
{
hr = m_pCapture->SetOutputFileName( &MEDIASUBTYPE_Avi, T2W( m_strVideoFile.GetBuffer(m_strVideoFile.GetLength()) ),
&pMux, &pSink );
if( FAILED( hr ) )
{
AfxMessageBox( TEXT("创建Mux and Writer Filter失败!"));
return false;
}
}
//智能连接preview pin
hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
{
AfxMessageBox("Preview Pin连接失败!");
return hr;
}
//根据模式标记进行Capture Pin 的连接
switch(nMode)
{
case 0:
break;
case 1:
hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,NULL,pMux);
break;
case 2:
//hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pCompFilter,pMux);
break;
default :
break;
}
if( FAILED( hr ) )
{
AfxMessageBox("Capture Pin 连接失败!");
return hr;
}
//从Grabber提取媒体格式
hr = m_pGrabber->GetConnectedMediaType( &mt );
if ( FAILED(hr) )
{
AfxMessageBox("Grabber Filter获取视频参数失败!");
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 );//截图后继续运行graph
hr = m_pGrabber->SetCallback( &mCB, 1 );////设置回调函数,0=SampleCb,1=BufferCb
//设置视频预览窗口
if (m_hPreviewWnd != NULL)
{
SetupVideoWindow();
}
//开始运行
hr = m_pMC->Run();
HWND h;
h = ::FindWindow(NULL,"XviD Status");
::PostMessage(h,WM_CLOSE,NULL,NULL);
if(FAILED(hr))
{
AfxMessageBox("启动graph失败!");
return hr;
}
return S_OK;
}
bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter) //参数一是枚举到的序号,参数二是要绑定的指针
{
if (deviceId < 0)
return false;
//枚举视频输入设备
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -