Skip to content

fix(dash): share one ABR availabilityStart + stop non-audio shards waiting for audio#19

Merged
ntt0601zcoder merged 1 commit into
mainfrom
fix/dash-abr-ast
Jun 13, 2026
Merged

fix(dash): share one ABR availabilityStart + stop non-audio shards waiting for audio#19
ntt0601zcoder merged 1 commit into
mainfrom
fix/dash-abr-ast

Conversation

@ntt0601zcoder

Copy link
Copy Markdown
Owner

Problem (audit B-4, MEDIUM)

In an ABR DASH ladder each shard anchored its own availabilityStartTime at its first flush. The audio-packing shard flushes at ~segDur, but a non-audio shard never has audioReady true, so it only flushed at the pairing deadline — ~1 s later. That per-shard AST skew (Δ≈1 s) caused:

  • (a) the single published AST is Δ-wrong for every rendition except the slug-sorted winner;
  • (b) behindPrevSegEnd paces each shard against its own later AST, so non-audio reps publish every segment Δ late forever (availability over-promise / edge-switch stall risk);
  • (c) if the audio shard isn't slug-first, the published AST can change mid-stream — a dynamic-MPD AST-constancy violation.

(On default config Δ≈1 s is absorbed by suggestedPresentationDelay=6 s, hence Medium.)

Fix

Two changes — no StartTicks rebase (timelines are already media-PTS-aligned):

  1. Non-audio shards pair on video alone. tryCut now computes audioReady := !p.cfg.PackAudio || (haveAudio && queue.AudioLen()>0), so an ABR non-primary shard cuts at the first IDR instead of waiting out the pairing window for audio it will never pack — collapsing the per-shard availStart skew to inter-shard IDR jitter (≤~150 ms).
  2. One ladder-wide AST. New ABRMaster.SharedAST(candidate) returns a single AST, set once by whichever shard flushes first; at its first flush each shard adopts it (p.availStart = ABRMaster.SharedAST(now)). Single-rendition streams have no master and keep their own now. All shards now anchor tfdt + behindPrevSegEnd pacing to the same origin → AST correct for every rendition (a, b) and constant for the session regardless of flush order (c).

Test

TestABRMaster_SharedAST (set-once semantics + zero-candidate guard), TestPackager_NonAudioShardEmitsBeforePairingDeadline (a PackAudio=false shard emits its first segment well within a 30 s pairing window — proving it paired on video alone).

go test -race ./internal/publisher/dash/ green incl. all existing table tests (no timeline regression), golangci-lint 0 issues, full go build ./... green.

…iting for audio

In an ABR DASH ladder each shard anchored its OWN availabilityStartTime at its
first flush. The audio-packing shard flushes at ~segDur, but a non-audio shard
never has audioReady true so it only flushed at the pairing deadline — ~1s
later. That skew meant: the single published AST was wrong for every rendition
but the slug-sorted winner; behindPrevSegEnd paced each shard against its own
later AST so non-audio reps published every segment ~1s late forever; and if
the audio shard wasn't the slug-first one the published AST could change
mid-stream, violating dynamic-MPD AST constancy.

Two changes, no StartTicks rebase (timelines are already media-aligned):

1. A non-audio shard pairs on video alone: audioReady is now
   `!PackAudio || (haveAudio && queue.AudioLen()>0)`, so it cuts at the first
   IDR instead of waiting out the pairing window — collapsing the per-shard
   availStart skew to inter-shard IDR jitter (≤~150 ms).

2. ABRMaster.SharedAST(candidate) returns one ladder-wide AST, set once by
   whichever shard flushes first; each shard adopts it at its first flush
   (single-rendition streams have no master and keep their own now). All shards
   now anchor tfdt + behindPrevSegEnd pacing to the same origin, and the
   published AST is correct for every rendition and constant for the session.

Tests: TestABRMaster_SharedAST (set-once / zero-candidate),
TestPackager_NonAudioShardEmitsBeforePairingDeadline (non-audio shard emits
well within a 30s pairing window). Existing DASH table tests pass unchanged.
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ntt0601zcoder ntt0601zcoder merged commit 2e8eef2 into main Jun 13, 2026
4 checks passed
@ntt0601zcoder ntt0601zcoder deleted the fix/dash-abr-ast branch June 13, 2026 15:42
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.

2 participants