Skip to content

Switch to the filler before a selected track's own EOS - #1473

Open
pksgit wants to merge 1 commit into
mainfrom
pradeepsharma/cs-2150-track-eos-filler-switch
Open

pksgit wants to merge 1 commit into
mainfrom
pradeepsharma/cs-2150-track-eos-filler-switch

Conversation

@pksgit

@pksgit pksgit commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #1465, which listed this path under Follow-ups: a selected track's own EOS reaching the selector while the egress is running.

input-selector forwards the active pad's EOS downstream. When a selected track ends on its own while the egress is still running, its EOS goes through the selector into video_encoder_queue. The track's removal then switches the selector to the filler behind that EOS. Two ways a track can end like this:

  • its appsrc stops with not-negotiated: basesrc pushes EOS right after posting the error, and removal follows from the bus message;
  • its app writer finishes before the track is removed, and pushes EOS as part of its cleanup.

The EOS travels through the track's video_input_queue on its own thread, so whether it reaches the selector before the removal's switch is a race. When it wins:

  • the video encoder has been sent EOS while the egress keeps running;
  • the filler renegotiates after the switch and sends an ALLOCATION query. If it reaches video_encoder_queue while that EOS is still draining, gst_queue keeps the query after its sender gives up and frees it, and the filler's STREAM_START later restarts the queue onto the freed pointer: Unexpected item ... dequeued from queue video_encoder_queue (refcounting problem?), followed by a stream error. This queue behaviour is the same in GStreamer 1.24 and 1.28.

Change

Each track's selector pad gets an event probe that calls onTrackEOS. When an EOS arrives while the pipeline is still running and the track is selected, the probe switches the selector to the filler before the EOS reaches the selector, and clears a pending handover to that track. The selector then holds the EOS as it does for any inactive input, until the track's removal releases the pad. This is the switch the track's removal already makes, moved ahead of the EOS.

A track's EOS at shutdown passes unchanged. Shutdown EOS can reach the selector before the video bin's EOS function runs, but always after the pipeline has left the running state, so the probe checks the pipeline state.

Order of events Before After
Selected track's EOS reaches the selector before its removal switches EOS into the encoder; the filler follows behind it; can fail as above Filler takes over at the EOS; the selector holds the EOS; the output continues on the filler
Removal switches before the track's EOS arrives EOS held on an inactive pad Same
Track pending (filler on screen) when its EOS arrives EOS held; the pending handover is cleared at removal EOS held; the pending handover is cleared at the EOS
Selected track's EOS during shutdown Forwarded, ends the video stream Same

Testing

  • New TestSelectorHandover_SelectedTrackEOSWhileRunning runs the sequence against the production gates, a real input-selector and the production video_encoder_queue: the filler is on screen, a track takes the selector, the track's EOS arrives (if forwarded, it is held past the encoder queue by a probe, standing in for the encoder draining it), the track's removal switches to the filler, the filler's ALLOCATION query is sent and freed once answered, then later filler frames arrive. It checks that the track's EOS never reaches the encoder queue, that no query is queued behind it, that pushes keep succeeding and that the filler's frames leave the selector. Without the probe it fails every run on both 1.24 and 1.28 core elements, and some runs log Unexpected item ... dequeued from queue video_encoder_queue (refcounting problem?), after which every push fails. With it, it passes.
  • New TestSelectorHandover_SelectedTrackEOSAtShutdown checks that once the pipeline is ending, a selected track's EOS leaves the selector and the track stays selected. It fails if the probe ignores the pipeline state.
  • go test ./pkg/... with the deadlock tag and golangci-lint, as run by build/test/Dockerfile, pass.
  • Integration, locally on linux/arm64 with an image built from this branch: file-media, stream, segments and edge pass. In multi, the Web and ParticipantComposite subtests fail in this local setup because the test can't find their manifest files; both egresses complete, and the same two subtests fail the same way without this change. CI builds amd64.

🤖 Generated with Claude Code

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Devin Review: 1 flag

Not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

AV-sync stats summary: view in run #39637731391

input-selector forwards the active pad's EOS. When a selected track ends
on its own while the egress runs (its appsrc stops on a negotiation
error, or its writer finishes before the track is removed), that EOS can
reach video_encoder_queue before the track's removal switches to the
filler. The filler then renegotiates behind the EOS, and its ALLOCATION
query can be left in the queue after its sender frees it, which the queue
later dequeues ("refcounting problem?").

Each track's selector pad now has an event probe. On EOS while the
pipeline is running, it switches to the filler first, so the selector
holds the EOS as it does for any inactive input. A shutdown EOS passes
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pksgit
pksgit force-pushed the pradeepsharma/cs-2150-track-eos-filler-switch branch from 14fc35d to c182370 Compare October 21, 2026 16:46

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant