screencapturekit/stream/configuration/
captured_frames.rs1use super::internal::SCStreamConfiguration;
2use crate::cm::CMTime;
3#[cfg(feature = "macos_14_0")]
4use crate::error::{SCError, SCResult};
5
6#[cfg(feature = "macos_14_0")]
7use super::SCCaptureResolutionType;
8
9pub const MIN_QUEUE_DEPTH: u32 = 3;
11pub const MAX_QUEUE_DEPTH: u32 = 8;
13
14impl SCStreamConfiguration {
15 pub fn set_queue_depth(&mut self, queue_depth: u32) -> &mut Self {
29 let clamped = queue_depth.clamp(MIN_QUEUE_DEPTH, MAX_QUEUE_DEPTH);
30 #[allow(clippy::cast_possible_wrap)]
32 unsafe {
33 crate::ffi::sc_stream_configuration_set_queue_depth(self.as_ptr(), clamped as isize);
34 }
35 self
36 }
37
38 #[must_use]
42 pub fn with_queue_depth(mut self, queue_depth: u32) -> Self {
43 self.set_queue_depth(queue_depth);
44 self
45 }
46
47 pub fn queue_depth(&self) -> u32 {
49 let raw = unsafe { crate::ffi::sc_stream_configuration_get_queue_depth(self.as_ptr()) };
50 u32::try_from(raw).unwrap_or(0)
51 }
52
53 pub fn set_minimum_frame_interval(&mut self, cm_time: &CMTime) -> &mut Self {
55 unsafe {
56 crate::ffi::sc_stream_configuration_set_minimum_frame_interval(
57 self.as_ptr(),
58 cm_time.value,
59 cm_time.timescale,
60 cm_time.flags,
61 cm_time.epoch,
62 );
63 }
64 self
65 }
66
67 #[must_use]
69 pub fn with_minimum_frame_interval(mut self, cm_time: &CMTime) -> Self {
70 self.set_minimum_frame_interval(cm_time);
71 self
72 }
73
74 pub fn minimum_frame_interval(&self) -> CMTime {
75 unsafe {
76 let mut value: i64 = 0;
77 let mut timescale: i32 = 0;
78 let mut flags: u32 = 0;
79 let mut epoch: i64 = 0;
80
81 crate::ffi::sc_stream_configuration_get_minimum_frame_interval(
82 self.as_ptr(),
83 &raw mut value,
84 &raw mut timescale,
85 &raw mut flags,
86 &raw mut epoch,
87 );
88
89 CMTime {
90 value,
91 timescale,
92 flags,
93 epoch,
94 }
95 }
96 }
97
98 #[allow(clippy::cast_possible_truncation)]
104 pub fn fps(&self) -> u32 {
105 let cm_time = self.minimum_frame_interval();
106 if cm_time.value == 0 || cm_time.timescale == 0 {
107 return 0;
108 }
109 #[allow(clippy::cast_sign_loss)]
110 let fps = (i64::from(cm_time.timescale) / cm_time.value) as u32;
111 fps
112 }
113
114 pub fn set_fps(&mut self, fps: u32) -> &mut Self {
138 let cm_time = if fps == 0 {
139 CMTime::new(0, 1)
140 } else {
141 #[allow(clippy::cast_possible_wrap)]
142 CMTime::new(1, fps as i32)
143 };
144 self.set_minimum_frame_interval(&cm_time)
145 }
146
147 #[must_use]
151 pub fn with_fps(mut self, fps: u32) -> Self {
152 self.set_fps(fps);
153 self
154 }
155
156 #[cfg(feature = "macos_14_0")]
173 #[allow(clippy::missing_errors_doc)]
174 pub fn set_capture_resolution_type(
175 &mut self,
176 resolution_type: SCCaptureResolutionType,
177 ) -> SCResult<&mut Self> {
178 let applied = unsafe {
179 crate::ffi::sc_stream_configuration_set_capture_resolution_type(
180 self.as_ptr(),
181 resolution_type as i32,
182 )
183 };
184 applied.then_some(self).ok_or_else(|| {
185 SCError::feature_not_available("SCStreamConfiguration.captureResolution", "14.0")
186 })
187 }
188
189 #[cfg(feature = "macos_14_0")]
191 #[allow(clippy::missing_errors_doc)]
192 pub fn with_capture_resolution_type(
193 mut self,
194 resolution_type: SCCaptureResolutionType,
195 ) -> SCResult<Self> {
196 self.set_capture_resolution_type(resolution_type)?;
197 Ok(self)
198 }
199
200 #[cfg(feature = "macos_14_0")]
202 #[allow(clippy::missing_errors_doc)]
203 pub fn capture_resolution_type(&self) -> SCResult<SCCaptureResolutionType> {
204 let mut raw = 0_i32;
205 let available = unsafe {
206 crate::ffi::sc_stream_configuration_get_capture_resolution_type(
207 self.as_ptr(),
208 &raw mut raw,
209 )
210 };
211 if !available {
212 return Err(SCError::feature_not_available(
213 "SCStreamConfiguration.captureResolution",
214 "14.0",
215 ));
216 }
217 SCCaptureResolutionType::from_raw(raw).ok_or_else(|| SCError::UnknownValue {
218 type_name: "SCCaptureResolutionType",
219 raw: i64::from(raw),
220 })
221 }
222}
223
224#[cfg(all(test, feature = "macos_14_0"))]
225mod tests {
226 use super::{SCCaptureResolutionType, SCStreamConfiguration};
227
228 #[test]
229 fn bridge_rejects_unknown_capture_resolution_raw_values() {
230 let mut config = SCStreamConfiguration::new();
231 config
232 .set_capture_resolution_type(SCCaptureResolutionType::Nominal)
233 .expect("macOS 14.0 or later");
234 for raw in [3, -1, i32::MAX, i32::MIN] {
235 let applied = unsafe {
236 crate::ffi::sc_stream_configuration_set_capture_resolution_type(
237 config.as_ptr(),
238 raw,
239 )
240 };
241 assert!(!applied, "the bridge accepted raw value {raw}");
242 assert_eq!(
243 config.capture_resolution_type(),
244 Ok(SCCaptureResolutionType::Nominal)
245 );
246 }
247 }
248}