1use num_traits::ToPrimitive;
4use vapoursynth4_rs::{
5 ffi::VSColorFamily,
6 frame::{VideoFormat, VideoFrame},
7 node::VideoNode,
8 SampleType, VideoInfo,
9};
10
11use crate::enums::ColorRange;
12
13pub trait HoldsVideoFormat: Sized {
15 #[must_use]
17 fn video_format(&self) -> &VideoFormat;
18
19 #[must_use]
21 fn color_family(&self) -> VSColorFamily {
22 self.video_format().color_family
23 }
24
25 #[must_use]
27 fn depth(&self) -> i32 {
28 self.video_format().bits_per_sample
29 }
30
31 #[must_use]
33 fn sample_type(&self) -> SampleType {
34 self.video_format().sample_type
35 }
36
37 #[must_use]
39 fn lowest_value(&self, chroma: Option<bool>, range_in: Option<ColorRange>) -> f32 {
40 let chroma = chroma.unwrap_or(false);
41 let range_in = range_in.unwrap_or(ColorRange::Full);
42
43 if self.sample_type() == SampleType::Float {
44 return if chroma { -0.5 } else { 0.0 };
45 }
46
47 if range_in == ColorRange::Limited {
48 return (16 << (self.depth() - 8))
49 .to_f32()
50 .expect("result should fit in a f32");
51 }
52
53 0.0
54 }
55
56 #[must_use]
58 fn neutral_value(&self) -> f32 {
59 if self.sample_type() == SampleType::Float {
60 return 0.0;
61 }
62
63 (1 << (self.depth() - 1))
64 .to_f32()
65 .expect("result should fit in a f32")
66 }
67
68 #[must_use]
70 fn peak_value(&self, chroma: Option<bool>, range_in: Option<ColorRange>) -> f32 {
71 let chroma = chroma.unwrap_or(false);
72 let range_in = range_in.unwrap_or(ColorRange::Full);
73
74 if self.sample_type() == SampleType::Float {
75 return if chroma { 0.5 } else { 1.0 };
76 }
77
78 if range_in == ColorRange::Limited {
79 return (if chroma { 240 } else { 235 } << (self.depth() - 8))
80 .to_f32()
81 .expect("result should fit in a f32");
82 }
83
84 ((1 << self.depth()) - 1)
85 .to_f32()
86 .expect("result should fit in a f32")
87 }
88}
89
90impl HoldsVideoFormat for VideoFrame {
91 fn video_format(&self) -> &VideoFormat {
92 self.get_video_format()
93 }
94}
95
96impl HoldsVideoFormat for VideoFormat {
97 fn video_format(&self) -> &VideoFormat {
98 self
99 }
100}
101
102impl HoldsVideoFormat for VideoInfo {
103 fn video_format(&self) -> &VideoFormat {
104 &self.format
105 }
106}
107
108impl HoldsVideoFormat for VideoNode {
109 fn video_format(&self) -> &VideoFormat {
110 self.info().video_format()
111 }
112}