Windows下摄像头采集驱动(DirectShow)

出处:http://blog.csdn.net/chenice9999/article/details/6968957 


枚举摄像头设备(不论设备能否被使用都会被枚举出来):

int EnumDevices()

 int id = 0; 
 
 //枚举视频扑捉设备 
 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); //you can get other info by first parame
   if (hr == NOERROR) 
   { 

        id++; 
        SysFreeString(var.bstrVal); 
   } 
   
   pBag->Release(); 
  } 
  
  pM->Release(); 
 } 
 
 return id; 
}

 

启动摄像头:

HWND m_hWnd; 
IGraphBuilder *m_pGB; 
ICaptureGraphBuilder2* m_pCapture; 
IBaseFilter* m_pBF; 
IMediaControl* m_pMC; 
IVideoWindow* m_pVW; 
CComPtr<ISampleGrabber> m_pGrabber;

1.初始化GraphBuilder

CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB); 
CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **) &m_pCapture);  
m_pCapture->SetFiltergraph(m_pGB); 
m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);  
m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVW); 

2.绑定一个设备到InputFilter

CComPtr<ICreateDevEnum> pCreateDevEnum; 
CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);  
CComPtr<IEnumMoniker> pEm; 
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0); 

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) 
   { 
    pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter); 
    SysFreeString(var.bstrVal); 
   } 
   pBag->Release(); 
  }
  pM->Release(); 
 }

3.创建一个OutputFilter

m_pGrabber.CoCreateInstance( CLSID_SampleGrabber ); 
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );

4.设置SampleGrabber的视频格式

AM_MEDIA_TYPE mt; 
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); 
mt.majortype = MEDIATYPE_Video; 
mt.subtype = MEDIASUBTYPE_RGB24; //这里只是设置输出的图像数据类型(24bit,32bit,...),directshow会对自动的对采集到的图像数据做转换
m_pGrabber->SetMediaType(&mt);

5.将2个Filter添加到GraphBuilder

m_pGB->AddFilter(m_pBF, L"Capture Filter"); 
m_pGB->AddFilter( pGrabBase, L"Grabber" );

6.尝试去RenderStream,失败则表示该设备无法使用(比如被其他应用程序所占用)

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(L"Can’t build the graph"); 
  return hr; 
 }

7.配置SampleGrabber

m_pGrabber->SetBufferSamples( FALSE ); //如果设置true,SampleGrabber会创建一个内部的buffer,可以通过GetCurrentBuffer获得当前帧数据
m_pGrabber->SetOneShot( FALSE ); //如果设置成true,表示只会进入callback函数一次
m_pGrabber->SetCallback( &mCB, 1 );//设置callback,第2个参数如果设置成0,则第一个参数必须是IMediaSample指针

8.开始视频捕获

m_pMC->Run();

 

枚举,设置InputFilter的数据格式:

CComPtr<IAMStreamConfig> pam;
m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,    m_pBF, IID_IAMStreamConfig, reinterpret_cast<void**>(&pam));
int nCount = 0;
int nSize = 0;
pam->GetNumberOfCapabilities(&nCount, &nSize);

AM_MEDIA_TYPE* pmmt = NULL;
VIDEO_STREAM_CONFIG_CAPS scc;

if (sizeof(VIDEO_STREAM_CONFIG_CAPS) == nSize) {
  for (int i=0; i<nCount; i++) {
   pmmt = NULL;

   hr = pam->GetStreamCaps(i, &pmmt, reinterpret_cast<BYTE*>(&scc));
   if (FAILED(hr))
   {
    continue;
   }

   if ( pmmt->majortype == MEDIATYPE_Video && pmmt->formattype == FORMAT_VideoInfo )
   {
    pam->SetFormat(pmmt);

    break;
   }
  }
 }

 

释放AM_MEDIA_TYPE类型资源:

void 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; 
 } 
}

 

绑定视频输出窗口:

创建一个picture空间,设置其属性(Type: Rectangle,Color:Gray)

m_pVW->put_Owner((OAHWND)m_hWnd);  
m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);  
 Rect rc; 
::GetClientRect(m_hWnd,&rc); 
float fk = (float)mCB.lWidth / (float)mCB.lHeight;
long rw = fk * rc.bottom;
int off_x = (rc.right - rw)/2;
m_pVW->SetWindowPosition(off_x, 0, rw, rc.bottom);//让捕获到的视频居中显示
m_pVW->put_Visible(OATRUE);

 

解绑视频输出窗口:

m_pVW->put_Visible(OAFALSE);
m_pVW->put_Owner(NULL);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值