zoomvtools/filters/
flow_fps.rs1#[cfg(test)]
2mod tests;
3
4use anyhow::{Result, ensure};
5
6use crate::{
7 analysis::MVAnalysisData,
8 fake::group_of_planes::FakeGroupOfPlanes,
9 frame::{FramePlanesMut, FrameView, PlaneSizeTuple},
10 video::VideoInfo,
11};
12
13use super::flow_inter::{FlowInterExtraVectors, FlowInterpolationBase, FlowInterpolationMode};
14
15#[derive(Debug, Clone, Copy)]
17pub struct FlowFPSOptions {
18 pub mask_mode: u8,
20 pub ml: f64,
22}
23
24pub struct FlowFPS {
26 base: FlowInterpolationBase,
27 mask_mode: u8,
28}
29
30impl FlowFPS {
31 #[inline]
36 pub fn new(
37 info: VideoInfo,
38 backward_data: MVAnalysisData,
39 forward_data: MVAnalysisData,
40 options: FlowFPSOptions,
41 ) -> Result<Self> {
42 ensure!(
43 (0..=2).contains(&options.mask_mode),
44 "FlowFPS: mask must be 0, 1, or 2."
45 );
46 ensure!(options.ml > 0.0, "FlowFPS: ml must be greater than 0.");
47
48 Ok(Self {
49 base: FlowInterpolationBase::new(
50 info,
51 backward_data,
52 forward_data,
53 options.ml,
54 "FlowFPS",
55 )?,
56 mask_mode: options.mask_mode,
57 })
58 }
59
60 #[inline]
68 pub fn render_frame<T: crate::util::Pixel>(
69 &self,
70 backward: &FrameView<'_, T>,
71 forward: &FrameView<'_, T>,
72 output: &mut FramePlanesMut<'_, T>,
73 output_pitch: PlaneSizeTuple,
74 backward_vectors: &FakeGroupOfPlanes,
75 forward_vectors: &FakeGroupOfPlanes,
76 extra_vectors: Option<FlowInterExtraVectors<'_>>,
77 time256: i32,
78 ) -> Result<()> {
79 ensure!(
80 self.mask_mode == 2 || extra_vectors.is_none(),
81 "FlowFPS: extra vectors require mask mode 2."
82 );
83
84 let mode = match (self.mask_mode, extra_vectors.is_some()) {
85 (0, _) => FlowInterpolationMode::Simple,
86 (1, _) => FlowInterpolationMode::Regular,
87 (2, true) => FlowInterpolationMode::Extra,
88 (2, false) => FlowInterpolationMode::Simple,
89 _ => unreachable!("mask_mode validated in constructor"),
90 };
91
92 self.base.render_frame(
93 mode,
94 time256,
95 backward,
96 forward,
97 output,
98 output_pitch,
99 backward_vectors,
100 forward_vectors,
101 extra_vectors,
102 )
103 }
104
105 #[inline]
110 pub fn blend_frame<T: crate::util::Pixel>(
111 &self,
112 current: &FrameView<'_, T>,
113 future: &FrameView<'_, T>,
114 output: &mut FramePlanesMut<'_, T>,
115 output_pitch: PlaneSizeTuple,
116 time256: i32,
117 ) -> Result<()> {
118 self.base
119 .blend_frame(time256, current, future, output, output_pitch)
120 }
121}