Skip to main content

screencapturekit/cm/
ffi.rs

1//! Raw FFI bindings for Core Media types.
2//!
3//! These are low-level bindings and are not intended for direct use.
4#![allow(missing_docs)]
5
6extern "C" {
7    pub fn cm_sample_buffer_get_frame_status(
8        sample_buffer: *mut std::ffi::c_void,
9        status: *mut i32,
10    ) -> bool;
11
12    /// Build a retained `CGImage` from the sample buffer's image buffer via
13    /// `VTCreateCGImageFromCVPixelBuffer`. Returns null on failure with
14    /// `out_status` set to the underlying `OSStatus` (0 = `noErr` on success).
15    pub fn cm_sample_buffer_create_cg_image(
16        sample_buffer: *mut std::ffi::c_void,
17        out_status: *mut i32,
18    ) -> *const std::ffi::c_void;
19
20    // Frame info accessors
21    pub fn cm_sample_buffer_get_display_time(
22        sample_buffer: *mut std::ffi::c_void,
23        out_value: *mut u64,
24    ) -> bool;
25    pub fn cm_sample_buffer_get_scale_factor(
26        sample_buffer: *mut std::ffi::c_void,
27        out_value: *mut f64,
28    ) -> bool;
29    pub fn cm_sample_buffer_get_content_scale(
30        sample_buffer: *mut std::ffi::c_void,
31        out_value: *mut f64,
32    ) -> bool;
33    pub fn cm_sample_buffer_get_content_rect(
34        sample_buffer: *mut std::ffi::c_void,
35        out_x: *mut f64,
36        out_y: *mut f64,
37        out_width: *mut f64,
38        out_height: *mut f64,
39    ) -> bool;
40    pub fn cm_sample_buffer_get_bounding_rect(
41        sample_buffer: *mut std::ffi::c_void,
42        out_x: *mut f64,
43        out_y: *mut f64,
44        out_width: *mut f64,
45        out_height: *mut f64,
46    ) -> bool;
47    pub fn cm_sample_buffer_get_screen_rect(
48        sample_buffer: *mut std::ffi::c_void,
49        out_x: *mut f64,
50        out_y: *mut f64,
51        out_width: *mut f64,
52        out_height: *mut f64,
53    ) -> bool;
54    #[cfg(feature = "macos_14_2")]
55    pub fn cm_sample_buffer_get_presenter_overlay_content_rect(
56        sample_buffer: *mut std::ffi::c_void,
57        out_x: *mut f64,
58        out_y: *mut f64,
59        out_width: *mut f64,
60        out_height: *mut f64,
61    ) -> bool;
62    pub fn cm_sample_buffer_get_dirty_rects(
63        sample_buffer: *mut std::ffi::c_void,
64        out_rects: *mut *mut std::ffi::c_void,
65        out_count: *mut usize,
66    ) -> bool;
67    pub fn cm_sample_buffer_free_dirty_rects(rects_ptr: *mut std::ffi::c_void);
68
69    /// Single-call frame attachment fetch — populates `out_fields` with bits
70    /// for each successfully-read field. See `FrameInfoFields` for the bit
71    /// layout. Replaces the per-attribute accessors above for the hot path
72    /// (one attachment-array fetch + one CF→Swift bridge cast vs. one per
73    /// field), measured at ~4× faster when reading multiple fields per frame.
74    ///
75    /// When the `DIRTY_RECTS` bit is set, `out_dirty_rects` receives a
76    /// bridge-allocated `[x, y, w, h] * out_dirty_rects_count` array that the
77    /// caller must hand back via `cm_sample_buffer_free_dirty_rects`.
78    pub fn cm_sample_buffer_get_frame_info(
79        sample_buffer: *mut std::ffi::c_void,
80        out_fields: *mut u32,
81        out_status: *mut i32,
82        out_display_time: *mut u64,
83        out_scale_factor: *mut f64,
84        out_content_scale: *mut f64,
85        out_content_rect: *mut f64,           // [4]: x, y, w, h
86        out_bounding_rect: *mut f64,          // [4]
87        out_screen_rect: *mut f64,            // [4]
88        out_presenter_overlay_rect: *mut f64, // [4]
89        out_dirty_rects: *mut *mut std::ffi::c_void,
90        out_dirty_rects_count: *mut usize,
91    ) -> bool;
92
93    pub fn cm_sample_buffer_get_presentation_timestamp(
94        sample_buffer: *mut std::ffi::c_void,
95        out_value: *mut i64,
96        out_timescale: *mut i32,
97        out_flags: *mut u32,
98        out_epoch: *mut i64,
99    );
100    pub fn cm_sample_buffer_get_duration(
101        sample_buffer: *mut std::ffi::c_void,
102        out_value: *mut i64,
103        out_timescale: *mut i32,
104        out_flags: *mut u32,
105        out_epoch: *mut i64,
106    );
107    pub fn cm_sample_buffer_release(sample_buffer: *mut std::ffi::c_void);
108    pub fn cm_sample_buffer_retain(sample_buffer: *mut std::ffi::c_void);
109    pub fn cm_sample_buffer_is_valid(sample_buffer: *mut std::ffi::c_void) -> bool;
110    pub fn cm_sample_buffer_get_num_samples(sample_buffer: *mut std::ffi::c_void) -> usize;
111    pub fn cm_block_buffer_release(block_buffer: *mut std::ffi::c_void);
112    pub fn cm_block_buffer_retain(block_buffer: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
113    pub fn cm_block_buffer_get_data_length(block_buffer: *mut std::ffi::c_void) -> usize;
114    pub fn cm_block_buffer_is_empty(block_buffer: *mut std::ffi::c_void) -> bool;
115    pub fn cm_block_buffer_is_range_contiguous(
116        block_buffer: *mut std::ffi::c_void,
117        offset: usize,
118        length: usize,
119    ) -> bool;
120    pub fn cm_block_buffer_get_data_pointer(
121        block_buffer: *mut std::ffi::c_void,
122        offset: usize,
123        out_length_at_offset: *mut usize,
124        out_total_length: *mut usize,
125        out_data_pointer: *mut *mut std::ffi::c_void,
126    ) -> i32;
127    pub fn cm_block_buffer_copy_data_bytes(
128        block_buffer: *mut std::ffi::c_void,
129        offset_to_data: usize,
130        data_length: usize,
131        destination: *mut std::ffi::c_void,
132    ) -> i32;
133    pub fn cm_sample_buffer_get_data_buffer(
134        sample_buffer: *mut std::ffi::c_void,
135    ) -> *mut std::ffi::c_void;
136
137    pub fn cm_sample_buffer_get_decode_timestamp(
138        sample_buffer: *mut std::ffi::c_void,
139        out_value: *mut i64,
140        out_timescale: *mut i32,
141        out_flags: *mut u32,
142        out_epoch: *mut i64,
143    );
144    pub fn cm_sample_buffer_get_output_presentation_timestamp(
145        sample_buffer: *mut std::ffi::c_void,
146        out_value: *mut i64,
147        out_timescale: *mut i32,
148        out_flags: *mut u32,
149        out_epoch: *mut i64,
150    );
151    pub fn cm_sample_buffer_set_output_presentation_timestamp(
152        sample_buffer: *mut std::ffi::c_void,
153        value: i64,
154        timescale: i32,
155        flags: u32,
156        epoch: i64,
157    ) -> i32;
158    pub fn cm_sample_buffer_get_sample_size(
159        sample_buffer: *mut std::ffi::c_void,
160        sample_index: usize,
161    ) -> usize;
162    pub fn cm_sample_buffer_get_total_sample_size(sample_buffer: *mut std::ffi::c_void) -> usize;
163    pub fn cm_sample_buffer_is_ready_for_data_access(sample_buffer: *mut std::ffi::c_void) -> bool;
164    pub fn cm_sample_buffer_make_data_ready(sample_buffer: *mut std::ffi::c_void) -> i32;
165
166    // New CMSampleBuffer APIs
167    pub fn cm_sample_buffer_get_format_description(
168        sample_buffer: *mut std::ffi::c_void,
169    ) -> *mut std::ffi::c_void;
170    pub fn cm_sample_buffer_get_sample_timing_info(
171        sample_buffer: *mut std::ffi::c_void,
172        sample_index: usize,
173        out_duration_value: *mut i64,
174        out_duration_timescale: *mut i32,
175        out_duration_flags: *mut u32,
176        out_duration_epoch: *mut i64,
177        out_pts_value: *mut i64,
178        out_pts_timescale: *mut i32,
179        out_pts_flags: *mut u32,
180        out_pts_epoch: *mut i64,
181        out_dts_value: *mut i64,
182        out_dts_timescale: *mut i32,
183        out_dts_flags: *mut u32,
184        out_dts_epoch: *mut i64,
185    ) -> i32;
186    pub fn cm_sample_buffer_invalidate(sample_buffer: *mut std::ffi::c_void) -> i32;
187    pub fn cm_sample_buffer_create_copy_with_new_timing(
188        sample_buffer: *mut std::ffi::c_void,
189        num_timing_infos: usize,
190        timing_info_array: *const std::ffi::c_void,
191        sample_buffer_out: *mut *mut std::ffi::c_void,
192    ) -> i32;
193    pub fn cm_sample_buffer_copy_pcm_data_into_audio_buffer_list(
194        sample_buffer: *mut std::ffi::c_void,
195        frame_offset: i32,
196        num_frames: i32,
197        buffer_list: *mut std::ffi::c_void,
198    ) -> i32;
199
200    // CMFormatDescription APIs
201    pub fn cm_format_description_get_media_type(format_description: *mut std::ffi::c_void) -> u32;
202    pub fn cm_format_description_get_media_subtype(
203        format_description: *mut std::ffi::c_void,
204    ) -> u32;
205    pub fn cm_format_description_get_extensions(
206        format_description: *mut std::ffi::c_void,
207    ) -> *const std::ffi::c_void;
208    pub fn cm_format_description_retain(
209        format_description: *mut std::ffi::c_void,
210    ) -> *mut std::ffi::c_void;
211    pub fn cm_format_description_release(format_description: *mut std::ffi::c_void);
212
213    // CMFormatDescription Audio APIs
214    pub fn cm_format_description_get_audio_sample_rate(
215        format_description: *mut std::ffi::c_void,
216    ) -> f64;
217    pub fn cm_format_description_get_audio_channel_count(
218        format_description: *mut std::ffi::c_void,
219    ) -> u32;
220    pub fn cm_format_description_get_audio_bits_per_channel(
221        format_description: *mut std::ffi::c_void,
222    ) -> u32;
223    pub fn cm_format_description_get_audio_bytes_per_frame(
224        format_description: *mut std::ffi::c_void,
225    ) -> u32;
226    pub fn cm_format_description_get_audio_format_flags(
227        format_description: *mut std::ffi::c_void,
228    ) -> u32;
229
230    // Hash functions
231    pub fn cm_sample_buffer_hash(sample_buffer: *mut std::ffi::c_void) -> usize;
232    pub fn cv_pixel_buffer_hash(pixel_buffer: *mut std::ffi::c_void) -> usize;
233    pub fn cm_block_buffer_hash(block_buffer: *mut std::ffi::c_void) -> usize;
234    pub fn cm_format_description_hash(format_description: *mut std::ffi::c_void) -> usize;
235    pub fn io_surface_hash(surface: *mut std::ffi::c_void) -> usize;
236
237    pub fn cv_pixel_buffer_get_width(pixel_buffer: *mut std::ffi::c_void) -> usize;
238    pub fn cv_pixel_buffer_get_height(pixel_buffer: *mut std::ffi::c_void) -> usize;
239    pub fn cv_pixel_buffer_get_pixel_format_type(pixel_buffer: *mut std::ffi::c_void) -> u32;
240    pub fn cv_pixel_buffer_get_bytes_per_row(pixel_buffer: *mut std::ffi::c_void) -> usize;
241    pub fn cv_pixel_buffer_lock_base_address(
242        pixel_buffer: *mut std::ffi::c_void,
243        flags: u64,
244    ) -> i32;
245    pub fn cv_pixel_buffer_unlock_base_address(
246        pixel_buffer: *mut std::ffi::c_void,
247        flags: u64,
248    ) -> i32;
249    pub fn cv_pixel_buffer_get_base_address(
250        pixel_buffer: *mut std::ffi::c_void,
251    ) -> *mut std::ffi::c_void;
252    pub fn cv_pixel_buffer_get_io_surface(
253        pixel_buffer: *mut std::ffi::c_void,
254    ) -> *mut std::ffi::c_void;
255    pub fn cv_pixel_buffer_release(pixel_buffer: *mut std::ffi::c_void);
256    pub fn cv_pixel_buffer_retain(pixel_buffer: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
257    pub fn cv_pixel_buffer_create(
258        width: usize,
259        height: usize,
260        pixel_format_type: u32,
261        pixel_buffer_out: *mut *mut std::ffi::c_void,
262    ) -> i32;
263    pub fn cv_pixel_buffer_create_with_bytes(
264        width: usize,
265        height: usize,
266        pixel_format_type: u32,
267        base_address: *mut std::ffi::c_void,
268        bytes_per_row: usize,
269        pixel_buffer_out: *mut *mut std::ffi::c_void,
270    ) -> i32;
271    pub fn cv_pixel_buffer_fill_extended_pixels(pixel_buffer: *mut std::ffi::c_void) -> i32;
272
273    // New CVPixelBuffer APIs
274    pub fn cv_pixel_buffer_create_with_planar_bytes(
275        width: usize,
276        height: usize,
277        pixel_format_type: u32,
278        num_planes: usize,
279        plane_base_addresses: *const *mut std::ffi::c_void,
280        plane_widths: *const usize,
281        plane_heights: *const usize,
282        plane_bytes_per_row: *const usize,
283        pixel_buffer_out: *mut *mut std::ffi::c_void,
284    ) -> i32;
285    pub fn cv_pixel_buffer_create_with_io_surface(
286        io_surface: *mut std::ffi::c_void,
287        pixel_buffer_out: *mut *mut std::ffi::c_void,
288    ) -> i32;
289    pub fn cv_pixel_buffer_get_type_id() -> usize;
290
291    pub fn cv_pixel_buffer_get_data_size(pixel_buffer: *mut std::ffi::c_void) -> usize;
292    pub fn cv_pixel_buffer_is_planar(pixel_buffer: *mut std::ffi::c_void) -> bool;
293    pub fn cv_pixel_buffer_get_plane_count(pixel_buffer: *mut std::ffi::c_void) -> usize;
294    pub fn cv_pixel_buffer_get_width_of_plane(
295        pixel_buffer: *mut std::ffi::c_void,
296        plane_index: usize,
297    ) -> usize;
298    pub fn cv_pixel_buffer_get_height_of_plane(
299        pixel_buffer: *mut std::ffi::c_void,
300        plane_index: usize,
301    ) -> usize;
302    pub fn cv_pixel_buffer_get_base_address_of_plane(
303        pixel_buffer: *mut std::ffi::c_void,
304        plane_index: usize,
305    ) -> *mut std::ffi::c_void;
306    pub fn cv_pixel_buffer_get_bytes_per_row_of_plane(
307        pixel_buffer: *mut std::ffi::c_void,
308        plane_index: usize,
309    ) -> usize;
310    pub fn cv_pixel_buffer_get_extended_pixels(
311        pixel_buffer: *mut std::ffi::c_void,
312        extra_columns_on_left: *mut usize,
313        extra_columns_on_right: *mut usize,
314        extra_rows_on_top: *mut usize,
315        extra_rows_on_bottom: *mut usize,
316    );
317
318    pub fn cm_sample_buffer_create_for_image_buffer(
319        image_buffer: *mut std::ffi::c_void,
320        presentation_time_value: i64,
321        presentation_time_scale: i32,
322        presentation_time_flags: u32,
323        presentation_time_epoch: i64,
324        duration_value: i64,
325        duration_scale: i32,
326        duration_flags: u32,
327        duration_epoch: i64,
328        sample_buffer_out: *mut *mut std::ffi::c_void,
329    ) -> i32;
330
331    // IOSurface functions
332    pub fn io_surface_get_width(surface: *mut std::ffi::c_void) -> usize;
333    pub fn io_surface_get_height(surface: *mut std::ffi::c_void) -> usize;
334    pub fn io_surface_get_bytes_per_row(surface: *mut std::ffi::c_void) -> usize;
335    pub fn io_surface_get_alloc_size(surface: *mut std::ffi::c_void) -> usize;
336    pub fn io_surface_get_pixel_format(surface: *mut std::ffi::c_void) -> u32;
337    pub fn io_surface_get_id(surface: *mut std::ffi::c_void) -> u32;
338    pub fn io_surface_get_seed(surface: *mut std::ffi::c_void) -> u32;
339    pub fn io_surface_get_plane_count(surface: *mut std::ffi::c_void) -> usize;
340    pub fn io_surface_get_width_of_plane(
341        surface: *mut std::ffi::c_void,
342        plane_index: usize,
343    ) -> usize;
344    pub fn io_surface_get_height_of_plane(
345        surface: *mut std::ffi::c_void,
346        plane_index: usize,
347    ) -> usize;
348    pub fn io_surface_get_bytes_per_row_of_plane(
349        surface: *mut std::ffi::c_void,
350        plane_index: usize,
351    ) -> usize;
352    pub fn io_surface_get_base_address_of_plane(
353        surface: *mut std::ffi::c_void,
354        plane_index: usize,
355    ) -> *mut std::ffi::c_void;
356    pub fn io_surface_get_base_address(surface: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
357    pub fn io_surface_get_bytes_per_element(surface: *mut std::ffi::c_void) -> usize;
358    pub fn io_surface_get_element_width(surface: *mut std::ffi::c_void) -> usize;
359    pub fn io_surface_get_element_height(surface: *mut std::ffi::c_void) -> usize;
360    pub fn io_surface_is_in_use(surface: *mut std::ffi::c_void) -> bool;
361    pub fn io_surface_increment_use_count(surface: *mut std::ffi::c_void);
362    pub fn io_surface_decrement_use_count(surface: *mut std::ffi::c_void);
363    pub fn io_surface_lock(surface: *mut std::ffi::c_void, options: u32, seed: *mut u32) -> i32;
364    pub fn io_surface_unlock(surface: *mut std::ffi::c_void, options: u32, seed: *mut u32) -> i32;
365    pub fn io_surface_release(surface: *mut std::ffi::c_void);
366    pub fn io_surface_retain(surface: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
367
368    // CMBlockBuffer creation (for testing)
369    pub fn cm_block_buffer_create_with_data(
370        data: *const std::ffi::c_void,
371        data_length: usize,
372        block_buffer_out: *mut *mut std::ffi::c_void,
373    ) -> i32;
374    pub fn cm_block_buffer_create_empty(block_buffer_out: *mut *mut std::ffi::c_void) -> i32;
375}