#[cfg(test)]
mod tests;
use anyhow::{Result, ensure};
use crate::{
analysis::MVAnalysisData,
fake::group_of_planes::FakeGroupOfPlanes,
frame::{FramePlanesMut, FrameView, PlaneSizeTuple},
video::VideoInfo,
};
use super::flow_inter::{FlowInterExtraVectors, FlowInterpolationBase, FlowInterpolationMode};
#[derive(Debug, Clone, Copy)]
pub struct FlowFPSOptions {
pub mask_mode: u8,
pub ml: f64,
}
pub struct FlowFPS {
base: FlowInterpolationBase,
mask_mode: u8,
}
impl FlowFPS {
#[inline]
pub fn new(
info: VideoInfo,
backward_data: MVAnalysisData,
forward_data: MVAnalysisData,
options: FlowFPSOptions,
) -> Result<Self> {
ensure!(
(0..=2).contains(&options.mask_mode),
"FlowFPS: mask must be 0, 1, or 2."
);
ensure!(options.ml > 0.0, "FlowFPS: ml must be greater than 0.");
Ok(Self {
base: FlowInterpolationBase::new(
info,
backward_data,
forward_data,
options.ml,
"FlowFPS",
)?,
mask_mode: options.mask_mode,
})
}
#[inline]
pub fn render_frame<T: crate::util::Pixel>(
&self,
backward: &FrameView<'_, T>,
forward: &FrameView<'_, T>,
output: &mut FramePlanesMut<'_, T>,
output_pitch: PlaneSizeTuple,
backward_vectors: &FakeGroupOfPlanes,
forward_vectors: &FakeGroupOfPlanes,
extra_vectors: Option<FlowInterExtraVectors<'_>>,
time256: i32,
) -> Result<()> {
ensure!(
self.mask_mode == 2 || extra_vectors.is_none(),
"FlowFPS: extra vectors require mask mode 2."
);
let mode = match (self.mask_mode, extra_vectors.is_some()) {
(0, _) => FlowInterpolationMode::Simple,
(1, _) => FlowInterpolationMode::Regular,
(2, true) => FlowInterpolationMode::Extra,
(2, false) => FlowInterpolationMode::Simple,
_ => unreachable!("mask_mode validated in constructor"),
};
self.base.render_frame(
mode,
time256,
backward,
forward,
output,
output_pitch,
backward_vectors,
forward_vectors,
extra_vectors,
)
}
#[inline]
pub fn blend_frame<T: crate::util::Pixel>(
&self,
current: &FrameView<'_, T>,
future: &FrameView<'_, T>,
output: &mut FramePlanesMut<'_, T>,
output_pitch: PlaneSizeTuple,
time256: i32,
) -> Result<()> {
self.base
.blend_frame(time256, current, future, output, output_pitch)
}
}