fn encode_loop<F>(
pool: &FramePool,
controls: &Controls,
settings: &CaptureSettings,
on_frame: &mut F,
)Expand description
Encode thread body: consume captured frames from the pool, keep the [pipeline::X11Pipeline] in
step with the capture size and cross-thread controls, encode, recycle, and deliver.
The loop runs until FramePool::take returns None (stop). For each frame:
- (Re)build the pipeline when it is missing, the frame size changed, or the surface
generation changed. A generation change alone forces the rebuild path because recreated shm
segments often reuse the old virtual base addresses, so encoder state keyed to base pointers
(NVENC’s pinned-host cache) must be dropped even at identical dimensions. An in-place
X11Pipeline::reshapeis preferred — NVENC reconfigures its live session and the CPU path just re-derives its region state — so a resize never stalls on a full encoder re-init; encoders that cannot follow in place (VAAPI) reportfalseand the pipeline is rebuilt. On a rebuild the old pipeline (with its GPU session/surfaces) is dropped BEFORE the new one is built, so an auto-adjust resize never holds two full encoder allocations at once (transient 2x GPU memory). The rebuilt settings pull the CURRENT bitrate / VBV / fps from the controls atomics, carrying live rate changes forward instead of reverting to the capture-start values. - Apply cross-thread controls here, on the thread that owns the pipeline: a pending
force_idrrequests a keyframe; arate_dirtyswap (Acquire, pairing with the setters’ Release stores so the bitrate / VBV / fps payload is never seen half-applied) pushes a live rate change; atunables_dirtyswap applies per-frame tunables into both the local settings copy and the pipeline. - Encode and hand off: read the pooled surface directly through its raw pointer — sound
because the pool guarantees the surface is not reused until it is recycled — run
X11Pipeline::process, recycle the surface BEFORE delivering so a slow consumer never holds a capture surface, then deliver any encoded stripes throughon_frame.
The optional Unix-socket recording sink (parity with the Wayland path) is bound ONCE here and owned outside the pipeline, so pipeline rebuilds on resize keep the socket listener and any attached recorders alive. It can only carry a full-frame video stream, so JPEG output is warned about up front.