1 windows下用dshow可以捕获摄像头和麦克风数据,参照上一篇获取设备信息后可以进一步写出获取数据的代码,继续抛砖
class CDeviceCapture : public ISampleGrabberCB { public: STDMETHODIMP_(ULONG) AddRef() { return 2; } STDMETHODIMP_(ULONG) Release() { return 1; } virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ){ return S_OK; }; virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ); virtual STDMETHODIMP QueryInterface( REFIID riid, void ** ppv ) { if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){ *ppv = (void *) static_cast<ISampleGrabberCB*> ( this ); return NOERROR; } return E_NOINTERFACE; }; public: CDeviceCapture(int iType,wstring wszFriendlyName,AM_MEDIA_TYPE* pAmType) { m_iType = iType; m_pAmType = NULL; setAmType(pAmType); m_wszFriendlyName = wszFriendlyName; buildDshowCapGraph(wszFriendlyName); } ~CDeviceCapture() { } AM_MEDIA_TYPE* getAmType() { return m_pAmType; } void startCap() { m_pControl->Run(); } void stopCap() { m_pControl->Stop(); } void pauseCap() { m_pControl->Pause(); } private: void setAmType(AM_MEDIA_TYPE* amType) { m_iType==DEVICE_CAP_VIDEO_TYPE?printAmInfo(amType):printAmInfo(amType,false); if(m_pAmType) { DeleteMediaType(m_pAmType); m_pAmType = NULL; } m_pAmType = CreateMediaType(amType); //FreeMediaType(*m_pAmType); //CopyMediaType(m_pAmType,amType); } bool createDeciceCap(wstring wszFridlyName,IBaseFilter*& device); bool buildDshowCapGraph(wstring wszFridlyName); private: int m_iType; CComPtr<ICaptureGraphBuilder2> m_pCapGraph2; CComPtr<IMediaControl> m_pControl; AM_MEDIA_TYPE* m_pAmType; wstring m_wszFriendlyName; CComPtr<ISampleGrabber> m_pSampleGrab; };
bool CDeviceCapture::createDeciceCap(wstring wszFridlyName,IBaseFilter*& device) { bool audio = m_iType== DEVICE_CAP_AUDIO_TYPE?true:false; CComPtr<ICreateDevEnum> de; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&de); if (hr != NOERROR) { __LOGOUT("Can't create CLSID_SystemDeviceEnum object"); return false; } CComPtr<IEnumMoniker> em; if (audio) { hr = de->CreateClassEnumerator(CLSID_AudioInputDeviceCategory,&em, 0); } else { hr = de->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&em, 0); } if (hr != NOERROR) { __LOGOUT("Can't create CLSID_***InputDeviceCategory object"); return false; } ULONG got; IMoniker *m; em->Reset(); while(hr = em->Next(1, &m, &got), hr==S_OK) { IPropertyBag *pb; hr = m->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pb); if(!SUCCEEDED(hr)) continue ; CDShowCapInfo* pCapInfo = new CDShowCapInfo(); VARIANT var; var.vt = VT_BSTR; hr = pb->Read(L"FriendlyName", &var, NULL); if (hr == S_OK) { wstring szName; szName.append((wchar_t*)var.bstrVal); pCapInfo->setFriendlyName(szName); SysFreeString(var.bstrVal); if(szName == wszFridlyName) { IBaseFilter* dev=NULL; hr = m->BindToObject(NULL,NULL,IID_IBaseFilter,(void**)&device); if (hr != S_OK) { __LOGOUT("Create Device faild, BindToObjcet error"); } //device = dev; return true; } } } return false; } bool CDeviceCapture::buildDshowCapGraph(wstring wszFridlyName) { bool audio = m_iType== DEVICE_CAP_AUDIO_TYPE?true:false; CComPtr<ICaptureGraphBuilder2> graphBuilder; CComPtr<IGraphBuilder> graph; CComPtr<IBaseFilter> device ; HRESULT hr; IBaseFilter** dev = NULL; //创建设备filter if (!createDeciceCap(wszFridlyName, (IBaseFilter*&)device)) { ThrowStdExp("Can't create AV device filter"); } assert(device); //创建filtergraph, capturegraphbuilder2对象 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&graph); if (FAILED(hr)) { ThrowStdExp("Can't create CLSID_FilterGraph, Direct X hasn't installed?"); } hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&graphBuilder); if (FAILED(hr)) { ThrowStdExp("Can't create CLSID_CaptureGraphBuilder2, Direct X hasn't installed?"); } hr = graphBuilder->SetFiltergraph(graph); if (FAILED(hr)) { ThrowStdExp("SetFiltergraph failed"); } //隐藏窗口 CComQIPtr<IMediaControl> control = graph; CComQIPtr<IVideoWindow> window = graph; window->put_Visible(OAFALSE); //加入source filter hr = graph->AddFilter(device, NULL); if (FAILED(hr)) { ThrowStdExp("source AddFilter failed"); } CComPtr<IBaseFilter> nullRender; hr = CoCreateInstance(CLSID_NullRenderer,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**)&nullRender); if(FAILED(hr)){ ThrowStdExp("Create Interface error"); } hr = graph->AddFilter(nullRender, NULL); if (FAILED(hr)) { ThrowStdExp("source AddFilter failed"); } CComPtr<ISampleGrabber> sampleGrabber; hr = CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,IID_ISampleGrabber,(void**)&sampleGrabber); if(FAILED(hr)){ ThrowStdExp("Create Interface error"); } CComPtr<IBaseFilter> filterGrab; filterGrab = sampleGrabber; hr = graph->AddFilter(filterGrab, NULL); if (FAILED(hr)) { ThrowStdExp("source AddFilter failed"); } const GUID gType = audio?MEDIATYPE_Audio:MEDIATYPE_Video; CComPtr<IAMStreamConfig> config; hr = graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &gType, device, IID_IAMStreamConfig, (void **)&config); if(FAILED(hr)){ ThrowStdExp("Create Interface error"); } hr = config->SetFormat(m_pAmType); //设置input pin的media type ,传null重置pin为默认type if (FAILED(hr)) { int iErr = ::GetLastError(); ThrowStdExp("Can't Pause for grabber"); } hr =sampleGrabber->SetMediaType(m_pAmType); //设置后,运行时会检查output pin 如果类型不符合会拒绝连接,可不调用 hr = graphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,&gType,device,filterGrab,nullRender); if(FAILED(hr)){ ThrowStdExp("Create Interface error"); } AM_MEDIA_TYPE iAmType; hr = sampleGrabber->GetConnectedMediaType(&iAmType); if (FAILED(hr)) { ThrowStdExp("Can't GetConnectedMediaType for grabber"); } this->setAmType(&iAmType); FreeMediaType(iAmType); sampleGrabber->SetCallback(this,1); hr = control->Pause(); if (FAILED(hr)) { int iErr = ::GetLastError(); ThrowStdExp("Can't Pause for grabber"); } m_pCapGraph2 = graphBuilder; m_pControl = control; m_pSampleGrab = sampleGrabber; return true; } STDMETHODIMP CDeviceCapture::BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) { printf("time: %f, buffer size: %ld ",SampleTime,BufferLen); if(m_iType == DEVICE_CAP_VIDEO_TYPE){ printAmInfo(m_pAmType); AM_MEDIA_TYPE amType ; m_pSampleGrab->GetConnectedMediaType(&amType); printAmInfo(&amType); } else { printAmInfo(m_pAmType,false); } printf("\r\n"); return S_OK; }
int _tmain(int argc, _TCHAR* argv[]) { try{ ::CoInitialize(NULL); CDshowCapInfoMgr* mgr = new CDshowCapInfoMgr(); mgr->enumAllCapInfo(); mgr->printCapDetail(); //CDShowCapInfo* pInfo = mgr->getVideoInfo(0); //CDeviceCapture* device = new CDeviceCapture(DEVICE_CAP_VIDEO_TYPE,pInfo->getFriendlyName(),pInfo->getMediaOption(8)); CDShowCapInfo* pInfo = mgr->getAudioInfo(0); CDeviceCapture* device = new CDeviceCapture(DEVICE_CAP_AUDIO_TYPE,pInfo->getFriendlyName(),pInfo->getMediaOption(0)); device->startCap(); while (true) { Sleep(1000); } }catch(std::exception e) { printf(e.what()); } return 0; }