Directshow 如何获取摄像头音视频设备,并判断摄像头是否占用。

Directshow 能很方便的获取连接的 视频和音频设备的名称。本篇文章同时介绍如何判断获取的摄像头是否正在占用。


代码如下:


(1) 获取摄像头音视频设备名称

void CDeviceTree::EnumDevices()
{
	
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum);

	hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
//将CLSID_VideoInputDeviceCategory 改成 CLSID_AudioInputDeviceCategory 即能获取音频设备

	if (FAILED(hr))
	{
		return;
	}

	if(hr == S_OK)
	{
		ULONG cFetched;

		while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
		{
			IPropertyBag* pPropBag;

			hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);

			if(SUCCEEDED(hr))
			{
			
				VARIANT varName;
				varName.vt=VT_BSTR;

				VariantInit(&varName);

				hr = pPropBag->Read(L"FriendlyName", &varName, 0);
				
				USES_CONVERSION;
				LPTSTR lpstrMsg = W2T(varName.bstrVal);

				if(SUCCEEDED(hr))
				{
					//videoDev[videoIndex]=lpstrMsg;
					//videoIndex++;
//此处即得到获得的视频设备名称  你可以将它打印出来 或者存入队列
				}

				pPropBag->Release();

			}
			pMoniker->Release();
		}
		
	}
}


(2) 判断摄像头是否占用。

