av_denoise/nlmeans/prefilter/
mod.rs1mod bilateral;
2
3pub use bilateral::bilateral_radius;
4pub(crate) use bilateral::inv_two_sigma_sq;
5use cubecl::prelude::*;
6use cubecl::server::Handle;
7
8#[non_exhaustive]
15#[derive(Debug, Default, Clone, Copy, PartialEq)]
16pub enum PrefilterMode {
17 #[default]
18 None,
19 External,
20 Bilateral {
21 sigma_s: f32,
22 sigma_r: f32,
23 },
24 NlmSpatial {
29 strength_scale: f32,
31 },
32}
33
34pub const DEFAULT_PILOT_STRENGTH_SCALE: f32 = 0.4;
39
40impl PrefilterMode {
41 pub(crate) fn needs_reference_buf(self) -> bool {
43 !matches!(self, Self::None)
44 }
45
46 pub(crate) fn is_gpu_internal(self) -> bool {
49 matches!(self, Self::Bilateral { .. } | Self::NlmSpatial { .. })
50 }
51}
52
53pub(crate) struct PrefilterCtx<'a> {
57 pub width: u32,
58 pub height: u32,
59 pub channels: u32,
60 pub stored_ch: u32,
61 pub frame_count: u32,
62 pub frame: u32,
63 pub input_buf: &'a Handle,
64 pub reference_buf: &'a Handle,
65}
66
67pub(crate) fn run_prefilter<R: Runtime>(
70 mode: PrefilterMode,
71 client: &ComputeClient<R>,
72 ctx: &PrefilterCtx<'_>,
73) -> Result<(), anyhow::Error> {
74 match mode {
75 PrefilterMode::None | PrefilterMode::External => Ok(()),
76 PrefilterMode::NlmSpatial { .. } => Ok(()),
81 PrefilterMode::Bilateral { sigma_s, sigma_r } => {
82 bilateral::run_bilateral::<R>(client, ctx, sigma_s, sigma_r)
83 },
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn none_requires_no_reference_buffer() {
93 assert!(!PrefilterMode::None.needs_reference_buf());
94 assert!(!PrefilterMode::None.is_gpu_internal());
95 }
96
97 #[test]
98 fn external_needs_buffer_but_not_gpu() {
99 assert!(PrefilterMode::External.needs_reference_buf());
100 assert!(!PrefilterMode::External.is_gpu_internal());
101 }
102
103 #[test]
104 fn bilateral_is_gpu_internal() {
105 let m = PrefilterMode::Bilateral {
106 sigma_s: 3.0,
107 sigma_r: 0.02,
108 };
109
110 assert!(m.needs_reference_buf());
111 assert!(m.is_gpu_internal());
112 }
113
114 #[test]
115 fn nlm_spatial_is_gpu_internal() {
116 let m = PrefilterMode::NlmSpatial { strength_scale: 1.0 };
117
118 assert!(m.needs_reference_buf());
119 assert!(m.is_gpu_internal());
120 }
121
122 #[test]
123 fn bilateral_radius_truncates_at_two_sigma() {
124 assert_eq!(bilateral_radius(0.1), 1);
125 assert_eq!(bilateral_radius(1.0), 2);
126 assert_eq!(bilateral_radius(3.0), 6);
127 assert_eq!(bilateral_radius(3.5), 7);
128 }
129}