Skip to main content

azure_kinect/
record.rs

1use crate::Capture;
2use crate::*;
3use azure_kinect_sys::k4a::*;
4use azure_kinect_sys::k4arecord::{
5    k4a_record_subtitle_settings_t, k4a_record_t, k4a_record_video_settings_t,
6};
7use std::ffi::CString;
8use std::ptr;
9
10pub struct RecordVideoSettings {
11    pub(crate) value: k4a_record_video_settings_t,
12}
13
14impl RecordVideoSettings {
15    pub fn new(width: u64, height: u64, frame_rate: u64) -> RecordVideoSettings {
16        RecordVideoSettings {
17            value: k4a_record_video_settings_t {
18                width,
19                height,
20                frame_rate,
21            },
22        }
23    }
24
25    #[doc = "< Frame width of the video"]
26    pub fn width(&self) -> u64 {
27        self.value.width
28    }
29    #[doc = "< Frame height of the video"]
30    pub fn height(&self) -> u64 {
31        self.value.height
32    }
33    #[doc = "< Frame rate (frames-per-second) of the video"]
34    pub fn frame_rate(&self) -> u64 {
35        self.value.frame_rate
36    }
37}
38
39pub struct RecordSubtitleSettings {
40    pub(crate) value: k4a_record_subtitle_settings_t,
41}
42
43impl RecordSubtitleSettings {
44    pub fn new(high_freq_data: bool) -> RecordSubtitleSettings {
45        RecordSubtitleSettings {
46            value: k4a_record_subtitle_settings_t { high_freq_data },
47        }
48    }
49
50    pub fn high_freq_data(&self) -> bool {
51        self.value.high_freq_data
52    }
53}
54
55pub struct Record<'a> {
56    pub(crate) api_record: &'a azure_kinect_sys::api::ApiRecord,
57    pub(crate) handle: k4a_record_t,
58}
59
60impl Record<'_> {
61    pub(crate) fn from_handle(
62        api_record: &azure_kinect_sys::api::ApiRecord,
63        handle: k4a_record_t,
64    ) -> Record {
65        Record { api_record, handle }
66    }
67
68    /// Flushes all pending recording data to disk
69    pub fn flush(&self) -> Result<(), Error> {
70        Error::from_k4a_result_t(unsafe { (self.api_record.funcs.k4a_record_flush)(self.handle) })
71            .to_result(())
72    }
73
74    /// Adds a tag to the recording
75    pub fn add_tag(&self, name: &str, value: &str) -> Result<(), Error> {
76        let name = CString::new(name).unwrap_or_default();
77        let value = CString::new(value).unwrap_or_default();
78        Error::from_k4a_result_t(unsafe {
79            (self.api_record.funcs.k4a_record_add_tag)(self.handle, name.as_ptr(), value.as_ptr())
80        })
81        .to_result(())
82    }
83
84    /// Adds the track header for recording IMU
85    pub fn add_imu_track(&self) -> Result<(), Error> {
86        Error::from_k4a_result_t(unsafe {
87            (self.api_record.funcs.k4a_record_add_imu_track)(self.handle)
88        })
89        .to_result(())
90    }
91
92    /// Adds an attachment to the recording
93    pub fn add_attachment(&self, attachment_name: &str, buffer: &[u8]) -> Result<(), Error> {
94        let attachment_name = CString::new(attachment_name).unwrap_or_default();
95        Error::from_k4a_result_t(unsafe {
96            (self.api_record.funcs.k4a_record_add_attachment)(
97                self.handle,
98                attachment_name.as_ptr(),
99                buffer.as_ptr(),
100                buffer.len(),
101            )
102        })
103        .to_result(())
104    }
105
106    /// Adds custom video tracks to the recording
107    pub fn add_custom_video_track(
108        &self,
109        track_name: &str,
110        codec_id: &str,
111        codec_context: &[u8],
112        track_settings: &RecordVideoSettings,
113    ) -> Result<(), Error> {
114        let track_name = CString::new(track_name).unwrap_or_default();
115        let codec_id = CString::new(codec_id).unwrap_or_default();
116        Error::from_k4a_result_t(unsafe {
117            (self.api_record.funcs.k4a_record_add_custom_video_track)(
118                self.handle,
119                track_name.as_ptr(),
120                codec_id.as_ptr(),
121                codec_context.as_ptr(),
122                codec_context.len(),
123                &track_settings.value,
124            )
125        })
126        .to_result(())
127    }
128
129    /// Adds custom subtitle tracks to the recording
130    pub fn add_custom_subtitle_track(
131        &self,
132        track_name: &str,
133        codec_id: &str,
134        codec_context: &[u8],
135        track_settings: &RecordSubtitleSettings,
136    ) -> Result<(), Error> {
137        let track_name = CString::new(track_name).unwrap_or_default();
138        let codec_id = CString::new(codec_id).unwrap_or_default();
139        Error::from_k4a_result_t(unsafe {
140            (self.api_record.funcs.k4a_record_add_custom_subtitle_track)(
141                self.handle,
142                track_name.as_ptr(),
143                codec_id.as_ptr(),
144                codec_context.as_ptr(),
145                codec_context.len(),
146                &track_settings.value,
147            )
148        })
149        .to_result(())
150    }
151
152    /// Writes the recording header and metadata to file
153    pub fn write_header(&self) -> Result<(), Error> {
154        Error::from_k4a_result_t(unsafe {
155            (self.api_record.funcs.k4a_record_write_header)(self.handle)
156        })
157        .to_result(())
158    }
159
160    /// Writes a camera capture to file
161    pub fn write_capture(&self, capture: &Capture) -> Result<(), Error> {
162        Error::from_k4a_result_t(unsafe {
163            (self.api_record.funcs.k4a_record_write_capture)(self.handle, capture.handle as _)
164        })
165        .to_result(())
166    }
167
168    /// Writes an imu sample to file
169    pub fn write_imu_sample(&self, imu_sample: &ImuSample) -> Result<(), Error> {
170        Error::from_k4a_result_t(unsafe {
171            (self.api_record.funcs.k4a_record_write_imu_sample)(
172                self.handle,
173                std::mem::transmute::<k4a_imu_sample_t, _>(imu_sample.value),
174            )
175        })
176        .to_result(())
177    }
178
179    pub fn write_custom_track_data(
180        &self,
181        track_name: &str,
182        device_timestamp_usec: u64,
183        custom_data: &[u8],
184    ) -> Result<(), Error> {
185        let track_name = CString::new(track_name).unwrap_or_default();
186        Error::from_k4a_result_t(unsafe {
187            (self.api_record.funcs.k4a_record_write_custom_track_data)(
188                self.handle,
189                track_name.as_ptr(),
190                device_timestamp_usec,
191                custom_data.as_ptr() as *mut u8,
192                custom_data.len(),
193            )
194        })
195        .to_result(())
196    }
197}
198
199impl Drop for Record<'_> {
200    fn drop(&mut self) {
201        unsafe {
202            (self.api_record.funcs.k4a_record_close)(self.handle);
203        }
204        self.handle = ptr::null_mut();
205    }
206}