ndi_sdk_sys/
subsampling.rs1use std::fmt::Debug;
6use std::fmt::Display;
7
8#[derive(Clone, Copy, Hash, PartialEq, Eq)]
14pub struct Subsampling {
15 pub x_ref: u8,
16 pub x_samples: u8,
17 pub x2_samples: u8,
18}
19
20impl Display for Subsampling {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 write!(f, "{}:{}:{}", self.x_ref, self.x_samples, self.x2_samples)
23 }
24}
25
26impl Debug for Subsampling {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 write!(
29 f,
30 "Subsampling({}:{}:{})",
31 self.x_ref, self.x_samples, self.x2_samples
32 )
33 }
34}
35
36impl Subsampling {
37 pub const fn new(x_ref: u8, x_samples: u8, x2_samples: u8) -> Self {
38 Subsampling {
39 x_ref,
40 x_samples,
41 x2_samples,
42 }
43 }
44
45 pub const fn none() -> Self {
47 Subsampling {
48 x_ref: 4,
49 x_samples: 4,
50 x2_samples: 4,
51 }
52 }
53
54 pub const fn is_subsampled(&self) -> bool {
55 self.x_ref != self.x_samples || self.x_ref != self.x2_samples
56 }
57
58 pub const fn is_regular(&self) -> bool {
60 if self.x_ref == 0 {
61 return false;
62 }
63
64 if self.x_samples > self.x_ref || self.x2_samples > self.x_samples {
65 return false;
66 }
67
68 self.x_ref.is_multiple_of(self.x_samples) && self.x2_samples.is_multiple_of(self.x_samples)
69 }
70
71 pub fn x_grouping(&self) -> u8 {
77 assert!(
78 self.is_regular(),
79 "Subsampling must be regular to get x grouping"
80 );
81
82 self.x_ref / self.x_samples
83 }
84
85 pub fn y_grouping(&self) -> u8 {
91 assert!(
92 self.is_regular(),
93 "Subsampling must be regular to get y grouping"
94 );
95
96 if self.x2_samples == 0 {
97 2
98 } else if self.x_samples == self.x2_samples {
99 1
100 } else {
101 panic!(
102 "Subsampling is not regular, cannot determine y grouping: {}",
103 self
104 )
105 }
106 }
107}
108
109impl Default for Subsampling {
110 fn default() -> Self {
111 Self {
112 x_ref: 4,
113 x_samples: 4,
114 x2_samples: 4,
115 }
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::Subsampling;
122
123 #[test]
124 fn no_subsampling() {
125 let not_subsampled = Subsampling::new(4, 4, 4);
126 assert!(!not_subsampled.is_subsampled());
127 assert!(not_subsampled.is_regular());
128 assert_eq!(not_subsampled.x_grouping(), 1);
129 assert_eq!(not_subsampled.y_grouping(), 1);
130 }
131
132 #[test]
133 fn subsampling_4_2_2() {
134 let subsampled = Subsampling::new(4, 2, 2);
135 assert!(subsampled.is_subsampled());
136 assert!(subsampled.is_regular());
137 assert_eq!(subsampled.x_grouping(), 2);
138 assert_eq!(subsampled.y_grouping(), 1);
139 }
140
141 #[test]
142 fn subsampling_4_2_0() {
143 let subsampled = Subsampling::new(4, 2, 0);
144 assert!(subsampled.is_subsampled());
145 assert!(subsampled.is_regular());
146 assert_eq!(subsampled.x_grouping(), 2);
147 assert_eq!(subsampled.y_grouping(), 2);
148 }
149
150 #[test]
151 fn subsampling_4_1_1() {
152 let subsampled = Subsampling::new(4, 1, 1);
153 assert!(subsampled.is_subsampled());
154 assert!(subsampled.is_regular());
155 assert_eq!(subsampled.x_grouping(), 4);
156 assert_eq!(subsampled.y_grouping(), 1);
157 }
158
159 #[test]
160 fn subsampling_4_4_0() {
161 let subsampled = Subsampling::new(4, 4, 0);
162 assert!(subsampled.is_subsampled());
163 assert!(subsampled.is_regular());
164 assert_eq!(subsampled.x_grouping(), 1);
165 assert_eq!(subsampled.y_grouping(), 2);
166 }
167
168 #[test]
169 fn irregular_subsampling() {
170 let irregular = Subsampling::new(4, 3, 2);
171 assert!(irregular.is_subsampled());
172 assert!(!irregular.is_regular());
173 }
174
175 #[test]
176 fn zero_reference() {
177 let zero_ref = Subsampling::new(0, 0, 0);
178 assert!(!zero_ref.is_regular());
179 }
180}