Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deferred export frame generator — ED.20

The optical printer was the lab's export stage: a camera and a projector locked together, re-photographing the cut negative one frame at a time onto fresh stock, honoring every splice and speed change as it advanced. ED.20 is that printer in software. Given an EditProject, the ExportFrameGenerator walks the project frames 0..project_duration and, for each, prints the right source frame onto the output.

flowchart LR
  F["project frame f"] --> ST["source_time(f)\n(trim · split · speed)"]
  ST --> DEC["EditorVideoStream.frame\n(seek + decode)"]
  DEC --> COMP["EditorPreview.render_frame\n(same compose as preview)"]
  COMP --> OUT["ExportFrame { bgra, pts, source_frame }"]
  OUT --> ENC["encoder (ED.21)"]

The key is that the timeline edits are already baked into the frame selection: source_time maps each project frame to its source frame, so a trimmed clip starts later, a split is invisible (two segments, one continuous source walk), and a 2× segment advances the source twice as fast. The generator composes through the same EditorPreview path the live preview uses, so the exported file matches the cut you scrubbed. Each ExportFrame carries a PTS computed with the same formula the live recorder's encoder feed uses, so timestamps line up when ED.21 hands the stream to the encoder.

Forward-only — the decoder never re-spawns

Project frames are visited in order, and the edit ops never reorder the timeline, so the source frames the generator requests are monotonic non-decreasing. EditorVideoStream only re-spawns its decode pipeline on a backward seek — so a full export is a single forward decode pass. The golden test asserts spawn_count() == 1 after generating every frame of a trim-plus-speed project, locking that invariant in (a regression that reorders or seeks backward would trip it immediately).

Frame selection now; visual transforms next

This chunk nails the frame-accurate timeline walk — trim, split, and speed are all honored, verified deterministically without a GPU-visual check. The cinematic visual edits (zoom punch-ins, crop reframe, background framing) apply as a transform on the composed screen sprite; that render-integration step lands next, where the crop-then-zoom NDC math gets the visual verification a headless golden frame can't provide.