Skip to content

fix(audio): avoid capture packet drops caused by queue contention - #16146

Draft
fufesou wants to merge 1 commit into
rustdesk:masterfrom
fufesou:fix/audio-capture-handoff
Draft

fix(audio): avoid capture packet drops caused by queue contention#16146
fufesou wants to merge 1 commit into
rustdesk:masterfrom
fufesou:fix/audio-capture-handoff

Conversation

@fufesou

@fufesou fufesou commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Related

Summary

The capture callback currently drops its new PCM packet if the encoder worker holds the shared queue mutex, even when free buffers are available. The single try_lock() keeps the callback from waiting, but can discard audio without a backlog.

Replace that shared queue lock with atomic buffer ownership transfers. A worker paused while consuming or recycling one buffer no longer prevents the callback from using the remaining capacity. Actual buffer exhaustion still uses the existing drop-oldest policy.

Fix details

  • Store the free-buffer set and ordered ready-buffer indices together in one AtomicU64. Claiming an index transfers exclusive ownership before either thread accesses its PCM.
  • Keep each buffer behind a separate mutex for safe Rust access. Release that mutex before publishing the index as ready or free, so the callback cannot claim a buffer whose lock the worker still holds.
  • Retain the ten preallocated buffers, packet sequence numbers, gap detection, and oldest-ready-packet discard behavior. If every buffer is checked out and none is ready, reject the new packet as before.
  • Keep the existing contention_dropped log field at zero for comparison with older builds. Genuine capacity drops remain in dropped.
  • Extend the existing queue tests for worker suspension before and after publication, saturation, sequence wrap, allocation behavior, and complete buffer recovery. No new dependencies or unsafe code.

Testing

Use a Windows or macOS machine as the audio-sending host. Linux and Android do not use this capture handoff. Compare the fix with master at c4221469d, using the same audio device, source, receiving machine, and network.

  • Connect with audio enabled and play continuous music or a test tone on the sending host. Listen through headphones on the receiving machine for several minutes. Check for new gaps, clicks, or accumulating delay.
  • Repeat while running a CPU-heavy workload, such as a build or video encode, on the sending host. Remove the load and check that audio continues normally. Repeat with both builds; contention on the old build is scheduling-dependent and may not occur in every run.
  • Inspect the sending host's logs. Audio capture PCM handoff loss reports dropped, contention_dropped, oversized, and recycle_failures. The fixed build must not report contention drops. Real saturation can still increase dropped; oversized and recycle_failures should stay zero. Loss messages are only emitted when there is something to report.
  • With debug logging enabled, also check Audio capture PCM handoff stats. observed_max_queued_packets must not exceed the existing capacity of ten. This is queued PCM only, not a measurement of end-to-end latency. A zero contention counter alone does not prove that no audio was lost.
  • Disconnect and reconnect several times, then repeat a short playback check. Confirm that capture starts and stops normally.

For a deterministic developer check, suspend only the audio-encoder thread after it claims a buffer or just before it publishes a recycled buffer. Keep the capture thread running and leave other buffers free. Submission should continue using that capacity before the worker resumes. If the pause lasts long enough to exhaust the pool, older queued packets may be dropped. Resume the worker and verify that delivery continues. Suspending the whole process does not exercise this case.

Validation and scope

Native macOS audio tests passed on this commit with both backends: 36 with the default backend and 34 with use_samplerate. The strengthened paused-worker tests fail with the old handoff and pass with this implementation.

The changes are confined to capture queue construction, buffer transfer/recycling, and loss accounting. Playback, resampling, encoding, and stream lifecycle code are unchanged. The packed representation supports up to twelve buffers; production still uses ten.

Windows execution and the hardware checks above are still pending. A short software comparison under CPU load had no drops with either implementation, so it does not establish the frequency or audible impact of the old contention issue. This fix does not claim to eliminate all audio interruptions.

Summary by CodeRabbit

  • Improvements
    • Improved audio capture buffering to reduce processing contention and provide more consistent handoff between recording and playback.
    • When the buffer reaches capacity, the oldest queued audio is discarded so newer audio remains available.
    • Improved buffer recycling and capacity validation for more reliable operation across different queue sizes.

Use atomic buffer ownership transfers for the capture handoff.
Preserve preallocation, packet ordering, and drop-oldest behavior.
Extend existing tests for paused workers, saturation, and sequence wrap.

Signed-off-by: fufesou <linlong1266@gmail.com>
@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: dee3b123-482c-4d53-b669-5d4cf41ca22e

📥 Commits

Reviewing files that changed from the base of the PR and between c422146 and 1d97c6d.

📒 Files selected for processing (3)
  • src/server/audio_service/audio_capture_queue.rs
  • src/server/audio_service/audio_capture_queue/buffer_pool.rs
  • src/server/audio_service/audio_capture_queue_tests.rs

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Audio capture buffering now uses an atomic-state BufferPool with indexed slot ownership. Submission, reception, recycling, initialization, loss reporting, and concurrency tests now use pool operations.

Changes

Audio capture buffer pool

Layer / File(s) Summary
Buffer pool state and slot operations
src/server/audio_service/audio_capture_queue/buffer_pool.rs
Added capacity validation, atomic ready-queue and availability tracking, indexed slot claiming, packet publication, extraction, recycling, and pool state checks.
Handoff ownership flow
src/server/audio_service/audio_capture_queue.rs, src/server/audio_service/audio_capture_queue/buffer_pool.rs
The handoff uses indexed pooled buffers for submission, reception, and recycling. Initialization delegates validation and allocation to BufferPool.
Pool and concurrency validation
src/server/audio_service/audio_capture_queue_tests.rs
Tests cover worker pause points, retained packet order, queue depths, pool restoration, maximum capacity, dynamic drops, and zero contention drops.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to 1d97c

Audio capture now transfers pooled buffer ownership atomically to avoid queue-contention packet drops. The updated coverage validates handoff behavior, retention, loss accounting, and buffer recovery, with no remaining merge-blocking risk identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.52% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 27 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing audio capture packet drops caused by queue contention.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@fufesou

fufesou commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@fufesou

fufesou commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator Author

@codexrabbitai full review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant