A cold seek needs a random-access point below its target (#412) - #430
Merged
Conversation
…412) Audio routes packets into segments by plan boundary while video routes them keyframe-gated, so inside a keyframe drought audio opens boundaries the cutter folded and those segments carry no random-access point at all. AVPlayer reaches back a fixed span on a cold seek and does NOT search for one, so where the drought is wider than that reach the picture starts at the next sync sample ABOVE the target and the seek silently skips content. Measured with `play --picture-probe` on a 12 s drought built from `Scripts/timecode-fixture.sh` + `Scripts/mkv-cue-fixture.py`, seeking back from 88 s with the drought cached from a sequential pass and no producer restart: target before after control (cues ARE sync samples) 46.0 46.00 46.00 46.00 50.0 55.00 50.00 50.00 54.0 54.96 54.00 54.00 The control is the same source cut on its real sync samples, where the drought is one segment beginning at its covering IRAP, and it lands exactly on every target. That is the property the fold exists to keep, and the audio cut is what destroys it. The producer now records, per adopted segment, where its first random-access point sits as an offset from the segment's ADVERTISED start, so the claim carries no axis with it. A cold seek asks that of the segment it lands in, and of the ones within reach below it, and re-cuts from the covering point only when nothing down there can open a run at the target. The seek target itself is not moved: measured 3 of 3, AVPlayer puts the re-cut segment at its own tfdt inside the timeline it is already building (`axisErr` 0.000 at offsets of 1, 5 and 9 s), so moving it would land exactly that far past the target instead. For the same reason such an epoch records no axis offset. Two things the issue got wrong, both from reading the extra fetch AVPlayer makes before the target segment as a repair. It is not one: the same reach back happens on the control, where every segment is independent. And the cost is therefore not one extra fetch, it is the landing. Falls back to today's behaviour wherever there is nothing to act on: live, a segment the producer made no claim for, a random-access point already in reach, or a re-cut whose gate does not open within 2 s. 2114 tests green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RbWZLwBVLGM1xUVXa9NeJ1
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.
Closes nothing yet: AE#412 stays open until this is measured on a device.
Audio routes packets into segments by plan boundary while video routes them keyframe-gated, so inside a keyframe drought audio opens boundaries the cutter folded and those segments carry no random-access point at all. AVPlayer reaches back a fixed span on a cold seek and does not search for one, so where the drought is wider than that reach the picture starts at the next sync sample ABOVE the target and the seek silently skips content.
Measured
play --picture-probeon a 12 s drought (Scripts/timecode-fixture.sh+Scripts/mkv-cue-fixture.py), seeking back from 88 s with the drought cached from a sequential pass and no producer restart:The control is the same source cut on its real sync samples, where the drought is one segment beginning at its covering IRAP. That is the property the cutter's fold exists to keep, and the audio cut is what destroys it.
What changed
The producer records, per adopted segment, where its first random-access point sits as an offset from the segment's ADVERTISED start, so the claim carries no axis with it. A cold seek asks that of the segment it lands in and of the ones within reach below it, and re-cuts from the covering point only when nothing down there can open a run at the target.
The seek target itself is not moved: measured 3 of 3, AVPlayer puts the re-cut segment at its own tfdt inside the timeline it is already building (
axisErr0.000 at offsets of 1, 5 and 9 s), so moving it would land exactly that far past the target instead. For the same reason such an epoch records no axis offset.Two corrections to the issue
Both come from reading the extra fetch AVPlayer makes before the target segment as a repair. It is not one: the same reach back happens on the control, where every segment is independent. And the cost is therefore not one extra fetch, it is the landing.
Fallbacks
Today's behaviour wherever there is nothing to act on: live, a segment the producer made no claim for, a random-access point already in reach, or a re-cut whose gate does not open within 2 s.
2114 tests green.
🤖 Generated with Claude Code
https://claude.ai/code/session_01RbWZLwBVLGM1xUVXa9NeJ1