Frame Cache
Playback and scrubbing read decoded frames from one SharedFrameCache (vv-media/src/cache.rs), filled ahead of the playhead by the RenderAhead thread (vv-app/src/render_ahead.rs). The UI thread only reads it and composites; it never decodes.
One cycle

Key properties
| Aspect | Behaviour |
|---|---|
| Key | (MediaId, source frame), so the same frame used by two clips is stored once. |
| Budget | Bytes, not frames (resolutions weigh differently). Default 1.2 GB, configurable in Settings > Playback. |
| Window | 3 s ahead and 2 s behind the playhead by default (minimum 4 frames each), crossing cuts, gaps, tracks and compound clips. Lookahead scales at speeds above 1×. |
| Eviction | Only reconcile evicts, never by recency: during a fill the frame at the playhead is the least recently inserted one. |
| Fill order | Forward window in 15-frame chunks from near to far, then the window behind, also nearest first. Forward always has priority on the budget. |
| Seek vs. decode | A gap larger than about one observed GOP triggers a real seek; the GOP estimate adapts per media. On all-intra proxies the threshold is 1 frame. |
Invalidation
reconcile cannot tell whether a cached frame still comes from the right source, so two cases clear explicitly: clear() when the proxy toggle or quality changes (different resolution), and remove_media when a MediaId now points to another file (relink).
The media pool preview uses a second RenderAhead on a synthetic timeline holding only the browsed media.
No comments to display
No comments to display