Skip to content

feat(live): the carriage verdict is read from the source, not waited out - #294

Merged
superuser404notfound merged 1 commit into
mainfrom
feat/live-carriage-probe-293
Aug 3, 2026
Merged

feat(live): the carriage verdict is read from the source, not waited out#294
superuser404notfound merged 1 commit into
mainfrom
feat/live-carriage-probe-293

Conversation

@superuser404notfound

Copy link
Copy Markdown
Owner

Re #293.

What changed

A live master that advertises HEVC and delivers MPEG-TS is carriage AVFoundation builds no video track for. The only thing that established that was the #168 watchdog: mount, readyToPlay, poll item.tracks for eight ticks, conclude from the absence of a track. Every first open of such a channel spent 4 s as audio over black before the reroute started, in every process; #199's verdict memory only removes it from the second load onwards inside one process.

The engine already answers the same question directly. #268 classifies this carriage from the playlist plus the first segment's PMT, no AVPlayer involved, and gates it to finite VOD.

  • HLSCarriageProbe lifts that chain out of HLSVODIngestReader (which now shares the segment-head read instead of carrying its own) and drops the VOD-only requirements, so a rolling live window with no EXT-X-ENDLIST can be judged. EXT-X-MAP settles a source as fMP4 before a segment byte is fetched; encrypted, unreachable and non-HEVC outcomes stay inconclusive, because only positive evidence may reroute.
  • It runs concurrently with the mount, never in front of it. A healthy stream's watchdog disarms and cancels it; a doomed one usually has its verdict in before the watchdog arms.
  • It never fires on its own. The verdict feeds the same pure Watchdog, which ends its wait early on positive evidence. A video track that does build still wins at any point, so no working session leaves the native path, and a wrong verdict costs the ingest path, which plays the same stream.
  • Gated on evidence AVFoundation already fetched and hands over free (AVAssetVariant), because per-token origins routinely cap concurrent connections: only a codec the HLS Authoring Spec sanctions in fMP4 alone (HEVC, Dolby Vision, AV1), or a source with no master evidence at all, reaches the network. An H.264 channel spends nothing.
  • A live media playlist URL is judged for the first time. The watchdog needs master variant evidence to fire, so a direct media playlist has none and disarms after the grace by design; HEVC-in-MPEG-TS behind such a URL stayed audio-only indefinitely.
  • The reroute line names the grace it removed, so a reporter measuring time to first frame sees this item rather than the sum (waitForSwitch() still runs when suppressDisplayCriteria=true, adding a residual startup wait even when the host is the sole criteria writer #274).

The fire itself still happens on the watchdog's first tick after readyToPlay, not before it: that keeps one firing path and one interleaving with the mount's own state machine. The saving is the grace, roughly 3.5 s of the 4 s, not the mount.

Verification

  • New Issue293LiveCarriageProbeTests (21 tests, all watched failing first): the probe gate's truth table, the watchdog's response to each evidence value, and the playlist chain end to end over a stubbed origin (live master, direct media playlist, fMP4, H.264, AES-128, unreachable playlist, unreachable segment).
  • swift test: 449 XCTest + 1479 swift-testing, 0 failures.
  • xcodebuild -destination 'generic/platform=tvOS Simulator': BUILD SUCCEEDED.
  • Swift 6 language mode (strict concurrency) clean.

Device verification is open: reproducing this needs a live HEVC-in-MPEG-TS channel. The log markers for it are [NativeAVPlayerHost] #N carriage probe: hevcInMPEGTS (#293) and the reroute line that follows, which states the grace it removed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HX5zV3Fcf7Nzq4DYGdXvQE

A live master that advertises HEVC and delivers MPEG-TS is carriage
AVFoundation builds no video track for, and the only thing that ever
established it was the #168 watchdog: mount the source, reach readyToPlay, poll
`item.tracks` for eight ticks, then conclude from the absence of a track. Every
first open of such a channel therefore spent 4 s as audio over black before the
reroute could start, in every process, and #199's verdict memory only removes
that from the second load onwards, inside one process.

The engine already owns a direct answer to the same question. #268 classifies
this carriage from the playlist plus the first segment's PMT, with no AVPlayer
involved, and gates it to finite VOD. `HLSCarriageProbe` lifts that chain out of
`HLSVODIngestReader` (which now shares the segment-head read rather than
carrying its own) and drops the VOD-only requirements, so a rolling live window
without EXT-X-ENDLIST can be judged too. It runs concurrently with the mount,
never in front of it, so nothing is serialized ahead of first frame: a healthy
stream's watchdog disarms and cancels the probe, and a doomed one usually has
its verdict in before the watchdog even arms.

The verdict does not fire on its own. It feeds the same pure `Watchdog`, which
ends its wait on positive evidence, so a video track that does build still wins
at any point and no working session is taken off the native path. A wrong
verdict costs the ingest path, which plays the same stream.

The probe is gated on evidence AVFoundation has already fetched and hands over
for free, because origins that authenticate per token routinely cap concurrent
connections: only a codec the HLS Authoring Spec sanctions in fMP4 alone
(HEVC, Dolby Vision, AV1), or a source with no master evidence at all, reaches
the network. An H.264 channel spends nothing.

That second case closes a hole of its own. The watchdog needs master variant
evidence to fire, so a live media playlist URL has none and disarms after the
grace by design; HEVC-in-MPEG-TS behind such a URL stayed audio-only
indefinitely. The PMT is evidence the master parse could not supply, so it is
now judged for the first time.

The reroute line names the grace it removed rather than leaving the reporter to
measure the sum (#274).

Filed as #293 out of the #199 retest, where the reporting host had shipped a
master probe of its own to route known channels onto the ingest before the
engine mounts natively. Reported by @kskchaitanya1993.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HX5zV3Fcf7Nzq4DYGdXvQE
@superuser404notfound
superuser404notfound merged commit a76e1f8 into main Aug 3, 2026
3 checks passed
@superuser404notfound
superuser404notfound deleted the feat/live-carriage-probe-293 branch August 3, 2026 16:52
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