azure_kinect/
factory.rs

1use crate::playback::Playback;
2use crate::record::Record;
3use crate::*;
4use azure_kinect_sys::k4a::{k4a_calibration_t, k4a_capture_t, k4a_image_t};
5use std::ffi::CString;
6use std::os::raw;
7use std::ptr;
8
9pub type DebugMessageHandler = dyn FnMut(LogLevel, &str, raw::c_int, &str);
10pub type MemoryDestroyCallback = extern "C" fn(buffer: *mut (), context: *mut ());
11
12pub trait PreAllocatedBufferInfo {
13    fn format(&self) -> ImageFormat;
14    fn width_pixels(&self) -> i32;
15    fn height_pixels(&self) -> i32;
16    fn stride_bytes(&self) -> i32;
17    fn buffer(&mut self) -> *mut u8;
18    fn buffer_size(&self) -> usize;
19}
20
21pub struct Factory {
22    pub(crate) api: azure_kinect_sys::api::Api,
23    debug_message_handler: Option<Box<DebugMessageHandler>>,
24}
25
26impl Factory {
27    pub fn new() -> Result<Factory, Error> {
28        Ok(Factory {
29            api: azure_kinect_sys::api::Api::new()?,
30            debug_message_handler: None,
31        })
32    }
33
34    pub fn with_library_directory(lib_dir: &str) -> Result<Factory, Error> {
35        Ok(Factory {
36            api: azure_kinect_sys::api::Api::with_library_directory(lib_dir)?,
37            debug_message_handler: None,
38        })
39    }
40
41    pub(crate) fn with_get_module() -> Result<Factory, Error> {
42        Ok(Factory {
43            api: azure_kinect_sys::api::Api::with_get_module()?,
44            debug_message_handler: None,
45        })
46    }
47
48    /// Sets and clears the callback function to receive debug messages from the Azure Kinect device.
49    pub fn set_debug_message_handler(
50        mut self,
51        debug_message_handler: Box<DebugMessageHandler>,
52        min_level: LogLevel,
53    ) -> Self {
54        self.set_debug_message_handler_internal(debug_message_handler, min_level);
55        self
56    }
57
58    /// Clears the callback function to receive debug messages from the Azure Kinect device.
59    pub fn reset_debug_message_handler(mut self) -> Self {
60        self.reset_debug_message_handler_internal();
61        self
62    }
63
64    pub(crate) fn set_debug_message_handler_internal(
65        &mut self,
66        debug_message_handler: Box<DebugMessageHandler>,
67        min_level: LogLevel,
68    ) {
69        self.debug_message_handler = Some(debug_message_handler);
70        unsafe {
71            (self.api.funcs.k4a_set_debug_message_handler)(
72                Some(Self::debug_message_handler_func),
73                std::mem::transmute(self.debug_message_handler.as_mut()),
74                min_level.into(),
75            );
76        }
77    }
78
79    pub(crate) fn reset_debug_message_handler_internal(&mut self) {
80        self.debug_message_handler = None;
81        unsafe {
82            (self.api.funcs.k4a_set_debug_message_handler)(
83                None,
84                ptr::null_mut(),
85                azure_kinect_sys::k4a::k4a_log_level_t_K4A_LOG_LEVEL_OFF,
86            );
87        }
88    }
89
90    /// Gets the number of connected devices
91    pub fn device_get_installed_count(&self) -> u32 {
92        unsafe { (self.api.funcs.k4a_device_get_installed_count)() }
93    }
94
95    /// Open a k4a device.
96    pub fn device_open(&self, index: u32) -> Result<Device, Error> {
97        let mut handle: azure_kinect_sys::k4a::k4a_device_t = ptr::null_mut();
98        Error::from_k4a_result_t(unsafe { (self.api.funcs.k4a_device_open)(index, &mut handle) })
99            .to_result_fn(|| Device::from_handle(&self.api, handle))
100    }
101
102    /// Get the camera calibration for a device from a raw calibration blob.
103    pub fn calibration_get_from_raw(
104        &self,
105        raw_calibration: &Vec<u8>,
106        target_depth_mode: DepthMode,
107        target_color_resolution: ColorResolution,
108    ) -> Result<Calibration, Error> {
109        let mut calibration = k4a_calibration_t::default();
110        Error::from_k4a_result_t(unsafe {
111            (self.api.funcs.k4a_calibration_get_from_raw)(
112                raw_calibration.as_ptr() as *mut i8,
113                raw_calibration.len(),
114                target_depth_mode.into(),
115                target_color_resolution.into(),
116                &mut calibration,
117            )
118        })
119        .to_result_fn(|| Calibration::from_handle(&self.api, calibration))
120    }
121
122    pub fn capture_create(&self) -> Result<Capture, Error> {
123        let mut handle: k4a_capture_t = ptr::null_mut();
124        Error::from_k4a_result_t(unsafe { (self.api.funcs.k4a_capture_create)(&mut handle) })
125            .to_result_fn(|| Capture::from_handle(&self.api, handle))
126    }
127
128    /// Create a blank image
129    pub fn image_create(
130        &self,
131        format: ImageFormat,
132        width_pixels: i32,
133        height_pixels: i32,
134        stride_bytes: i32,
135    ) -> Result<Image, Error> {
136        let mut handle: k4a_image_t = ptr::null_mut();
137        Error::from_k4a_result_t(unsafe {
138            (self.api.funcs.k4a_image_create)(
139                format.into(),
140                width_pixels,
141                height_pixels,
142                stride_bytes,
143                &mut handle,
144            )
145        })
146        .to_result_fn(|| Image::from_handle(&self.api, handle))
147    }
148
149    /// Create an image from a pre-allocated buffer
150    pub fn image_create_from_buffer_native(
151        &self,
152        format: ImageFormat,
153        width_pixels: i32,
154        height_pixels: i32,
155        stride_bytes: i32,
156        buffer: *mut u8,
157        buffer_size: usize,
158        buffer_release_cb: Option<MemoryDestroyCallback>,
159        buffer_release_cb_context: *mut (),
160    ) -> Result<Image, Error> {
161        let mut handle: k4a_image_t = ptr::null_mut();
162        Error::from_k4a_result_t(unsafe {
163            (self.api.funcs.k4a_image_create_from_buffer)(
164                format.into(),
165                width_pixels,
166                height_pixels,
167                stride_bytes,
168                buffer,
169                buffer_size,
170                std::mem::transmute(buffer_release_cb),
171                buffer_release_cb_context as _,
172                &mut handle,
173            )
174        })
175        .to_result_fn(|| Image::from_handle(&self.api, handle))
176    }
177
178    /// Create an image from a pre-allocated buffer
179    pub fn image_create_from_buffer<T: FnOnce(*mut ())>(
180        &self,
181        format: ImageFormat,
182        width_pixels: i32,
183        height_pixels: i32,
184        stride_bytes: i32,
185        buffer: *mut u8,
186        buffer_size: usize,
187        buffer_release_cb: Box<T>,
188    ) -> Result<Image, Error> {
189        self.image_create_from_buffer_native(
190            format.into(),
191            width_pixels,
192            height_pixels,
193            stride_bytes,
194            buffer,
195            buffer_size,
196            Some(Self::buffer_release_callback::<T>),
197            Box::<T>::into_raw(buffer_release_cb) as _,
198        )
199    }
200
201    /// Create an image from a pre-allocated buffer
202    pub fn image_create_from_buffer_with_info<T: PreAllocatedBufferInfo + Drop>(
203        &self,
204        mut buffer_info: Box<T>,
205    ) -> Result<Image, Error> {
206        self.image_create_from_buffer(
207            buffer_info.format().into(),
208            buffer_info.width_pixels(),
209            buffer_info.height_pixels(),
210            buffer_info.stride_bytes(),
211            buffer_info.buffer(),
212            buffer_info.buffer_size(),
213            Box::new(move |_| {
214                let _ = buffer_info;
215            }),
216        )
217    }
218
219    /// Get handle to transformation handle.
220    pub fn transformation_create<'a>(&'a self, calibration: &'a Calibration) -> Transformation<'a> {
221        let handle =
222            unsafe { (self.api.funcs.k4a_transformation_create)(&calibration.calibration) };
223        Transformation::from_handle(&self, handle, calibration)
224    }
225
226    extern "C" fn debug_message_handler_func(
227        context: *mut ::std::os::raw::c_void,
228        level: azure_kinect_sys::k4a::k4a_log_level_t,
229        file: *const ::std::os::raw::c_char,
230        line: ::std::os::raw::c_int,
231        message: *const ::std::os::raw::c_char,
232    ) {
233        unsafe {
234            let f = std::mem::transmute::<_, &mut Box<DebugMessageHandler>>(context);
235            f(
236                LogLevel::from_primitive(level),
237                std::ffi::CStr::from_ptr(file).to_str().unwrap_or_default(),
238                line,
239                std::ffi::CStr::from_ptr(message)
240                    .to_str()
241                    .unwrap_or_default(),
242            );
243        }
244    }
245
246    extern "C" fn buffer_release_callback<T: FnOnce(*mut ())>(buffer: *mut (), context: *mut ()) {
247        unsafe {
248            let f = Box::<T>::from_raw(context as _);
249            f(buffer);
250        }
251    }
252}
253
254pub struct FactoryRecord {
255    core: Factory,
256    pub(crate) api_record: azure_kinect_sys::api::ApiRecord,
257}
258
259impl FactoryRecord {
260    pub fn new() -> Result<FactoryRecord, Error> {
261        FactoryRecord::with_api_record(azure_kinect_sys::api::ApiRecord::new()?)
262    }
263
264    pub fn with_library_directory(lib_dir: &str) -> Result<FactoryRecord, Error> {
265        FactoryRecord::with_api_record(azure_kinect_sys::api::ApiRecord::with_library_directory(
266            lib_dir,
267        )?)
268    }
269
270    fn with_api_record(
271        api_record: azure_kinect_sys::api::ApiRecord,
272    ) -> Result<FactoryRecord, Error> {
273        Ok(FactoryRecord {
274            core: Factory::with_get_module()?,
275            api_record,
276        })
277    }
278
279    /// Sets and clears the callback function to receive debug messages from the Azure Kinect device.
280    pub fn set_debug_message_handler(
281        mut self,
282        debug_message_handler: Box<DebugMessageHandler>,
283        min_level: LogLevel,
284    ) -> Self {
285        self.core
286            .set_debug_message_handler_internal(debug_message_handler, min_level);
287        self
288    }
289
290    /// Clears the callback function to receive debug messages from the Azure Kinect device.
291    pub fn reset_debug_message_handler(mut self) -> Self {
292        self.core.reset_debug_message_handler_internal();
293        self
294    }
295
296    pub fn core(&self) -> &Factory {
297        &self.core
298    }
299
300    /// Opens a K4A recording for playback.
301    pub fn playback_open(&self, path: &str) -> Result<Playback, Error> {
302        let mut handle: azure_kinect_sys::k4arecord::k4a_playback_t = ptr::null_mut();
303        let path = CString::new(path).unwrap_or_default();
304        Error::from_k4a_result_t(unsafe {
305            (self.api_record.funcs.k4a_playback_open)(path.as_ptr(), &mut handle)
306        })
307        .to_result_fn(|| Playback::from_handle(&self, handle))
308    }
309
310    /// Opens a new recording file for writing
311    pub fn record_create(
312        &self,
313        path: &str,
314        device: &Device,
315        device_configuration: &DeviceConfiguration,
316    ) -> Result<Record, Error> {
317        let mut handle: azure_kinect_sys::k4arecord::k4a_record_t = ptr::null_mut();
318        let path = CString::new(path).unwrap_or_default();
319        Error::from_k4a_result_t(unsafe {
320            (self.api_record.funcs.k4a_record_create)(
321                path.as_ptr(),
322                device.handle as _,
323                *device_configuration.for_k4arecord(),
324                &mut handle,
325            )
326        })
327        .to_result_fn(|| Record::from_handle(&self.api_record, handle))
328    }
329}
330
331#[cfg(test)]
332mod tests {
333    use crate::factory::PreAllocatedBufferInfo;
334    use crate::*;
335
336    #[test]
337    fn test() -> std::result::Result<(), Box<dyn std::error::Error>> {
338        let manager = Factory::with_library_directory(
339            std::env::current_dir()?.to_str().ok_or(Error::Failed)?,
340        );
341        assert!(manager.is_ok());
342        let manager2 = manager.unwrap();
343        let c = unsafe { (manager2.api.funcs.k4a_device_get_installed_count)() };
344        println!("device count = {}", c);
345        Ok(())
346    }
347
348    #[test]
349    fn test_image_create_from_buffer() -> std::result::Result<(), Box<dyn std::error::Error>> {
350        let factory = Factory::with_library_directory(
351            std::env::current_dir()?.to_str().ok_or(Error::Failed)?,
352        );
353        assert!(factory.is_ok());
354
355        let mut mem = Vec::<u8>::with_capacity(256 * 4 * 256);
356        unsafe {
357            mem.set_len(mem.capacity());
358        }
359
360        let factory = factory.unwrap();
361        let _ = factory.image_create_from_buffer(
362            ImageFormat::BGRA32,
363            255,
364            256,
365            256 * 4,
366            &mut mem[0] as _,
367            mem.len(),
368            Box::new(|x| {
369                assert_eq!(x as *const u8, &mem[0] as *const u8);
370            }),
371        )?;
372
373        Ok(())
374    }
375
376    pub struct BufferInfo {
377        mem: Vec<u8>,
378    }
379
380    impl BufferInfo {
381        pub fn new() -> BufferInfo {
382            let mut mem = Vec::<u8>::with_capacity(256 * 4 * 256);
383            unsafe {
384                mem.set_len(mem.capacity());
385            }
386
387            BufferInfo { mem }
388        }
389    }
390
391    impl PreAllocatedBufferInfo for BufferInfo {
392        fn format(&self) -> ImageFormat {
393            ImageFormat::BGRA32
394        }
395
396        fn width_pixels(&self) -> i32 {
397            256
398        }
399
400        fn height_pixels(&self) -> i32 {
401            256
402        }
403
404        fn stride_bytes(&self) -> i32 {
405            256 * 4
406        }
407
408        fn buffer(&mut self) -> *mut u8 {
409            &mut self.mem[0]
410        }
411
412        fn buffer_size(&self) -> usize {
413            self.mem.len()
414        }
415    }
416
417    impl Drop for BufferInfo {
418        fn drop(&mut self) {
419            println!("drop BufferInfo");
420        }
421    }
422
423    #[test]
424    fn test_image_create_from_buffer_with_info(
425    ) -> std::result::Result<(), Box<dyn std::error::Error>> {
426        let factory = Factory::with_library_directory(
427            std::env::current_dir()?.to_str().ok_or(Error::Failed)?,
428        );
429        assert!(factory.is_ok());
430
431        let factory = factory.unwrap();
432        let buffer_info = Box::new(BufferInfo::new());
433        let _ = factory.image_create_from_buffer_with_info(buffer_info)?;
434
435        Ok(())
436    }
437}