vapoursynth/
video_info.rs

1//! Video clip formats.
2
3use std::fmt::Debug;
4use std::ops::Deref;
5
6use vapoursynth_sys as ffi;
7
8use crate::format::Format;
9
10/// Represents video resolution.
11#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
12pub struct Resolution {
13    /// Width of the clip, greater than 0.
14    pub width: usize,
15
16    /// Height of the clip, greater than 0.
17    pub height: usize,
18}
19
20/// Represents video framerate.
21#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
22pub struct Framerate {
23    /// FPS numerator, greater than 0.
24    pub numerator: u64,
25
26    /// FPS denominator, greater than 0.
27    pub denominator: u64,
28}
29
30/// Represents a property that can be either constant or variable, like the resolution or the
31/// framerate.
32#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
33pub enum Property<T: Debug + Clone + Copy + Eq + PartialEq> {
34    /// This property is variable.
35    Variable,
36
37    /// This property is constant.
38    Constant(T),
39}
40
41/// Contains information about a video clip.
42#[derive(Debug, Copy, Clone)]
43pub struct VideoInfo<'core> {
44    /// Format of the clip.
45    pub format: Format<'core>,
46
47    /// Framerate of the clip.
48    pub framerate: Property<Framerate>,
49
50    /// Resolution of the clip.
51    pub resolution: Property<Resolution>,
52
53    /// Length of the clip, greater than 0.
54    pub num_frames: usize,
55}
56
57impl<'core> VideoInfo<'core> {
58    /// Creates a `VideoInfo` from a raw pointer.
59    ///
60    /// # Safety
61    /// The caller must ensure `ptr` and the lifetime is valid.
62    pub(crate) unsafe fn from_ptr(ptr: *const ffi::VSVideoInfo) -> Self {
63        let info = unsafe { &*ptr };
64
65        debug_assert!(info.fpsNum >= 0);
66        debug_assert!(info.fpsDen >= 0);
67        debug_assert!(info.width >= 0);
68        debug_assert!(info.height >= 0);
69        debug_assert!(info.numFrames >= 0);
70
71        let format = unsafe { Format::from_ptr(&info.format) };
72
73        let framerate = if info.fpsNum == 0 {
74            debug_assert!(info.fpsDen == 0);
75            Property::Variable
76        } else {
77            debug_assert!(info.fpsDen != 0);
78            Property::Constant(Framerate {
79                numerator: info.fpsNum as _,
80                denominator: info.fpsDen as _,
81            })
82        };
83
84        let resolution = if info.width == 0 {
85            debug_assert!(info.height == 0);
86            Property::Variable
87        } else {
88            debug_assert!(info.height != 0);
89            Property::Constant(Resolution {
90                width: info.width as _,
91                height: info.height as _,
92            })
93        };
94
95        let num_frames = {
96            debug_assert!(info.numFrames != 0);
97            info.numFrames as _
98        };
99
100        Self {
101            format,
102            framerate,
103            resolution,
104            num_frames,
105        }
106    }
107
108    /// Converts the Rust struct into a C struct.
109    pub(crate) fn ffi_type(self) -> ffi::VSVideoInfo {
110        let format = self.format.deref();
111
112        let (fps_num, fps_den) = match self.framerate {
113            Property::Variable => (0, 0),
114            Property::Constant(Framerate {
115                numerator,
116                denominator,
117            }) => (numerator as i64, denominator as i64),
118        };
119
120        let (width, height) = match self.resolution {
121            Property::Variable => (0, 0),
122            Property::Constant(Resolution { width, height }) => (width as i32, height as i32),
123        };
124
125        let num_frames = self.num_frames as i32;
126
127        ffi::VSVideoInfo {
128            format: *format,
129            fpsNum: fps_num,
130            fpsDen: fps_den,
131            width,
132            height,
133            numFrames: num_frames,
134        }
135    }
136}
137
138impl<T> From<T> for Property<T>
139where
140    T: Debug + Clone + Copy + Eq + PartialEq,
141{
142    #[inline]
143    fn from(x: T) -> Self {
144        Property::Constant(x)
145    }
146}