Skip to content

fix: resolve passthrough audio not flowing in media player bridge#486

Merged
srperens merged 2 commits intomainfrom
fix/mediaplayer-passthrough-audio
Apr 13, 2026
Merged

fix: resolve passthrough audio not flowing in media player bridge#486
srperens merged 2 commits intomainfrom
fix/mediaplayer-passthrough-audio

Conversation

@srperens
Copy link
Copy Markdown
Collaborator

Summary

  • Fix audio not reaching downstream blocks (e.g. mpegtssrt) in media player passthrough mode
  • Root cause: clocksync element's internal flushing flag is only cleared during PAUSED→PLAYING transition — when pad-added fires during pipeline preroll, clocksync stays in PAUSED and silently drops all audio buffers
  • Also fix link ordering (upstream last) and make push_sample errors non-fatal to handle startup timing

Changes

  1. Set clocksync to PLAYING explicitly instead of sync_state_with_parent() which leaves it in PAUSED during preroll
  2. Link upstream pad last — after elements are started and callbacks installed, preventing multiqueue from pushing to unready elements
  3. Don't kill appsink on push_sample failure — return Ok on transient errors (FLUSHING) to keep the bridge alive while the main pipeline starts

Why video worked but audio didn't

Video prerolled first (before adding a sink dropped the internal pipeline's aggregate state to PAUSED), so its clocksync got PLAYING state. Audio pad-added fired second, by which time the pipeline was in PAUSED, leaving audio clocksync stuck.

Test plan

  • Verified with "media player pass" flow: both video and audio samples now deliver through the bridge
  • mpegtssrt audio chain links successfully: identity -> aacparse (AAC) -> mpegtsmux
  • Pipeline reaches PLAYING state
  • Manual verification: play SRT output with ffplay/VLC and confirm A/V

🤖 Generated with Claude Code

Per Enstedt and others added 2 commits April 13, 2026 10:32
Three issues prevented audio from reaching downstream blocks (e.g.
mpegtssrt) in passthrough mode:

1. clocksync in PAUSED state silently drops buffers — its internal
   flushing flag is only cleared during PAUSED→PLAYING transition.
   When pad-added fires during pipeline preroll, sync_state_with_parent
   leaves clocksync in PAUSED because the pipeline hasn't reached
   PLAYING yet. Fix: set clocksync to PLAYING explicitly.

2. Upstream pad linked before elements are started — urisourcebin's
   internal multiqueue pushes buffered data the instant a pad is
   linked. If clocksync is still in NULL/READY state, the push returns
   FLUSHING and the multiqueue permanently kills that stream's thread.
   Fix: link downstream first, start elements, then link upstream last.

3. push_sample error kills appsink permanently — the main pipeline's
   appsrc may not be ready when the first samples arrive (internal
   pipeline starts before main pipeline). The ? operator on push_sample
   returns FlowError::Error which GStreamer treats as a permanent
   failure. Fix: return Ok on transient errors to keep the bridge alive.

Video worked by luck: it prerolled first (before adding a sink dropped
the pipeline to PAUSED) so its clocksync got PLAYING state, and its
multiqueue thread hadn't started pushing when the link was made.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@srperens srperens merged commit b5f05e5 into main Apr 13, 2026
7 checks passed
@srperens srperens deleted the fix/mediaplayer-passthrough-audio branch April 13, 2026 08:53
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