6.15.1 - A bypass that can no longer hang in silence
One fix on the nativeRemoteHLS bypass: a session that could neither play nor fail now does one of the two. Drop-in from 6.15.0, internal surface only.
The shape
An origin that stops answering is covered: the lean bypass runs without a readiness watchdog on purpose and lets AVPlayer's own "gave up" signal surface a dead upstream. An origin that answers everything while AVFoundation can build no track from what it serves is not. Nothing fails, readyToPlay never arrives, and state stays .loading for as long as the host leaves it there. A live channel carrying HEVC in MPEG-TS with no audio track is exactly that: the carriage reroute is the fix for it, and there is no audio track to reach readiness with either.
The carriage machinery could not rescue it, because all of it hangs off the same anchor:
- the #293 probe settled
hevcInMPEGTSfrom the playlists within a second, and that verdict was then only ever read by a loop that arms atreadyToPlay; - the deferred segment-head probe waited out its 20 s readiness ceiling and returned without reading the one thing that could have judged the source.
Three changes
A settled verdict reroutes on its own. It is read off the source's own playlists or PMT, so it needs no grace and no anchor. A video track that does exist still outranks it, so a source that contradicts the probe keeps its native session.
The deferred probe reads the segment head when the ceiling expires. Deferring existed so that read would not compete with the mount; a mount that has not settled in 20 s is not competing for anything, and giving up there is what left the source unjudged.
The bypass has a ceiling on silence. 45 s with no readiness, no reroute and no failure publishes a real error instead of an endless spinner:
The stream never became playable: AVFoundation built no track for it within 45s
and the source's carriage could not be identified.
It is a ceiling on silence, not on how long a slow origin may take. Readiness at any point, a carriage reroute, or an AVPlayer failure that already published a terminal state all disarm it, so a Jellyfin transcode spin-up or a slow IPTV token handshake never meets it. The budget also clears the deferred probe's own 20 s ceiling plus the segment read that follows it, which is asserted in a test rather than left to a comment.
Verification
12 new tests, 1618 tests in 240 suites green, -strict-concurrency=complete clean, tvOS and iOS Simulator builds green.
Each layer was run against a synthetic live master carrying HEVC in MPEG-TS with no audio track, the shape that produced the hang:
| Fixture | Before | After |
|---|---|---|
CODECS="hvc1..." |
25 s in state=loading, verdict logged and unused |
reroutes about a second in, plays |
no CODECS |
same hang, segment head never read | ceiling logged, head read, reroute at ~20 s, plays |
CODECS="avc1..." while carrying HEVC |
hang, nothing able to judge it | terminal .error at 45 s |
Worth knowing before upgrading: a session that used to sit in .loading forever now ends in .error. That is the point of the change, and it is the first case where the bypass raises a failure of its own rather than passing AVPlayer's through.