Expand description
Frame-processing policy shared by the X11 and Wayland backends. Frame-processing policy shared by the two capture backends. It lives in its own module for one reason: the Wayland path (dmabuf, compositor damage) and the X11 path (host-ARGB, stripe-hash damage) capture pixels in completely different ways, but a viewer must never be able to tell which one produced a frame — a paint-over refresh or a recovery keyframe has to behave identically either way. Keeping the decision logic here, source-agnostic, is what guarantees it.
Structs§
- Encoder
Quality - What an encoder says about the frames it codes, which the cleanup reads: the quality index
its rate control last coded a frame at, where it reports one (
FrameEncoder::last_quality), the bytes of that frame, where it reports them too (FrameEncoder::last_size), whether it holds a frame at a quantizer it is asked for (FrameEncoder::holds_quantizer), whether a change of its constant quality re-opens it on a key frame (FrameEncoder::reopens_on_quality), whether its constant-rate cleanup ends on a key frame (FrameEncoder::cleans_up_with_key), where it holds a band of a frame at that quantizer (FrameEncoder::band_size), the bytes of its last held frame, where it measures a frame’s reconstruction against its source when asked (FrameEncoder::measures), the last measurement, and where it took its last frame back for coming out past its cap and coded it again (FrameEncoder::refit), how far that frame’s held band then reached, or 0 for a frame of its rate control’s. - HwFrame
Decision - Outcome of the full-frame send decision produced by
decide_hw_fullframe. - X11Pipeline
- Everything the X11 host-ARGB path has to remember between frames.
Enums§
- Cleanup
- What the cleanup policy decided for one region’s frame.
- Convergence
- Where a rate control that the cleanup runs through stands after its last frame, of
bytesat quality indexlast, against the paint-over quantizer andbudgetbytes a frame. - Damage
- How much of a frame changed since the frame before it, as far as its capture can tell.
Constants§
- BAND_
BUDGETS 🔒 - CLEANUP_
FRAME_ 🔒S - Seconds of a link at the cleanup’s rate a cleanup’s frame may take to cross it (
cleanup_cap): the session’s buffer at 8 fps, under the backpressure gate’s allowance. - CLEANUP_
RATE_ 🔒MAX - The most a cleanup runs at, in multiples of the session’s rate (
cleanup_rate): a sweep at 8 fps and 500 kbps over a fast path codes bands of two to six budgets. - CONVERGED_
SHARE 🔒 - A constant-rate cleanup that runs through the rate control keeps the frames flowing until the rate control codes the region at the paint-over quantizer or finer in a frame under this share of the frame budget: it has nothing left to refine.
- CONVERGE_
S 🔒 - Seconds a constant-rate cleanup through the rate control flows at most.
- DAMAGE_
BAND_ 🔒ROWS - Rows per band of the content hash a full-frame X11 session reads its damage from: one band is
under
SMALL_AREAof a screen from 720 rows up, so a caret or a clock reads as the small change it is. - EMPTY_S 🔒
- Seconds of such frames after which a constant-rate cleanup through x264 ends: x264 keeps its
quantizer on a screen that does not change, and at 0.1 Mbit/s refines one in frames as far
as 2.4 s apart. A session that holds no quantizer and measures nothing ends the same way
once its frames at its coarsest have kept the size of the one before as long
(
SAME_FRAME_SHARE). - EMPTY_
SLICE_ 🔒BYTES - Bytes a slice that refines nothing comes to at most: a frame of x264’s four slices skipping every block takes 61 to 66 at 720p and 1080p with the wire header, a third of the budget at 0.1 Mbit/s, so never a small frame.
- FIRST_
BAND 🔒 - Where the encoder holds a band of the picture (
EncoderQuality::band), the refresh that falls back from a constant-rate cleanup sweeps the picture a band a frame in raster order, the firstFIRST_BANDof it and each next sized from the bytes of the last toBAND_BUDGETSframe budgets, so the stream keeps its rate: a whole refresh at the paint-over quantizer is 86 budgets of text at 2 Mbit/s at 1080p and queues for 240 ms on a 12 Mbit/s link. - KEY_
CLEANUP_ 🔒MASS - The change since the last key-frame cleanup, in screens, past which a region still for
KEY_STILL_TRIGGERStrigger periods is cleaned up by a key frame. - KEY_
STILL_ 🔒TRIGGERS - The trigger periods a region holds still before its key-frame cleanup.
- LEAST_
BAND 🔒 - The least share of the picture a band covers. A band that small costs next to nothing, so a held frame of one that comes out past its budget is the rest of the frame’s cost.
- LEVEL_S 🔒
- Seconds the finest quantizer such a session has coded the still screen at stands before its
rate control counts as done with the picture, where the session says its quantizer and does
not measure: at 0.25 Mbit/s at 1080p x265 takes a step finer every 2 to 8 s for a tenth of
a dB a second, and libvpx’s VP9 one every 6 s after its first ten, each for all of
REFINE_Sat the full rate, where at 2 Mbit/s x265 takes one every 2 s for its first twenty. - LOW_
MOTION_ 🔒SHARE - LOW_
MOTION_ 🔒TRIGGERS - A region that keeps changing is still due a cleanup once this many trigger periods passed
since it first changed, where at most a quarter of its frames carry more than a small change,
on an average over as many frames (
StripeState::motion), so the motion that went before (a scroll) ages out of it while a caret blinks. - OVERSHOOT_
BUDGETS 🔒 - Frame budgets the rate control’s frames of a still screen exceed for a trigger period when it is pinned at its coarsest quantizer, refining nothing within the rate: NVENC’s H.264 codes a still screen of texture at 0.1 Mbit/s at 1080p in 3.3 kB frames, 16 budgets, at quantizer 51, where at 2 Mbit/s single frames after a change reach 4.5 budgets.
- PLATEAU_
CHECKS 🔒 - PLATEAU_
GAIN_ 🔒DB - PLATEAU_
TRIGGERS 🔒 - Trigger periods between two measurements of a picture a constant-rate cleanup is refining
(
FrameEncoder::last_psnr), the gain in dB under which one finds the picture level with the one before, and the level measurements in a row after which the rate control is done with it. A rate control that has a whole screen of dense text to refine at 2 Mbit/s at 1080p gains 0.2 dB a second at first, coding a few blocks of it a frame, and one that is done with a screen under 0.06. - REFINE_
S 🔒 - The same for a session that holds no quantizer but says the one it codes at or measures its pictures, which has no refresh to fall back to and ends its cleanup at the paint-over quantizer or once the picture stops improving: at 2 Mbit/s at 1080p x265’s rate control refines a screen of text by 0.7 dB a second, still short of that quality after ten. A band sweep runs this long at most too.
- SAME_
FRAME_ 🔒QUALITY - SAME_
FRAME_ 🔒SHARE - The share of the frame before it within which a frame of a still screen codes nothing new, and the quality index from which its rate control sits at its coarsest: at 0.1 Mbit/s at 1080p libvpx’s VP9 frames are 266 bytes each at index 51, or 220-221 at 46-47, and x265’s 224 at 50-51, its strict constant rate padding them with filler, while the picture stays level, so never small against the 208-byte budget. From 1 Mbit/s their rate controls code a still screen at 36 and finer, x265’s padded frames again of one size while it refines.
- SMALL_
AREA 🔒 - A change covering at most this fraction of the frame is small: it does not count as motion toward the low-motion cleanup.
- STALL_
TRIGGERS 🔒 - Trigger periods of such small frames at a quantizer still coarser than the paint-over one after which the rate control counts as stalled: it stopped refining short of the paint-over quality, as NVENC’s does at 2 Mbit/s at 1080p.
- SWEEP_
FINER_ 🔒SHARE - The share of a sweep’s frames left that the rest of the picture may take at a quantizer step finer before the sweep steps finer: room for the bands’ cost to vary down the picture.
- UNKNOWN_
MASS 🔒 - How much of a screen a change of unknown extent counts for toward a key-frame cleanup, from the third frame of a run of changed frames on: sustained motion, where an isolated change (a caret, a clock, a keystroke) counts for nothing.
- UNKNOWN_
RUN 🔒
Functions§
- band_
damage 🔒 - The damage a band hash (
hash_bands) reads: the fraction of the bands that changed. No bands read yet, before a capture’s first hash, is all new. - band_
rects 🔒 - The rows a band hash (
hash_bands) found changed in awidthxheightframe, as full-width rectangles, one per run of changed bands: the CPU path’s dirty map. No bands read yet is the whole frame. - band_
share 🔒 - The share of the picture the next band of a sweep covers, after one of
sizewhose held frame came out atbytes(FIRST_BANDonward):BAND_BUDGETSofbudget, at most doubling or halving a frame. - cleanup_
cap 🔒 - The bytes a constant-rate cleanup’s frame may come to: the session’s own buffer, what its rate
control holds a frame to, or
CLEANUP_FRAME_Sof the cleanup’s rate (cleanup_rate) where that is more. A still screen’s frames past what the path carries queue on it, where congestion control reads them as the path falling behind; at 60 fps and 500 kbps NVENC’s rate control refines a 1080p page a budget a frame, and now and then mispredicts one at fifty. - cleanup_
due - The still-screen cleanup of one region (a whole frame, or a stripe): track how long and how
much it has been changing, and say when it is due a cleanup and of which kind.
keysfalse (JPEG, whose every stripe is a picture of its own, and a constant-rate session cleaned up through its rate control) never answersCleanup::Key. - cleanup_
frames 🔒 converge_framesfor the sessionencoderdescribes (REFINE_S).- cleanup_
pending - Whether
cleanup_duewould answer a cleanup for a frame that changed nothing, without moving the bookkeeping: what an idle frame has to know before it skips a region. - cleanup_
rate - The rate (kbps) a constant-rate cleanup’s sweep is paced to and its frames capped by: what the
path carries (
CaptureSettings::video_link_kbps), never under the session’s rate nor overCLEANUP_RATE_MAXtimes it, and the session’s rate where the path’s is not known. A still screen’s refresh at the paint-over quantizer is many seconds of a low rate (1080p text at 500 kbps, 20 s), which a path faster than the stream carries at once and one near its rate only at that rate. - converge_
frames - Frames a constant-rate cleanup through the rate control flows at most (
CONVERGE_S). - convergence
- Where the rate control stands (
Convergence). - cpu_
list 🔒 - A kernel CPU list (“0-3,32-35”) as a set.
- decide_
constant_ 🔒quality decide_hw_fullframefor a constant-quality session: the cleanup moves the session’s own quality to the paint-over one, as main’s paint-over did, rather than holding a frame at a quantizer. Each encoder then codes the cleanup the way it codes any frame at that quality: x264’s and x265’s rate factor give a key frame their intra offset (about three steps finer than the paint-over index), SVT-AV1 its key-frame qindex, and the encoders whose quality change re-opens the session (x265, SVT-AV1, kvazaar) open on a key frame at it. A frame held at the paint-over quantizer itself came out coarser than main’s (SVT-AV1 49.6 against 61.0 dB, x264 53.7 against 56.5 dB).- decide_
constant_ 🔒rate decide_hw_fullframefor a constant-rate session,recovery_idrthe key frame a consumer asked for or the schedule’s.- decide_
hw_ fullframe - The send / quality / keyframe policy every full-frame encoder obeys. A constant-quality
session takes
decide_constant_quality; what follows is the constant-rate one. - due_
cleanup 🔒 - The cleanup a region is due with
stillframes held still,uncleanframes since it first changed after its last cleanup, andmotionthe share of its recent frames in motion. - frame_
budget - Bytes a frame of the constant-rate target, at
kbpsandfps. - hash_
bands 🔒 - Which bands of
DAMAGE_BAND_ROWSrows of a host frame (stridebytes per row,heightrows) changed against the frame before, read from a content hash per band (StripeState::content_dirty, one state per band inbands, with its damage blocks). The bands hash in turn on the calling thread: a band takes tens of microseconds, less than waking the rayon pool for it costs, which on a many-core host spent several times the hash in CPU and added milliseconds waiting on the slowest worker. - hash_
beside 🔒 - Run
encodeon this thread while a thread of its own hashes the frame’s bands (hash_bands), and return whatencodereturned with the bands that changed: a Turbo frame’s hash kept off its encode’s path. A scoped thread per frame rather than the rayon pool, whose idle workers spin after every wake; where no thread starts, the hash runs here after the encode. The thread keeps to the CPUs sharing this one’s last-level cache (share_cache_with). - hash_
damage 🔒 - The damage of a host frame against the one before it, from its band hash (
hash_bands). - hashed_
bands 🔒 - The bands that changed by hashes taken where the frame was uploaded (
hash_next_upload), read through each band’s state as the CPU’s own hashes are (StripeState::hash_dirty). - hashed_
damage 🔒 - The damage of a frame whose bands were hashed where it lies (NvFBC’s, on the GPU) against the
hashes of the frame before, which
lastkeeps: the share of the bands that changed. No hashes before is all new. - held_
refresh_ quality - The quality index a refresh held in one frame (a predicted frame) is coded at: the paint-over
one, or, where a constant rate last coded far coarser, as much finer than that as
HELD_KEY_BUDGET_Sof the target allows at six steps a doubling, since a refresh of a whole screen at the paint-over quantizer after heavy motion at a low rate would cost many frames of budget at once. The bands of the sweep a cleanup through the rate control falls back to, each sized to a frame’s budget, are coded at the paint-over quantizer instead: counted from the rate control’s last quantizer, which a key frame after a loss leaves at the coarsest, the sweep ended up to 13 dB short of it at 8 fps. - last_
cache_ 🔒cpus - The CPUs sharing
cpu’s last-level cache, the highest level its sysfs cache entries list. - paint_
over_ improves - Whether a cleanup improves the picture at all: at a constant quality where the paint-over
quality is finer than the session’s (the cleanup then moves the session’s quality, see
decide_constant_quality); at a constant rate where it is finer than the quality index the rate control last coded at, less the steps its frames need to come to the paint-over quality (EncoderQuality::finer), or the encoder does not say. A rate control that has already refined a still screen past it (a constant rate refines every frame it sends) is left alone: holding the paint-over quantizer there would coarsen the picture. A constant-rate encoder that holds no quantizer is cleaned up by the rate control’s own frames, a refresh and its burst, which it refines; a key frame there would come out at the rate control’s quantizer, which a small buffer starves. - periodic_
idr_ due - Whether a scheduled keyframe is due this tick.
- plan_
refinement - The block ledger’s part of a full-frame decision
d(ledger): take this frame’s change intost’s ledger, from where the source says it changed (changed, in the frame’s coordinates, read with whether the region’s hash saw it change,StripeState::hash_changed, throughBlockLedger::frame_reported), or the whole frame where the source cannot say anddamagesays something changed; and where the frame goes at the session’s own quality while the region moves, on a session that refines (refines, how:ledger::Refiner) with the cleanup armed, name the blocks it refines, the offset taken from the quality index the rate control last coded at (last) where a rate binds the session (bound,FrameEncoder::rate_bound), paced against the frame budget (ledger::RefinePace), or from the session’s own at a constant quality no peak binds. A capped constant quality its peak let go codes again the blocks it coded while bound that held still since, so many a frame at its own quality (BlockLedger::refresh,ledger::RefreshPace), the rest held as skips, sending a still screen’s frames for it, and first, at the paint-over quality, the blocks owed it (BlockLedger::refresh_owed): a cleanup it spent under the binding peak, or one falling due on blocks it has yet to refresh or refreshed at its own quality, which it takes in place of that cleanup’s frame; it refines nothing on those frames and waits while the peak binds again. - plateau 🔒
- One frame of a cleanup that measures the picture it is refining, where the encoder can
(
FrameEncoder::measure): whether this frame is to be measured, one everyperiod, and whether the measurement of the last such frame,psnr, was thePLATEAU_CHECKSth in a row to gain less thanPLATEAU_GAIN_DBon the one before, the rate control having nothing left to give the picture. - recent_
motion 🔒 - The share of a region’s recent frames that carried more than a small change,
motiontaking in one more frame: an average overLOW_MOTION_TRIGGERStrigger periods. - refine_
frames - Frames a constant-rate cleanup through a rate control that says its quantizer flows at most,
with no refresh to fall back to (
REFINE_S). - refinement_
coded - What a full-frame frame decided as
dleft inst’s ledger once coded inbytes, the encoder now reportingquality: its refined blocks are clean where the rate control’s quality index put them at the target (BlockLedger::refinement_coded) and, where a rate binds the session (bound, asplan_refinementtakes it), the pace follows the rate control (RefinePace); a frame held whole at the paint-over quality, or the region’s cleanup having run its course, cleans the region, and a key frame at the rate control’s own leaves it unclean. A frame coded under a capped constant quality’s binding peak (capped,FrameEncoder::coded_capped) leaves the blocks it coded coarse and cleans nothing; one coded without it takes the blocks it refreshed (HwFrameDecision::refresh) off the coarse ones and paces the refresh against the peak’s frame budget (ledger::RefreshPace), where it came out at all (bytesabove 0). The last block owed the paint-over (BlockLedger::spent,plan_refinement) refreshed, the cleanup falls due again. - refresh_
quality 🔒 held_refresh_qualityfrom a rate control’s last frame ofspentframe budgets rather than one: a rate control pinned at its coarsest quantizer (OVERSHOOT_BUDGETS) refreshed in one held frame, which then costs that much more.- refresh_
start - The still frames a refresh after the region moved waits for (
cleanup_due’sstart): a refresh through the rate control (converges) is that rate control’s own frames, each within its budget, so it starts on the first still frame, where waitingtriggerframes only left the picture as the motion did; a refresh held at the paint-over quantizer waits for the screen to stay still. A region that changed only a little (a caret, a keystroke) waitstriggereither way, or a caret blinking on a clean screen would send every frame. - share_
cache_ 🔒with - Keep this thread to the CPUs it may run on that share
cpu’s last-level cache. - start_
sweep 🔒 - Start a refresh sweep at the top of the picture: its first band in this frame at
qp, the rest a band a frame after it (FIRST_BAND,band_share). - sweep_
refresh 🔒 - A refresh due on a session that sweeps it (
decide_hw_fullframe’ssweeps): a sweep from the top, or, with one under way, which is already refreshing the picture, nothing held, the frame going at the rate control’s quality: a sweep started over at every change of a blinking caret would never cover the picture, and a whole held frame is what the sweep spreads.