fix(audio): preserve compatible playback and recover failed Windows outputs - #16150
Draft
fufesou wants to merge 15 commits into
Draft
fix(audio): preserve compatible playback and recover failed Windows outputs#16150fufesou wants to merge 15 commits into
fufesou wants to merge 15 commits into
Conversation
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Signed-off-by: fufesou <linlong1266@gmail.com>
Collaborator
Author
|
@codex review |
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.
4 tasks
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When remote capture restarts, a failed playback replacement can discard a usable output. On Windows, a terminal WASAPI error can also leave playback silent until reconnecting. Preserve compatible playback through replacement startup and recover terminally failed outputs on the audio owner thread.
Changes
Ok(())fromplay()only acknowledges command submission. Reject already-terminal candidates and roll back errors arriving before confirmation. Keep decoding and playing incoming packets on the old output while waiting, then transfer that decoder history when promoting the candidate. Before a later valid format supersedes the pending attempt, resolve readiness and errors so a started, usable candidate can become the retained output. Preserve a terminal-failure result after draining its queue. This resolution does not reopen the old format.b8ad274fufesou/cpal@b8ad274. Dependency fix: fix(wasapi): release command events after worker exit rustdesk-org/cpal#6. Before merging this PR, switch the dependency back torustdesk-org/cpalat its merged fix. The exact dependency range fufesou/cpal@69ad257...b8ad274 contains only WASAPI command-event ownership, worker cleanup, notification error propagation and their regressions. Retain shared event ownership until both the stream and worker release it. Follow upstream teardown: attempt termination, join independently of notification success, skip self-join, and discard termination/join errors without stderr diagnostics. Normal play/pause notification errors still propagate. No other dependency is updated.Related: #16095 #16095 introduced the affected playback replacement and capture-worker paths. #15827 #15827 and discussion #15828 #15828 report audio returning after reconnecting; those reports do not establish either failure mechanism fixed here.
Tests
Windows 11 manual results are recorded in local
test-16150.md(2026-09-13/14, headbf6f7e57f9e1f8154eb7f9fb9e5516d02aad4338); T01-T13 refer to that record. Earlier native and automated tests are identified by commit below. T12 is the main remaining manual check. Extended cases remain unchecked, and the voice-delay and USB-output observations below remain open.e545fa6confirmed the parked encoder exits and the same host process resumes capture after reconnecting. The extra three idle reconnects were not repeated in the guided run and remain an optional extended check. (T06 step 6)e545fa6retained A after B failed to open. Generated silent Opus decoded exactly like a fresh decoder, unlike the old-decoder control; the checked output window contained zero PCM. Decoder regressions also passed with both resamplers onb5146c2. (T10)b5146c2, with both resamplers, verified that A keeps consuming audio while B awaits confirmation, B is promoted after confirmation, and A survives an injected candidate failure before confirmation. (T11)play()returns but before the first output callback; the compatible old output must survive. This hardware failure has not been reproduced. (T11)macOS1.4.9 can't be used to test the voice call. fix(macOS): preserve release entitlements when signing #16125Scope and limitations
The application runtime changes are confined to non-Linux format replacement and Windows playback recovery/confirmation, including the incoming voice-call owner. The dependency fix changes WASAPI input/output stream notification errors and destruction. Linux playback, non-Windows CPAL backends, capture queue policy, codec settings and the wire format are unchanged. A healthy compatible output retained after replacement failure stays active; a subsequent format announcement or terminal failure can trigger another replacement. Callback confirmation does not prove audible output.
Windows 7 systemloopback remains unsupported by the pinned event-driven WASAPI capture path: Microsoft's loopback documentation https://learn.microsoft.com/en-us/windows/win32/coreaudio/loopback-recording describes the missing capture events before Windows 10 1703. This predates #16095. Microphone/input-device capture remains enabled. #16095 moved encoding/message submission into the worker and introduced the callback-to-worker
unpark()dependency. With Rust 1.75 on Windows 7 https://github.com/rust-lang/rust/blob/1.75.0/library/std/src/sys/windows/thread_parking.rs, notification can wait between publication ofPARKEDand entry intoNtWaitForKeyedEvent;park_timeout()does not bound that callback wait. The previously accepted Win7 scheduling risk remains unmeasured and is outside these two playback/cleanup fixes.Earlier hardware runs do not complete the unchecked cases. The guided Windows 11 checks above cover basic audibility and recovery; sustained voice quality and 30-minute endurance/handle trends remain unverified. T04 still records a subjectively estimated ~1 s voice delay, also observed in a new call before another device fault. Its cause and whether it is a regression remain undetermined; callback timings are not end-to-end latency measurements. During T06, the controller's USB output became silent even for local playback. Microphone-switch retests passed after replugging the headset, but the initial silence remains unexplained. Earlier recordings with gaps and PCM buffer discards remain part of the evidence.