Repository navigation
perf(editor): halve seek latency and stop seeks showing frames from the wrong GOP - #2603
Closed
richiemcilroy wants to merge 3 commits into
Closed
richiemcilroy wants to merge 3 commits into
richiemcilroy wants to merge 3 commits into
Conversation
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
richiemcilroy
force-pushed
the
perf/editor-seek-exact-keyframe
branch
from
October 15, 2026 03:53
264c014 to
18f8d40
Compare
richiemcilroy
changed the base branch from
main
to
fix/export-camera-frame-runaway
October 15, 2026 03:53
Member
Author
|
@greptileai review |
Member
Author
|
Superseded by #2638 (merged), which fixes the same decoder request handling with the suite's oracle proof. |
This branch was successfully deployed
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.
Seeking in the macOS editor took 40-300 ms to show a frame, and could show a different frame than playback or export would show at that time. There were two causes, both in the AVAssetReader decode path.
Stacked on #2595 (
fix/export-camera-frame-runaway). The reset rule here is decided per request from the decoder's cache and its pts-hole map. #2595 changes how that hole map is kept when it fills up and how long IOSurface sources are held, and the broad reset below is only correct with #2595's hole map underneath. Onmainalone, camera playback of a 180 s recording also drifts ahead after about 35 s (fixed by #2595), so seek answers cannot be scored againstmain's own sequential render. Merge #2595 first; this PR then retargets tomainwith no conflicts.Readers started just before the keyframe
compute_seek_timepicks the keyframe at or before the request, but the reader was then created withcm::Time::with_secs(time, 100), which rounds to 10 ms. About half the time that lands a fraction of a tick before the keyframe. AVAssetReader then starts decoding at the previous sync sample, decodes and discards that whole GOP (~25 frames at 3K), and vends its last frame retimed to the start. The preview could therefore show a frame from the previous GOP under the keyframe's frame number.KeyframeIndexkeeps the streamtime_base, andreader_start_timestarts every reader on the keyframe's exact tick.A reused decoder could answer from an unrelated seek
After scattered seeks, the decoder chosen for a request could answer with the newest cached frame at or before it, even when that frame was left over from an earlier, unrelated seek. In one run a request for frame 1899 showed frame 948.
flowchart LR Q[request frame N] --> S[select_best_decoder] S --> C{newest cached frame <= N<br/>was vended in this reader's<br/>current run?} C -- yes --> A[answer from cache / keep decoding] C -- no, or nothing cached <= N --> R[reset the reader at N's keyframe]DecoderInstancetracksrun_start, the first frame of its current uninterrupted vend run (crates/rendering/src/decoder/avassetreader.rs).reuse_would_serve_stale_frameforces a reset when the newest cached frame at or before the request predates that run, or when nothing at or before the request is cached at all. The second case covers returning into a pts hole whose held frame was evicted by a distant seek: the reader has already passed the request, so reusing it could only answer with a later frame.Benchmark
Seek to rendered frame through
FrameRenderer(decode + render at 1248x702), M4 Max, #2595 head (905e093) vs this PR on top of it. Warm-seek p50, same harness, both builds run back to back on a machine shared with other builds, so treat single numbers as ±20%:Frames rendered right after a seek are unchanged (p50 3.8-4.9 ms on both).
cap-renderingandcap-video-decodetests, renders sequential playback byte-identically, and answers the shuffled and random seek sets on the 60s and 180s fixtures with no wrong frames.

Confidence Score: 5/5
This PR appears safe to merge after #2595.Summary
This PR starts macOS readers on exact keyframe ticks and resets reused readers when their cached earlier frame is missing or predates the current run.
Reviews (2) · Last reviewed commit: "fix(rendering): reset a reused decoder w..." · Reviewed by Greptile