一、主要点:
1、调用Windows系统函数,搜寻目标设备:
if (m_path.isEmpty())
return;
// 创建系统设备枚举器
ICreateDevEnum* dev_enum = nullptr;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, CLSCTX_INPROC, IID_ICreateDevEnum, (void**)&dev_enum);
if (FAILED(hr))
{
return;
}
IGraphBuilder* graph = nullptr;
ICaptureGraphBuilder2* builder = nullptr;
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&graph);
if (SUCCEEDED(hr))
{
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, nullptr,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void**)&builder);
if (SUCCEEDED(hr))
{
hr = builder->SetFiltergraph(graph);
}
else
{
return;
}
}
else
{
return;
}
// 为类别创建枚举器
IEnumMoniker* class_enum = nullptr;
hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &class_enum, 0);
if (hr != S_OK)
return;
IMoniker* moniker = nullptr;
ULONG fetched;
// 使用 IEnumMoniker 接口枚举所有的设备标识
while (class_enum->Next(1, &moniker, &fetched) == S_OK)
{
IPropertyBag* prop_bag = nullptr;
hr = moniker->BindToStorage(NULL, NULL, IID_IPropertyBag, (void**)&prop_bag);
VARIANT var_name;
VariantInit(&var_name);
hr = prop_bag->Read(L"DevicePath", &var_name, NULL);
WCHAR* devicePath = var_name.bstrVal;
if (devicePath != nullptr) {
QString dest = Wchat_tToQString(devicePath);
qDebug()<<" dest:"<<dest;
if (m_path.contains(dest)) // 设备匹配
{
IBaseFilter* src = nullptr;
moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&src);
// 查找 ProcAmp 接口,该接口控制亮度等相关参数
src->QueryInterface(IID_IAMVideoProcAmp, (void**)&m_proc_amp);
// 查找 Control 接口,该接口控制缩放等相关参数
src->QueryInterface(IID_IAMCameraControl, (void**)&m_control);
// 查找 Config 接口,该接口查询摄像头支持的格式
builder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, src, IID_IAMStreamConfig, (void**)&m_config);
src->Release();
prop_bag->Release();
moniker->Release();
break;
}
}
prop_bag->Release();
moniker->Release();
}
class_enum->Release();
dev_enum->Release();
builder->Release();
graph->Release();
2、获取参数(放大缩小)
UVCParameter UvcDevice::GetZoom()
{
UVCParameter parameter;
if (!m_control)
return parameter;
HRESULT hr;
hr = m_control->GetRange(CameraControl_Zoom, ¶meter.min_val,
¶meter.max_val, ¶meter.step, ¶meter.def, ¶meter.flags);
hr = m_control->Get(CameraControl_Zoom, ¶meter.val, ¶meter.flags);
return parameter;
}
3、设置参数(放大缩小)
HRESULT UvcDevice::SetZoom(long value, bool isAuto)
{
if (!m_control)
return E_HANDLE;
long flag = isAuto ? CameraControl_Flags_Auto : CameraControl_Flags_Manual;
return m_control->Set(CameraControl_Zoom, value, flag);
}
二、完整代码:
1、UvcDevice.h
#ifndef UVCDEVICE_H
#define UVCDEVICE_H
#include <QString>
#include <windows.h>
#include <winnt.h>
#include <strmif.h>
#include <dshow.h>
#include <Ks.h>
#include <Ksmedia.h>
#pragma comment(lib,"Strmiids.lib")
struct UVCParameter
{
UVCParameter()
:result(0)
,min_val(0)
,max_val(0)
,val(0)
,def(0)
,step(0)
,flags(0)
,progress(0)
{
}
HRESULT result;
long min_val;
long max_val;
long val;
long def;
long step;
long flags;
long progress;
};
class UvcDevice
{
public:
UvcDevice();
~UvcDevice();
void SetPath(QString path);
UVCParameter GetZoom();
HRESULT SetZoom(long value, bool isAuto);
private:
void InitDirect(QString path);
void SearchDestDevInfo();
QString Wchat_tToQString(wchar_t* name);
private:
QString m_path{""};
IAMVideoProcAmp* m_proc_amp{nullptr};
IAMCameraControl* m_control{nullptr};
IAMStreamConfig* m_config{nullptr};
};
#endif // UVCDEVICE_H
2、UvcDevice.cpp
#include "UvcDevice.h"
#include <uuids.h>
#include <QDebug>
UvcDevice::UvcDevice()
{
}
UvcDevice::~UvcDevice()
{
if (m_proc_amp)
{
m_proc_amp->Release();
m_proc_amp = nullptr;
}
if (m_control)
{
m_control->Release();
m_control = nullptr;
}
if (m_config)
{
m_config->Release();
m_config = nullptr;
}
}
void UvcDevice::SetPath(QString path)
{
InitDirect(path);
}
UVCParameter UvcDevice::GetZoom()
{
UVCParameter parameter;
if (!m_control)
return parameter;
HRESULT hr;
hr = m_control->GetRange(CameraControl_Zoom, ¶meter.min_val,
¶meter.max_val, ¶meter.step, ¶meter.def, ¶meter.flags);
hr = m_control->Get(CameraControl_Zoom, ¶meter.val, ¶meter.flags);
return parameter;
}
HRESULT UvcDevice::SetZoom(long value, bool isAuto)
{
if (!m_control)
return E_HANDLE;
long flag = isAuto ? CameraControl_Flags_Auto : CameraControl_Flags_Manual;
return m_control->Set(CameraControl_Zoom, value, flag);
}
void UvcDevice::InitDirect(QString path)
{
m_path = path.toLower();
if (m_proc_amp)
{
m_proc_amp->Release();
m_proc_amp = nullptr;
}
if (m_control)
{
m_control->Release();
m_control = nullptr;
}
if (m_config)
{
m_config->Release();
m_config = nullptr;
}
SearchDestDevInfo();
}
void UvcDevice::SearchDestDevInfo()
{
if (m_path.isEmpty())
return;
// 创建系统设备枚举器
ICreateDevEnum* dev_enum = nullptr;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, CLSCTX_INPROC, IID_ICreateDevEnum, (void**)&dev_enum);
if (FAILED(hr))
{
return;
}
IGraphBuilder* graph = nullptr;
ICaptureGraphBuilder2* builder = nullptr;
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&graph);
if (SUCCEEDED(hr))
{
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, nullptr,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void**)&builder);
if (SUCCEEDED(hr))
{
hr = builder->SetFiltergraph(graph);
}
else
{
return;
}
}
else
{
return;
}
// 为类别创建枚举器
IEnumMoniker* class_enum = nullptr;
hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &class_enum, 0);
if (hr != S_OK)
return;
IMoniker* moniker = nullptr;
ULONG fetched;
// 使用 IEnumMoniker 接口枚举所有的设备标识
while (class_enum->Next(1, &moniker, &fetched) == S_OK)
{
IPropertyBag* prop_bag = nullptr;
hr = moniker->BindToStorage(NULL, NULL, IID_IPropertyBag, (void**)&prop_bag);
VARIANT var_name;
VariantInit(&var_name);
hr = prop_bag->Read(L"DevicePath", &var_name, NULL);
WCHAR* devicePath = var_name.bstrVal;
if (devicePath != nullptr) {
QString dest = Wchat_tToQString(devicePath);
qDebug()<<" dest:"<<dest;
if (m_path.contains(dest)) // 设备匹配
{
IBaseFilter* src = nullptr;
moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&src);
// 查找 ProcAmp 接口,该接口控制亮度等相关参数
src->QueryInterface(IID_IAMVideoProcAmp, (void**)&m_proc_amp);
// 查找 Control 接口,该接口控制缩放等相关参数
src->QueryInterface(IID_IAMCameraControl, (void**)&m_control);
// 查找 Config 接口,该接口查询摄像头支持的格式
builder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, src, IID_IAMStreamConfig, (void**)&m_config);
src->Release();
prop_bag->Release();
moniker->Release();
break;
}
}
prop_bag->Release();
moniker->Release();
}
class_enum->Release();
dev_enum->Release();
builder->Release();
graph->Release();
}
QString UvcDevice::Wchat_tToQString(wchar_t *name)
{
QString ret = QString((QChar*)name, wcslen(name));
return ret;
}
三、错误解决:
错误:UvcDevice.obj : error LNK2019: 无法解析的外部符号 __imp__CoCreateInstance@20,函数 “private: void __thiscall UvcDevice::SearchDestDevInfo(void)” (?SearchDestDevInfo@UvcDevice@@AAEXXZ) 中引用了该符号
UvcDevice.obj : error LNK2019: 无法解析的外部符号 __imp__VariantInit@4,函数 “private: void __thiscall UvcDevice::SearchDestDevInfo(void)” (?SearchDestDevInfo@UvcDevice@@AAEXXZ) 中引用了该符号
debug\UvcCameraTest.exe : fatal error LNK1120: 2 个无法解析的外部命令
解决方法:在.pro中引入模块:axcontainer
QT += core gui multimedia axcontainer