You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while verifying #321 against a synthetic live master. A nativeRemoteHLS session whose item never reaches readyToPlay stays in state = .loading indefinitely: no error, no timeout, and nothing acts on a carriage verdict that has already been settled.
Repro
A live master advertising CODECS="hvc1.1.6.L120.90" whose segments carry HEVC in MPEG-TS, and which has no audio track:
The identical fixture with an AAC track muxed in reaches readyToPlay, the watchdog arms, and the #293 verdict reroutes it within a second. The only difference is whether AVFoundation could build any track.
Why it hangs
Three things compose:
The watchdog is anchored at readyToPlay (NativeAVPlayerHost.startVideoCarriageWatchdog, armed from the .readyToPlay branch). The anchor is deliberate and correct for the grace-based verdict: a dead origin must never be able to fire it. But it also gates the evidence-based verdict, which needs no grace at all.
The bypass has no readiness deadline at all. By design (AetherEngine+Loading.swift, surfaceEndFailures: true): the lean path leaves a dead upstream to AVPlayer's own "gave up" signal. This source is not dead. It serves every segment it is asked for, so AVPlayer neither fails nor becomes ready, and no terminal state is ever published.
The deferred segment-head probe has the same shape: awaitReadyForDeferredProbe waits 20 s (400 x 0.05 s) for a readiness that will not come and then returns without probing, so the one read that could settle the case is skipped precisely when it is needed.
Field relevance
Video-only channels are uncommon but real (camera feeds, some IPTV service channels). The failure is worse than a black picture: the host sees .loading forever, so a retune loop or a user-visible error never triggers. Anything that leaves AVFoundation unable to build a single track lands here, not just HEVC-in-TS.
Direction
Act on a settled transportStreamHEVC verdict when it arrives, rather than only inside a loop that starts at readyToPlay. The evidence is read off the source and does not need the grace.
When the readiness ceiling expires, run the deferred segment-head probe instead of giving up. After 20 s without readiness the mount has demonstrably not settled, so "do not compete with the mount" no longer applies.
Give the bypass a terminal state: a generous readiness budget that ends in .error when nothing became ready and no reroute happened, so an unjudgeable source stops being silent.
Found while verifying #321 against a synthetic live master. A
nativeRemoteHLSsession whose item never reachesreadyToPlaystays instate = .loadingindefinitely: no error, no timeout, and nothing acts on a carriage verdict that has already been settled.Repro
A live master advertising
CODECS="hvc1.1.6.L120.90"whose segments carry HEVC in MPEG-TS, and which has no audio track:The identical fixture with an AAC track muxed in reaches
readyToPlay, the watchdog arms, and the #293 verdict reroutes it within a second. The only difference is whether AVFoundation could build any track.Why it hangs
Three things compose:
readyToPlay(NativeAVPlayerHost.startVideoCarriageWatchdog, armed from the.readyToPlaybranch). The anchor is deliberate and correct for the grace-based verdict: a dead origin must never be able to fire it. But it also gates the evidence-based verdict, which needs no grace at all.hevcInMPEGTS from playlist evidenceis conclusive on its own:CODECSnames an fMP4-only sample type and the media playlist carries noEXT-X-MAP, so AVFoundation will never build a video track for this source. It is recorded incarriageProbeEvidenceand then only ever read by a loop that has not started.AetherEngine+Loading.swift,surfaceEndFailures: true): the lean path leaves a dead upstream to AVPlayer's own "gave up" signal. This source is not dead. It serves every segment it is asked for, so AVPlayer neither fails nor becomes ready, and no terminal state is ever published.The deferred segment-head probe has the same shape:
awaitReadyForDeferredProbewaits 20 s (400 x 0.05 s) for a readiness that will not come and then returns without probing, so the one read that could settle the case is skipped precisely when it is needed.Field relevance
Video-only channels are uncommon but real (camera feeds, some IPTV service channels). The failure is worse than a black picture: the host sees
.loadingforever, so a retune loop or a user-visible error never triggers. Anything that leaves AVFoundation unable to build a single track lands here, not just HEVC-in-TS.Direction
transportStreamHEVCverdict when it arrives, rather than only inside a loop that starts atreadyToPlay. The evidence is read off the source and does not need the grace..errorwhen nothing became ready and no reroute happened, so an unjudgeable source stops being silent.