From d8a5918bd00c5c32e5599e01c09e7846532b6414 Mon Sep 17 00:00:00 2001 From: Kishi85 Date: Wed, 17 Jun 2026 16:12:36 +0200 Subject: [PATCH 1/2] fix(linux/pipewire): Do not stop pw_thread_loop twice and early Before it was stopped at the beginning and end of the destructor. Doing it once at the end is what makes sense logically. --- src/platform/linux/pipewire.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/platform/linux/pipewire.cpp b/src/platform/linux/pipewire.cpp index d7a20940409..a6903e4c41b 100644 --- a/src/platform/linux/pipewire.cpp +++ b/src/platform/linux/pipewire.cpp @@ -105,16 +105,12 @@ namespace pipewire { ~pipewire_t() { BOOST_LOG(debug) << "[pipewire] Destroying pipewire_t"sv; - if (loop) { - BOOST_LOG(debug) << "[pipewire] Stop PW thread loop"sv; - pw_thread_loop_stop(loop); - } try { cleanup_stream(); } catch (const std::exception &e) { - BOOST_LOG(error) << "[pipewire] Standard exception caught in ~pipewire_t: "sv << e.what(); + BOOST_LOG(error) << "[pipewire] Standard exception caught in ~pipewire_t cleanup_stream: "sv << e.what(); } catch (...) { - BOOST_LOG(error) << "[pipewire] Unknown exception caught in ~pipewire_t"sv; + BOOST_LOG(error) << "[pipewire] Unknown exception caught in ~pipewire_t cleanup_stream"sv; } pw_thread_loop_lock(loop); From fb1b08bf491fa8121ddcd8bca528b232497702e9 Mon Sep 17 00:00:00 2001 From: Kishi85 Date: Thu, 4 Jun 2026 16:10:30 +0200 Subject: [PATCH 2/2] fix(linux/pipewire): avoid video stream freeze (on display switch) This is a trial-and-error workaround to avoid video stream freezing when display switching that somehow happens when not using the added thread sleeps due to a racecondition that needs to be further diagnosed. Pipewire state change logging is also move to information log level to improve initial issue analysis without enabling debug logging --- src/platform/linux/pipewire.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/platform/linux/pipewire.cpp b/src/platform/linux/pipewire.cpp index a6903e4c41b..dd0f55727b9 100644 --- a/src/platform/linux/pipewire.cpp +++ b/src/platform/linux/pipewire.cpp @@ -416,8 +416,13 @@ namespace pipewire { }; static void on_stream_state_changed(void *user_data, enum pw_stream_state old, enum pw_stream_state state, const char *err_msg) { - BOOST_LOG(debug) << "[pipewire] PipeWire stream state: " << pw_stream_state_as_string(old) - << " -> " << pw_stream_state_as_string(state); + if (err_msg != nullptr) { + BOOST_LOG(info) << "[pipewire] PipeWire stream error '" << err_msg << "' on state: " << pw_stream_state_as_string(old) + << " -> " << pw_stream_state_as_string(state); + } else { + BOOST_LOG(info) << "[pipewire] PipeWire stream state: " << pw_stream_state_as_string(old) + << " -> " << pw_stream_state_as_string(state); + } auto *d = static_cast(user_data); @@ -849,18 +854,20 @@ namespace pipewire { case platf::capture_e::timeout: if (!pull_free_image_cb(img_out)) { // Detect if shutdown is pending - BOOST_LOG(debug) << "[pipewire] PipeWire: timeout -> interrupt nudge"; + BOOST_LOG(debug) << "[pipewire] PipeWire: timeout -> shutdown pending -> interrupt nudge"; pipewire.frame_cv().notify_all(); return platf::capture_e::interrupted; } if (!push_captured_image_cb(std::move(img_out), false)) { - BOOST_LOG(debug) << "[pipewire] PipeWire: !push_captured_image_cb -> ok"; + BOOST_LOG(debug) << "[pipewire] PipeWire: timeout -> !push_captured_image_cb -> ok"; + std::this_thread::sleep_for(10us); // Workaround: delay OK to avoid video stream freezing return platf::capture_e::ok; } break; case platf::capture_e::ok: if (!push_captured_image_cb(std::move(img_out), true)) { - BOOST_LOG(debug) << "[pipewire] PipeWire: !push_captured_image_cb -> ok"; + BOOST_LOG(debug) << "[pipewire] PipeWire: ok -> !push_captured_image_cb -> ok"; + std::this_thread::sleep_for(10us); // Workaround: delay OK to avoid video stream freezing return platf::capture_e::ok; } break;