1pub use num_rational::Ratio;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3
4#[derive(Clone, Copy, Debug, Eq, PartialEq)]
5pub enum FrameRate {
6 _24_00,
7 _25_00,
8 _30_00,
9 _50_00,
10 _60_00,
11 _120_00,
12 _23_97,
13 _24_97,
14 _29_97,
15 _59_94,
16 FrCustom(Ratio<u32>),
17}
18
19impl FrameRate {
20 pub fn new(num: u32, den: u32) -> Self {
21 Ratio::new(num, den).into()
22 }
23}
24
25impl From<&FrameRate> for f64 {
26 fn from(frame_rate: &FrameRate) -> Self {
27 let ratio: Ratio<u32> = (*frame_rate).into();
28 *ratio.numer() as f64 / *ratio.denom() as f64
29 }
30}
31
32impl From<FrameRate> for Ratio<u32> {
33 fn from(frame_rate: FrameRate) -> Self {
34 match frame_rate {
35 FrameRate::_24_00 => Self::from_integer(24),
36 FrameRate::_25_00 => Self::from_integer(25),
37 FrameRate::_30_00 => Self::from_integer(30),
38 FrameRate::_50_00 => Self::from_integer(50),
39 FrameRate::_60_00 => Self::from_integer(60),
40 FrameRate::_120_00 => Self::from_integer(120),
41 FrameRate::_23_97 => Self::new(24000, 1001),
42 FrameRate::_24_97 => Self::new(25000, 1001),
43 FrameRate::_29_97 => Self::new(30000, 1001),
44 FrameRate::_59_94 => Self::new(60000, 1001),
45 FrameRate::FrCustom(rational) => rational,
46 }
47 }
48}
49
50impl From<Ratio<u32>> for FrameRate {
51 fn from(rational: Ratio<u32>) -> Self {
52 match (rational.numer(), rational.denom()) {
53 (24, 1) => Self::_24_00,
54 (25, 1) => Self::_25_00,
55 (30, 1) => Self::_30_00,
56 (50, 1) => Self::_50_00,
57 (60, 1) => Self::_60_00,
58 (120, 1) => Self::_120_00,
59 (24000, 1001) => Self::_23_97,
60 (25000, 1001) => Self::_24_97,
61 (30000, 1001) => Self::_29_97,
62 (60000, 1001) => Self::_59_94,
63 _ => Self::FrCustom(rational),
64 }
65 }
66}
67
68#[derive(Serialize, Deserialize)]
69struct SerializeRational {
70 num: u32,
71 den: u32,
72}
73
74impl From<Ratio<u32>> for SerializeRational {
75 fn from(rational: Ratio<u32>) -> Self {
76 Self {
77 num: *rational.numer(),
78 den: *rational.denom(),
79 }
80 }
81}
82
83impl From<SerializeRational> for Ratio<u32> {
84 fn from(serialize_rational: SerializeRational) -> Self {
85 Self::new(serialize_rational.num, serialize_rational.den)
86 }
87}
88
89impl Serialize for FrameRate {
90 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91 where
92 S: Serializer,
93 {
94 SerializeRational::from(Ratio::<u32>::from(*self)).serialize(serializer)
95 }
96}
97
98impl<'de> Deserialize<'de> for FrameRate {
99 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
100 where
101 D: Deserializer<'de>,
102 {
103 Ok(Self::from(Ratio::<u32>::from(
104 SerializeRational::deserialize(deserializer)?,
105 )))
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn rational_from_frame_rate() {
115 assert_eq!(Ratio::from(FrameRate::_24_00), Ratio::from_integer(24));
116 assert_eq!(Ratio::from(FrameRate::_25_00), Ratio::from_integer(25));
117 assert_eq!(Ratio::from(FrameRate::_30_00), Ratio::from_integer(30));
118 assert_eq!(Ratio::from(FrameRate::_50_00), Ratio::from_integer(50));
119 assert_eq!(Ratio::from(FrameRate::_60_00), Ratio::from_integer(60));
120 assert_eq!(Ratio::from(FrameRate::_120_00), Ratio::from_integer(120));
121 assert_eq!(Ratio::from(FrameRate::_23_97), Ratio::new(24000, 1001));
122 assert_eq!(Ratio::from(FrameRate::_24_97), Ratio::new(25000, 1001));
123 assert_eq!(Ratio::from(FrameRate::_29_97), Ratio::new(30000, 1001));
124 assert_eq!(Ratio::from(FrameRate::_59_94), Ratio::new(60000, 1001));
125 let rational_2_3 = Ratio::new(2, 3);
126 let rational_6_9 = Ratio::new(6, 9);
127 assert_eq!(Ratio::from(FrameRate::FrCustom(rational_2_3)), rational_2_3);
128 assert_eq!(Ratio::from(FrameRate::FrCustom(rational_6_9)), rational_2_3);
129 }
130
131 #[test]
132 fn frame_rate_from_rational() {
133 assert_eq!(FrameRate::from(Ratio::from_integer(24)), FrameRate::_24_00);
134 assert_eq!(FrameRate::from(Ratio::from_integer(25)), FrameRate::_25_00);
135 assert_eq!(FrameRate::from(Ratio::from_integer(30)), FrameRate::_30_00);
136 assert_eq!(FrameRate::from(Ratio::from_integer(50)), FrameRate::_50_00);
137 assert_eq!(FrameRate::from(Ratio::from_integer(60)), FrameRate::_60_00);
138 assert_eq!(
139 FrameRate::from(Ratio::from_integer(120)),
140 FrameRate::_120_00
141 );
142 assert_eq!(FrameRate::from(Ratio::new(24000, 1001)), FrameRate::_23_97);
143 assert_eq!(FrameRate::from(Ratio::new(25000, 1001)), FrameRate::_24_97);
144 assert_eq!(FrameRate::from(Ratio::new(30000, 1001)), FrameRate::_29_97);
145 assert_eq!(FrameRate::from(Ratio::new(60000, 1001)), FrameRate::_59_94);
146 let rational_2_3 = Ratio::new(2, 3);
147 let rational_6_9 = Ratio::new(6, 9);
148 assert_eq!(
149 FrameRate::from(rational_2_3),
150 FrameRate::FrCustom(rational_2_3)
151 );
152 assert_eq!(
153 FrameRate::from(rational_2_3),
154 FrameRate::FrCustom(rational_6_9)
155 );
156 assert_eq!(FrameRate::from(Ratio::new(200, 4)), FrameRate::_50_00);
157 }
158
159 #[test]
160 fn serialize() {
161 assert_eq!(
162 serde_json::to_value(FrameRate::_24_00).unwrap(),
163 serde_json::json!({
164 "num": 24,
165 "den": 1
166 })
167 );
168 assert_eq!(
169 serde_json::to_value(FrameRate::_25_00).unwrap(),
170 serde_json::json!({
171 "num": 25,
172 "den": 1
173 })
174 );
175 assert_eq!(
176 serde_json::to_value(FrameRate::_30_00).unwrap(),
177 serde_json::json!({
178 "num": 30,
179 "den": 1
180 })
181 );
182 assert_eq!(
183 serde_json::to_value(FrameRate::_50_00).unwrap(),
184 serde_json::json!({
185 "num": 50,
186 "den": 1
187 })
188 );
189 assert_eq!(
190 serde_json::to_value(FrameRate::_60_00).unwrap(),
191 serde_json::json!({
192 "num": 60,
193 "den": 1
194 })
195 );
196 assert_eq!(
197 serde_json::to_value(FrameRate::_120_00).unwrap(),
198 serde_json::json!({
199 "num": 120,
200 "den": 1
201 })
202 );
203 assert_eq!(
204 serde_json::to_value(FrameRate::_23_97).unwrap(),
205 serde_json::json!({
206 "num": 24000,
207 "den": 1001
208 })
209 );
210 assert_eq!(
211 serde_json::to_value(FrameRate::_24_97).unwrap(),
212 serde_json::json!({
213 "num": 25000,
214 "den": 1001
215 })
216 );
217 assert_eq!(
218 serde_json::to_value(FrameRate::_29_97).unwrap(),
219 serde_json::json!({
220 "num": 30000,
221 "den": 1001
222 })
223 );
224 assert_eq!(
225 serde_json::to_value(FrameRate::_59_94).unwrap(),
226 serde_json::json!({
227 "num": 60000,
228 "den": 1001
229 })
230 );
231 assert_eq!(
232 serde_json::to_value(FrameRate::FrCustom(Ratio::new(2, 3))).unwrap(),
233 serde_json::json!({
234 "num": 2,
235 "den": 3
236 })
237 );
238 assert_eq!(
239 serde_json::to_value(FrameRate::FrCustom(Ratio::new(6, 9))).unwrap(),
240 serde_json::json!({
241 "num": 2,
242 "den": 3
243 })
244 );
245 }
246
247 #[test]
248 fn deserialize() {
249 assert_eq!(
250 serde_json::from_value::<FrameRate>(serde_json::json!({
251 "num": 24,
252 "den": 1
253 }))
254 .unwrap(),
255 FrameRate::_24_00
256 );
257 assert_eq!(
258 serde_json::from_value::<FrameRate>(serde_json::json!({
259 "num": 25,
260 "den": 1
261 }))
262 .unwrap(),
263 FrameRate::_25_00
264 );
265 assert_eq!(
266 serde_json::from_value::<FrameRate>(serde_json::json!({
267 "num": 30,
268 "den": 1
269 }))
270 .unwrap(),
271 FrameRate::_30_00
272 );
273 assert_eq!(
274 serde_json::from_value::<FrameRate>(serde_json::json!({
275 "num": 50,
276 "den": 1
277 }))
278 .unwrap(),
279 FrameRate::_50_00
280 );
281 assert_eq!(
282 serde_json::from_value::<FrameRate>(serde_json::json!({
283 "num": 60,
284 "den": 1
285 }))
286 .unwrap(),
287 FrameRate::_60_00
288 );
289 assert_eq!(
290 serde_json::from_value::<FrameRate>(serde_json::json!({
291 "num": 120,
292 "den": 1
293 }))
294 .unwrap(),
295 FrameRate::_120_00
296 );
297 assert_eq!(
298 serde_json::from_value::<FrameRate>(serde_json::json!({
299 "num": 24000,
300 "den": 1001
301 }))
302 .unwrap(),
303 FrameRate::_23_97
304 );
305 assert_eq!(
306 serde_json::from_value::<FrameRate>(serde_json::json!({
307 "num": 25000,
308 "den": 1001
309 }))
310 .unwrap(),
311 FrameRate::_24_97
312 );
313 assert_eq!(
314 serde_json::from_value::<FrameRate>(serde_json::json!({
315 "num": 30000,
316 "den": 1001
317 }))
318 .unwrap(),
319 FrameRate::_29_97
320 );
321 assert_eq!(
322 serde_json::from_value::<FrameRate>(serde_json::json!({
323 "num": 60000,
324 "den": 1001
325 }))
326 .unwrap(),
327 FrameRate::_59_94
328 );
329 assert_eq!(
330 serde_json::from_value::<FrameRate>(serde_json::json!({
331 "num": 2,
332 "den": 3
333 }))
334 .unwrap(),
335 FrameRate::FrCustom(Ratio::new(2, 3))
336 );
337 assert_eq!(
338 serde_json::from_value::<FrameRate>(serde_json::json!({
339 "num": 6,
340 "den": 9
341 }))
342 .unwrap(),
343 FrameRate::FrCustom(Ratio::new(2, 3))
344 );
345 assert_eq!(
346 serde_json::from_value::<FrameRate>(serde_json::json!({
347 "num": 200,
348 "den": 4
349 }))
350 .unwrap(),
351 FrameRate::_50_00
352 );
353 }
354}