Skip to main content

screencapturekit/stream/configuration/
captured_frames.rs

1use super::internal::SCStreamConfiguration;
2use crate::cm::CMTime;
3
4#[cfg(feature = "macos_14_0")]
5use super::SCCaptureResolutionType;
6
7impl SCStreamConfiguration {
8    /// Set the queue depth for frame buffering
9    pub fn set_queue_depth(&mut self, queue_depth: u32) -> &mut Self {
10        // FFI expects isize; u32 may wrap on 32-bit platforms (acceptable)
11        #[allow(clippy::cast_possible_wrap)]
12        unsafe {
13            crate::ffi::sc_stream_configuration_set_queue_depth(
14                self.as_ptr(),
15                queue_depth as isize,
16            );
17        }
18        self
19    }
20
21    /// Set the queue depth (builder pattern)
22    #[must_use]
23    pub fn with_queue_depth(mut self, queue_depth: u32) -> Self {
24        self.set_queue_depth(queue_depth);
25        self
26    }
27
28    pub fn queue_depth(&self) -> u32 {
29        // FFI returns isize but queue depth is always positive and fits in u32
30        #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
31        unsafe {
32            crate::ffi::sc_stream_configuration_get_queue_depth(self.as_ptr()) as u32
33        }
34    }
35
36    /// Set the minimum frame interval
37    pub fn set_minimum_frame_interval(&mut self, cm_time: &CMTime) -> &mut Self {
38        unsafe {
39            crate::ffi::sc_stream_configuration_set_minimum_frame_interval(
40                self.as_ptr(),
41                cm_time.value,
42                cm_time.timescale,
43                cm_time.flags,
44                cm_time.epoch,
45            );
46        }
47        self
48    }
49
50    /// Set the minimum frame interval (builder pattern)
51    #[must_use]
52    pub fn with_minimum_frame_interval(mut self, cm_time: &CMTime) -> Self {
53        self.set_minimum_frame_interval(cm_time);
54        self
55    }
56
57    pub fn minimum_frame_interval(&self) -> CMTime {
58        unsafe {
59            let mut value: i64 = 0;
60            let mut timescale: i32 = 0;
61            let mut flags: u32 = 0;
62            let mut epoch: i64 = 0;
63
64            crate::ffi::sc_stream_configuration_get_minimum_frame_interval(
65                self.as_ptr(),
66                &mut value,
67                &mut timescale,
68                &mut flags,
69                &mut epoch,
70            );
71
72            CMTime {
73                value,
74                timescale,
75                flags,
76                epoch,
77            }
78        }
79    }
80
81    /// Get the target frame rate in frames per second
82    ///
83    /// Converts the minimum frame interval (`CMTime`) to FPS.
84    /// Returns 0 if the frame interval is invalid.
85    #[allow(clippy::cast_possible_truncation)]
86    pub fn fps(&self) -> u32 {
87        let cm_time = self.minimum_frame_interval();
88        if cm_time.value == 0 {
89            return 0;
90        }
91        #[allow(clippy::cast_sign_loss)]
92        let fps = (i64::from(cm_time.timescale) / cm_time.value) as u32;
93        fps
94    }
95
96    /// Set the target frame rate in frames per second
97    ///
98    /// This is a convenience method that creates the appropriate `CMTime` for the given FPS.
99    /// For example, 60 FPS creates a frame interval of 1/60 second.
100    ///
101    /// # Arguments
102    /// * `fps` - Target frames per second (e.g., 30, 60, 120)
103    ///
104    /// # Examples
105    ///
106    /// ```no_run
107    /// use screencapturekit::stream::configuration::SCStreamConfiguration;
108    ///
109    /// let config = SCStreamConfiguration::new()
110    ///     .with_fps(60);
111    /// ```
112    pub fn set_fps(&mut self, fps: u32) -> &mut Self {
113        #[allow(clippy::cast_possible_wrap)]
114        let cm_time = CMTime::new(1, fps as i32);
115        self.set_minimum_frame_interval(&cm_time)
116    }
117
118    /// Set the target frame rate (builder pattern)
119    ///
120    /// See [`set_fps`](Self::set_fps) for details.
121    #[must_use]
122    pub fn with_fps(mut self, fps: u32) -> Self {
123        self.set_fps(fps);
124        self
125    }
126
127    /// Set the capture resolution type (macOS 14.0+)
128    ///
129    /// Controls how the capture resolution is determined.
130    ///
131    /// # Arguments
132    /// * `resolution_type` - The resolution strategy to use
133    ///
134    /// # Examples
135    ///
136    /// ```no_run
137    /// use screencapturekit::stream::configuration::{SCStreamConfiguration, SCCaptureResolutionType};
138    ///
139    /// let config = SCStreamConfiguration::new()
140    ///     .with_capture_resolution_type(SCCaptureResolutionType::Best);
141    /// ```
142    #[cfg(feature = "macos_14_0")]
143    pub fn set_capture_resolution_type(
144        &mut self,
145        resolution_type: SCCaptureResolutionType,
146    ) -> &mut Self {
147        unsafe {
148            crate::ffi::sc_stream_configuration_set_capture_resolution_type(
149                self.as_ptr(),
150                resolution_type as i32,
151            );
152        }
153        self
154    }
155
156    /// Set the capture resolution type (builder pattern, macOS 14.0+)
157    #[cfg(feature = "macos_14_0")]
158    #[must_use]
159    pub fn with_capture_resolution_type(
160        mut self,
161        resolution_type: SCCaptureResolutionType,
162    ) -> Self {
163        self.set_capture_resolution_type(resolution_type);
164        self
165    }
166
167    /// Get the capture resolution type (macOS 14.0+)
168    #[cfg(feature = "macos_14_0")]
169    pub fn capture_resolution_type(&self) -> SCCaptureResolutionType {
170        let value = unsafe {
171            crate::ffi::sc_stream_configuration_get_capture_resolution_type(self.as_ptr())
172        };
173        match value {
174            1 => SCCaptureResolutionType::Best,
175            2 => SCCaptureResolutionType::Nominal,
176            _ => SCCaptureResolutionType::Automatic,
177        }
178    }
179}