The Linux audio service in `--server` ignored the `Err` from `next_raw()`, so
once the cm-side `_pa` peer closed, every iteration re-polled a dead socket:
tokio-util's paused `Framed` issues one 0-byte read per poll and returns ready
at once, never `Pending`. The thread never parked and burned a full core for
the life of the process. Propagate instead, so `ServiceTmpl::run`'s existing
backoff ends the inner loop and reconnects.
Two sibling loops on the same audio path have the same shape:
- `ipc::start_pa` (runs in `--cm`) ignored the `Err` from
`psimple::Simple::read`, so a dead pulse handle spins there instead.
- `start_voice_call`'s forwarding thread polls two channels with `try_recv`
and has no blocking primitive at all: measured 99.8% of a core for the whole
call, against 1.0% with a 1 ms pause (audio packets arrive every 10 ms).
fix https://github.com/rustdesk/rustdesk/issues/16226
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(audio): add streaming resampler
* fix(audio): preserve stream resampling state
* fix(audio): keep playback callback nonblocking
* fix(audio): decouple capture conversion from dasp
* fix(audio): support stateful samplerate backend
* refactor(audio): isolate stream callback state
* refactor(audio): group capture output options
* fix(audio): clear stale playback state after startup failure
Reset non-Linux playback state when stream startup fails to prevent
new-format audio from using the previous stream or resampler.
Add regression tests for failed format changes and successful playback.
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): honor capture resampler selection and reuse buffers
Use the selected resampling backend for fixed-frame capture.
Convert samples directly into the input queue and
reuse the PCM frame buffer.
Add tests for anti-aliasing, thread transfer, and
partial-frame draining.
Signed-off-by: fufesou <linlong1266@gmail.com>
* refact: reduce diffs
Signed-off-by: fufesou <linlong1266@gmail.com>
* test(audio): check resampler output count and passband energy
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): reset incompatible Linux playback state on
startup failure
Preserve compatible output streams when replacement
startup fails.
Clear state when no compatible stream exists and cover
both paths in tests.
Signed-off-by: fufesou <linlong1266@gmail.com>
* perf(audio): reuse PCM buffers in the capture pipeline
- Reuse capture framing, resampling, and channel conversion buffers
- Deliver borrowed packets and write Sinc output into reusable storage
- Add allocation and output-equivalence regression tests
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): smooth buffer discard discontinuities
Signal receiver PCM discards and fade from the current playback output when the callback reaches the new timeline.
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): add missing Cargo.toml
Signed-off-by: fufesou <linlong1266@gmail.com>
* perf(audio): move capture encoding off the CPAL callback
Move Opus encoding and service delivery to a dedicated worker.
Use a preallocated bounded PCM queue with explicit loss reporting.
Add tests for callback allocations and queue saturation.
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): smooth capture gaps and report losses during backlog
Signed-off-by: fufesou <linlong1266@gmail.com>
* feat(audio): report capture queue high-water mark
Track peak queued PCM packets and log the approximate
queued audio duration alongside capture loss statistics.
Signed-off-by: fufesou <linlong1266@gmail.com>
* refact(audio): reduce diffs
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): avoid blocking capture on encoder queue contention
Use preallocated queues with try_lock in the capture callback.
Count and drop the current packet on contention, preserving
drop-oldest behavior on overflow.
Add regressions for paused workers, buffer reuse, and sequence wrap.
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix: add the missing files
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): isolate zero-gate state per encoder
Signed-off-by: fufesou <linlong1266@gmail.com>
* refact: reduce diffs
Signed-off-by: fufesou <linlong1266@gmail.com>
* refact(audio): simple refactor
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(audio): avoid waiting on playback callback locks
Use one PCM try_lock attempt and preserve queued samples during contention. Replace readiness locking with per-stream atomic status and report callback errors from the receiving thread.
Cover callback progress, retained audio, recovery, and poisoned-buffer handling.
* fix(audio): restart capture after processing errors
Stop further processing until the service recreates the stream.
Document the guard as defensive recovery for an unconfirmed failure.
Group capture and resampler submodules under their parent directories.
Signed-off-by: fufesou <linlong1266@gmail.com>
* audio: report capture queue contention drops separately
- Add contention_dropped to loss reports while preserving total drop counts
- Document packet rejection on contention even when buffers are available
- Extend existing contention and saturation test assertions
Signed-off-by: fufesou <linlong1266@gmail.com>
* refact unit tests
Signed-off-by: fufesou <linlong1266@gmail.com>
---------
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(macos): recreate system-stopped audio capture streams
Pin CPAL's ScreenCaptureKit stop notifications and retain interruption
state with each capture stream. Recreate an interrupted stream through
the existing service restart path, outside the backend error callback,
and resend its audio format. Late callbacks cannot restart a replacement.
A natural -3821 stop was observed with the remote connection still open.
Its OS trigger remains unknown and it has no deterministic natural
reproducer. Controlled verification stops the real SCStream and delivers
an explicitly marked -3821 notification; this is not a natural failure.
Dependency: https://github.com/rustdesk-org/cpal/pull/5
Validation: requested macOS Rust and Flutter debug builds; three full-crate
regression tests; build check without ScreenCaptureKit; two controlled
recreations on one connection with independently recorded receiver audio.
* chore(macos): log audio capture startup and resumed samples
* Update deps, cpal
Signed-off-by: fufesou <linlong1266@gmail.com>
---------
Signed-off-by: fufesou <linlong1266@gmail.com>
* fix: windows, improve audio buffer (#9770)
* .
* fix statics does not record
and avoid channel changing when drio audio when audio is stero
* add some commence
* fix mis-align problem when converting &[u8] to &[f32]
* add safety commence
* revert client.rs
* avoid tmp lifetime extends
* avoid move in loop
* avoid use after drop
* another use after free
* another use after free
* make code more reasonable
---------
Co-authored-by: zylthinking <zhaoyulong@qianxin.com>