* Disk cache: stamp footage files for the salt off the UI thread
Importing an After Effects project whose footage includes long image
sequences on a network share froze the desktop app for 15-27 s. The
import itself takes about 0.25 s; the time went into the edit's bump(),
where refresh_disk_salt() stats every footage file (13,466 sequence
frames in the measured project, ~15 s) on the UI thread whenever a disk
cache is attached. File > Open and footage reload hit the same path.
With Session::disk_salt_background (set by the desktop app) the salt is
taken on a worker thread and picked up by poll_disk_salt() from the UI
tick. Until it lands the layer cache runs memory-only, so keys under the
old salt (other files, or another project's items) are never read. A
newer footage change supersedes a salt still being taken. Headless
sessions keep taking it synchronously.
A settings change that keeps the disk cache folder no longer re-stamps
every footage file either.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Disk cache: opening a project drops the footage salt being taken
A salt job still running for the old project was kept when the new project named the
same footage, so the salt stamped before the files changed stayed in use.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Session::crypto_coverage returns the coverage of one Cryptomatte ID over the layer, read from
the probe Session::crypto_probe_job keeps: at most max_side samples on the long side, each at
the centre of its cell, or None until the probe is built. It is what the Cryptomatte
eyedropper's hover highlight will draw.
Tests cover the coverage of an ID from the kept probe and the cost of a highlight with six
ranks.
The pool learned that an effect reads a footage item's channels only at the
first aux() call, so the first frame was decoded twice (picture, then in
full), and the hint was never cleared after the effect was removed.
The session now gives the footage source the whole set of files read by
enabled 3D Channel effects (FootageSource::set_aux_footage) with every
project change (Session::bump: edits, undo, redo, history jumps, rollbacks,
project open), sending it only when it changed. The pool keeps that set and,
as a safety net, what aux() learns; a new set drops what was learned.
Refs #474
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the Interpret Footage form against main's split into
interpret_footage_form and project_settings_form, keeping the Cineon
Settings fields and the pointUnits readback. Restore the Arc, rayon
prelude and cineon_frame imports that main's explicit use lists dropped.
effect.cryptomatteAt rendered the effect's input on every call to learn its pixel grid (up
to ~1 s per hover on a 3D precomp). The aux channels and that grid are now kept in a
CryptoProbe on the Session, keyed by the project revision, layer, effect, frame, scale and
render prefs (nested switches, draft shadows). On footage with nothing animated before the
Cryptomatte effect the frame is the source frame, so a still or a held frame keeps one
probe for every comp time. The effect's own Selection doesn't count: the probe never reads
it, so an animated Selection keeps the probe too.
Session::crypto_probe_ready says whether a query answers from the kept probe and changes
nothing. Session::crypto_probe_job builds it on another thread for the viewer; asking for a
job is starting it. Each started job has a generation: it stores its result only while it
is the newest, a newer job or an edit cancels it, and a panic in the build becomes the
probe's error. A cancelled build checks its generation between its stages (reading the IDs,
rendering the effect's input), so it stops early and lets go of what it read. `probeOnly`
makes cryptomatteAt / pickCryptomatte answer {pending} instead of building on the caller.
A pick re-keys the probe (it only edits the Selection), and undo, redo and history jumps
over picks keep it too (each pick is labelled "Pick Cryptomatte"). Any other edit, footage
changes, Open / New and Session::drop_crypto_probe (the eyedropper disarmed) let it go. The
slot's type is crate-private (the Session field stays public, doc(hidden), so other crates
can still build a Session); crypto_probe_stats and crypto_probe_jobs (jobs run, cancelled
ones included) are doc(hidden), for tests.