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        let cm_time = CMTime {
114            value: 1,
115            #[allow(clippy::cast_possible_wrap)]
116            timescale: fps as i32,
117            flags: 1, // kCMTimeFlags_Valid
118            epoch: 0,
119        };
120        self.set_minimum_frame_interval(&cm_time)
121    }
122
123    /// Set the target frame rate (builder pattern)
124    ///
125    /// See [`set_fps`](Self::set_fps) for details.
126    #[must_use]
127    pub fn with_fps(mut self, fps: u32) -> Self {
128        self.set_fps(fps);
129        self
130    }
131
132    /// Set the capture resolution type (macOS 14.0+)
133    ///
134    /// Controls how the capture resolution is determined.
135    ///
136    /// # Arguments
137    /// * `resolution_type` - The resolution strategy to use
138    ///
139    /// # Examples
140    ///
141    /// ```no_run
142    /// use screencapturekit::stream::configuration::{SCStreamConfiguration, SCCaptureResolutionType};
143    ///
144    /// let config = SCStreamConfiguration::new()
145    ///     .with_capture_resolution_type(SCCaptureResolutionType::Best);
146    /// ```
147    #[cfg(feature = "macos_14_0")]
148    pub fn set_capture_resolution_type(
149        &mut self,
150        resolution_type: SCCaptureResolutionType,
151    ) -> &mut Self {
152        unsafe {
153            crate::ffi::sc_stream_configuration_set_capture_resolution_type(
154                self.as_ptr(),
155                resolution_type as i32,
156            );
157        }
158        self
159    }
160
161    /// Set the capture resolution type (builder pattern, macOS 14.0+)
162    #[cfg(feature = "macos_14_0")]
163    #[must_use]
164    pub fn with_capture_resolution_type(
165        mut self,
166        resolution_type: SCCaptureResolutionType,
167    ) -> Self {
168        self.set_capture_resolution_type(resolution_type);
169        self
170    }
171
172    /// Get the capture resolution type (macOS 14.0+)
173    #[cfg(feature = "macos_14_0")]
174    pub fn capture_resolution_type(&self) -> SCCaptureResolutionType {
175        let value = unsafe {
176            crate::ffi::sc_stream_configuration_get_capture_resolution_type(self.as_ptr())
177        };
178        match value {
179            1 => SCCaptureResolutionType::Best,
180            2 => SCCaptureResolutionType::Nominal,
181            _ => SCCaptureResolutionType::Automatic,
182        }
183    }
184}