pub struct PlanarDenoiser { /* private fields */ }Expand description
Wraps the luma and chroma Denoiser instances needed for one
subsampled YUV source.
The caller pushes planar frames in and gets planar frames out. The luma and chroma split is invisible from the outside.
Implementations§
Source§impl PlanarDenoiser
impl PlanarDenoiser
pub fn create(opts: &PlaneOptions, layout: FrameLayout) -> Result<Self, Error>
Sourcepub fn temporal_radius(&self) -> u32
pub fn temporal_radius(&self) -> u32
The temporal radius the underlying denoisers run at.
Sourcepub fn push(&mut self, planes: &Planes) -> Result<(), DenoiserError>
pub fn push(&mut self, planes: &Planes) -> Result<(), DenoiserError>
Pushes one planar frame.
On QueueFull the caller should receive one frame and then retry
the whole call. Any other error is passed on unchanged.
The denoiser push runs before either passthrough queue is touched, so a retry replays the whole frame cleanly instead of queueing the disabled side’s plane twice.
§Why a retry cannot duplicate a frame
In LumaChroma mode luma and chroma are both real
Denoisers with their own queues. A retry pushes again into
whichever half already succeeded, which would duplicate that
half’s frame if the two could ever sit at different fill levels.
They cannot. Both are built from the same opts.mode, so they
share a temporal radius and a MAX_PENDING ceiling. Every
successful push or receive moves both on by exactly one frame,
and a failed push moves neither, because the QueueFull check
runs before anything changes.
So the two halves always enter this function with the same frame
count and the same pending depth, and the QueueFull check
inside push_frame_wire answers the same way for each. If the luma
push succeeds then the chroma push succeeds too, which makes the
duplicate unreachable.
Sourcepub fn recv(&mut self) -> Result<Option<Planes>, Error>
pub fn recv(&mut self) -> Result<Option<Planes>, Error>
Blocks until each enabled half emits one frame, then reassembles them into a planar frame.
Returns Ok(None) if neither half had pending output.
Sourcepub fn flush(&mut self, sink: impl FnMut(Planes)) -> Result<(), Error>
pub fn flush(&mut self, sink: impl FnMut(Planes)) -> Result<(), Error>
Drains the temporal tail of both halves.
sink is called once per emitted planar frame.
Sourcepub fn window_span(&self) -> WindowSpan
pub fn window_span(&self) -> WindowSpan
The number of frames behind and ahead of a target frame a
Self::reseed window must supply, for whichever algorithm this
PlanarDenoiser runs.
Every owned Denoiser was built from the same algorithm, so any
one of them answers for all of them.
Sourcepub fn reseed(&mut self, window: &[Planes]) -> Result<Planes, Error>
pub fn reseed(&mut self, window: &[Planes]) -> Result<Planes, Error>
Denoises the target frame of an explicit window, sized and
shaped exactly as Self::window_span reports for whichever
algorithm this PlanarDenoiser runs.
This abandons whatever stream was running and starts a new one
from the window, keeping every GPU allocation. When it returns,
the stream sits exactly where it would be had the window been
pushed frame by frame, so the caller can carry on with
Self::push and Self::recv for the frame after the target.
Callers clamp the window’s indices at the clip’s ends, matching how the streaming path repeats the first and last frames.
§Why the window is wider than 2r+1 for some algorithms
The two NLM algorithms produce one output per submit once their
own 2r+1-frame window is full, so a symmetric window centred
on the target frame is enough.
nl4d scatters every pass’s contribution across the 2r+1
frames that pass reaches, and a target frame’s own region only
starts collecting contributions once the earliest pass able to
reach it, the one centred r frames behind the target, has
actually run, which itself needs the front end’s own window
full at that earlier centre. Both of those requirements push
the target’s own r-wide neighbourhood back by another r, on
both sides, which is exactly what Self::window_span reports
through nl4d’s doubled behind and ahead. This is bit-exact
with the streaming path because every frame the window supplies
is real, distinct content, run through the same sequence of
passes streaming would have run to reach the target frame.