int DeviceIsBusy(char *videoName,char *audioName)
{
	//输入设备的音视频名称
	HRESULT hr;
	HRESULT hhr;
	int ret=0;
	int videoBusy=1;
	int audioBusy=1;

	CoInitialize(NULL);

	ICreateDevEnum* pSysDevEnum = NULL;

	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum);

	IEnumMoniker* pEnumCat ;

	hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);

	if(hr == S_OK)
	{
		IMoniker* pMoniker = NULL;
		IMoniker* pm1=NULL;
		ULONG cFetched;

		while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
		{
			IPropertyBag* pPropBag;
			hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);

			if(SUCCEEDED(hr))
			{

				VARIANT varName;
				varName.vt=VT_BSTR;

				VariantInit(&varName);

				hr = pPropBag->Read(L"FriendlyName", &varName, 0);

				USES_CONVERSION;
				LPTSTR lpstrMsg = W2T(varName.bstrVal);

				if(SUCCEEDED(hr))
				{
					if (!strcmp(videoName,lpstrMsg))//存在设备
					{
						LPBC *pbc=NULL;
						IBaseFilter *P_VCamTrans=NULL;
						IBaseFilter *pCap=NULL;

						CreateBindCtx(0,pbc);

						hr=pMoniker->BindToObject((IBindCtx *)pbc,0,IID_IBaseFilter,(void **)&pCap); 

						ICaptureGraphBuilder2 *m_pCapGB;    
						IGraphBuilder *m_pGB;   
						IMediaControl *m_pMC;   
						IVideoWindow   *m_pVW;

						hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);  

						if (FAILED(hr)) return hr;  

						m_pGB->AddFilter(pCap,NULL);

						hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);  

						if (FAILED(hr)) return hr;  

						m_pCapGB->SetFiltergraph(m_pGB);

						IAMCrossbar *pXBar1 = NULL;

						hr=m_pCapGB->FindInterface(&LOOK_UPSTREAM_ONLY,NULL,pCap,IID_IAMCrossbar,(void **)&pXBar1);

						if (SUCCEEDED(hr))
						{
							long OutputPinCount;
							long InputPinCount;
							long PinIndexRelated;
							long PhysicalType;
							long inPort = 0;
							long outPort = 0;

							pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);

							//对于存在输入输出引脚的摄像头。此处采用轮询所有的引脚 
							for(int i =0;i<InputPinCount;i++)
							{
								pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);

								if(PhysConn_Video_Composite==PhysicalType)
								{
									inPort = i;
									break;
								}

							}

							for(int i =0;i<OutputPinCount;i++)
							{
								pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);

								if(PhysConn_Video_VideoDecoder==PhysicalType)
								{
									outPort = i;
									break;
								}
							}

							for (int i=0;i<InputPinCount;i++)
							{
								for (int j=0;j<OutputPinCount;j++)
								{
									if(S_OK==pXBar1->CanRoute(j,i))
									{
										pXBar1->Route(j,i);

										m_pGB->AddFilter(pCap, L"Capture Filter");
										m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
										hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
										hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);

										hr = m_pVW->put_Owner((OAHWND)NULL); 
										hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
										hr = m_pVW->put_Visible(OAFALSE);   
										hr=m_pVW->put_AutoShow(OAFALSE);

										hhr=m_pMC->StopWhenReady();

										if (SUCCEEDED(hhr))
										{
											videoBusy=0;
										}

									}
								}
							}

							if (videoBusy == 1)
							{
								ret=-1; //视频设备占用
							}
						}
						else
						{
							m_pGB->AddFilter(pCap, L"Capture Filter");
							m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
							hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
							hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);

							hr = m_pVW->put_Owner((OAHWND)NULL); 
							hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
							hr = m_pVW->put_Visible(OAFALSE);   
							hr=m_pVW->put_AutoShow(OAFALSE);

							hhr=m_pMC->StopWhenReady();

							if (FAILED(hhr))
							{
								ret=-1;  //视频设备占用
							}

						}

					}

				}

				pPropBag->Release();

			}
			pMoniker->Release();
		}

	}

	//判断音频的方法和上面的一样 重复。
	hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnumCat, 0);

	if(hr == S_OK)
	{
		IMoniker* pMoniker = NULL;
		IMoniker* pm1=NULL;
		ULONG cFetched;

		while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
		{
			IPropertyBag* pPropBag;
			hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);

			if(SUCCEEDED(hr))
			{

				VARIANT varName;
				varName.vt=VT_BSTR;

				VariantInit(&varName);

				hr = pPropBag->Read(L"FriendlyName", &varName, 0);

				USES_CONVERSION;
				LPTSTR lpstrMsg = W2T(varName.bstrVal);

				if(SUCCEEDED(hr))
				{
					if (!strcmp(videoName,lpstrMsg))//存在设备
					{
						LPBC *pbc=NULL;
						IBaseFilter *P_VCamTrans=NULL;
						IBaseFilter *pCap=NULL;

						CreateBindCtx(0,pbc);

						hr=pMoniker->BindToObject((IBindCtx *)pbc,0,IID_IBaseFilter,(void **)&pCap); 

						ICaptureGraphBuilder2 *m_pCapGB;    
						IGraphBuilder *m_pGB;   
						IMediaControl *m_pMC;   
						IVideoWindow   *m_pVW;

						hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);  

						if (FAILED(hr)) return hr;  

						m_pGB->AddFilter(pCap,NULL);

						hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);  

						if (FAILED(hr)) return hr;  

						m_pCapGB->SetFiltergraph(m_pGB);

						IAMCrossbar *pXBar1 = NULL;

						hr=m_pCapGB->FindInterface(&LOOK_UPSTREAM_ONLY,NULL,pCap,IID_IAMCrossbar,(void **)&pXBar1);

						if (SUCCEEDED(hr))
						{
							long OutputPinCount;
							long InputPinCount;
							long PinIndexRelated;
							long PhysicalType;
							long inPort = 0;
							long outPort = 0;

							pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);

							for(int i =0;i<InputPinCount;i++)
							{
								pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);

								if(PhysConn_Video_Composite==PhysicalType)
								{
									inPort = i;
									break;
								}

							}

							for(int i =0;i<OutputPinCount;i++)
							{
								pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);

								if(PhysConn_Video_VideoDecoder==PhysicalType)
								{
									outPort = i;
									break;
								}
							}

							for (int i=0;i<InputPinCount;i++)
							{
								for (int j=0;j<OutputPinCount;j++)
								{
									if(S_OK==pXBar1->CanRoute(j,i))
									{
										pXBar1->Route(j,i);

										m_pGB->AddFilter(pCap, L"Capture Filter");
										m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
										hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
										hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);

										hr = m_pVW->put_Owner((OAHWND)NULL); 
										hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
										hr = m_pVW->put_Visible(OAFALSE);   
										hr=m_pVW->put_AutoShow(OAFALSE);

										hhr=m_pMC->StopWhenReady();

										if (SUCCEEDED(hhr))
										{
											audioBusy=0;
										}

									}
								}
							}

							if (audioBusy == 1)
							{
								ret=-1; //音频设备占用
							}
						}
						else
						{
							m_pGB->AddFilter(pCap, L"Capture Filter");
							m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
							hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
							hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);

							hr = m_pVW->put_Owner((OAHWND)NULL); 
							hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
							hr = m_pVW->put_Visible(OAFALSE);   
							hr=m_pVW->put_AutoShow(OAFALSE);

							hhr=m_pMC->StopWhenReady();

							if (FAILED(hhr))
							{
								ret=-1;  //音频设备占用
							}

						}

					}

				}

				pPropBag->Release();

			}
			pMoniker->Release();
		}

	}


	pSysDevEnum->Release();

	CoUninitialize();

	return ret;
}



