Skip to content

fix: work around GStreamer jitterbuffer stall after mute gap#472

Merged
srperens merged 4 commits intomainfrom
feat/whep-jitterbuffer-fix
Apr 7, 2026
Merged

fix: work around GStreamer jitterbuffer stall after mute gap#472
srperens merged 4 commits intomainfrom
feat/whep-jitterbuffer-fix

Conversation

@srperens
Copy link
Copy Markdown
Collaborator

@srperens srperens commented Apr 2, 2026

Summary

  • Set drop-on-latency=true on rtpbin in WHEP input blocks to work around a GStreamer rtpjitterbuffer bug that causes audio to stall after mute/unmute with packet loss
  • Add optional diagnostic pad probes for WHEP inputs (STROM_WHEP_PROBE=1)
  • Add regression test reproducing the bug with and without the fix

The bug

GStreamer's rtpjitterbuffer has a calculate_packet_spacing function that uses an exponential moving average to estimate the time between packets. When a mute gap ends (RTP resumes with continuous sequence numbers but a large timestamp jump), the function interprets the timestamp jump as packet spacing. If packet loss then occurs, lost timers are scheduled based on this corrupted spacing — potentially seconds or minutes into the future — stalling audio output.

This has been a known issue upstream since 2018 with multiple unmerged fix attempts:

The workaround

drop-on-latency=true causes the jitterbuffer to drop queued packets exceeding the configured latency, advancing next_seqnum past the stall point. For live audio this is the correct behavior — packets older than the latency window should never be output.

Test plan

  • test_jitterbuffer_stalls_without_drop_on_latency — proves the bug exists
  • test_jitterbuffer_recovers_with_drop_on_latency — proves the workaround works
  • Verified locally: drop-on-latency=TRUE visible on rtpjitterbuffer for both whepsrc and whepclientsrc

🤖 Generated with Claude Code

Per Enstedt and others added 4 commits April 1, 2026 16:44
Add per-buffer packet counters at every element in the WHEP pipeline
chain (NiceSrc through LiveAdder) to diagnose intermittent audio
delivery failures. Activated via STROM_WHEP_PROBE=1, output written
to file (path configurable via STROM_WHEP_PROBE_DIR).

Uses AtomicU64 counters only in the hot path — no mutex, no allocation,
no string formatting in buffer probe callbacks. A periodic reporter
task writes changed counters to a log file every 5 seconds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set drop-on-latency=true on rtpbin in WHEP input blocks (both whepsrc
and whepclientsrc). This works around a long-standing GStreamer bug where
rtpjitterbuffer's calculate_packet_spacing interprets the RTP timestamp
jump after a mute gap as packet spacing. The corrupted spacing causes
lost timers to be scheduled far in the future, stalling audio output
for the duration of the mute gap when packet loss occurs after unmute.

Upstream references (none merged as of 2026-04):
  - https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/570
  - https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/951
  - https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/221

Includes regression test reproducing the bug with and without the fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extend the jitterbuffer packet_spacing workaround to all input blocks
that use rtpjitterbuffer: WHIP ingest (whipserversrc) and AES67 input.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The jitterbuffer_mute_test requires rtpjitterbuffer from plugins-good.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@srperens srperens merged commit dfd6d4a into main Apr 7, 2026
7 checks passed
@srperens srperens deleted the feat/whep-jitterbuffer-fix branch April 7, 2026 07:23
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