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_image_buffer(
8        sample_buffer: *mut std::ffi::c_void,
9    ) -> *mut std::ffi::c_void;
10    pub fn cm_sample_buffer_get_frame_status(sample_buffer: *mut std::ffi::c_void) -> i32;
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    pub fn cm_sample_buffer_get_frame_info(
75        sample_buffer: *mut std::ffi::c_void,
76        out_fields: *mut u32,
77        out_status: *mut i32,
78        out_display_time: *mut u64,
79        out_scale_factor: *mut f64,
80        out_content_scale: *mut f64,
81        out_content_rect: *mut f64,           // [4]: x, y, w, h
82        out_bounding_rect: *mut f64,          // [4]
83        out_screen_rect: *mut f64,            // [4]
84        out_presenter_overlay_rect: *mut f64, // [4]
85    ) -> bool;
86
87    pub fn cm_sample_buffer_get_presentation_timestamp(
88        sample_buffer: *mut std::ffi::c_void,
89        out_value: *mut i64,
90        out_timescale: *mut i32,
91        out_flags: *mut u32,
92        out_epoch: *mut i64,
93    );
94    pub fn cm_sample_buffer_get_duration(
95        sample_buffer: *mut std::ffi::c_void,
96        out_value: *mut i64,
97        out_timescale: *mut i32,
98        out_flags: *mut u32,
99        out_epoch: *mut i64,
100    );
101    pub fn cm_sample_buffer_release(sample_buffer: *mut std::ffi::c_void);
102    pub fn cm_sample_buffer_retain(sample_buffer: *mut std::ffi::c_void);
103    pub fn cm_sample_buffer_is_valid(sample_buffer: *mut std::ffi::c_void) -> bool;
104    pub fn cm_sample_buffer_get_num_samples(sample_buffer: *mut std::ffi::c_void) -> usize;
105    pub fn cm_sample_buffer_get_audio_buffer_list(
106        sample_buffer: *mut std::ffi::c_void,
107        out_num_buffers: *mut u32,
108        out_buffers_ptr: *mut *mut std::ffi::c_void,
109        out_buffers_len: *mut usize,
110        out_block_buffer: *mut *mut std::ffi::c_void,
111    );
112    pub fn cm_block_buffer_release(block_buffer: *mut std::ffi::c_void);
113    pub fn cm_block_buffer_retain(block_buffer: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
114    pub fn cm_block_buffer_get_data_length(block_buffer: *mut std::ffi::c_void) -> usize;
115    pub fn cm_block_buffer_is_empty(block_buffer: *mut std::ffi::c_void) -> bool;
116    pub fn cm_block_buffer_is_range_contiguous(
117        block_buffer: *mut std::ffi::c_void,
118        offset: usize,
119        length: usize,
120    ) -> bool;
121    pub fn cm_block_buffer_get_data_pointer(
122        block_buffer: *mut std::ffi::c_void,
123        offset: usize,
124        out_length_at_offset: *mut usize,
125        out_total_length: *mut usize,
126        out_data_pointer: *mut *mut std::ffi::c_void,
127    ) -> i32;
128    pub fn cm_block_buffer_copy_data_bytes(
129        block_buffer: *mut std::ffi::c_void,
130        offset_to_data: usize,
131        data_length: usize,
132        destination: *mut std::ffi::c_void,
133    ) -> i32;
134    pub fn cm_sample_buffer_get_data_buffer(
135        sample_buffer: *mut std::ffi::c_void,
136    ) -> *mut std::ffi::c_void;
137
138    pub fn cm_sample_buffer_get_decode_timestamp(
139        sample_buffer: *mut std::ffi::c_void,
140        out_value: *mut i64,
141        out_timescale: *mut i32,
142        out_flags: *mut u32,
143        out_epoch: *mut i64,
144    );
145    pub fn cm_sample_buffer_get_output_presentation_timestamp(
146        sample_buffer: *mut std::ffi::c_void,
147        out_value: *mut i64,
148        out_timescale: *mut i32,
149        out_flags: *mut u32,
150        out_epoch: *mut i64,
151    );
152    pub fn cm_sample_buffer_set_output_presentation_timestamp(
153        sample_buffer: *mut std::ffi::c_void,
154        value: i64,
155        timescale: i32,
156        flags: u32,
157        epoch: i64,
158    ) -> i32;
159    pub fn cm_sample_buffer_get_sample_size(
160        sample_buffer: *mut std::ffi::c_void,
161        sample_index: usize,
162    ) -> usize;
163    pub fn cm_sample_buffer_get_total_sample_size(sample_buffer: *mut std::ffi::c_void) -> usize;
164    pub fn cm_sample_buffer_is_ready_for_data_access(sample_buffer: *mut std::ffi::c_void) -> bool;
165    pub fn cm_sample_buffer_make_data_ready(sample_buffer: *mut std::ffi::c_void) -> i32;
166
167    // New CMSampleBuffer APIs
168    pub fn cm_sample_buffer_get_format_description(
169        sample_buffer: *mut std::ffi::c_void,
170    ) -> *mut std::ffi::c_void;
171    pub fn cm_sample_buffer_get_sample_timing_info(
172        sample_buffer: *mut std::ffi::c_void,
173        sample_index: usize,
174        out_duration_value: *mut i64,
175        out_duration_timescale: *mut i32,
176        out_duration_flags: *mut u32,
177        out_duration_epoch: *mut i64,
178        out_pts_value: *mut i64,
179        out_pts_timescale: *mut i32,
180        out_pts_flags: *mut u32,
181        out_pts_epoch: *mut i64,
182        out_dts_value: *mut i64,
183        out_dts_timescale: *mut i32,
184        out_dts_flags: *mut u32,
185        out_dts_epoch: *mut i64,
186    ) -> i32;
187    pub fn cm_sample_buffer_invalidate(sample_buffer: *mut std::ffi::c_void) -> i32;
188    pub fn cm_sample_buffer_create_copy_with_new_timing(
189        sample_buffer: *mut std::ffi::c_void,
190        num_timing_infos: usize,
191        timing_info_array: *const std::ffi::c_void,
192        sample_buffer_out: *mut *mut std::ffi::c_void,
193    ) -> i32;
194    pub fn cm_sample_buffer_copy_pcm_data_into_audio_buffer_list(
195        sample_buffer: *mut std::ffi::c_void,
196        frame_offset: i32,
197        num_frames: i32,
198        buffer_list: *mut std::ffi::c_void,
199    ) -> i32;
200
201    // CMFormatDescription APIs
202    pub fn cm_format_description_get_media_type(format_description: *mut std::ffi::c_void) -> u32;
203    pub fn cm_format_description_get_media_subtype(
204        format_description: *mut std::ffi::c_void,
205    ) -> u32;
206    pub fn cm_format_description_get_extensions(
207        format_description: *mut std::ffi::c_void,
208    ) -> *const std::ffi::c_void;
209    pub fn cm_format_description_retain(
210        format_description: *mut std::ffi::c_void,
211    ) -> *mut std::ffi::c_void;
212    pub fn cm_format_description_release(format_description: *mut std::ffi::c_void);
213
214    // CMFormatDescription Audio APIs
215    pub fn cm_format_description_get_audio_sample_rate(
216        format_description: *mut std::ffi::c_void,
217    ) -> f64;
218    pub fn cm_format_description_get_audio_channel_count(
219        format_description: *mut std::ffi::c_void,
220    ) -> u32;
221    pub fn cm_format_description_get_audio_bits_per_channel(
222        format_description: *mut std::ffi::c_void,
223    ) -> u32;
224    pub fn cm_format_description_get_audio_bytes_per_frame(
225        format_description: *mut std::ffi::c_void,
226    ) -> u32;
227    pub fn cm_format_description_get_audio_format_flags(
228        format_description: *mut std::ffi::c_void,
229    ) -> u32;
230
231    // Hash functions
232    pub fn cm_sample_buffer_hash(sample_buffer: *mut std::ffi::c_void) -> usize;
233    pub fn cv_pixel_buffer_hash(pixel_buffer: *mut std::ffi::c_void) -> usize;
234    pub fn cv_pixel_buffer_pool_hash(pool: *mut std::ffi::c_void) -> usize;
235    pub fn cm_block_buffer_hash(block_buffer: *mut std::ffi::c_void) -> usize;
236    pub fn cm_format_description_hash(format_description: *mut std::ffi::c_void) -> usize;
237    pub fn io_surface_hash(surface: *mut std::ffi::c_void) -> usize;
238
239    pub fn cv_pixel_buffer_get_width(pixel_buffer: *mut std::ffi::c_void) -> usize;
240    pub fn cv_pixel_buffer_get_height(pixel_buffer: *mut std::ffi::c_void) -> usize;
241    pub fn cv_pixel_buffer_get_pixel_format_type(pixel_buffer: *mut std::ffi::c_void) -> u32;
242    pub fn cv_pixel_buffer_get_bytes_per_row(pixel_buffer: *mut std::ffi::c_void) -> usize;
243    pub fn cv_pixel_buffer_lock_base_address(
244        pixel_buffer: *mut std::ffi::c_void,
245        flags: u32,
246    ) -> i32;
247    pub fn cv_pixel_buffer_unlock_base_address(
248        pixel_buffer: *mut std::ffi::c_void,
249        flags: u32,
250    ) -> i32;
251    pub fn cv_pixel_buffer_get_base_address(
252        pixel_buffer: *mut std::ffi::c_void,
253    ) -> *mut std::ffi::c_void;
254    pub fn cv_pixel_buffer_get_io_surface(
255        pixel_buffer: *mut std::ffi::c_void,
256    ) -> *mut std::ffi::c_void;
257    pub fn cv_pixel_buffer_release(pixel_buffer: *mut std::ffi::c_void);
258    pub fn cv_pixel_buffer_retain(pixel_buffer: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
259    pub fn cv_pixel_buffer_create(
260        width: usize,
261        height: usize,
262        pixel_format_type: u32,
263        pixel_buffer_out: *mut *mut std::ffi::c_void,
264    ) -> i32;
265    pub fn cv_pixel_buffer_create_with_bytes(
266        width: usize,
267        height: usize,
268        pixel_format_type: u32,
269        base_address: *mut std::ffi::c_void,
270        bytes_per_row: usize,
271        pixel_buffer_out: *mut *mut std::ffi::c_void,
272    ) -> i32;
273    pub fn cv_pixel_buffer_fill_extended_pixels(pixel_buffer: *mut std::ffi::c_void) -> i32;
274
275    // New CVPixelBuffer APIs
276    pub fn cv_pixel_buffer_create_with_planar_bytes(
277        width: usize,
278        height: usize,
279        pixel_format_type: u32,
280        num_planes: usize,
281        plane_base_addresses: *const *mut std::ffi::c_void,
282        plane_widths: *const usize,
283        plane_heights: *const usize,
284        plane_bytes_per_row: *const usize,
285        pixel_buffer_out: *mut *mut std::ffi::c_void,
286    ) -> i32;
287    pub fn cv_pixel_buffer_create_with_io_surface(
288        io_surface: *mut std::ffi::c_void,
289        pixel_buffer_out: *mut *mut std::ffi::c_void,
290    ) -> i32;
291    pub fn cv_pixel_buffer_get_type_id() -> usize;
292
293    // CVPixelBufferPool APIs
294    pub fn cv_pixel_buffer_pool_create(
295        width: usize,
296        height: usize,
297        pixel_format_type: u32,
298        max_buffers: usize,
299        pool_out: *mut *mut std::ffi::c_void,
300    ) -> i32;
301    pub fn cv_pixel_buffer_pool_create_pixel_buffer(
302        pool: *mut std::ffi::c_void,
303        pixel_buffer_out: *mut *mut std::ffi::c_void,
304    ) -> i32;
305    pub fn cv_pixel_buffer_pool_flush(pool: *mut std::ffi::c_void);
306    pub fn cv_pixel_buffer_pool_get_type_id() -> usize;
307    pub fn cv_pixel_buffer_pool_retain(pool: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
308    pub fn cv_pixel_buffer_pool_release(pool: *mut std::ffi::c_void);
309
310    // Additional pool APIs
311    pub fn cv_pixel_buffer_pool_get_attributes(
312        pool: *mut std::ffi::c_void,
313    ) -> *const std::ffi::c_void;
314    pub fn cv_pixel_buffer_pool_get_pixel_buffer_attributes(
315        pool: *mut std::ffi::c_void,
316    ) -> *const std::ffi::c_void;
317
318    pub fn cv_pixel_buffer_get_data_size(pixel_buffer: *mut std::ffi::c_void) -> usize;
319    pub fn cv_pixel_buffer_is_planar(pixel_buffer: *mut std::ffi::c_void) -> bool;
320    pub fn cv_pixel_buffer_get_plane_count(pixel_buffer: *mut std::ffi::c_void) -> usize;
321    pub fn cv_pixel_buffer_get_width_of_plane(
322        pixel_buffer: *mut std::ffi::c_void,
323        plane_index: usize,
324    ) -> usize;
325    pub fn cv_pixel_buffer_get_height_of_plane(
326        pixel_buffer: *mut std::ffi::c_void,
327        plane_index: usize,
328    ) -> usize;
329    pub fn cv_pixel_buffer_get_base_address_of_plane(
330        pixel_buffer: *mut std::ffi::c_void,
331        plane_index: usize,
332    ) -> *mut std::ffi::c_void;
333    pub fn cv_pixel_buffer_get_bytes_per_row_of_plane(
334        pixel_buffer: *mut std::ffi::c_void,
335        plane_index: usize,
336    ) -> usize;
337    pub fn cv_pixel_buffer_get_extended_pixels(
338        pixel_buffer: *mut std::ffi::c_void,
339        extra_columns_on_left: *mut usize,
340        extra_columns_on_right: *mut usize,
341        extra_rows_on_top: *mut usize,
342        extra_rows_on_bottom: *mut usize,
343    );
344
345    pub fn cm_sample_buffer_create_for_image_buffer(
346        image_buffer: *mut std::ffi::c_void,
347        presentation_time_value: i64,
348        presentation_time_scale: i32,
349        duration_value: i64,
350        duration_scale: i32,
351        sample_buffer_out: *mut *mut std::ffi::c_void,
352    ) -> i32;
353
354    // IOSurface functions
355    pub fn io_surface_get_width(surface: *mut std::ffi::c_void) -> usize;
356    pub fn io_surface_get_height(surface: *mut std::ffi::c_void) -> usize;
357    pub fn io_surface_get_bytes_per_row(surface: *mut std::ffi::c_void) -> usize;
358    pub fn io_surface_get_alloc_size(surface: *mut std::ffi::c_void) -> usize;
359    pub fn io_surface_get_pixel_format(surface: *mut std::ffi::c_void) -> u32;
360    pub fn io_surface_get_id(surface: *mut std::ffi::c_void) -> u32;
361    pub fn io_surface_get_seed(surface: *mut std::ffi::c_void) -> u32;
362    pub fn io_surface_get_plane_count(surface: *mut std::ffi::c_void) -> usize;
363    pub fn io_surface_get_width_of_plane(
364        surface: *mut std::ffi::c_void,
365        plane_index: usize,
366    ) -> usize;
367    pub fn io_surface_get_height_of_plane(
368        surface: *mut std::ffi::c_void,
369        plane_index: usize,
370    ) -> usize;
371    pub fn io_surface_get_bytes_per_row_of_plane(
372        surface: *mut std::ffi::c_void,
373        plane_index: usize,
374    ) -> usize;
375    pub fn io_surface_get_base_address_of_plane(
376        surface: *mut std::ffi::c_void,
377        plane_index: usize,
378    ) -> *mut std::ffi::c_void;
379    pub fn io_surface_get_base_address(surface: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
380    pub fn io_surface_get_bytes_per_element(surface: *mut std::ffi::c_void) -> usize;
381    pub fn io_surface_get_element_width(surface: *mut std::ffi::c_void) -> usize;
382    pub fn io_surface_get_element_height(surface: *mut std::ffi::c_void) -> usize;
383    pub fn io_surface_is_in_use(surface: *mut std::ffi::c_void) -> bool;
384    pub fn io_surface_increment_use_count(surface: *mut std::ffi::c_void);
385    pub fn io_surface_decrement_use_count(surface: *mut std::ffi::c_void);
386    pub fn io_surface_lock(surface: *mut std::ffi::c_void, options: u32, seed: *mut u32) -> i32;
387    pub fn io_surface_unlock(surface: *mut std::ffi::c_void, options: u32, seed: *mut u32) -> i32;
388    pub fn io_surface_release(surface: *mut std::ffi::c_void);
389    pub fn io_surface_retain(surface: *mut std::ffi::c_void) -> *mut std::ffi::c_void;
390
391    // CMBlockBuffer creation (for testing)
392    pub fn cm_block_buffer_create_with_data(
393        data: *const std::ffi::c_void,
394        data_length: usize,
395        block_buffer_out: *mut *mut std::ffi::c_void,
396    ) -> i32;
397    pub fn cm_block_buffer_create_empty(block_buffer_out: *mut *mut std::ffi::c_void) -> i32;
398}