more_fps/
frame_generator.rs

1use crate::command;
2use crate::Error;
3use crate::NonZeroDecimal;
4use crate::FPS;
5use rust_decimal::Decimal;
6use std::fs;
7use std::path::Path;
8use std::path::PathBuf;
9
10#[derive(Debug)]
11pub struct FrameGenerator<'a> {
12    pub binary: &'a Path,
13    pub model: &'a Path,
14    pub fps: FPS,
15    pub input_dir: &'a Path,
16    pub output_dir: &'a PathBuf,
17    pub extra_args: &'a str,
18}
19
20impl<'a> FrameGenerator<'a> {
21    pub fn clear_output_dir(&self) -> Result<(), Error> {
22        if self.output_dir.exists() {
23            fs::remove_dir_all(self.output_dir)?;
24            fs::create_dir_all(self.output_dir)?;
25        }
26        Ok(())
27    }
28    pub fn execute(&self, duration: NonZeroDecimal) -> Result<&Path, Error> {
29        self.clear_output_dir()?;
30
31        let frame_count = self.frame_count(duration)?;
32        let args = format!(
33            "-m {} -i {} -o {} -n {frame_count} {}",
34            self.model.display(),
35            self.input_dir.display(),
36            self.output_dir.display(),
37            self.extra_args
38        );
39        command::run(
40            &self.binary.display().to_string(),
41            args.as_str().try_into()?,
42            Error::AICommand,
43        )?;
44        Ok(self.output_dir)
45    }
46
47    /// the frame count for ai binary to target
48    /// denoted as the -n flag
49    /// While this function does always return a `NonZeroDecimal`, we need a `Decimal` to `Display` in
50    /// `execute`. So there's no point in returning a `NonZeroDecimal`
51    fn frame_count(&self, duration: NonZeroDecimal) -> Result<Decimal, Error> {
52        let fps = *NonZeroDecimal::try_new(self.fps.non_zero_usize().get())
53            .ok_or(Error::BadFPS(self.fps.non_zero_usize()))?;
54
55        let frame_count = fps
56            .checked_mul(*duration)
57            .ok_or(Error::MultiplicationOverflow(
58                fps.to_string(),
59                duration.to_string(),
60            ))?
61            .round_dp(0);
62
63        Ok(frame_count)
64    }
65}