Skip to main content

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

cache-cycle.png

Key properties

AspectBehaviour
Key(MediaId, source frame), so the same frame used by two clips is stored once.
BudgetBytes, not frames (resolutions weigh differently). Default 1.2 GB, configurable in Settings > Playback.
Window3 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×.
EvictionOnly reconcile evicts, never by recency: during a fill the frame at the playhead is the least recently inserted one.
Fill orderForward 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. decodeA 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.