24#include <unordered_map>
29#ifndef __AMCAMERACONTROL__
30#define CameraControl_Pan 0L
31#define CameraControl_Tilt 1L
32#define CameraControl_Roll 2L
33#define CameraControl_Zoom 3L
34#define CameraControl_Exposure 4L
35#define CameraControl_Iris 5L
36#define CameraControl_Focus 6L
37#define CameraControl_ScanMode 7L
38#define CameraControl_Privacy 8L
39#define CameraControl_PanRelative 9L
40#define CameraControl_TiltRelative 10L
41#define CameraControl_RollRelative 11L
42#define CameraControl_ZoomRelative 12L
43#define CameraControl_ExposureRelative 13L
44#define CameraControl_IrisRelative 14L
45#define CameraControl_FocusRelative 15L
46#define CameraControl_PanTilt 16L
47#define CameraControl_PanTiltRelative 17L
48#define CameraControl_FocusSimple 18L
49#define CameraControl_DigitalZoom 19L
50#define CameraControl_DigitalZoomRelative 20L
51#define CameraControl_BacklightCompensation 21L
52#define CameraControl_Lamp 22L
53#define CameraControl_Flags_Auto 0x0001
54#define CameraControl_Flags_Manual 0x0002
58#ifndef __AMVIDEOPROCAMP__
59#define VideoProcAmp_Brightness 0
60#define VideoProcAmp_Contrast 1
61#define VideoProcAmp_Hue 2
62#define VideoProcAmp_Saturation 3
63#define VideoProcAmp_Sharpness 4
64#define VideoProcAmp_Gamma 5
65#define VideoProcAmp_ColorEnable 6
66#define VideoProcAmp_WhiteBalance 7
67#define VideoProcAmp_BacklightCompensation 8
68#define VideoProcAmp_Gain 9
69#define VideoProcAmp_Flags_Auto 0x0001
70#define VideoProcAmp_Flags_Manual 0x0002
74#pragma comment(lib, "ole32.lib")
75#pragma comment(lib, "oleaut32.lib")
76#pragma comment(lib, "strmiids.lib")
93 if (
this != &
o) {
reset(); p_ =
o.p_;
o.p_ =
nullptr; }
110 std::string
out(
sz > 0 ?
sz - 1 : 0,
'\0');
117 std::ostringstream
oss;
118 oss <<
where <<
" failed (hr=0x" << std::hex <<
hr <<
")";
119 if (
err.ErrorMessage()) {
123 oss <<
" - " <<
err.ErrorMessage();
126 throw std::runtime_error(
oss.str());
204 return name.empty() ?
L"" : name;
211 if (!
dp.empty())
return dp;
251 if (!
d.path.empty() && !path.empty()) {
252 if (
_wcsicmp(
d.path.c_str(), path.c_str()) == 0)
return true;
254 if (!
d.name.empty() && !name.empty()) {
255 if (
_wcsicmp(
d.name.c_str(), name.c_str()) == 0)
return true;
263 if (!
en)
throw std::runtime_error(
"No video devices available");
275 throw std::runtime_error(
"Device not found");
390 if (
pid < 0)
return false;
392 long value = 0,
flags = 0;
396 val.
value =
static_cast<int>(value);
406 if (
pid < 0)
return false;
418 if (
pid < 0)
return false;
420 long value = 0,
flags = 0;
424 val.
value =
static_cast<int>(value);
434 if (
pid < 0)
return false;
446 if (
pid < 0)
return false;
448 long min = 0, max = 0, step = 0,
def = 0,
flags = 0;
452 range.
min =
static_cast<int>(min);
453 range.
max =
static_cast<int>(max);
454 range.
step =
static_cast<int>(step);
465 if (
pid < 0)
return false;
467 long min = 0, max = 0, step = 0,
def = 0,
flags = 0;
471 range.
min =
static_cast<int>(min);
472 range.
max =
static_cast<int>(max);
473 range.
step =
static_cast<int>(step);
483 std::wstring
key =
dev.path.empty() ?
dev.name :
dev.path;
487 return it->second.get();
491 auto conn = std::make_unique<DeviceConnection>(
dev);
492 if (!
conn->is_valid())
return nullptr;
501 std::wstring
key =
dev.path.empty() ?
dev.name :
dev.path;
520 wc.lpszClassName =
L"DuvcDeviceNotification";
555 if (!
en)
return false;
567 return conn !=
nullptr &&
conn->is_valid();
585 std::vector<uint8_t>& data) {
589 if (!
props)
return false;
597 hr =
props->Get(property_set, property_id,
nullptr, 0,
603 const std::vector<uint8_t>& data) {
607 if (!
props)
return false;
610 const_cast<uint8_t*
>(data.data()), data.size());
618 if (!
props)
return false;
628 std::vector<Device>
out;
640 out.emplace_back(std::move(
d));
649 return conn ? conn->get_range(prop, range) :
false;
652bool get(
const Device& dev,
CamProp prop, PropSetting& val) {
654 return conn ? conn->get(prop, val) :
false;
657bool set(
const Device& dev,
CamProp prop,
const PropSetting& val) {
659 return conn ? conn->set(prop, val) :
false;
664 return conn ? conn->get_range(prop, range) :
false;
667bool get(
const Device& dev,
VidProp prop, PropSetting& val) {
669 return conn ? conn->get(prop, val) :
false;
672bool set(
const Device& dev,
VidProp prop,
const PropSetting& val) {
674 return conn ? conn->set(prop, val) :
false;
703 default:
return "Unknown";
732 default:
return L"Unknown";
748 default:
return "Unknown";
764 default:
return L"Unknown";
785bool get(
const Device&,
CamProp, PropSetting&) {
return false; }
786bool set(
const Device&,
CamProp,
const PropSetting&) {
return false; }
788bool get(
const Device&,
VidProp, PropSetting&) {
return false; }
789bool set(
const Device&,
VidProp,
const PropSetting&) {
return false; }
804bool get_vendor_property(
const Device&,
const GUID&, ULONG, std::vector<uint8_t>&) {
return false; }
805bool set_vendor_property(
const Device&,
const GUID&, ULONG,
const std::vector<uint8_t>&) {
return false; }
RAII wrapper for DirectShow device connections.
DeviceConnection(const Device &dev)
bool get(CamProp prop, PropSetting &val)
bool set(CamProp prop, const PropSetting &val)
bool get_range(CamProp prop, PropRange &range)
Result type that can contain either a value or an error.
const T & value() const &
Get the value (assumes success)
com_ptr() noexcept=default
T * operator->() const noexcept
com_ptr(com_ptr &&o) noexcept
com_ptr & operator=(const com_ptr &)=delete
com_ptr(const com_ptr &)=delete
com_ptr & operator=(com_ptr &&o) noexcept
#define VideoProcAmp_Contrast
#define CameraControl_PanRelative
#define CameraControl_Roll
#define VideoProcAmp_ColorEnable
#define CameraControl_DigitalZoom
#define CameraControl_Tilt
#define CameraControl_Zoom
#define VideoProcAmp_Sharpness
#define CameraControl_Focus
#define CameraControl_IrisRelative
#define CameraControl_Lamp
#define CameraControl_FocusSimple
#define CameraControl_TiltRelative
#define CameraControl_ExposureRelative
#define CameraControl_PanTiltRelative
#define VideoProcAmp_WhiteBalance
#define CameraControl_ZoomRelative
#define VideoProcAmp_Gamma
#define CameraControl_ScanMode
#define CameraControl_Pan
#define CameraControl_Privacy
#define CameraControl_Exposure
#define CameraControl_Flags_Manual
#define CameraControl_DigitalZoomRelative
#define CameraControl_Iris
#define VideoProcAmp_BacklightCompensation
#define CameraControl_PanTilt
#define CameraControl_RollRelative
#define CameraControl_BacklightCompensation
#define CameraControl_Flags_Auto
#define CameraControl_FocusRelative
#define VideoProcAmp_Flags_Manual
#define VideoProcAmp_Brightness
#define VideoProcAmp_Flags_Auto
#define VideoProcAmp_Saturation
#define VideoProcAmp_Gain
EXTERN_C const IID IID_IPropertyBag
EXTERN_C const CLSID CLSID_SystemDeviceEnum
EXTERN_C const CLSID CLSID_VideoInputDeviceCategory
EXTERN_C const IID IID_ICreateDevEnum
bool get(const Device &, CamProp, PropSetting &)
Get a camera control property value.
bool set(const Device &, CamProp, const PropSetting &)
Set a camera control property value.
bool get_range(const Device &, CamProp, PropRange &)
Get the valid range for a camera control property.
#define KSPROPERTY_SUPPORT_SET
#define KSPROPERTY_SUPPORT_GET
std::wstring read_friendly_name(IMoniker *mon)
Read friendly name from device moniker.
static std::mutex g_cache_mutex
static std::string wide_to_utf8(const wchar_t *ws)
static com_ptr< IAMVideoProcAmp > get_vproc(IBaseFilter *f)
static std::wstring read_prop_bstr(IPropertyBag *bag, const wchar_t *key)
VidProp
Video processing properties (IAMVideoProcAmp interface)
@ Saturation
Color saturation 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.
void clear_connection_cache()
com_ptr< IBaseFilter > open_device_filter(const Device &dev)
Create DirectShow filter from device.
bool is_same_device(const Device &d, const std::wstring &name, const std::wstring &path)
Check if two device identifiers refer to same device.
static DeviceChangeCallback g_device_callback
com_ptr< IEnumMoniker > enum_video_devices(ICreateDevEnum *dev)
Enumerate video input devices.
static void throw_hr(HRESULT hr, const char *where)
std::vector< Device > list_devices()
Enumerate all available video input devices.
std::wstring read_device_path(IMoniker *mon)
Read device path from moniker.
void unregister_device_change_callback()
Unregister device change callback.
void release_cached_connection(const Device &dev)
CamMode
Property control mode.
@ Auto
Automatic control by camera.
@ Manual
Manual control by application.
static com_ptr< IAMCameraControl > get_cam_ctrl(IBaseFilter *f)
bool query_vendor_property_support(const Device &dev, const GUID &property_set, ULONG property_id)
Query whether device supports a vendor-specific property.
static LRESULT CALLBACK device_wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
static std::unordered_map< std::wstring, std::unique_ptr< DeviceConnection > > g_connection_cache
const wchar_t * to_wstring(CamProp)
Convert camera property enum to wide string.
static com_ptr< IBaseFilter > bind_to_filter(IMoniker *mon)
static com_ptr< IKsPropertySet > get_property_set(IBaseFilter *f)
const char * to_string(CamProp)
Convert camera property enum to string.
CamProp
Camera control properties (IAMCameraControl interface)
@ 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.
@ 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 HDEVNOTIFY g_device_notify
bool get_vendor_property(const Device &dev, const GUID &property_set, ULONG property_id, std::vector< uint8_t > &data)
Get vendor-specific property data from device.
static long to_flag(CamMode m, bool is_camera_control)
DeviceConnection * get_cached_connection(const Device &dev)
bool set_vendor_property(const Device &dev, const GUID &property_set, ULONG property_id, const std::vector< uint8_t > &data)
Set vendor-specific property data on device.
bool is_device_connected(const Device &dev)
Check if a device is currently connected and accessible.
com_ptr< ICreateDevEnum > create_dev_enum()
Create DirectShow device enumerator.
void register_device_change_callback(DeviceChangeCallback callback)
Register callback for device hotplug events.
std::function< void(bool device_added, const std::wstring &device_path)> DeviceChangeCallback
Device change callback function type.
static long camprop_to_dshow(CamProp p)
static HWND g_notification_window
static CamMode from_flag(long flag, bool is_camera_control)
static long vidprop_to_dshow(VidProp p)
Represents a camera device.
Property range and default information.
int default_val
Default value.
int min
Minimum supported value.
int step
Step size between valid values.
int max
Maximum supported value.
CamMode default_mode
Default control mode.
Property setting with value and control mode.