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