Dshow 捕获设备数据

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


你可能感兴趣的:(Dshow 捕获设备数据)