1use crate::{
2 ColorImageFormat,
3 bindings::{
4 BOOLEAN, IColorCameraSettings, IColorFrame, IColorFrameArrivedEventArgs, IColorFrameReader,
5 IColorFrameReference, IColorFrameSource, IFrameCapturedEventArgs, IFrameDescription,
6 IKinectSensor, TIMESPAN, WAITABLE_HANDLE,
7 },
8 frame::{FrameCapturedEventArgs, FrameDescription},
9 kinect::KinectSensor,
10};
11use std::ptr;
12use windows::{
13 Win32::Foundation::{E_FAIL, E_INVALIDARG, E_POINTER},
14 core::Error,
15};
16
17#[derive(Debug, Clone)]
18pub struct ColorFrame {
19 ptr: *mut IColorFrame,
20}
21
22impl ColorFrame {
23 pub(crate) fn new(ptr: *mut IColorFrame) -> Self {
24 assert!(!ptr.is_null(), "ColorFrame pointer cannot be null");
25 Self { ptr }
26 }
27
28 pub fn get_frame_description(&self) -> Result<FrameDescription, Error> {
29 if self.ptr.is_null() {
30 return Err(Error::from_hresult(E_POINTER));
31 }
32 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
33 let get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
34 let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
35 let hr = unsafe { get_fn(self.ptr, &mut desc_ptr) };
36 if hr.is_ok() {
37 Ok(FrameDescription::new(desc_ptr))
38 } else {
39 Err(Error::from_hresult(hr))
40 }
41 }
42
43 pub fn get_raw_color_image_format(&self) -> Result<ColorImageFormat, Error> {
44 if self.ptr.is_null() {
45 return Err(Error::from_hresult(E_POINTER));
46 }
47 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
48 let get_fn = vtbl.get_RawColorImageFormat.ok_or(E_FAIL)?;
49 let mut format: ColorImageFormat = ColorImageFormat::None;
50 let hr = unsafe { get_fn(self.ptr, &mut format) };
51 if hr.is_ok() {
52 Ok(format)
53 } else {
54 Err(Error::from_hresult(hr))
55 }
56 }
57 pub fn copy_raw_frame_data_to_array(&self, frame_data: &mut [u8]) -> Result<(), Error> {
58 if self.ptr.is_null() {
59 return Err(Error::from_hresult(E_POINTER));
60 }
61 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
62 let copy_fn = vtbl.CopyRawFrameDataToArray.ok_or(E_FAIL)?;
63 let capacity = frame_data.len() as u32;
64 let hr = unsafe { copy_fn(self.ptr, capacity, frame_data.as_mut_ptr()) };
65 if hr.is_ok() {
66 Ok(())
67 } else {
68 Err(Error::from_hresult(hr))
69 }
70 }
71 pub fn access_raw_underlying_buffer(&self) -> Result<&[u8], Error> {
72 if self.ptr.is_null() {
73 return Err(Error::from_hresult(E_POINTER));
74 }
75 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
76 let access_fn = vtbl.AccessRawUnderlyingBuffer.ok_or(E_FAIL)?;
77 let mut capacity: u32 = 0;
78 let mut buffer: *mut u8 = ptr::null_mut();
79 let hr = unsafe { access_fn(self.ptr, &mut capacity, &mut buffer) };
80 if hr.is_ok() {
81 if buffer.is_null() || capacity == 0 {
82 Err(Error::from_hresult(E_POINTER))
83 } else {
84 let slice =
86 unsafe { std::slice::from_raw_parts(buffer as *const u8, capacity as usize) };
87 Ok(slice)
88 }
89 } else {
90 Err(Error::from_hresult(hr))
91 }
92 }
93 pub fn copy_converted_frame_data_to_array(
94 &self,
95 frame_data: &mut [u8],
96 color_format: ColorImageFormat,
97 ) -> Result<(), Error> {
98 if self.ptr.is_null() {
99 return Err(Error::from_hresult(E_POINTER));
100 }
101 if frame_data.is_empty() || matches!(color_format, ColorImageFormat::None) {
103 return Err(Error::from_hresult(E_INVALIDARG));
104 }
105 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
106 let copy_fn = vtbl.CopyConvertedFrameDataToArray.ok_or(E_FAIL)?;
107
108 let capacity =
110 u32::try_from(frame_data.len()).map_err(|_| Error::from_hresult(E_INVALIDARG))?;
111
112 let hr = unsafe {
113 copy_fn(
114 self.ptr,
115 capacity, frame_data.as_mut_ptr(),
117 color_format,
118 )
119 };
120 if hr.is_ok() {
121 Ok(())
122 } else {
123 Err(Error::from_hresult(hr))
124 }
125 }
126
127 pub fn create_frame_description(
128 &self,
129 format: ColorImageFormat,
130 ) -> Result<FrameDescription, Error> {
131 if self.ptr.is_null() {
132 return Err(Error::from_hresult(E_POINTER));
133 }
134 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
135 let create_fn = vtbl.CreateFrameDescription.ok_or(E_FAIL)?;
136 let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
137 let hr = unsafe { create_fn(self.ptr, format, &mut desc_ptr) };
138 if hr.is_ok() {
139 Ok(FrameDescription::new(desc_ptr))
140 } else {
141 Err(Error::from_hresult(hr))
142 }
143 }
144
145 pub fn get_color_camera_settings(&self) -> Result<ColorCameraSettings, Error> {
146 if self.ptr.is_null() {
147 return Err(Error::from_hresult(E_POINTER));
148 }
149 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
150 let get_fn = vtbl.get_ColorCameraSettings.ok_or(E_FAIL)?;
151 let mut settings_ptr: *mut IColorCameraSettings = ptr::null_mut();
152 let hr = unsafe { get_fn(self.ptr, &mut settings_ptr) };
153 if hr.is_ok() {
154 Ok(ColorCameraSettings::new(settings_ptr))
155 } else {
156 Err(Error::from_hresult(hr))
157 }
158 }
159
160 pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
161 if self.ptr.is_null() {
162 return Err(Error::from_hresult(E_POINTER));
163 }
164 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
165 let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
166 let mut time: TIMESPAN = 0;
167 let hr = unsafe { get_fn(self.ptr, &mut time) };
168 if hr.is_ok() {
169 Ok(time)
170 } else {
171 Err(Error::from_hresult(hr))
172 }
173 }
174
175 pub fn get_color_frame_source(&self) -> Result<ColorFrameSource, Error> {
176 if self.ptr.is_null() {
177 return Err(Error::from_hresult(E_POINTER));
178 }
179 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
180 let get_fn = vtbl.get_ColorFrameSource.ok_or(E_FAIL)?;
181 let mut source_ptr: *mut IColorFrameSource = ptr::null_mut();
182 let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
183 if hr.is_ok() {
184 Ok(ColorFrameSource::new(source_ptr))
185 } else {
186 Err(Error::from_hresult(hr))
187 }
188 }
189}
190
191impl Drop for ColorFrame {
192 fn drop(&mut self) {
193 if !self.ptr.is_null() {
194 unsafe {
195 let vtbl = (*self.ptr)
196 .lpVtbl
197 .as_ref()
198 .expect("VTable pointer is null in Drop");
199 let release_fn = vtbl
200 .Release
201 .expect("Release function pointer is null in Drop");
202 release_fn(self.ptr);
203 }
204 self.ptr = ptr::null_mut();
205 }
206 }
207}
208
209#[derive(Debug, Clone)]
210pub struct ColorFrameArrivedEventArgs {
211 ptr: *mut IColorFrameArrivedEventArgs,
212}
213
214impl ColorFrameArrivedEventArgs {
215 pub(crate) fn new(ptr: *mut IColorFrameArrivedEventArgs) -> Self {
216 assert!(
217 !ptr.is_null(),
218 "ColorFrameArrivedEventArgs pointer cannot be null"
219 );
220 Self { ptr }
221 }
222
223 pub fn get_frame_reference(&self) -> Result<ColorFrameReference, Error> {
224 if self.ptr.is_null() {
225 return Err(Error::from_hresult(E_POINTER));
226 }
227 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
228 let get_fn = vtbl.get_FrameReference.ok_or(E_FAIL)?;
229 let mut ref_ptr: *mut IColorFrameReference = ptr::null_mut();
230 let hr = unsafe { get_fn(self.ptr, &mut ref_ptr) };
231 if hr.is_ok() {
232 Ok(ColorFrameReference::new(ref_ptr))
233 } else {
234 Err(Error::from_hresult(hr))
235 }
236 }
237}
238
239impl Drop for ColorFrameArrivedEventArgs {
240 fn drop(&mut self) {
241 if !self.ptr.is_null() {
242 unsafe {
243 let vtbl = (*self.ptr)
244 .lpVtbl
245 .as_ref()
246 .expect("VTable pointer is null in Drop");
247 let release_fn = vtbl
248 .Release
249 .expect("Release function pointer is null in Drop");
250 release_fn(self.ptr);
251 }
252 self.ptr = ptr::null_mut();
253 }
254 }
255}
256
257#[derive(Debug, Clone)]
258pub struct ColorFrameReference {
259 ptr: *mut IColorFrameReference,
260}
261
262impl ColorFrameReference {
263 pub(crate) fn new(ptr: *mut IColorFrameReference) -> Self {
264 assert!(!ptr.is_null(), "ColorFrameReference pointer cannot be null");
265 Self { ptr }
266 }
267
268 pub fn acquire_frame(&self) -> Result<ColorFrame, Error> {
269 if self.ptr.is_null() {
270 return Err(Error::from_hresult(E_POINTER));
271 }
272 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
273 let acquire_fn = vtbl.AcquireFrame.ok_or(E_FAIL)?;
274 let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
275 let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
276 if hr.is_ok() {
277 Ok(ColorFrame::new(frame_ptr))
278 } else {
279 Err(Error::from_hresult(hr))
280 }
281 }
282
283 pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
284 if self.ptr.is_null() {
285 return Err(Error::from_hresult(E_POINTER));
286 }
287 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
288 let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
289 let mut time: TIMESPAN = 0;
290 let hr = unsafe { get_fn(self.ptr, &mut time) };
291 if hr.is_ok() {
292 Ok(time)
293 } else {
294 Err(Error::from_hresult(hr))
295 }
296 }
297}
298
299impl Drop for ColorFrameReference {
300 fn drop(&mut self) {
301 if !self.ptr.is_null() {
302 unsafe {
303 let vtbl = (*self.ptr)
304 .lpVtbl
305 .as_ref()
306 .expect("VTable pointer is null in Drop");
307 let release_fn = vtbl
308 .Release
309 .expect("Release function pointer is null in Drop");
310 release_fn(self.ptr);
311 }
312 self.ptr = ptr::null_mut();
313 }
314 }
315}
316
317pub struct ColorCameraSettings {
318 ptr: *mut IColorCameraSettings,
319}
320
321impl ColorCameraSettings {
322 pub(crate) fn new(ptr: *mut IColorCameraSettings) -> Self {
323 assert!(!ptr.is_null(), "ColorCameraSettings pointer cannot be null");
324 Self { ptr }
325 }
326
327 pub fn get_exposure_time(&self) -> Result<TIMESPAN, Error> {
328 if self.ptr.is_null() {
329 return Err(Error::from_hresult(E_POINTER));
330 }
331 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
332 let get_fn = vtbl.get_ExposureTime.ok_or(E_FAIL)?;
333 let mut time: TIMESPAN = 0;
334 let hr = unsafe { get_fn(self.ptr, &mut time) };
335 if hr.is_ok() {
336 Ok(time)
337 } else {
338 Err(Error::from_hresult(hr))
339 }
340 }
341
342 pub fn get_frame_interval(&self) -> Result<TIMESPAN, Error> {
343 if self.ptr.is_null() {
344 return Err(Error::from_hresult(E_POINTER));
345 }
346 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
347 let get_fn = vtbl.get_FrameInterval.ok_or(E_FAIL)?;
348 let mut interval: TIMESPAN = 0;
349 let hr = unsafe { get_fn(self.ptr, &mut interval) };
350 if hr.is_ok() {
351 Ok(interval)
352 } else {
353 Err(Error::from_hresult(hr))
354 }
355 }
356
357 pub fn get_gain(&self) -> Result<f32, Error> {
358 if self.ptr.is_null() {
359 return Err(Error::from_hresult(E_POINTER));
360 }
361 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
362 let get_fn = vtbl.get_Gain.ok_or(E_FAIL)?;
363 let mut gain: f32 = 0.0;
364 let hr = unsafe { get_fn(self.ptr, &mut gain) };
365 if hr.is_ok() {
366 Ok(gain)
367 } else {
368 Err(Error::from_hresult(hr))
369 }
370 }
371
372 pub fn get_gamma(&self) -> Result<f32, Error> {
373 if self.ptr.is_null() {
374 return Err(Error::from_hresult(E_POINTER));
375 }
376 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
377 let get_fn = vtbl.get_Gamma.ok_or(E_FAIL)?;
378 let mut gamma: f32 = 0.0;
379 let hr = unsafe { get_fn(self.ptr, &mut gamma) };
380 if hr.is_ok() {
381 Ok(gamma)
382 } else {
383 Err(Error::from_hresult(hr))
384 }
385 }
386}
387
388impl Drop for ColorCameraSettings {
389 fn drop(&mut self) {
390 if !self.ptr.is_null() {
391 unsafe {
392 let vtbl = (*self.ptr)
393 .lpVtbl
394 .as_ref()
395 .expect("VTable pointer is null in Drop");
396 let release_fn = vtbl
397 .Release
398 .expect("Release function pointer is null in Drop");
399 release_fn(self.ptr);
400 }
401 self.ptr = ptr::null_mut();
402 }
403 }
404}
405
406pub struct ColorFrameReader {
407 ptr: *mut IColorFrameReader,
408}
409
410impl ColorFrameReader {
411 pub(crate) fn new(ptr: *mut IColorFrameReader) -> Self {
412 assert!(!ptr.is_null(), "ColorFrameReader pointer cannot be null");
413 Self { ptr }
414 }
415
416 pub fn subscribe_frame_arrived(
417 &self,
418 waitable_handle: &mut WAITABLE_HANDLE,
419 ) -> 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 sub_fn = vtbl.SubscribeFrameArrived.ok_or(E_FAIL)?;
425 let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
426 if hr.is_ok() {
427 Ok(())
428 } else {
429 Err(Error::from_hresult(hr))
430 }
431 }
432
433 pub fn unsubscribe_frame_arrived(&self, waitable_handle: WAITABLE_HANDLE) -> Result<(), 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 unsub_fn = vtbl.UnsubscribeFrameArrived.ok_or(E_FAIL)?;
439 let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
440 if hr.is_ok() {
441 Ok(())
442 } else {
443 Err(Error::from_hresult(hr))
444 }
445 }
446
447 pub fn get_frame_arrived_event_data(
448 &self,
449 waitable_handle: WAITABLE_HANDLE,
450 ) -> Result<ColorFrameArrivedEventArgs, Error> {
451 if self.ptr.is_null() {
452 return Err(Error::from_hresult(E_POINTER));
453 }
454 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
455 let get_fn = vtbl.GetFrameArrivedEventData.ok_or(E_FAIL)?;
456 let mut args_ptr: *mut IColorFrameArrivedEventArgs = ptr::null_mut();
457 let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
458 if hr.is_ok() {
459 Ok(ColorFrameArrivedEventArgs::new(args_ptr))
460 } else {
461 Err(Error::from_hresult(hr))
462 }
463 }
464
465 pub fn acquire_latest_frame(&self) -> Result<ColorFrame, Error> {
466 if self.ptr.is_null() {
467 return Err(Error::from_hresult(E_POINTER));
468 }
469 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
470 let acquire_fn = vtbl.AcquireLatestFrame.ok_or(E_FAIL)?;
471 let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
472 let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
473 if hr.is_ok() {
474 Ok(ColorFrame::new(frame_ptr))
475 } else {
476 Err(Error::from_hresult(hr))
477 }
478 }
479
480 pub fn get_is_paused(&self) -> Result<bool, Error> {
481 if self.ptr.is_null() {
482 return Err(Error::from_hresult(E_POINTER));
483 }
484 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
485 let get_fn = vtbl.get_IsPaused.ok_or(E_FAIL)?;
486 let mut paused: BOOLEAN = 0;
487 let hr = unsafe { get_fn(self.ptr, &mut paused) };
488 if hr.is_ok() {
489 Ok(paused != 0)
490 } else {
491 Err(Error::from_hresult(hr))
492 }
493 }
494
495 pub fn put_is_paused(&self, is_paused: bool) -> Result<(), Error> {
496 if self.ptr.is_null() {
497 return Err(Error::from_hresult(E_POINTER));
498 }
499 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
500 let put_fn = vtbl.put_IsPaused.ok_or(E_FAIL)?;
501 let hr = unsafe { put_fn(self.ptr, is_paused as BOOLEAN) };
502 if hr.is_ok() {
503 Ok(())
504 } else {
505 Err(Error::from_hresult(hr))
506 }
507 }
508
509 pub fn get_color_frame_source(&self) -> Result<ColorFrameSource, Error> {
510 if self.ptr.is_null() {
511 return Err(Error::from_hresult(E_POINTER));
512 }
513 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
514 let get_fn = vtbl.get_ColorFrameSource.ok_or(E_FAIL)?;
515 let mut source_ptr: *mut IColorFrameSource = ptr::null_mut();
516 let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
517 if hr.is_ok() {
518 Ok(ColorFrameSource::new(source_ptr))
519 } else {
520 Err(Error::from_hresult(hr))
521 }
522 }
523}
524
525impl Drop for ColorFrameReader {
526 fn drop(&mut self) {
527 if !self.ptr.is_null() {
528 unsafe {
529 let vtbl = (*self.ptr)
530 .lpVtbl
531 .as_ref()
532 .expect("VTable pointer is null in Drop");
533 let release_fn = vtbl
534 .Release
535 .expect("Release function pointer is null in Drop");
536 release_fn(self.ptr);
537 }
538 self.ptr = ptr::null_mut();
539 }
540 }
541}
542
543pub struct ColorFrameSource {
544 pub(crate) ptr: *mut IColorFrameSource, }
546
547impl ColorFrameSource {
548 pub(crate) fn new(ptr: *mut IColorFrameSource) -> Self {
549 assert!(!ptr.is_null(), "ColorFrameSource pointer cannot be null");
550 Self { ptr }
551 }
552
553 pub fn subscribe_frame_captured(
554 &self,
555 waitable_handle: &mut WAITABLE_HANDLE,
556 ) -> Result<(), Error> {
557 if self.ptr.is_null() {
558 return Err(Error::from_hresult(E_POINTER));
559 }
560 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
561 let sub_fn = vtbl.SubscribeFrameCaptured.ok_or(E_FAIL)?;
562 let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
563 if hr.is_ok() {
564 Ok(())
565 } else {
566 Err(Error::from_hresult(hr))
567 }
568 }
569
570 pub fn unsubscribe_frame_captured(
571 &self,
572 waitable_handle: WAITABLE_HANDLE,
573 ) -> Result<(), Error> {
574 if self.ptr.is_null() {
575 return Err(Error::from_hresult(E_POINTER));
576 }
577 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
578 let unsub_fn = vtbl.UnsubscribeFrameCaptured.ok_or(E_FAIL)?;
579 let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
580 if hr.is_ok() {
581 Ok(())
582 } else {
583 Err(Error::from_hresult(hr))
584 }
585 }
586
587 pub fn get_frame_captured_event_data(
588 &self,
589 waitable_handle: WAITABLE_HANDLE,
590 ) -> Result<FrameCapturedEventArgs, Error> {
591 if self.ptr.is_null() {
592 return Err(Error::from_hresult(E_POINTER));
593 }
594 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
595 let get_fn = vtbl.GetFrameCapturedEventData.ok_or(E_FAIL)?;
596 let mut args_ptr: *mut IFrameCapturedEventArgs = ptr::null_mut();
597 let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
598 if hr.is_ok() {
599 Ok(FrameCapturedEventArgs::new(args_ptr))
600 } else {
601 Err(Error::from_hresult(hr))
602 }
603 }
604
605 pub fn get_is_active(&self) -> Result<bool, Error> {
606 if self.ptr.is_null() {
607 return Err(Error::from_hresult(E_POINTER));
608 }
609 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
610 let get_fn = vtbl.get_IsActive.ok_or(E_FAIL)?;
611 let mut active: BOOLEAN = 0;
612 let hr = unsafe { get_fn(self.ptr, &mut active) };
613 if hr.is_ok() {
614 Ok(active != 0)
615 } else {
616 Err(Error::from_hresult(hr))
617 }
618 }
619
620 pub fn open_reader(&self) -> Result<ColorFrameReader, Error> {
621 if self.ptr.is_null() {
622 return Err(Error::from_hresult(E_POINTER));
623 }
624 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
625 let open_fn = vtbl.OpenReader.ok_or(E_FAIL)?;
626 let mut reader_ptr: *mut IColorFrameReader = ptr::null_mut();
627 let hr = unsafe { open_fn(self.ptr, &mut reader_ptr) };
628 if hr.is_ok() {
629 Ok(ColorFrameReader::new(reader_ptr))
630 } else {
631 Err(Error::from_hresult(hr))
632 }
633 }
634
635 pub fn create_frame_description(
636 &self,
637 format: ColorImageFormat,
638 ) -> Result<FrameDescription, Error> {
639 if self.ptr.is_null() {
640 return Err(Error::from_hresult(E_POINTER));
641 }
642 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
643 let create_fn = vtbl.CreateFrameDescription.ok_or(E_FAIL)?;
644 let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
645 let hr = unsafe { create_fn(self.ptr, format, &mut desc_ptr) };
646 if hr.is_ok() {
647 Ok(FrameDescription::new(desc_ptr))
648 } else {
649 Err(Error::from_hresult(hr))
650 }
651 }
652
653 pub fn get_frame_description(&self) -> Result<FrameDescription, Error> {
654 if self.ptr.is_null() {
655 return Err(Error::from_hresult(E_POINTER));
656 }
657 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
658 let get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
659 let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
660 let hr = unsafe { get_fn(self.ptr, &mut desc_ptr) };
661 if hr.is_ok() {
662 Ok(FrameDescription::new(desc_ptr))
663 } else {
664 Err(Error::from_hresult(hr))
665 }
666 }
667
668 pub fn get_kinect_sensor(&self) -> Result<KinectSensor, Error> {
669 if self.ptr.is_null() {
670 return Err(Error::from_hresult(E_POINTER));
671 }
672 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
673 let get_fn = vtbl.get_KinectSensor.ok_or(E_FAIL)?;
674 let mut sensor_ptr: *mut IKinectSensor = ptr::null_mut();
675 let hr = unsafe { get_fn(self.ptr, &mut sensor_ptr) };
676 if hr.is_ok() {
677 Ok(KinectSensor::new(sensor_ptr))
678 } else {
679 Err(Error::from_hresult(hr))
680 }
681 }
682}
683
684impl Drop for ColorFrameSource {
685 fn drop(&mut self) {
686 if !self.ptr.is_null() {
687 unsafe {
688 let vtbl = (*self.ptr)
689 .lpVtbl
690 .as_ref()
691 .expect("VTable pointer is null in Drop");
692 let release_fn = vtbl
693 .Release
694 .expect("Release function pointer is null in Drop");
695 release_fn(self.ptr);
696 }
697 self.ptr = ptr::null_mut();
698 }
699 }
700}
701
702#[cfg(test)]
704mod tests {
705 use std::{thread, time::Duration};
706
707 use super::*;
708 use crate::{DEFAULT_FRAME_WAIT_TIMEOUT_MS, kinect};
709 use anyhow::Context;
710 use windows::Win32::{
711 Foundation::{WAIT_OBJECT_0, WAIT_TIMEOUT},
712 System::{Com::Urlmon::E_PENDING, Threading::WaitForSingleObject},
713 };
714
715 #[test]
716 fn get_latest_color_frame() -> anyhow::Result<()> {
717 let kinect = kinect::get_default_kinect_sensor()?;
718 kinect.open()?;
719 let color_frame_source = kinect.color_frame_source()?;
720 let color_frame_reader = color_frame_source.open_reader()?;
721
722 let mut frame_count = 0;
723 loop {
724 match color_frame_reader.acquire_latest_frame() {
725 Ok(color_frame) => {
726 let frame_description = color_frame.get_frame_description()?;
727 let width = frame_description.get_width()?;
728 let height = frame_description.get_height()?;
729 assert_eq!(width, 1920);
730 assert_eq!(height, 1080);
731 frame_count += 1;
732
733 if frame_count > 10 {
734 break; }
736 }
737 Err(e) => {
738 if e.code() == E_PENDING {
739 thread::sleep(Duration::from_millis(100));
741 } else {
742 return Err(anyhow::Error::new(e));
744 }
745 }
746 }
747 }
748
749 Ok(())
750 }
751
752 #[test]
753 fn subscribe_color_frame_arrived_event() -> anyhow::Result<()> {
754 let kinect = kinect::get_default_kinect_sensor()?;
755 kinect.open()?;
756 let color_frame_source = kinect.color_frame_source()?;
757 let color_frame_reader = color_frame_source.open_reader()?;
758 let mut waitable_handle: WAITABLE_HANDLE = WAITABLE_HANDLE::default();
759 color_frame_reader.subscribe_frame_arrived(&mut waitable_handle)?;
760 let mut frame_count = 0;
761 let is_active = color_frame_source.get_is_active()?;
762 assert!(is_active, "Color frame source should be active");
763 loop {
764 let result =
765 unsafe { WaitForSingleObject(waitable_handle, DEFAULT_FRAME_WAIT_TIMEOUT_MS) };
766 if WAIT_OBJECT_0 == result {
767 let event_args = color_frame_reader
768 .get_frame_arrived_event_data(waitable_handle)
769 .context("Failed to get frame arrived event data")?;
770
771 let frame_reference = event_args.get_frame_reference()?;
772 let color_frame = frame_reference.acquire_frame()?;
773 let frame_description = color_frame.get_frame_description()?;
774 let width = frame_description.get_width()? as u32;
775 let height = frame_description.get_height()? as u32;
776 let rel_time = frame_reference.get_relative_time()?;
777 let bytes_per_pixel = frame_description.get_bytes_per_pixel()?;
778
779 assert_eq!(width, 1920);
780 assert_eq!(height, 1080);
781 assert!(rel_time > 0);
782 assert_eq!(bytes_per_pixel, 2);
783 let image_format = color_frame.get_raw_color_image_format()?;
784 println!("Color image format: {image_format:?}");
785 let capacity = width * height * bytes_per_pixel;
786 let mut frame_data: Vec<u8> = vec![0; capacity as usize];
787 color_frame
788 .copy_raw_frame_data_to_array(&mut frame_data)
789 .context("Failed to copy raw frame data to array")?;
790 println!("frame_data.len: {:?}", frame_data.len());
791
792 frame_count += 1;
793 if frame_count > 10 {
794 break; }
796 } else if WAIT_TIMEOUT == result {
797 println!("No new color frame available, waiting...");
798 } else {
799 return Err(anyhow::anyhow!(
800 "WaitForSingleObject failed with result: {:?}",
801 result
802 ));
803 }
804 }
805
806 color_frame_reader.unsubscribe_frame_arrived(waitable_handle)?;
808
809 Ok(())
810 }
811
812 }