duvc-ctl 2.1.0
USB Video Class Camera Control Library
Loading...
Searching...
No Matches
connection_pool.cpp
Go to the documentation of this file.
1
6#ifdef _WIN32
7
9#include <duvc-ctl/detail/com_helpers.h>
11#include <memory>
12#include <mutex>
13#include <unordered_map>
14
15#include <dshow.h>
16#include <strmif.h>
17
18// DirectShow control interfaces
19#ifndef __AMCAMERACONTROL__
20#define CameraControl_Pan 0L
21#define CameraControl_Tilt 1L
22#define CameraControl_Roll 2L
23#define CameraControl_Zoom 3L
24#define CameraControl_Exposure 4L
25#define CameraControl_Iris 5L
26#define CameraControl_Focus 6L
27#define CameraControl_ScanMode 7L
28#define CameraControl_Privacy 8L
29#define CameraControl_PanRelative 9L
30#define CameraControl_TiltRelative 10L
31#define CameraControl_RollRelative 11L
32#define CameraControl_ZoomRelative 12L
33#define CameraControl_ExposureRelative 13L
34#define CameraControl_IrisRelative 14L
35#define CameraControl_FocusRelative 15L
36#define CameraControl_PanTilt 16L
37#define CameraControl_PanTiltRelative 17L
38#define CameraControl_FocusSimple 18L
39#define CameraControl_DigitalZoom 19L
40#define CameraControl_DigitalZoomRelative 20L
41#define CameraControl_BacklightCompensation 21L
42#define CameraControl_Lamp 22L
43#define CameraControl_Flags_Auto 0x0001
44#define CameraControl_Flags_Manual 0x0002
45#endif
46
47#ifndef __AMVIDEOPROCAMP__
48#define VideoProcAmp_Brightness 0
49#define VideoProcAmp_Contrast 1
50#define VideoProcAmp_Hue 2
51#define VideoProcAmp_Saturation 3
52#define VideoProcAmp_Sharpness 4
53#define VideoProcAmp_Gamma 5
54#define VideoProcAmp_ColorEnable 6
55#define VideoProcAmp_WhiteBalance 7
56#define VideoProcAmp_BacklightCompensation 8
57#define VideoProcAmp_Gain 9
58#define VideoProcAmp_DigitalMultiplier 10
59#define VideoProcAmp_DigitalMultiplierLimit 11
60#define VideoProcAmp_WhiteBalanceComponent 12
61#define VideoProcAmp_PowerLineFrequency 13
62#define VideoProcAmp_Flags_Auto 0x0001
63#define VideoProcAmp_Flags_Manual 0x0002
64#endif
65
66#ifdef _MSC_VER
67#pragma comment(lib, "ole32.lib")
68#pragma comment(lib, "oleaut32.lib")
69#pragma comment(lib, "strmiids.lib")
70#endif
71
72namespace duvc {
73
74using namespace detail;
75
76// Forward declarations for DirectShow enumeration
77extern com_ptr<ICreateDevEnum> create_dev_enum();
78extern com_ptr<IEnumMoniker> enum_video_devices(ICreateDevEnum *dev);
79extern std::wstring read_friendly_name(IMoniker *mon);
80extern std::wstring read_device_path(IMoniker *mon);
81extern bool is_same_device(const Device &d, const std::wstring &name,
82 const std::wstring &path);
83
84// DirectShow interface helpers
87 HRESULT hr = mon->BindToObject(nullptr, nullptr, IID_IBaseFilter,
88 reinterpret_cast<void **>(f.put()));
89 if (FAILED(hr))
90 throw_hr(hr, "BindToObject(IBaseFilter)");
91 return f;
92}
93
96 if (FAILED(f->QueryInterface(IID_IAMCameraControl,
97 reinterpret_cast<void **>(cam.put())))) {
98 return {};
99 }
100 return cam;
101}
102
105 if (FAILED(f->QueryInterface(IID_IAMVideoProcAmp,
106 reinterpret_cast<void **>(vp.put())))) {
107 return {};
108 }
109 return vp;
110}
111
112static com_ptr<IBaseFilter> open_device_filter(const Device &dev) {
113 extern com_ptr<ICreateDevEnum> create_dev_enum();
114 extern com_ptr<IEnumMoniker> enum_video_devices(ICreateDevEnum * dev);
115
116 auto de = create_dev_enum();
117 auto en = enum_video_devices(de.get());
118 if (!en)
119 throw std::runtime_error("No video devices available");
120
121 ULONG fetched = 0;
122 com_ptr<IMoniker> mon;
123 while (en->Next(1, mon.put(), &fetched) == S_OK && fetched) {
124 auto dpath = read_device_path(mon.get());
125 if (!dev.path.empty() && !dpath.empty() &&
126 _wcsicmp(dev.path.c_str(), dpath.c_str()) == 0) {
127 return bind_to_filter(mon.get());
128 }
129 mon.reset();
130 }
131
132 throw std::runtime_error("Device not found");
133}
134
135// Property mapping helpers
137 switch (p) {
138 case CamProp::Pan:
139 return CameraControl_Pan;
140 case CamProp::Tilt:
141 return CameraControl_Tilt;
142 case CamProp::Roll:
143 return CameraControl_Roll;
144 case CamProp::Zoom:
145 return CameraControl_Zoom;
148 case CamProp::Iris:
149 return CameraControl_Iris;
150 case CamProp::Focus:
151 return CameraControl_Focus;
154 case CamProp::Privacy:
170 case CamProp::PanTilt:
182 case CamProp::Lamp:
183 return CameraControl_Lamp;
184 default:
185 return -1;
186 }
187}
188
223
233
241
242// DeviceConnection implementation
243DeviceConnection::DeviceConnection(const Device &dev)
244 : com_(std::make_unique<com_apartment>()), filter_(nullptr),
245 cam_ctrl_(nullptr), vid_proc_(nullptr) {
246
247 try {
248 auto filter = open_device_filter(dev);
249 if (filter) {
250 auto cam_ctrl = get_cam_ctrl(filter.get());
251 auto vid_proc = get_vproc(filter.get());
252
253 // Store as raw pointers but keep references
254 filter_ = new com_ptr<IBaseFilter>(std::move(filter));
255 cam_ctrl_ = new com_ptr<IAMCameraControl>(std::move(cam_ctrl));
256 vid_proc_ = new com_ptr<IAMVideoProcAmp>(std::move(vid_proc));
257 }
258 } catch (...) {
259 filter_ = nullptr;
260 }
261}
262
263DeviceConnection::~DeviceConnection() {
264 delete static_cast<com_ptr<IBaseFilter> *>(filter_);
265 delete static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
266 delete static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
267}
268
269bool DeviceConnection::get(CamProp prop, PropSetting &val) {
270 auto *cam_ctrl = static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
271 if (!cam_ctrl || !*cam_ctrl)
272 return false;
273
274 long pid = camprop_to_dshow(prop);
275 if (pid < 0)
276 return false;
277
278 long value = 0, flags = 0;
279 HRESULT hr = (*cam_ctrl)->Get(pid, &value, &flags);
280 if (FAILED(hr))
281 return false;
282
283 val.value = static_cast<int>(value);
284 val.mode = from_flag(flags, true);
285 return true;
286}
287
288bool DeviceConnection::set(CamProp prop, const PropSetting &val) {
289 auto *cam_ctrl = static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
290 if (!cam_ctrl || !*cam_ctrl)
291 return false;
292
293 long pid = camprop_to_dshow(prop);
294 if (pid < 0)
295 return false;
296
297 long flags = to_flag(val.mode, true);
298 HRESULT hr = (*cam_ctrl)->Set(pid, static_cast<long>(val.value), flags);
299 return SUCCEEDED(hr);
300}
301
302bool DeviceConnection::get(VidProp prop, PropSetting &val) {
303 auto *vid_proc = static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
304 if (!vid_proc || !*vid_proc)
305 return false;
306
307 long pid = vidprop_to_dshow(prop);
308 if (pid < 0)
309 return false;
310
311 long value = 0, flags = 0;
312 HRESULT hr = (*vid_proc)->Get(pid, &value, &flags);
313 if (FAILED(hr))
314 return false;
315
316 val.value = static_cast<int>(value);
317 val.mode = from_flag(flags, false);
318 return true;
319}
320
321bool DeviceConnection::set(VidProp prop, const PropSetting &val) {
322 auto *vid_proc = static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
323 if (!vid_proc || !*vid_proc)
324 return false;
325
326 long pid = vidprop_to_dshow(prop);
327 if (pid < 0)
328 return false;
329
330 long flags = to_flag(val.mode, false);
331 HRESULT hr = (*vid_proc)->Set(pid, static_cast<long>(val.value), flags);
332 return SUCCEEDED(hr);
333}
334
335bool DeviceConnection::get_range(CamProp prop, PropRange &range) {
336 auto *cam_ctrl = static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
337 if (!cam_ctrl || !*cam_ctrl)
338 return false;
339
340 long pid = camprop_to_dshow(prop);
341 if (pid < 0)
342 return false;
343
344 long min = 0, max = 0, step = 0, def = 0, flags = 0;
345 HRESULT hr = (*cam_ctrl)->GetRange(pid, &min, &max, &step, &def, &flags);
346 if (FAILED(hr))
347 return false;
348
349 range.min = static_cast<int>(min);
350 range.max = static_cast<int>(max);
351 range.step = static_cast<int>(step);
352 range.default_val = static_cast<int>(def);
353 range.default_mode = from_flag(flags, true);
354 return true;
355}
356
357bool DeviceConnection::get_range(VidProp prop, PropRange &range) {
358 auto *vid_proc = static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
359 if (!vid_proc || !*vid_proc)
360 return false;
361
362 long pid = vidprop_to_dshow(prop);
363 if (pid < 0)
364 return false;
365
366 long min = 0, max = 0, step = 0, def = 0, flags = 0;
367 HRESULT hr = (*vid_proc)->GetRange(pid, &min, &max, &step, &def, &flags);
368 if (FAILED(hr))
369 return false;
370
371 range.min = static_cast<int>(min);
372 range.max = static_cast<int>(max);
373 range.step = static_cast<int>(step);
374 range.default_val = static_cast<int>(def);
375 range.default_mode = from_flag(flags, false);
376 return true;
377}
378
379} // namespace duvc
380
381#endif // _WIN32
DeviceConnection(const Device &dev)
Definition core.cpp:366
Result type that can contain either a value or an error.
Definition result.h:75
Windows-specific device connection pooling.
#define VideoProcAmp_Contrast
Definition core.cpp:60
#define VideoProcAmp_Hue
Definition core.cpp:61
#define CameraControl_PanRelative
Definition core.cpp:39
#define CameraControl_Roll
Definition core.cpp:32
#define VideoProcAmp_ColorEnable
Definition core.cpp:65
#define CameraControl_DigitalZoom
Definition core.cpp:49
#define CameraControl_Tilt
Definition core.cpp:31
#define CameraControl_Zoom
Definition core.cpp:33
#define VideoProcAmp_Sharpness
Definition core.cpp:63
#define VideoProcAmp_WhiteBalanceComponent
Definition core.cpp:71
#define CameraControl_Focus
Definition core.cpp:36
#define CameraControl_IrisRelative
Definition core.cpp:44
#define CameraControl_Lamp
Definition core.cpp:52
#define CameraControl_FocusSimple
Definition core.cpp:48
#define CameraControl_TiltRelative
Definition core.cpp:40
#define CameraControl_ExposureRelative
Definition core.cpp:43
#define CameraControl_PanTiltRelative
Definition core.cpp:47
#define VideoProcAmp_WhiteBalance
Definition core.cpp:66
#define CameraControl_ZoomRelative
Definition core.cpp:42
#define VideoProcAmp_Gamma
Definition core.cpp:64
#define CameraControl_ScanMode
Definition core.cpp:37
#define VideoProcAmp_PowerLineFrequency
Definition core.cpp:72
#define CameraControl_Pan
Definition core.cpp:30
#define CameraControl_Privacy
Definition core.cpp:38
#define CameraControl_Exposure
Definition core.cpp:34
#define CameraControl_Flags_Manual
Definition core.cpp:54
#define CameraControl_DigitalZoomRelative
Definition core.cpp:50
#define CameraControl_Iris
Definition core.cpp:35
#define VideoProcAmp_BacklightCompensation
Definition core.cpp:67
#define CameraControl_PanTilt
Definition core.cpp:46
#define VideoProcAmp_DigitalMultiplierLimit
Definition core.cpp:70
#define CameraControl_RollRelative
Definition core.cpp:41
#define VideoProcAmp_DigitalMultiplier
Definition core.cpp:69
#define CameraControl_BacklightCompensation
Definition core.cpp:51
#define CameraControl_Flags_Auto
Definition core.cpp:53
#define CameraControl_FocusRelative
Definition core.cpp:45
#define VideoProcAmp_Flags_Manual
Definition core.cpp:74
#define VideoProcAmp_Brightness
Definition core.cpp:59
#define VideoProcAmp_Flags_Auto
Definition core.cpp:73
#define VideoProcAmp_Saturation
Definition core.cpp:62
#define VideoProcAmp_Gain
Definition core.cpp:68
Device enumeration and management functions.
Definition core.h:13
std::wstring read_friendly_name(IMoniker *mon)
Read friendly name from device moniker.
Definition core.cpp:203
static com_ptr< IAMVideoProcAmp > get_vproc(IBaseFilter *f)
Definition core.cpp:240
VidProp
Video processing properties (IAMVideoProcAmp interface)
Definition types.h:50
@ PowerLineFrequency
Power line frequency (anti-flicker setting)
@ DigitalMultiplier
Digital multiplier level.
@ Saturation
Color saturation level.
@ Gain
Sensor gain level.
@ WhiteBalanceComponent
White balance component adjustment.
@ WhiteBalance
White balance adjustment.
@ DigitalMultiplierLimit
Maximum digital multiplier level.
@ Brightness
Image brightness level.
@ ColorEnable
Color vs. monochrome mode.
@ Sharpness
Image sharpness level.
@ Contrast
Image contrast level.
@ Gamma
Gamma correction value.
@ BacklightCompensation
Backlight compensation level.
@ Hue
Color hue adjustment.
com_ptr< IBaseFilter > open_device_filter(const Device &dev)
Create DirectShow filter from device.
Definition core.cpp:264
bool is_same_device(const Device &d, const std::wstring &name, const std::wstring &path)
Check if two device identifiers refer to same device.
Definition core.cpp:254
com_ptr< IEnumMoniker > enum_video_devices(ICreateDevEnum *dev)
Enumerate video input devices.
Definition core.cpp:185
static void throw_hr(HRESULT hr, const char *where)
Definition core.cpp:119
std::wstring read_device_path(IMoniker *mon)
Read device path from moniker.
Definition core.cpp:211
CamMode
Property control mode.
Definition types.h:70
@ Auto
Automatic control by camera.
@ Manual
Manual control by application.
static com_ptr< IAMCameraControl > get_cam_ctrl(IBaseFilter *f)
Definition core.cpp:234
static com_ptr< IBaseFilter > bind_to_filter(IMoniker *mon)
Definition core.cpp:227
CamProp
Camera control properties (IAMCameraControl interface)
Definition types.h:18
@ ExposureRelative
Relative exposure adjustment.
@ Roll
Camera roll rotation.
@ FocusSimple
Simple focus control.
@ PanRelative
Relative pan movement.
@ RollRelative
Relative roll movement.
@ Zoom
Optical zoom level.
@ Lamp
Camera lamp/flash control.
@ PanTiltRelative
Relative pan/tilt movement.
@ Tilt
Vertical camera rotation.
@ TiltRelative
Relative tilt movement.
@ ScanMode
Scan mode (progressive/interlaced)
@ ZoomRelative
Relative zoom movement.
@ Privacy
Privacy mode on/off.
@ IrisRelative
Relative iris adjustment.
@ Iris
Aperture/iris setting.
@ Exposure
Exposure time.
@ Focus
Focus position.
@ FocusRelative
Relative focus adjustment.
@ PanTilt
Combined pan/tilt control.
@ DigitalZoomRelative
Relative digital zoom.
@ Pan
Horizontal camera rotation.
@ BacklightCompensation
Backlight compensation.
@ DigitalZoom
Digital zoom level.
static long to_flag(CamMode m, bool is_camera_control)
Definition core.cpp:332
com_ptr< ICreateDevEnum > create_dev_enum()
Create DirectShow device enumerator.
Definition core.cpp:177
static long camprop_to_dshow(CamProp p)
Definition core.cpp:283
static CamMode from_flag(long flag, bool is_camera_control)
Definition core.cpp:340
static long vidprop_to_dshow(VidProp p)
Definition core.cpp:312