kinect_v2_sys/
depth.rs

1use crate::bindings::{
2    BOOLEAN, IDepthFrame, IDepthFrameArrivedEventArgs, IDepthFrameReader, IDepthFrameReference,
3    IDepthFrameSource, IFrameCapturedEventArgs, IFrameDescription, IKinectSensor, TIMESPAN, UINT,
4    UINT16, WAITABLE_HANDLE,
5};
6use crate::frame::{FrameCapturedEventArgs, FrameDescription};
7use crate::kinect::KinectSensor;
8use std::ptr;
9use windows::{
10    Win32::Foundation::{E_FAIL, E_POINTER},
11    core::Error,
12};
13
14pub struct DepthFrameSource {
15    ptr: *mut IDepthFrameSource,
16}
17
18impl DepthFrameSource {
19    pub(crate) fn new(ptr: *mut IDepthFrameSource) -> Self {
20        assert!(!ptr.is_null());
21        Self { ptr }
22    }
23
24    pub fn subscribe_frame_captured(&self) -> Result<WAITABLE_HANDLE, Error> {
25        if self.ptr.is_null() {
26            return Err(Error::from_hresult(E_POINTER));
27        }
28        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
29        let subscribe_fn = vtbl.SubscribeFrameCaptured.ok_or(E_FAIL)?;
30        let mut waitable_handle: WAITABLE_HANDLE = windows::Win32::Foundation::HANDLE::default();
31        let hr = unsafe { subscribe_fn(self.ptr, &mut waitable_handle) };
32        if hr.is_ok() {
33            Ok(waitable_handle)
34        } else {
35            Err(Error::from_hresult(hr))
36        }
37    }
38
39    pub fn unsubscribe_frame_captured(
40        &self,
41        waitable_handle: WAITABLE_HANDLE,
42    ) -> Result<(), Error> {
43        if self.ptr.is_null() {
44            return Err(Error::from_hresult(E_POINTER));
45        }
46        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
47        let unsubscribe_fn = vtbl.UnsubscribeFrameCaptured.ok_or(E_FAIL)?;
48        let hr = unsafe { unsubscribe_fn(self.ptr, waitable_handle) };
49        if hr.is_ok() {
50            Ok(())
51        } else {
52            Err(Error::from_hresult(hr))
53        }
54    }
55
56    pub fn get_frame_captured_event_data(
57        &self,
58        waitable_handle: WAITABLE_HANDLE,
59    ) -> Result<FrameCapturedEventArgs, Error> {
60        if self.ptr.is_null() {
61            return Err(Error::from_hresult(E_POINTER));
62        }
63        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
64        let get_data_fn = vtbl.GetFrameCapturedEventData.ok_or(E_FAIL)?;
65        let mut event_data: *mut IFrameCapturedEventArgs = ptr::null_mut();
66        let hr = unsafe { get_data_fn(self.ptr, waitable_handle, &mut event_data) };
67        if hr.is_ok() {
68            Ok(FrameCapturedEventArgs::new(event_data))
69        } else {
70            Err(Error::from_hresult(hr))
71        }
72    }
73
74    pub fn get_is_active(&self) -> Result<bool, Error> {
75        if self.ptr.is_null() {
76            return Err(Error::from_hresult(E_POINTER));
77        }
78        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
79        let get_active_fn = vtbl.get_IsActive.ok_or(E_FAIL)?;
80        let mut is_active: BOOLEAN = 0;
81        let hr = unsafe { get_active_fn(self.ptr, &mut is_active) };
82        if hr.is_ok() {
83            Ok(is_active != 0)
84        } else {
85            Err(Error::from_hresult(hr))
86        }
87    }
88
89    pub fn open_reader(&self) -> Result<DepthFrameReader, Error> {
90        if self.ptr.is_null() {
91            return Err(Error::from_hresult(E_POINTER));
92        }
93        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
94        let open_fn = vtbl.OpenReader.ok_or(E_FAIL)?;
95        let mut reader_ptr: *mut IDepthFrameReader = ptr::null_mut();
96        let hr = unsafe { open_fn(self.ptr, &mut reader_ptr) };
97        if hr.is_ok() {
98            Ok(DepthFrameReader::new(reader_ptr))
99        } else {
100            Err(Error::from_hresult(hr))
101        }
102    }
103
104    pub fn get_depth_min_reliable_distance(&self) -> Result<UINT16, Error> {
105        if self.ptr.is_null() {
106            return Err(Error::from_hresult(E_POINTER));
107        }
108        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
109        let get_fn = vtbl.get_DepthMinReliableDistance.ok_or(E_FAIL)?;
110        let mut distance: UINT16 = 0;
111        let hr = unsafe { get_fn(self.ptr, &mut distance) };
112        if hr.is_ok() {
113            Ok(distance)
114        } else {
115            Err(Error::from_hresult(hr))
116        }
117    }
118
119    pub fn get_depth_max_reliable_distance(&self) -> Result<UINT16, Error> {
120        if self.ptr.is_null() {
121            return Err(Error::from_hresult(E_POINTER));
122        }
123        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
124        let get_fn = vtbl.get_DepthMaxReliableDistance.ok_or(E_FAIL)?;
125        let mut distance: UINT16 = 0;
126        let hr = unsafe { get_fn(self.ptr, &mut distance) };
127        if hr.is_ok() {
128            Ok(distance)
129        } else {
130            Err(Error::from_hresult(hr))
131        }
132    }
133
134    pub fn get_frame_description(&self) -> Result<FrameDescription, Error> {
135        if self.ptr.is_null() {
136            return Err(Error::from_hresult(E_POINTER));
137        }
138        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
139        let get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
140        let mut frame_description_ptr: *mut IFrameDescription = ptr::null_mut();
141        let hr = unsafe { get_fn(self.ptr, &mut frame_description_ptr) };
142        if hr.is_ok() {
143            Ok(FrameDescription::new(frame_description_ptr))
144        } else {
145            Err(Error::from_hresult(hr))
146        }
147    }
148
149    pub fn get_kinect_sensor(&self) -> Result<KinectSensor, Error> {
150        if self.ptr.is_null() {
151            return Err(Error::from_hresult(E_POINTER));
152        }
153        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
154        let get_fn = vtbl.get_KinectSensor.ok_or(E_FAIL)?;
155        let mut sensor_ptr: *mut IKinectSensor = ptr::null_mut();
156        let hr = unsafe { get_fn(self.ptr, &mut sensor_ptr) };
157        if hr.is_ok() {
158            Ok(KinectSensor::new(sensor_ptr))
159        } else {
160            Err(Error::from_hresult(hr))
161        }
162    }
163}
164
165impl Drop for DepthFrameSource {
166    fn drop(&mut self) {
167        if !self.ptr.is_null() {
168            unsafe {
169                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
170                    && let Some(release_fn) = vtbl.Release
171                {
172                    release_fn(self.ptr);
173                }
174            }
175            self.ptr = ptr::null_mut();
176        }
177    }
178}
179
180pub struct DepthFrameReader {
181    ptr: *mut IDepthFrameReader,
182}
183
184impl DepthFrameReader {
185    pub(crate) fn new(ptr: *mut IDepthFrameReader) -> Self {
186        assert!(!ptr.is_null());
187        Self { ptr }
188    }
189
190    pub fn subscribe_frame_arrived(&self) -> Result<WAITABLE_HANDLE, Error> {
191        if self.ptr.is_null() {
192            return Err(Error::from_hresult(E_POINTER));
193        }
194        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
195        let subscribe_fn = vtbl.SubscribeFrameArrived.ok_or(E_FAIL)?;
196        let mut waitable_handle: WAITABLE_HANDLE = windows::Win32::Foundation::HANDLE::default();
197        let hr = unsafe { subscribe_fn(self.ptr, &mut waitable_handle) };
198        if hr.is_ok() {
199            Ok(waitable_handle)
200        } else {
201            Err(Error::from_hresult(hr))
202        }
203    }
204
205    pub fn unsubscribe_frame_arrived(&self, waitable_handle: WAITABLE_HANDLE) -> Result<(), Error> {
206        if self.ptr.is_null() {
207            return Err(Error::from_hresult(E_POINTER));
208        }
209        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
210        let unsubscribe_fn = vtbl.UnsubscribeFrameArrived.ok_or(E_FAIL)?;
211        let hr = unsafe { unsubscribe_fn(self.ptr, waitable_handle) };
212        if hr.is_ok() {
213            Ok(())
214        } else {
215            Err(Error::from_hresult(hr))
216        }
217    }
218
219    pub fn get_frame_arrived_event_data(
220        &self,
221        waitable_handle: WAITABLE_HANDLE,
222    ) -> Result<DepthFrameArrivedEventArgs, Error> {
223        if self.ptr.is_null() {
224            return Err(Error::from_hresult(E_POINTER));
225        }
226        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
227        let get_fn = vtbl.GetFrameArrivedEventData.ok_or(E_FAIL)?;
228        let mut args_ptr: *mut IDepthFrameArrivedEventArgs = ptr::null_mut();
229        let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
230        if hr.is_ok() {
231            Ok(DepthFrameArrivedEventArgs::new(args_ptr))
232        } else {
233            Err(Error::from_hresult(hr))
234        }
235    }
236
237    pub fn acquire_latest_frame(&self) -> Result<DepthFrame, Error> {
238        if self.ptr.is_null() {
239            return Err(Error::from_hresult(E_POINTER));
240        }
241        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
242        let acquire_fn = vtbl.AcquireLatestFrame.ok_or(E_FAIL)?;
243        let mut frame_ptr: *mut IDepthFrame = ptr::null_mut();
244        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
245        if hr.is_ok() {
246            Ok(DepthFrame::new(frame_ptr))
247        } else {
248            Err(Error::from_hresult(hr))
249        }
250    }
251
252    pub fn get_is_paused(&self) -> Result<bool, Error> {
253        if self.ptr.is_null() {
254            return Err(Error::from_hresult(E_POINTER));
255        }
256        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
257        let get_fn = vtbl.get_IsPaused.ok_or(E_FAIL)?;
258        let mut is_paused: BOOLEAN = 0;
259        let hr = unsafe { get_fn(self.ptr, &mut is_paused) };
260        if hr.is_ok() {
261            Ok(is_paused != 0)
262        } else {
263            Err(Error::from_hresult(hr))
264        }
265    }
266
267    pub fn set_is_paused(&self, is_paused: bool) -> Result<(), Error> {
268        if self.ptr.is_null() {
269            return Err(Error::from_hresult(E_POINTER));
270        }
271        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
272        let put_fn = vtbl.put_IsPaused.ok_or(E_FAIL)?;
273        let paused_value: BOOLEAN = if is_paused { 1 } else { 0 };
274        let hr = unsafe { put_fn(self.ptr, paused_value) };
275        if hr.is_ok() {
276            Ok(())
277        } else {
278            Err(Error::from_hresult(hr))
279        }
280    }
281
282    pub fn get_depth_frame_source(&self) -> Result<DepthFrameSource, Error> {
283        if self.ptr.is_null() {
284            return Err(Error::from_hresult(E_POINTER));
285        }
286        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
287        let get_fn = vtbl.get_DepthFrameSource.ok_or(E_FAIL)?;
288        let mut source_ptr: *mut IDepthFrameSource = ptr::null_mut();
289        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
290        if hr.is_ok() {
291            Ok(DepthFrameSource::new(source_ptr))
292        } else {
293            Err(Error::from_hresult(hr))
294        }
295    }
296}
297
298impl Drop for DepthFrameReader {
299    fn drop(&mut self) {
300        if !self.ptr.is_null() {
301            unsafe {
302                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
303                    && let Some(release_fn) = vtbl.Release
304                {
305                    release_fn(self.ptr);
306                }
307            }
308            self.ptr = ptr::null_mut();
309        }
310    }
311}
312
313pub struct DepthFrameArrivedEventArgs {
314    ptr: *mut IDepthFrameArrivedEventArgs,
315}
316
317impl DepthFrameArrivedEventArgs {
318    pub(crate) fn new(ptr: *mut IDepthFrameArrivedEventArgs) -> Self {
319        assert!(!ptr.is_null());
320        Self { ptr }
321    }
322
323    pub fn get_frame_reference(&self) -> Result<DepthFrameReference, Error> {
324        if self.ptr.is_null() {
325            return Err(Error::from_hresult(E_POINTER));
326        }
327        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
328        let get_fn = vtbl.get_FrameReference.ok_or(E_FAIL)?;
329        let mut ref_ptr: *mut IDepthFrameReference = ptr::null_mut();
330        let hr = unsafe { get_fn(self.ptr, &mut ref_ptr) };
331        if hr.is_ok() {
332            Ok(DepthFrameReference::new(ref_ptr))
333        } else {
334            Err(Error::from_hresult(hr))
335        }
336    }
337}
338
339impl Drop for DepthFrameArrivedEventArgs {
340    fn drop(&mut self) {
341        if !self.ptr.is_null() {
342            unsafe {
343                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
344                    && let Some(release_fn) = vtbl.Release
345                {
346                    release_fn(self.ptr);
347                }
348            }
349            self.ptr = ptr::null_mut();
350        }
351    }
352}
353
354pub struct DepthFrameReference {
355    ptr: *mut IDepthFrameReference,
356}
357
358impl DepthFrameReference {
359    pub(crate) fn new(ptr: *mut IDepthFrameReference) -> Self {
360        assert!(!ptr.is_null());
361        Self { ptr }
362    }
363
364    pub fn acquire_frame(&self) -> Result<DepthFrame, Error> {
365        if self.ptr.is_null() {
366            return Err(Error::from_hresult(E_POINTER));
367        }
368        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
369        let acquire_fn = vtbl.AcquireFrame.ok_or(E_FAIL)?;
370        let mut frame_ptr: *mut IDepthFrame = ptr::null_mut();
371        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
372        if hr.is_ok() {
373            Ok(DepthFrame::new(frame_ptr))
374        } else {
375            Err(Error::from_hresult(hr))
376        }
377    }
378
379    pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
380        if self.ptr.is_null() {
381            return Err(Error::from_hresult(E_POINTER));
382        }
383        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
384        let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
385        let mut time: TIMESPAN = 0;
386        let hr = unsafe { get_fn(self.ptr, &mut time) };
387        if hr.is_ok() {
388            Ok(time)
389        } else {
390            Err(Error::from_hresult(hr))
391        }
392    }
393}
394
395impl Drop for DepthFrameReference {
396    fn drop(&mut self) {
397        if !self.ptr.is_null() {
398            unsafe {
399                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
400                    && let Some(release_fn) = vtbl.Release
401                {
402                    release_fn(self.ptr);
403                }
404            }
405            self.ptr = ptr::null_mut();
406        }
407    }
408}
409
410pub struct DepthFrame {
411    ptr: *mut IDepthFrame,
412}
413
414impl DepthFrame {
415    pub(crate) fn new(ptr: *mut IDepthFrame) -> Self {
416        assert!(!ptr.is_null());
417        Self { ptr }
418    }
419    pub fn copy_frame_data_to_array(&self, frame_data: &mut [u16]) -> Result<(), Error> {
420        if self.ptr.is_null() {
421            return Err(Error::from_hresult(E_POINTER));
422        }
423        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
424        let copy_fn = vtbl.CopyFrameDataToArray.ok_or(E_FAIL)?;
425        let capacity = frame_data.len() as UINT;
426        let hr = unsafe { copy_fn(self.ptr, capacity, frame_data.as_mut_ptr()) };
427        if hr.is_ok() {
428            Ok(())
429        } else {
430            Err(Error::from_hresult(hr))
431        }
432    }
433    pub fn access_underlying_buffer(&self) -> Result<&[u16], Error> {
434        if self.ptr.is_null() {
435            return Err(Error::from_hresult(E_POINTER));
436        }
437        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
438        let access_fn = vtbl.AccessUnderlyingBuffer.ok_or(E_FAIL)?;
439        let mut capacity: UINT = 0;
440        let mut buffer: *mut UINT16 = ptr::null_mut();
441        let hr = unsafe { access_fn(self.ptr, &mut capacity, &mut buffer) };
442        if hr.is_ok() {
443            if buffer.is_null() || capacity == 0 {
444                Err(Error::from_hresult(E_POINTER))
445            } else {
446                // Create a safe slice from the raw pointer
447                let slice =
448                    unsafe { std::slice::from_raw_parts(buffer as *const u16, capacity as usize) };
449                Ok(slice)
450            }
451        } else {
452            Err(Error::from_hresult(hr))
453        }
454    }
455
456    pub fn get_frame_description(&self) -> Result<FrameDescription, Error> {
457        if self.ptr.is_null() {
458            return Err(Error::from_hresult(E_POINTER));
459        }
460        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
461        let get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
462        let mut frame_description_ptr: *mut IFrameDescription = ptr::null_mut();
463        let hr = unsafe { get_fn(self.ptr, &mut frame_description_ptr) };
464        if hr.is_ok() {
465            Ok(FrameDescription::new(frame_description_ptr))
466        } else {
467            Err(Error::from_hresult(hr))
468        }
469    }
470
471    pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
472        if self.ptr.is_null() {
473            return Err(Error::from_hresult(E_POINTER));
474        }
475        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
476        let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
477        let mut time: TIMESPAN = 0;
478        let hr = unsafe { get_fn(self.ptr, &mut time) };
479        if hr.is_ok() {
480            Ok(time)
481        } else {
482            Err(Error::from_hresult(hr))
483        }
484    }
485
486    pub fn get_depth_frame_source(&self) -> Result<DepthFrameSource, Error> {
487        if self.ptr.is_null() {
488            return Err(Error::from_hresult(E_POINTER));
489        }
490        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
491        let get_fn = vtbl.get_DepthFrameSource.ok_or(E_FAIL)?;
492        let mut source_ptr: *mut IDepthFrameSource = ptr::null_mut();
493        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
494        if hr.is_ok() {
495            Ok(DepthFrameSource::new(source_ptr))
496        } else {
497            Err(Error::from_hresult(hr))
498        }
499    }
500
501    pub fn get_depth_min_reliable_distance(&self) -> Result<UINT16, Error> {
502        if self.ptr.is_null() {
503            return Err(Error::from_hresult(E_POINTER));
504        }
505        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
506        let get_fn = vtbl.get_DepthMinReliableDistance.ok_or(E_FAIL)?;
507        let mut distance: UINT16 = 0;
508        let hr = unsafe { get_fn(self.ptr, &mut distance) };
509        if hr.is_ok() {
510            Ok(distance)
511        } else {
512            Err(Error::from_hresult(hr))
513        }
514    }
515
516    pub fn get_depth_max_reliable_distance(&self) -> Result<UINT16, Error> {
517        if self.ptr.is_null() {
518            return Err(Error::from_hresult(E_POINTER));
519        }
520        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
521        let get_fn = vtbl.get_DepthMaxReliableDistance.ok_or(E_FAIL)?;
522        let mut distance: UINT16 = 0;
523        let hr = unsafe { get_fn(self.ptr, &mut distance) };
524        if hr.is_ok() {
525            Ok(distance)
526        } else {
527            Err(Error::from_hresult(hr))
528        }
529    }
530}
531
532impl Drop for DepthFrame {
533    fn drop(&mut self) {
534        if !self.ptr.is_null() {
535            unsafe {
536                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
537                    && let Some(release_fn) = vtbl.Release
538                {
539                    release_fn(self.ptr);
540                }
541            }
542            self.ptr = ptr::null_mut();
543        }
544    }
545}
546
547// tests
548#[cfg(test)]
549mod tests {
550    use std::{thread, time::Duration};
551
552    use crate::{DEFAULT_FRAME_WAIT_TIMEOUT_MS, kinect};
553    use anyhow::Context;
554    use windows::Win32::{
555        Foundation::{WAIT_OBJECT_0, WAIT_TIMEOUT},
556        System::{Com::Urlmon::E_PENDING, Threading::WaitForSingleObject},
557    };
558
559    #[test]
560    fn get_latest_depth_frame() -> anyhow::Result<()> {
561        let kinect = kinect::get_default_kinect_sensor()?;
562        kinect.open()?;
563        let depth_frame_source = kinect.depth_frame_source()?;
564        let depth_frame_reader = depth_frame_source.open_reader()?;
565
566        let mut frame_count = 0;
567        loop {
568            match depth_frame_reader.acquire_latest_frame() {
569                Ok(depth_frame) => {
570                    let frame_description = depth_frame.get_frame_description()?;
571                    let width = frame_description.get_width()?;
572                    let height = frame_description.get_height()?;
573                    assert_eq!(width, 512);
574                    assert_eq!(height, 424);
575                    frame_count += 1;
576
577                    if frame_count > 10 {
578                        break; // Exit after getting 10 frames
579                    }
580                }
581                Err(e) => {
582                    if e.code() == E_PENDING {
583                        // If the frame is not ready yet, wait and try again
584                        thread::sleep(Duration::from_millis(100));
585                    } else {
586                        // If it's a different error, return it
587                        return Err(anyhow::Error::new(e));
588                    }
589                }
590            }
591        }
592
593        Ok(())
594    }
595
596    #[test]
597    fn subscribe_depth_frame_arrived_event() -> anyhow::Result<()> {
598        let kinect_sensor = kinect::get_default_kinect_sensor()?;
599        kinect_sensor.open()?;
600
601        let depth_frame_source = kinect_sensor
602            .depth_frame_source()
603            .context("Failed to get depth frame source")?;
604
605        let depth_frame_reader = depth_frame_source.open_reader()?;
606        let waitable_handle = depth_frame_reader.subscribe_frame_arrived()?;
607        let mut frame_count = 0;
608
609        let is_active = depth_frame_source.get_is_active()?;
610        assert!(is_active, "Depth frame source should be active");
611
612        loop {
613            let result =
614                unsafe { WaitForSingleObject(waitable_handle, DEFAULT_FRAME_WAIT_TIMEOUT_MS) };
615            if result == WAIT_OBJECT_0 {
616                let event_args =
617                    depth_frame_reader.get_frame_arrived_event_data(waitable_handle)?;
618                let frame_reference = event_args.get_frame_reference()?;
619                let depth_frame = frame_reference.acquire_frame()?;
620                let frame_description = depth_frame.get_frame_description()?;
621                let width = frame_description.get_width()? as u32;
622                let height = frame_description.get_height()? as u32;
623                let rel_time = frame_reference.get_relative_time()?;
624                let bytes_per_pixel = frame_description.get_bytes_per_pixel()?;
625
626                assert_eq!(width, 512);
627                assert_eq!(height, 424);
628                assert!(rel_time > 0);
629                assert_eq!(bytes_per_pixel, 2); // The capacity for CopyFrameDataToArray is the number of UINT16 elements.
630                // A depth frame consists of width * height pixels, where each pixel is a UINT16.
631                let capacity = width * height;
632                let mut frame_data: Vec<u16> = vec![0; capacity as usize];
633                depth_frame
634                    .copy_frame_data_to_array(&mut frame_data)
635                    .context("Failed to copy depth frame data to array")?;
636                println!("depth frame data len: {:?}", frame_data.len());
637
638                frame_count += 1;
639                if frame_count > 10 {
640                    break; // Exit after getting 10 frames
641                }
642            } else if result == WAIT_TIMEOUT {
643                println!("No new depth frame arrived within the timeout period");
644            } else {
645                eprintln!("Error waiting for depth frame: {result:?}");
646                break;
647            }
648        }
649
650        Ok(())
651    }
652}