(3)头文件

#include "windows.h"
#include "stdio.h"
#include "string.h"
#include <string>
#include "Dshow.h"
#include "atlconv.h"

#pragma   comment(lib,"Strmiids.lib")   
#pragma   comment(lib,"Quartz.lib")

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
DirectShow是Windows平台上的一个多媒体框架,用于处理音频和视频流。使用DirectShow捕捉摄像头视频数据需要以下步骤: 1. 枚举可用的视频捕捉设备并选择需要使用的设备。 2. 创建一个Filter Graph Manager对象,用于管理DirectShow图形。 3. 创建一个视频捕捉设备的Filter对象,并添加到Filter Graph Manager中。 4. 创建一个Sample Grabber Filter对象,用于获取视频数据。 5. 创建一个Null Renderer对象,用于显示视频数据。 6. 将Sample Grabber Filter对象和Null Renderer对象添加到Filter Graph Manager中,并建立连接。 7. 设置Sample Grabber Filter对象的回调函数,用于处理视频数据。 8. 开始视频捕捉。 以下是C++代码示例: ```cpp #include <dshow.h> // 枚举可用的视频捕捉设备 HRESULT EnumerateDevices(REFGUID category, IEnumMoniker** ppEnum) { // 创建系统设备枚举器 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum); if (FAILED(hr)) { return hr; } // 枚举视频捕捉设备 hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0); if (hr == S_FALSE) { hr = VFW_E_NOT_FOUND; } pDevEnum->Release(); return hr; } // 创建Filter Graph Manager对象 IGraphBuilder* pGraphBuilder = NULL; IMediaControl* pMediaControl = NULL; IMediaEventEx* pMediaEvent = NULL; HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraphBuilder); if (FAILED(hr)) { return hr; } // 创建视频捕捉设备的Filter对象 IEnumMoniker* pEnumMoniker = NULL; hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnumMoniker); if (FAILED(hr)) { return hr; } IMoniker* pMoniker = NULL; ULONG cFetched; while (pEnumMoniker->Next(1, &pMoniker, &cFetched) == S_OK) { IBaseFilter* pFilter = NULL; hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter); if (SUCCEEDED(hr)) { // 添加到Filter Graph Manager中 pGraphBuilder->AddFilter(pFilter, L"Video Capture"); pFilter->Release(); } pMoniker->Release(); } pEnumMoniker->Release(); // 创建Sample Grabber Filter对象 ISampleGrabber* pSampleGrabber = NULL; hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSampleGrabber); if (FAILED(hr)) { return hr; } // 设置Sample Grabber Filter对象的回调函数 hr = pSampleGrabber->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber); if (FAILED(hr)) { return hr; } AM_MEDIA_TYPE mt; ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB24; mt.formattype = FORMAT_VideoInfo; hr = pGrabber->SetMediaType(&mt); if (FAILED(hr)) { return hr; } hr = pGrabber->SetCallback(&SampleGrabberCallback, 0); if (FAILED(hr)) { return hr; } // 创建Null Renderer对象 IBaseFilter* pNullRenderer = NULL; hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pNullRenderer); if (FAILED(hr)) { return hr; } // 将Sample Grabber Filter对象和Null Renderer对象添加到Filter Graph Manager中,并建立连接 hr = pGraphBuilder->AddFilter(pSampleGrabber, L"Sample Grabber"); if (FAILED(hr)) { return hr; } hr = pGraphBuilder->AddFilter(pNullRenderer, L"Null Renderer"); if (FAILED(hr)) { return hr; } IPin* pGrabberOut = GetPin(pSampleGrabber, PINDIR_OUTPUT); IPin* pRendererIn = GetPin(pNullRenderer, PINDIR_INPUT); hr = pGraphBuilder->Connect(pGrabberOut, pRendererIn); if (FAILED(hr)) { return hr; } // 开始视频捕捉 hr = pGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&pMediaControl); if (FAILED(hr)) { return hr; } hr = pMediaControl->Run(); if (FAILED(hr)) { return hr; } // 处理视频数据的回调函数 HRESULT SampleGrabberCallback::SampleCB(double Time, IMediaSample *pSample) { BYTE* pData = NULL; pSample->GetPointer(&pData); long lDataLen = pSample->GetActualDataLength(); // 处理视频数据 return S_OK; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零凌灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值