duvc-ctl 2.0.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_Flags_Auto 0x0001
59#define VideoProcAmp_Flags_Manual 0x0002
60#endif
61
62#ifdef _MSC_VER
63#pragma comment(lib, "ole32.lib")
64#pragma comment(lib, "oleaut32.lib")
65#pragma comment(lib, "strmiids.lib")
66#endif
67
68namespace duvc {
69
70using namespace detail;
71
72// Forward declarations for DirectShow enumeration
73extern com_ptr<ICreateDevEnum> create_dev_enum();
74extern com_ptr<IEnumMoniker> enum_video_devices(ICreateDevEnum *dev);
75extern std::wstring read_friendly_name(IMoniker *mon);
76extern std::wstring read_device_path(IMoniker *mon);
77extern bool is_same_device(const Device &d, const std::wstring &name,
78 const std::wstring &path);
79
80// DirectShow interface helpers
83 HRESULT hr = mon->BindToObject(nullptr, nullptr, IID_IBaseFilter,
84 reinterpret_cast<void **>(f.put()));
85 if (FAILED(hr))
86 throw_hr(hr, "BindToObject(IBaseFilter)");
87 return f;
88}
89
92 if (FAILED(f->QueryInterface(IID_IAMCameraControl,
93 reinterpret_cast<void **>(cam.put())))) {
94 return {};
95 }
96 return cam;
97}
98
101 if (FAILED(f->QueryInterface(IID_IAMVideoProcAmp,
102 reinterpret_cast<void **>(vp.put())))) {
103 return {};
104 }
105 return vp;
106}
107
108static com_ptr<IBaseFilter> open_device_filter(const Device &dev) {
109 extern com_ptr<ICreateDevEnum> create_dev_enum();
110 extern com_ptr<IEnumMoniker> enum_video_devices(ICreateDevEnum * dev);
111
112 auto de = create_dev_enum();
113 auto en = enum_video_devices(de.get());
114 if (!en)
115 throw std::runtime_error("No video devices available");
116
117 ULONG fetched = 0;
118 com_ptr<IMoniker> mon;
119 while (en->Next(1, mon.put(), &fetched) == S_OK && fetched) {
120 auto fname = read_friendly_name(mon.get());
121 auto dpath = read_device_path(mon.get());
122 if (is_same_device(dev, fname, dpath)) {
123 return bind_to_filter(mon.get());
124 }
125 mon.reset();
126 }
127
128 throw std::runtime_error("Device not found");
129}
130
131// Property mapping helpers
133 switch (p) {
134 case CamProp::Pan:
135 return CameraControl_Pan;
136 case CamProp::Tilt:
137 return CameraControl_Tilt;
138 case CamProp::Roll:
139 return CameraControl_Roll;
140 case CamProp::Zoom:
141 return CameraControl_Zoom;
144 case CamProp::Iris:
145 return CameraControl_Iris;
146 case CamProp::Focus:
147 return CameraControl_Focus;
150 case CamProp::Privacy:
166 case CamProp::PanTilt:
178 case CamProp::Lamp:
179 return CameraControl_Lamp;
180 default:
181 return -1;
182 }
183}
184
186 switch (p) {
191 case VidProp::Hue:
192 return VideoProcAmp_Hue;
197 case VidProp::Gamma:
198 return VideoProcAmp_Gamma;
205 case VidProp::Gain:
206 return VideoProcAmp_Gain;
207 default:
208 return -1;
209 }
210}
211
221
229
230// DeviceConnection implementation
231DeviceConnection::DeviceConnection(const Device &dev)
232 : com_(std::make_unique<com_apartment>()), filter_(nullptr),
233 cam_ctrl_(nullptr), vid_proc_(nullptr) {
234
235 try {
236 auto filter = open_device_filter(dev);
237 if (filter) {
238 auto cam_ctrl = get_cam_ctrl(filter.get());
239 auto vid_proc = get_vproc(filter.get());
240
241 // Store as raw pointers but keep references
242 filter_ = new com_ptr<IBaseFilter>(std::move(filter));
243 cam_ctrl_ = new com_ptr<IAMCameraControl>(std::move(cam_ctrl));
244 vid_proc_ = new com_ptr<IAMVideoProcAmp>(std::move(vid_proc));
245 }
246 } catch (...) {
247 filter_ = nullptr;
248 }
249}
250
251DeviceConnection::~DeviceConnection() {
252 delete static_cast<com_ptr<IBaseFilter> *>(filter_);
253 delete static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
254 delete static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
255}
256
257bool DeviceConnection::get(CamProp prop, PropSetting &val) {
258 auto *cam_ctrl = static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
259 if (!cam_ctrl || !*cam_ctrl)
260 return false;
261
262 long pid = camprop_to_dshow(prop);
263 if (pid < 0)
264 return false;
265
266 long value = 0, flags = 0;
267 HRESULT hr = (*cam_ctrl)->Get(pid, &value, &flags);
268 if (FAILED(hr))
269 return false;
270
271 val.value = static_cast<int>(value);
272 val.mode = from_flag(flags, true);
273 return true;
274}
275
276bool DeviceConnection::set(CamProp prop, const PropSetting &val) {
277 auto *cam_ctrl = static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
278 if (!cam_ctrl || !*cam_ctrl)
279 return false;
280
281 long pid = camprop_to_dshow(prop);
282 if (pid < 0)
283 return false;
284
285 long flags = to_flag(val.mode, true);
286 HRESULT hr = (*cam_ctrl)->Set(pid, static_cast<long>(val.value), flags);
287 return SUCCEEDED(hr);
288}
289
290bool DeviceConnection::get(VidProp prop, PropSetting &val) {
291 auto *vid_proc = static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
292 if (!vid_proc || !*vid_proc)
293 return false;
294
295 long pid = vidprop_to_dshow(prop);
296 if (pid < 0)
297 return false;
298
299 long value = 0, flags = 0;
300 HRESULT hr = (*vid_proc)->Get(pid, &value, &flags);
301 if (FAILED(hr))
302 return false;
303
304 val.value = static_cast<int>(value);
305 val.mode = from_flag(flags, false);
306 return true;
307}
308
309bool DeviceConnection::set(VidProp prop, const PropSetting &val) {
310 auto *vid_proc = static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
311 if (!vid_proc || !*vid_proc)
312 return false;
313
314 long pid = vidprop_to_dshow(prop);
315 if (pid < 0)
316 return false;
317
318 long flags = to_flag(val.mode, false);
319 HRESULT hr = (*vid_proc)->Set(pid, static_cast<long>(val.value), flags);
320 return SUCCEEDED(hr);
321}
322
323bool DeviceConnection::get_range(CamProp prop, PropRange &range) {
324 auto *cam_ctrl = static_cast<com_ptr<IAMCameraControl> *>(cam_ctrl_);
325 if (!cam_ctrl || !*cam_ctrl)
326 return false;
327
328 long pid = camprop_to_dshow(prop);
329 if (pid < 0)
330 return false;
331
332 long min = 0, max = 0, step = 0, def = 0, flags = 0;
333 HRESULT hr = (*cam_ctrl)->GetRange(pid, &min, &max, &step, &def, &flags);
334 if (FAILED(hr))
335 return false;
336
337 range.min = static_cast<int>(min);
338 range.max = static_cast<int>(max);
339 range.step = static_cast<int>(step);
340 range.default_val = static_cast<int>(def);
341 range.default_mode = from_flag(flags, true);
342 return true;
343}
344
345bool DeviceConnection::get_range(VidProp prop, PropRange &range) {
346 auto *vid_proc = static_cast<com_ptr<IAMVideoProcAmp> *>(vid_proc_);
347 if (!vid_proc || !*vid_proc)
348 return false;
349
350 long pid = vidprop_to_dshow(prop);
351 if (pid < 0)
352 return false;
353
354 long min = 0, max = 0, step = 0, def = 0, flags = 0;
355 HRESULT hr = (*vid_proc)->GetRange(pid, &min, &max, &step, &def, &flags);
356 if (FAILED(hr))
357 return false;
358
359 range.min = static_cast<int>(min);
360 range.max = static_cast<int>(max);
361 range.step = static_cast<int>(step);
362 range.default_val = static_cast<int>(def);
363 range.default_mode = from_flag(flags, false);
364 return true;
365}
366
367} // namespace duvc
368
369#endif // _WIN32
DeviceConnection(const Device &dev)
Definition core.cpp:358
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 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 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 CameraControl_RollRelative
Definition core.cpp:41
#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:70
#define VideoProcAmp_Brightness
Definition core.cpp:59
#define VideoProcAmp_Flags_Auto
Definition core.cpp:69
#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:199
static com_ptr< IAMVideoProcAmp > get_vproc(IBaseFilter *f)
Definition core.cpp:236
VidProp
Video processing properties (IAMVideoProcAmp interface)
Definition types.h:50
@ Saturation
Color saturation level.
@ Gain
Sensor gain level.
@ WhiteBalance
White balance adjustment.
@ 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:260
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:250
com_ptr< IEnumMoniker > enum_video_devices(ICreateDevEnum *dev)
Enumerate video input devices.
Definition core.cpp:181
static void throw_hr(HRESULT hr, const char *where)
Definition core.cpp:115
std::wstring read_device_path(IMoniker *mon)
Read device path from moniker.
Definition core.cpp:207
CamMode
Property control mode.
Definition types.h:66
@ Auto
Automatic control by camera.
@ Manual
Manual control by application.
static com_ptr< IAMCameraControl > get_cam_ctrl(IBaseFilter *f)
Definition core.cpp:230
static com_ptr< IBaseFilter > bind_to_filter(IMoniker *mon)
Definition core.cpp:223
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:324
com_ptr< ICreateDevEnum > create_dev_enum()
Create DirectShow device enumerator.
Definition core.cpp:173
static long camprop_to_dshow(CamProp p)
Definition core.cpp:279
static CamMode from_flag(long flag, bool is_camera_control)
Definition core.cpp:332
static long vidprop_to_dshow(VidProp p)
Definition core.cpp:308