an.engines.capture#
The capture loop: drive a session through every frame, resolve, write – for ANY engine.
Moved out of the stage renderer (an/adapters/cutout/render.py’s
_capture_frames and _capture_frames_canvas, an#247) and generalised over
the session members of an.engines.protocol. The algorithms are the ones
the stage shipped, unchanged, because the decoded frames are the contract (the
golden corpus and the canvas equivalence gate compare them):
Sequential (a session without
frames): per frame,frame(t)for each instant; a frame of ONE instant at supersample 1 with noresolvemember is written as the engine’s own bytes – nothing decoded, so off is free – and anything else goes through the resolve.Batched (a session with
frames(requests)): the requests go out in frame order, samples in the order given, at mostbatchframes andbatch_pixelscaptured pixels per round trip (a frame whose instants alone exceed it is split over round trips and resolved once); the resolve runs on a small thread pool while the engine draws the next batch, with BACK-PRESSURE – at mostmax_inflightframes (and twice the pixel budget) wait on the pool, after which the loop blocks on the oldest before asking for more.
The resolve runs here, in the frame stage, before a file is written:
supersampling (an.media.supersample, an exact block mean) and the open
shutter (an.media.shutter, an exact temporal mean). Nothing downstream
reads a resolution off a file or averages anything; an ffmpeg -vf scale is
refused for the reasons in an-dev-render-pipeline §2. A session’s own
resolve member replaces the default resolve (the stage’s canvas session
refuses non-opaque pixels there); the default is
an.media.shutter.mean_png_bytes().
Two corruptions are silent unless refused, so both are refused: a dropped or
reordered frame (every file is named by its frame number, and every frame
0..N-1 must exist on disk before the loop returns), and unbounded buffering
(the bounds above).
**The bench’s supersample lever rebinds** capture_frames() **on this
module** to force the product’s own factor, so an.engines.frame_stage
calls it as a module attribute, at call time.
Module Attributes
Frames per round trip of a batched session. |
|
Threads resolving and encoding frames while the engine draws the next batch. |
|
a supersample counts k² times, an open shutter once per instant): at most this many per round trip, twice this many waiting on the pool. |
|
frames handed to the pool and not yet written. |
Functions
|
Write one PNG per request into |
|
The core's resolve: spatially by |
Exceptions
The frame stage could not produce a frame directory it can vouch for. |
- an.engines.capture.DEFAULT_BATCH: int = 8#
Frames per round trip of a batched session. Measured on the stage at 1920x1080 on an M1 Max: 67 ms/frame one frame per call, 46 at four, 46 at eight – the round trip is ~20 ms of fixed cost, amortised by the batch.
- an.engines.capture.DEFAULT_BATCH_PIXELS: int = 4147200#
a supersample counts k² times, an open shutter once per instant): at most this many per round trip, twice this many waiting on the pool. A frame COUNT bounds nothing when a frame is a k-times, many-sample, incompressible canvas (an#192 review: one reply overflowed the driver’s string limit and the render hung).
- Type:
The same two bounds in CAPTURED PIXELS (backbuffer pixels
- an.engines.capture.DEFAULT_ENCODE_WORKERS: int = 2#
Threads resolving and encoding frames while the engine draws the next batch. The stage’s decode/encode is ~60 ms/frame of Pillow at 1080p, the same order as the page’s own work, so it must overlap it. Two, not
cpu_count(): a parallel render already runs one engine per shot.
- an.engines.capture.DEFAULT_MAX_INFLIGHT: int = 16#
frames handed to the pool and not yet written.
- Type:
BACK-PRESSURE
- exception an.engines.capture.FrameStageError[source]#
Bases:
RuntimeErrorThe frame stage could not produce a frame directory it can vouch for.
A renderer built by
frame_stage_renderer(..., error=...)re-raises it as its own typed error at its boundary.
- an.engines.capture.capture_frames(session, requests, frames_dir, *, factor=1, size=None, batch=None, workers=None, max_inflight=None, batch_pixels=None)[source]#
Write one PNG per request into
frames_dir, resolved to the declared size.sessionis time-driven (frame(t)), optionally batched (frames(requests)), optionally with its ownresolve. A state-driven session is adapted by the frame stage before it reaches here.size, when known, sets the pixel budget and is passed to the resolve.Nonefor any tunable reads the module default at call time.- Return type: