windows c++ directShow com 获取本机摄像头列表以及分辨率

windows c++ 获取本机摄像头列表以及分辨率

如果是qt 的话 可以通过QCameraInfo 来进行获取

    auto a = QCameraInfo::availableCameras();
    a[0].deviceName();
    a[0].description();

但是我看了下QCameraInfo 的源码也是通过DirectShow COM 接口获取的
看来windows平台下 涉及硬件相关的都离不开com啊
qt 源码
\Qt5.12.11\5.12.11\Src\qtmultimedia\src\plugins\directshow\camera\dsvideodevicecontrol.cpp
DSVideoDeviceControl::updateDevices()

在这里插入图片描述

下面我写一下c++ com接口是怎么获取的 ,直接粘贴就可以运行的

头文件

#include <uuids.h>
#include <amvideo.h>
#include <vector>
#include <strmif.h>

定一下 我们的结构体
摄像头的名字 和 摄像头支持的分辨率列表

struct CameraInfo
{
	std::string cameraName;
	std::vector<std::pair<int, int>> resolutionList;

	CameraInfo()
	{
		resolutionList.clear();
	}
	~CameraInfo()
	{
		resolutionList.clear();
	}
};

获取摄像头信息

std::vector<CameraInfo> CameraInfoCollector::getCameraInfoList()
{
	std::vector<CameraInfo> nameList;
	HRESULT hr;

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

	if (FAILED(hr))
	{
		pSysDevEnum->Release();
		return nameList;
	}

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

	if (FAILED(hr))
	{
		pSysDevEnum->Release();
		return nameList;
	}

	IMoniker* pMoniker = NULL;
	ULONG cFetched;
	auto index = 0;
	while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
	{
		IPropertyBag* pPropBag;
		hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
		if (SUCCEEDED(hr))
		{
			IBaseFilter* pFilter;
			hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
			if (!pFilter)
			{
				pMoniker->Release();
				break;
			}

			VARIANT varName;
			VariantInit(&varName);
			hr = pPropBag->Read(L"FriendlyName", &varName, 0);
			if (SUCCEEDED(hr))
			{
				CameraInfo info;
				info.resolutionList = getCameraSupportResolutions(pFilter);
				info.cameraName = wcharToString(varName.bstrVal);

				nameList.push_back(info);
			}
			VariantClear(&varName);
			pFilter->Release();
			pPropBag->Release();
		}
		pMoniker->Release();
	}
	pEnumCat->Release();

	return nameList;
}

获取支持的分辨率列表

std::vector<std::pair<int, int>> CameraInfoCollector::getCameraSupportResolutions(IBaseFilter* pBaseFilter)
{
	HRESULT hr = 0;
	std::vector<IPin*> pins;
	IEnumPins* EnumPins;
	pBaseFilter->EnumPins(&EnumPins);
	pins.clear();

	std::vector<std::pair<int, int>> result;

	for (;;)
	{
		IPin* pin;
		hr = EnumPins->Next(1, &pin, NULL);
		if (hr != S_OK)
		{
			break;
		}
		pins.push_back(pin);
		pin->Release();
	}

	EnumPins->Release();

	PIN_INFO pInfo;
	for (int i = 0; i < pins.size(); i++)
	{
		if (nullptr == pins[i])
		{
			break;
		}
		pins[i]->QueryPinInfo(&pInfo);

		IEnumMediaTypes* emt = NULL;
		pins[i]->EnumMediaTypes(&emt);
		AM_MEDIA_TYPE* pmt;

		for (;;)
		{
			hr = emt->Next(1, &pmt, NULL);
			if (hr != S_OK)
			{
				break;
			}
			if ((pmt->formattype == FORMAT_VideoInfo)
				//&& (pmt->subtype == MEDIASUBTYPE_RGB24)
				&& (pmt->cbFormat >= sizeof(VIDEOINFOHEADER))
				&& (pmt->pbFormat != NULL)) {

				VIDEOINFOHEADER* pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;

				auto insertParam = std::pair<int, int>{ pVIH->bmiHeader.biWidth, pVIH->bmiHeader.biHeight };
				bool isSet = false;

				for (auto param : result)
				{
					if (param.first == insertParam.first && param.second == insertParam.second)
					{
						isSet = true;
						break;
					}
				}

				if (!isSet)
				{
					result.push_back(insertParam);
				}
			}

			if (pmt->cbFormat != 0)
			{
				CoTaskMemFree((PVOID)pmt->pbFormat);
				pmt->cbFormat = 0;
				pmt->pbFormat = NULL;
			}
			if (pmt->pUnk != NULL)
			{
				// pUnk should not be used.
				pmt->pUnk->Release();
				pmt->pUnk = NULL;
			}
		}
		break;
		emt->Release();
	}

	return result;
}

ok , 复制这俩函数 + 头文件 + 结构体 就可以跑起来了

end

可以使用的摄像头采集模块 videoCapture
点我点我点我
https://blog.csdn.net/weixin_42837024/article/details/119545575?spm=1001.2014.3001.5501

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值