fix(dash): un-latch track presence so the live edge survives a mid-session track death#14
Merged
Merged
Conversation
…ssion track death The DASH packager derived haveVideo/haveAudio from videoInit/audioInit, which are built once and never cleared. When one elementary stream stopped mid-session (encoder fault, or a failover swap to a single-track feed while the publisher keeps running by design) the presence flag stayed true, so buildCutDecision's V/A duration coupling held every cut waiting for the dead track's frames — Ok=false on every tick. The live edge froze permanently for all DASH viewers, the frame queue saturated and overflow-dropped, and only a manual restart recovered it. HLS on the same stream kept working, masking it. Derive presence from arrival liveness instead: handleH264/handleAAC stamp the last-frame-arrival wallclock per track, and a new liveTrackPresence(now) declares a track dead once the stream is Live and that track has both an empty queue and no arrival within trackLossTimeout (6 s). Down-grading is gated to StateLive only, so the pairing handshake and post-session-boundary stale timestamps are untouched. Audio death then skips the coupling and video cuts resume; video death routes to cutAudioOnly. Presence flips back automatically when the track resumes, and the wallclock-anchored tfdt lands the resumed segment at the live edge with no extra re-anchoring. Test TestLiveTrackPresence_TrackDeath covers audio-dead, video-dead, still-draining-queue, recent-frames, waiting-for-pairing (no down-grade), and genuine single-track cases.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem (audit A-8, HIGH)
The DASH packager derived
haveVideo/haveAudiofromvideoInit/audioInit, which are built once and never cleared. When one elementary stream stops mid-session — an encoder fault, or a failover swap to a single-track feed while the publisher keeps running by design — the presence flag stays latched true.buildCutDecision's V/A duration coupling then holds every cut waiting for the dead track's frames (Ok=falseon every 50 ms tick), so:FrameQueuesaturatesmaxQueueSpanMsand overflow-drops every incoming frame,The symmetric video-death case is unreachable too:
cutAudioOnlyrequires!haveVideo, which never becomes false while latched.Fix
Derive track presence from arrival liveness instead of init existence:
handleH264/handleAACstamplastVideoFrameAt/lastAudioFrameAton every accepted frame.liveTrackPresence(now)declares a track dead once the stream isStateLiveand that track has both an empty queue and no arrival withintrackLossTimeout(6 s).StateLiveonly —WaitingForPairing(pairing handshake) andSessionBoundary(post-reset stale timestamps) keep init-presence so neither is disturbed.Audio death →
haveAudio=false→ coupling skipped (buildCutDecision's audio block already gates onhaveAudio) → video cuts resume. Video death →haveVideo=false→cutAudioOnlyengages. Presence flips back automatically when the track resumes (handlers re-stamp), and the wallclock-anchored tfdt lands the resumed segment at the live edge with no extra re-anchoring.Test
TestLiveTrackPresence_TrackDeathcovers: audio-dead/video-survives, video-dead/audio-survives, still-draining-queue (not dead), recent-frames (alive), waiting-for-pairing (no down-grade), and genuine single-track stream.Package:
go test -race ./internal/publisher/dash/green,golangci-lint0 issues, fullgo build ./...green.