more_fps/
frame_generator.rs1use 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 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}