fix(vod): open the restart scan-forward gate on keyframe pts and recover a gate starved to EOF#201
Merged
Conversation
…ver a gate starved to EOF (#169) The restart gate compared packet dts against a plan-boundary PTS (segmentPlan[baseIndex].startPts). Under B-frame reorder a keyframe's dts sits a reorder delay below its own pts, so the gate dropped the exact IRAP the restart seeked for (the defect class the #92 cutter fix removed from segment cutting). Mid-file the next IRAP rescued the miss one GOP late; at the file tail there is no next IRAP, so the unbounded VOD gate dropped every remaining packet to EOF and the pump exited with packetsWritten=0 (rrgomes' seg719 trace: dropped=200, lastDts past target, isKey never true). Three layers: - The gate now judges packets by presentation time (videoGateTargetSatisfied, pts with dts fallback), so the anchor IRAP opens its own segment instead of being dropped into the previous one. - A VOD pump that still starves its gate to EOF (no runtime keyframe at or after the targeted plan boundary, the structurally unproducible tail segment) re-anchors production on the segment of the last keyframe the gate dropped, bounded by a #99-shaped revive gate, so the tail content gets produced and end-of-media completes through the tail-park. - The startup readiness gate's data-wait consults pump liveness: production that already exited with nothing served fails over immediately instead of riding 8 rounds (24 s) of false hope behind a message describing the opposite of reality. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NAPCg4tCDdSqkK6tPkNptw
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 (AetherEngine#169, round 3)
rrgomes' 5.19.1 retest showed the forward-wait escalation working (
restarted=trueon every tail miss), but the final segment was never produced by any pump, under any anchoring. The most diagnostic lifecycle: a producer anchored at the tail segment seeks to its advertised start (target=2878501), drops 200 packets waiting for a keyframe, and exits at EOF withpacketsWritten=0.Root cause
The restart scan-forward gate compared packet dts against a plan-boundary PTS (
segmentPlan[baseIndex].startPts, a Cues timestamp). Under B-frame reorder a keyframe's dts sits a reorder delay below its own pts, so the gate dropped the exact IRAP the restart seeked for. This is the same defect class the #92 cutter fix removed from segment cutting; the pregate kept the dts comparison. Mid-file the next IRAP rescues the miss one GOP late (subtle content misalignment); at the file tail there is no next IRAP, so the unbounded VOD gate starved to EOF, matching the trace exactly (dropped=200 lastDts=2880419 isKey=false target=2878501, pumpreason=eof packetsWritten=0).Fix (three layers)
HLSSegmentProducer.videoGateTargetSatisfied): packets are judged by presentation time (dts fallback for NOPTS pts), so the anchor IRAP opens its own segment. Identical behavior for dts==pts sources.shouldReanchorVODAfterGateStarvation+handleVODGateStarvationExit): a VOD pump whose gate starved to EOF proves no runtime keyframe exists at/after the targeted boundary (tail Cues drift or a mis-flagged tail IRAP). The engine re-anchors production on the segment of the last keyframe the gate dropped (bounded, VOD start at resume position with bridged audio (mp3→EAC3) never becomes ready; recovery re-anchor kills the muxer ("Cannot write moov atom before EAC3 packets parsed") with no escalation (#93 residual) #99-shaped gate), so the tail content gets produced and end-of-media completes through the 5.16.2 tail-park instead of dying at -12889 on a structurally unproducible segment.currentProducerFinished, restart-in-flight aware). Production that already exited with nothing served fails over immediately instead of riding 8 rounds (24 s) behind a "still producing over a slow link" message describing the opposite of reality.Verification
Issue169GateStarvationTests(7) +StartupReadinessGateTests(+2), TDD red-to-green-strict-concurrency=completeclean, tvOS Simulator build green🤖 Generated with Claude Code
https://claude.ai/code/session_01NAPCg4tCDdSqkK6tPkNptw