kinect_v2/
multi_source_capture.rs1use kinect_v2_sys::{
2 ColorImageFormat, DEFAULT_FRAME_WAIT_TIMEOUT_MS, WAITABLE_HANDLE,
3 bindings::FrameSourceTypes,
4 kinect::{self, KinectSensor},
5 multi_source_frame::{MultiSourceFrame, MultiSourceFrameReader},
6};
7use windows::Win32::Foundation::{E_FAIL, WAIT_OBJECT_0, WAIT_TIMEOUT};
8use windows::Win32::System::Threading::WaitForSingleObject;
9use windows::{Win32::Foundation::WAIT_EVENT, core::Error};
10
11use crate::{
12 body_capture::BodyFrameData, body_index_capture::BodyIndexFrameData,
13 color_capture::ColorFrameData, depth_capture::DepthFrameData,
14 infrared_capture::InfraredFrameData,
15};
16
17pub struct MultiSourceCapture {
18 kinect: KinectSensor,
19}
20
21impl MultiSourceCapture {
22 pub fn new() -> Result<Self, windows::core::Error> {
31 let kinect = kinect::get_default_kinect_sensor()?;
32 kinect.open()?;
33
34 Ok(MultiSourceCapture { kinect })
35 }
36
37 pub fn iter(&self) -> Result<MultiSourceCaptureIter, Error> {
48 let enabled_frame_source_types = FrameSourceTypes::Color
49 | FrameSourceTypes::Depth
50 | FrameSourceTypes::Infrared
51 | FrameSourceTypes::BodyIndex
52 | FrameSourceTypes::Body;
53 let reader = self
54 .kinect
55 .open_multi_source_frame_reader(enabled_frame_source_types)?;
56
57 let mut waitable_handle = WAITABLE_HANDLE::default();
58 reader.subscribe_multi_source_frame_arrived(&mut waitable_handle)?;
59 Ok(MultiSourceCaptureIter {
60 reader,
61 waitable_handle,
62 timeout_ms: DEFAULT_FRAME_WAIT_TIMEOUT_MS,
63 })
64 }
65}
66
67pub struct MultiSourceCaptureIter {
72 reader: MultiSourceFrameReader,
73 waitable_handle: WAITABLE_HANDLE,
74 timeout_ms: u32,
75}
76
77impl Drop for MultiSourceCaptureIter {
78 fn drop(&mut self) {
79 if let Err(e) = self
82 .reader
83 .unsubscribe_multi_source_frame_arrived(self.waitable_handle)
84 {
85 log::warn!("Failed to unsubscribe multi-source frame arrived event: {e:?}");
86 }
87 }
88}
89
90impl Iterator for MultiSourceCaptureIter {
91 type Item = Result<MultiSourceFrameData, Error>;
92
93 fn next(&mut self) -> Option<Self::Item> {
94 loop {
95 let wait_status: WAIT_EVENT =
96 unsafe { WaitForSingleObject(self.waitable_handle, self.timeout_ms) };
97
98 if wait_status == WAIT_OBJECT_0 {
99 let result = (|| {
102 let event_args = self
103 .reader
104 .get_multi_source_frame_arrived_event_data(self.waitable_handle)?;
105 let frame_reference = event_args.get_frame_reference()?;
106 let multi_source_frame = frame_reference.acquire_frame()?;
107 MultiSourceFrameData::new(&multi_source_frame)
108 })(); return Some(result);
110 } else if wait_status == WAIT_TIMEOUT {
111 continue;
114 } else {
115 return Some(Err(Error::from_hresult(E_FAIL)));
116 }
117 }
118 }
119}
120
121#[derive(Debug)]
126pub struct MultiSourceFrameData {
127 pub color_frame: Option<ColorFrameData>,
128 pub depth_frame: Option<DepthFrameData>,
129 pub infrared_frame: Option<InfraredFrameData>,
130 pub body_index_frame: Option<BodyIndexFrameData>,
131 pub body_frame: Option<BodyFrameData>,
132}
133
134impl MultiSourceFrameData {
135 pub fn new(multi_source_frame: &MultiSourceFrame) -> Result<Self, Error> {
136 let color_frame = Self::get_color_frame_data(multi_source_frame, None);
138 let depth_frame = Self::get_depth_frame_data(multi_source_frame);
139 let infrared_frame = Self::get_infrared_frame_data(multi_source_frame);
140 let body_index_frame = Self::get_body_index_frame_data(multi_source_frame);
141 let body_frame = Self::get_body_frame_data(multi_source_frame);
142
143 Ok(Self {
144 color_frame,
145 depth_frame,
146 infrared_frame,
147 body_index_frame,
148 body_frame,
149 })
150 }
151
152 fn get_color_frame_data(
153 multi_source_frame: &MultiSourceFrame,
154 format: Option<ColorImageFormat>,
155 ) -> Option<ColorFrameData> {
156 let color_frame_reference = multi_source_frame.get_color_frame_reference().ok()?;
157 let color_frame = color_frame_reference.acquire_frame().ok()?;
158 ColorFrameData::new(&color_frame, format).ok()
159 }
160
161 fn get_depth_frame_data(multi_source_frame: &MultiSourceFrame) -> Option<DepthFrameData> {
162 let depth_frame_reference = multi_source_frame.get_depth_frame_reference().ok()?;
163 let depth_frame = depth_frame_reference.acquire_frame().ok()?;
164 DepthFrameData::new(&depth_frame).ok()
165 }
166
167 fn get_infrared_frame_data(multi_source_frame: &MultiSourceFrame) -> Option<InfraredFrameData> {
168 let infrared_frame_reference = multi_source_frame.get_infrared_frame_reference().ok()?;
169 let infrared_frame = infrared_frame_reference.acquire_frame().ok()?;
170 InfraredFrameData::new(&infrared_frame).ok()
171 }
172
173 fn get_body_index_frame_data(
174 multi_source_frame: &MultiSourceFrame,
175 ) -> Option<BodyIndexFrameData> {
176 let body_index_frame_reference =
177 multi_source_frame.get_body_index_frame_reference().ok()?;
178 let body_index_frame = body_index_frame_reference.acquire_frame().ok()?;
179 BodyIndexFrameData::new(&body_index_frame).ok()
180 }
181
182 fn get_body_frame_data(multi_source_frame: &MultiSourceFrame) -> Option<BodyFrameData> {
183 let body_frame_reference = multi_source_frame.get_body_frame_reference().ok()?;
184 let body_frame = body_frame_reference.acquire_frame().ok()?;
185 BodyFrameData::new(&body_frame).ok()
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192 use anyhow::anyhow;
193 use std::sync::mpsc;
194
195 #[test]
196 fn multi_source_capture_test() -> anyhow::Result<()> {
197 let (tx, rx) = mpsc::channel::<MultiSourceFrameData>();
198 let max_frames_to_capture = 10;
199 let capture_thread = std::thread::spawn(move || -> anyhow::Result<()> {
200 let capture = MultiSourceCapture::new()?;
201 for (frame_count, frame) in capture.iter()?.enumerate() {
202 if frame_count >= max_frames_to_capture {
203 break;
204 }
205 let data =
206 frame.map_err(|e| anyhow!("Error capturing multi-source frame: {}", e))?;
207 if tx.send(data).is_err() {
208 break;
209 }
210 }
211 Ok(())
212 });
213
214 let processing_thread = std::thread::spawn(move || -> anyhow::Result<()> {
215 for _ in 0..max_frames_to_capture {
216 let frame_data = match rx.recv() {
217 Ok(data) => data,
218 Err(_) => break,
219 };
220 println!("Received multi-source frame");
221 anyhow::ensure!(
223 frame_data.color_frame.is_some()
224 || frame_data.depth_frame.is_some()
225 || frame_data.infrared_frame.is_some()
226 || frame_data.body_index_frame.is_some()
227 || frame_data.body_frame.is_some(),
228 "No frame data present in multi-source frame"
229 );
230 }
231 Ok(())
232 });
233
234 capture_thread
235 .join()
236 .map_err(|e| anyhow!("Multi-source capture thread join error: {:?}", e))??;
237 processing_thread
238 .join()
239 .map_err(|e| anyhow!("Processing thread join error: {:?}", e))??;
240 Ok(())
241 }
242}