From 23e131439f4e0faf5dd3bf30c23b2a9c5e06e2e3 Mon Sep 17 00:00:00 2001 From: Lukas Senionis Date: Mon, 27 Jan 2025 19:19:47 +0200 Subject: [PATCH] fix(video): allow encoder probing when there are no devices at all (#3594) --- src/display_device.cpp | 12 ++++-------- src/display_device.h | 8 ++++---- src/video.cpp | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/display_device.cpp b/src/display_device.cpp index d9c2d7953a0..cd593ebe547 100644 --- a/src/display_device.cpp +++ b/src/display_device.cpp @@ -810,19 +810,15 @@ namespace display_device { }); } - bool is_any_device_active() { + EnumeratedDeviceList enumerate_devices() { std::lock_guard lock {DD_DATA.mutex}; if (!DD_DATA.sm_instance) { - // Platform is not supported, assume success. - return true; + // Platform is not supported. + return {}; } return DD_DATA.sm_instance->execute([](auto &settings_iface) { - const auto devices {settings_iface.enumAvailableDevices()}; - // If at least one device has additional info, it is active. - return std::any_of(std::begin(devices), std::end(devices), [](const auto &device) { - return static_cast(device.m_info); - }); + return settings_iface.enumAvailableDevices(); }); } diff --git a/src/display_device.h b/src/display_device.h index 96723606b06..d49698bdb52 100644 --- a/src/display_device.h +++ b/src/display_device.h @@ -121,14 +121,14 @@ namespace display_device { [[nodiscard]] bool reset_persistence(); /** - * @brief Check if any of the display devices is currently active. - * @return True if at least one device is active. + * @brief Enumerate the available devices. + * @return A list of devices. * * @examples - * const auto result = is_any_device_active(); + * const auto devices = enumerate_devices(); * @examples_end */ - [[nodiscard]] bool is_any_device_active(); + [[nodiscard]] EnumeratedDeviceList enumerate_devices(); /** * @brief A tag structure indicating that configuration parsing has failed. diff --git a/src/video.cpp b/src/video.cpp index 732849824b8..000a3c7e826 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -40,6 +40,37 @@ using namespace std::literals; namespace video { + namespace { + /** + * @brief Check if we can allow probing for the encoders. + * @return True if there should be no issues with the probing, false if we should prevent it. + */ + bool allow_encoder_probing() { + const auto devices {display_device::enumerate_devices()}; + + // If there are no devices, then either the API is not working correctly or OS does not support the lib. + // Either way we should not block the probing in this case as we can't tell what's wrong. + if (devices.empty()) { + return true; + } + + // Since Windows 11 24H2, it is possible that there will be no active devices present + // for some reason (probably a bug). Trying to probe encoders in such a state locks/breaks the DXGI + // and also the display device for Windows. So we must have at least 1 active device. + const bool at_least_one_device_is_active = std::any_of(std::begin(devices), std::end(devices), [](const auto &device) { + // If device has additional info, it is active. + return static_cast(device.m_info); + }); + + if (at_least_one_device_is_active) { + return true; + } + + BOOST_LOG(error) << "No display devices are active at the moment! Cannot probe the encoders."; + return false; + } + } // namespace + void free_ctx(AVCodecContext *ctx) { avcodec_free_context(&ctx); } @@ -2550,8 +2581,8 @@ namespace video { } int probe_encoders() { - if (!display_device::is_any_device_active()) { - BOOST_LOG(error) << "No display devices are active at the moment! Cannot probe encoders as this could break Sunshine."; + if (!allow_encoder_probing()) { + // Error already logged return -1; }