mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-20 19:31:00 +03:00
fix(audio): preserve compatible playback and recover failed Windows outputs (#16150)
* fix(audio): preserve compatible playback on replacement failure * fix(audio): use Windows events for capture worker wakeups * fix(audio): recover Windows playback after output device failure * reduce diffs Signed-off-by: fufesou <linlong1266@gmail.com> * fix(audio): reset decoder when retaining compatible playback * fix(audio): integrate playback retention and Windows capture wakeups * revert(audio): remove Windows capture-event notification changes * docs(audio): explain Windows 7 capture limitations * docs(audio): clarify capture changes introduced by #16095 * fix(audio): preserve playback through asynchronous Windows startup Keep a compatible active output until the replacement callback confirms startup, preserving decoder progress on promotion or rollback. Handle superseding formats and simultaneous output failures without losing recovery state. Pin the scoped CPAL WASAPI event-ownership fix and add deterministic and native regressions. * fix(audio): retain ready output across superseding formats * fix(audio): update CPAL teardown recovery Pin the upstream-aligned WASAPI cleanup with shared event lifetime, self-join prevention and fallible destructor diagnostics. Preserve the existing dependency graph and audio implementation. * Use upstream-style CPAL stream teardown * Refact: remove low value test Signed-off-by: fufesou <linlong1266@gmail.com> * fix(audio): retry playback when startup confirmation times out Signed-off-by: fufesou <linlong1266@gmail.com> * update cpal Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -391,6 +391,15 @@ mod cpal_impl {
|
||||
if !audio_input.is_empty() {
|
||||
return get_audio_input(&audio_input);
|
||||
}
|
||||
// The pinned CPAL uses event-driven WASAPI loopback here. Windows versions
|
||||
// before Windows 10 1703 do not signal capture events, so system audio does
|
||||
// not work on Win7. #16095 kept the same CPAL revision and loopback path;
|
||||
// this limitation predates that PR.
|
||||
// Ordinary microphone input is supported on Win7 and uses the branch above.
|
||||
// #16095 added its callback-to-encoder wake dependency; see CapturePcmSender::wake
|
||||
// for the new scheduling risk, whose audible impact on Win7 is unmeasured.
|
||||
// https://learn.microsoft.com/en-us/windows/win32/coreaudio/loopback-recording
|
||||
// https://learn.microsoft.com/en-us/windows/win32/coreaudio/capturesharedeventdriven
|
||||
let device = HOST
|
||||
.default_output_device()
|
||||
.with_context(|| "Failed to get default output device for loopback")?;
|
||||
|
||||
@@ -97,6 +97,7 @@ impl Drop for CaptureEncoderWorker {
|
||||
fn drop(&mut self) {
|
||||
self.stop.store(true, Ordering::Release);
|
||||
if let Some(handle) = self.handle.take() {
|
||||
// Owner-thread shutdown already waits via join(); see CapturePcmSender::wake for Win7.
|
||||
handle.thread().unpark();
|
||||
if let Err(error) = handle.join() {
|
||||
log::error!("Failed to join audio encoder thread: {error:?}");
|
||||
@@ -209,6 +210,16 @@ impl CapturePcmSender {
|
||||
|
||||
fn wake(&self) {
|
||||
if let Some(thread) = self.handoff.wake_thread.get() {
|
||||
// #16095 moved Opus encoding and message submission from the capture callback to a worker.
|
||||
// Previously, the callback did that work directly, with allocations and blocking locks.
|
||||
// On Win7 with Rust 1.75, if the worker is descheduled after publishing PARKED but before
|
||||
// NtWaitForKeyedEvent, unpark() waits in NtReleaseKeyedEvent until the worker enters that wait.
|
||||
// It does not wait for encoding; park_timeout() does not bound the callback's wait.
|
||||
// Delays can cause gaps or stall teardown; a Win7 microphone regression has not been measured.
|
||||
// System loopback already failed on Win7 before #16095 (see cpal_impl::get_device),
|
||||
// so the affected path is microphone/input-device capture, including outgoing voice calls.
|
||||
// Accept this risk to preserve Win7 input capture without a separate legacy notifier.
|
||||
// https://github.com/rust-lang/rust/blob/1.75.0/library/std/src/sys/windows/thread_parking.rs
|
||||
thread.unpark();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user