Skip to content

Commit 0237129

Browse files
committed
fix compile err
1 parent f3c2dbf commit 0237129

1 file changed

Lines changed: 78 additions & 34 deletions

File tree

src/ccap_imp_windows.cpp

Lines changed: 78 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,58 @@ using namespace ccap;
9191
namespace {
9292
constexpr FrameOrientation kDefaultFrameOrientation = FrameOrientation::BottomToTop;
9393

94+
#if defined(_MSC_VER) || (defined(__MINGW64__) && defined(__SEH__))
95+
#define CCAP_SEH_SUPPORTED 1
96+
#else
97+
#define CCAP_SEH_SUPPORTED 0
98+
#endif
99+
100+
enum class DeviceBindResult {
101+
Success = 0,
102+
Failed = 1,
103+
Exception = 2
104+
};
105+
106+
/// Bind moniker to filter with SEH protection for device validation
107+
DeviceBindResult tryBindMonikerToFilter(IMoniker* moniker, std::string_view name) {
108+
#if CCAP_SEH_SUPPORTED
109+
__try {
110+
#endif
111+
IBaseFilter* filter = nullptr;
112+
HRESULT hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&filter);
113+
if (SUCCEEDED(hr) && filter) {
114+
filter->Release();
115+
return DeviceBindResult::Success;
116+
} else {
117+
CCAP_LOG_I("ccap: \"%s\" is not a valid video capture device, removed\n", name.data());
118+
return DeviceBindResult::Failed;
119+
}
120+
#if CCAP_SEH_SUPPORTED
121+
} __except (EXCEPTION_EXECUTE_HANDLER) {
122+
CCAP_LOG_W("ccap: \"%s\" caused an exception during device binding, skipping\n", name.data());
123+
return DeviceBindResult::Exception;
124+
}
125+
#endif
126+
}
127+
128+
/// Bind moniker to device filter with SEH protection for device opening
129+
DeviceBindResult tryBindMonikerForOpen(IMoniker* moniker, IBaseFilter** deviceFilter) {
130+
#if CCAP_SEH_SUPPORTED
131+
__try {
132+
#endif
133+
HRESULT hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)deviceFilter);
134+
if (SUCCEEDED(hr)) {
135+
return DeviceBindResult::Success;
136+
} else {
137+
return DeviceBindResult::Failed;
138+
}
139+
#if CCAP_SEH_SUPPORTED
140+
} __except (EXCEPTION_EXECUTE_HANDLER) {
141+
return DeviceBindResult::Exception;
142+
}
143+
#endif
144+
}
145+
94146
// Release the format block for a media type.
95147
void freeMediaType(AM_MEDIA_TYPE& mt) {
96148
if (mt.cbFormat != 0) {
@@ -400,21 +452,12 @@ std::vector<std::string> ProviderDirectShow::findDeviceNames() {
400452

401453
enumerateDevices([&](IMoniker* moniker, std::string_view name) {
402454
// Try to bind device, check if available
403-
// Use SEH to catch crashes from buggy drivers (e.g., unplugged devices like Oculus Quest 3)
404-
__try {
405-
IBaseFilter* filter = nullptr;
406-
HRESULT hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&filter);
407-
if (SUCCEEDED(hr) && filter) {
408-
m_allDeviceNames.emplace_back(name.data(), name.size());
409-
filter->Release();
410-
} else {
411-
CCAP_LOG_I("ccap: \"%s\" is not a valid video capture device, removed\n", name.data());
412-
}
413-
} __except (EXCEPTION_EXECUTE_HANDLER) {
414-
// Catch crashes from buggy camera drivers (e.g., when camera is physically unplugged)
415-
CCAP_LOG_W("ccap: \"%s\" caused an exception during device binding, skipping\n", name.data());
455+
// Use helper function with SEH to catch crashes from exception-throwing devices
456+
DeviceBindResult result = tryBindMonikerToFilter(moniker, name);
457+
if (result == DeviceBindResult::Success) {
458+
m_allDeviceNames.emplace_back(name.data(), name.size());
416459
}
417-
// Unavailable devices are not added to the list
460+
// Unavailable devices (Failed or Exception) are not added to the list
418461
return false; // Continue enumeration
419462
});
420463

@@ -666,28 +709,29 @@ bool ProviderDirectShow::open(std::string_view deviceName) {
666709

667710
enumerateDevices([&](IMoniker* moniker, std::string_view name) {
668711
if (deviceName.empty() || deviceName == name) {
669-
// Use SEH to catch crashes from buggy drivers (e.g., unplugged devices like Oculus Quest 3)
670-
__try {
671-
auto hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_deviceFilter);
672-
if (SUCCEEDED(hr)) {
673-
CCAP_LOG_V("ccap: Using video capture device: %s\n", name.data());
674-
m_deviceName = name;
675-
found = true;
676-
return true; // stop enumeration when returning true
712+
// Use helper function with SEH to catch crashes from exception-throwing devices
713+
DeviceBindResult result = tryBindMonikerForOpen(moniker, &m_deviceFilter);
714+
715+
if (result == DeviceBindResult::Success) {
716+
// Success - save device name and stop enumeration
717+
CCAP_LOG_V("ccap: Using video capture device: %s\n", name.data());
718+
m_deviceName = name;
719+
found = true;
720+
return true;
721+
} else if (!deviceName.empty()) {
722+
// Specific device was requested but failed
723+
if (result == DeviceBindResult::Exception) {
724+
reportError(ErrorCode::InvalidDevice, "\"" + std::string(deviceName) + "\" caused an exception during binding");
677725
} else {
678-
if (!deviceName.empty()) {
679-
reportError(ErrorCode::InvalidDevice, "\"" + std::string(deviceName) + "\" is not a valid video capture device, bind failed");
680-
return true; // stop enumeration when returning true
681-
}
682-
683-
CCAP_LOG_I("ccap: bind \"%s\" failed(result=%x), try next device...\n", name.data(), hr);
726+
reportError(ErrorCode::InvalidDevice, "\"" + std::string(deviceName) + "\" is not a valid video capture device, bind failed");
684727
}
685-
} __except (EXCEPTION_EXECUTE_HANDLER) {
686-
// Catch crashes from buggy camera drivers (e.g., when camera is physically unplugged)
687-
CCAP_LOG_W("ccap: \"%s\" caused an exception during device binding, skipping\n", name.data());
688-
if (!deviceName.empty()) {
689-
reportError(ErrorCode::InvalidDevice, "\"" + std::string(deviceName) + "\" caused an exception during binding");
690-
return true; // stop enumeration when returning true
728+
return true; // stop enumeration
729+
} else {
730+
// No specific device requested and this one failed - log and continue trying next device
731+
if (result == DeviceBindResult::Exception) {
732+
CCAP_LOG_W("ccap: \"%s\" caused an exception during device binding, skipping\n", name.data());
733+
} else {
734+
CCAP_LOG_I("ccap: bind \"%s\" failed, try next device...\n", name.data());
691735
}
692736
}
693737
}

0 commit comments

Comments
 (0)