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 if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
196 && let Some(release_fn) = vtbl.Release
197 {
198 release_fn(self.ptr);
199 }
200 }
201 self.ptr = ptr::null_mut();
202 }
203 }
204}
205
206#[derive(Debug, Clone)]
207pub struct ColorFrameArrivedEventArgs {
208 ptr: *mut IColorFrameArrivedEventArgs,
209}
210
211impl ColorFrameArrivedEventArgs {
212 pub(crate) fn new(ptr: *mut IColorFrameArrivedEventArgs) -> Self {
213 assert!(
214 !ptr.is_null(),
215 "ColorFrameArrivedEventArgs pointer cannot be null"
216 );
217 Self { ptr }
218 }
219
220 pub fn get_frame_reference(&self) -> Result<ColorFrameReference, Error> {
221 if self.ptr.is_null() {
222 return Err(Error::from_hresult(E_POINTER));
223 }
224 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
225 let get_fn = vtbl.get_FrameReference.ok_or(E_FAIL)?;
226 let mut ref_ptr: *mut IColorFrameReference = ptr::null_mut();
227 let hr = unsafe { get_fn(self.ptr, &mut ref_ptr) };
228 if hr.is_ok() {
229 Ok(ColorFrameReference::new(ref_ptr))
230 } else {
231 Err(Error::from_hresult(hr))
232 }
233 }
234}
235
236impl Drop for ColorFrameArrivedEventArgs {
237 fn drop(&mut self) {
238 if !self.ptr.is_null() {
239 unsafe {
240 if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
241 && let Some(release_fn) = vtbl.Release
242 {
243 release_fn(self.ptr);
244 }
245 }
246 self.ptr = ptr::null_mut();
247 }
248 }
249}
250
251#[derive(Debug, Clone)]
252pub struct ColorFrameReference {
253 ptr: *mut IColorFrameReference,
254}
255
256impl ColorFrameReference {
257 pub(crate) fn new(ptr: *mut IColorFrameReference) -> Self {
258 assert!(!ptr.is_null(), "ColorFrameReference pointer cannot be null");
259 Self { ptr }
260 }
261
262 pub fn acquire_frame(&self) -> Result<ColorFrame, Error> {
263 if self.ptr.is_null() {
264 return Err(Error::from_hresult(E_POINTER));
265 }
266 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
267 let acquire_fn = vtbl.AcquireFrame.ok_or(E_FAIL)?;
268 let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
269 let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
270 if hr.is_ok() {
271 Ok(ColorFrame::new(frame_ptr))
272 } else {
273 Err(Error::from_hresult(hr))
274 }
275 }
276
277 pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
278 if self.ptr.is_null() {
279 return Err(Error::from_hresult(E_POINTER));
280 }
281 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
282 let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
283 let mut time: TIMESPAN = 0;
284 let hr = unsafe { get_fn(self.ptr, &mut time) };
285 if hr.is_ok() {
286 Ok(time)
287 } else {
288 Err(Error::from_hresult(hr))
289 }
290 }
291}
292
293impl Drop for ColorFrameReference {
294 fn drop(&mut self) {
295 if !self.ptr.is_null() {
296 unsafe {
297 if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
298 && let Some(release_fn) = vtbl.Release
299 {
300 release_fn(self.ptr);
301 }
302 }
303 self.ptr = ptr::null_mut();
304 }
305 }
306}
307
308pub struct ColorCameraSettings {
309 ptr: *mut IColorCameraSettings,
310}
311
312impl ColorCameraSettings {
313 pub(crate) fn new(ptr: *mut IColorCameraSettings) -> Self {
314 assert!(!ptr.is_null(), "ColorCameraSettings pointer cannot be null");
315 Self { ptr }
316 }
317
318 pub fn get_exposure_time(&self) -> Result<TIMESPAN, Error> {
319 if self.ptr.is_null() {
320 return Err(Error::from_hresult(E_POINTER));
321 }
322 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
323 let get_fn = vtbl.get_ExposureTime.ok_or(E_FAIL)?;
324 let mut time: TIMESPAN = 0;
325 let hr = unsafe { get_fn(self.ptr, &mut time) };
326 if hr.is_ok() {
327 Ok(time)
328 } else {
329 Err(Error::from_hresult(hr))
330 }
331 }
332
333 pub fn get_frame_interval(&self) -> Result<TIMESPAN, Error> {
334 if self.ptr.is_null() {
335 return Err(Error::from_hresult(E_POINTER));
336 }
337 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
338 let get_fn = vtbl.get_FrameInterval.ok_or(E_FAIL)?;
339 let mut interval: TIMESPAN = 0;
340 let hr = unsafe { get_fn(self.ptr, &mut interval) };
341 if hr.is_ok() {
342 Ok(interval)
343 } else {
344 Err(Error::from_hresult(hr))
345 }
346 }
347
348 pub fn get_gain(&self) -> Result<f32, Error> {
349 if self.ptr.is_null() {
350 return Err(Error::from_hresult(E_POINTER));
351 }
352 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
353 let get_fn = vtbl.get_Gain.ok_or(E_FAIL)?;
354 let mut gain: f32 = 0.0;
355 let hr = unsafe { get_fn(self.ptr, &mut gain) };
356 if hr.is_ok() {
357 Ok(gain)
358 } else {
359 Err(Error::from_hresult(hr))
360 }
361 }
362
363 pub fn get_gamma(&self) -> Result<f32, Error> {
364 if self.ptr.is_null() {
365 return Err(Error::from_hresult(E_POINTER));
366 }
367 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
368 let get_fn = vtbl.get_Gamma.ok_or(E_FAIL)?;
369 let mut gamma: f32 = 0.0;
370 let hr = unsafe { get_fn(self.ptr, &mut gamma) };
371 if hr.is_ok() {
372 Ok(gamma)
373 } else {
374 Err(Error::from_hresult(hr))
375 }
376 }
377}
378
379impl Drop for ColorCameraSettings {
380 fn drop(&mut self) {
381 if !self.ptr.is_null() {
382 unsafe {
383 if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
384 && let Some(release_fn) = vtbl.Release
385 {
386 release_fn(self.ptr);
387 }
388 }
389 self.ptr = ptr::null_mut();
390 }
391 }
392}
393
394pub struct ColorFrameReader {
395 ptr: *mut IColorFrameReader,
396}
397
398impl ColorFrameReader {
399 pub(crate) fn new(ptr: *mut IColorFrameReader) -> Self {
400 assert!(!ptr.is_null(), "ColorFrameReader pointer cannot be null");
401 Self { ptr }
402 }
403
404 pub fn subscribe_frame_arrived(
405 &self,
406 waitable_handle: &mut WAITABLE_HANDLE,
407 ) -> Result<(), Error> {
408 if self.ptr.is_null() {
409 return Err(Error::from_hresult(E_POINTER));
410 }
411 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
412 let sub_fn = vtbl.SubscribeFrameArrived.ok_or(E_FAIL)?;
413 let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
414 if hr.is_ok() {
415 Ok(())
416 } else {
417 Err(Error::from_hresult(hr))
418 }
419 }
420
421 pub fn unsubscribe_frame_arrived(&self, waitable_handle: WAITABLE_HANDLE) -> Result<(), Error> {
422 if self.ptr.is_null() {
423 return Err(Error::from_hresult(E_POINTER));
424 }
425 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
426 let unsub_fn = vtbl.UnsubscribeFrameArrived.ok_or(E_FAIL)?;
427 let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
428 if hr.is_ok() {
429 Ok(())
430 } else {
431 Err(Error::from_hresult(hr))
432 }
433 }
434
435 pub fn get_frame_arrived_event_data(
436 &self,
437 waitable_handle: WAITABLE_HANDLE,
438 ) -> Result<ColorFrameArrivedEventArgs, Error> {
439 if self.ptr.is_null() {
440 return Err(Error::from_hresult(E_POINTER));
441 }
442 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
443 let get_fn = vtbl.GetFrameArrivedEventData.ok_or(E_FAIL)?;
444 let mut args_ptr: *mut IColorFrameArrivedEventArgs = ptr::null_mut();
445 let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
446 if hr.is_ok() {
447 Ok(ColorFrameArrivedEventArgs::new(args_ptr))
448 } else {
449 Err(Error::from_hresult(hr))
450 }
451 }
452
453 pub fn acquire_latest_frame(&self) -> Result<ColorFrame, Error> {
454 if self.ptr.is_null() {
455 return Err(Error::from_hresult(E_POINTER));
456 }
457 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
458 let acquire_fn = vtbl.AcquireLatestFrame.ok_or(E_FAIL)?;
459 let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
460 let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
461 if hr.is_ok() {
462 Ok(ColorFrame::new(frame_ptr))
463 } else {
464 Err(Error::from_hresult(hr))
465 }
466 }
467
468 pub fn get_is_paused(&self) -> Result<bool, Error> {
469 if self.ptr.is_null() {
470 return Err(Error::from_hresult(E_POINTER));
471 }
472 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
473 let get_fn = vtbl.get_IsPaused.ok_or(E_FAIL)?;
474 let mut paused: BOOLEAN = 0;
475 let hr = unsafe { get_fn(self.ptr, &mut paused) };
476 if hr.is_ok() {
477 Ok(paused != 0)
478 } else {
479 Err(Error::from_hresult(hr))
480 }
481 }
482
483 pub fn put_is_paused(&self, is_paused: bool) -> Result<(), Error> {
484 if self.ptr.is_null() {
485 return Err(Error::from_hresult(E_POINTER));
486 }
487 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
488 let put_fn = vtbl.put_IsPaused.ok_or(E_FAIL)?;
489 let hr = unsafe { put_fn(self.ptr, is_paused as BOOLEAN) };
490 if hr.is_ok() {
491 Ok(())
492 } else {
493 Err(Error::from_hresult(hr))
494 }
495 }
496
497 pub fn get_color_frame_source(&self) -> Result<ColorFrameSource, Error> {
498 if self.ptr.is_null() {
499 return Err(Error::from_hresult(E_POINTER));
500 }
501 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
502 let get_fn = vtbl.get_ColorFrameSource.ok_or(E_FAIL)?;
503 let mut source_ptr: *mut IColorFrameSource = ptr::null_mut();
504 let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
505 if hr.is_ok() {
506 Ok(ColorFrameSource::new(source_ptr))
507 } else {
508 Err(Error::from_hresult(hr))
509 }
510 }
511}
512
513impl Drop for ColorFrameReader {
514 fn drop(&mut self) {
515 if !self.ptr.is_null() {
516 unsafe {
517 if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
518 && let Some(release_fn) = vtbl.Release
519 {
520 release_fn(self.ptr);
521 }
522 }
523 self.ptr = ptr::null_mut();
524 }
525 }
526}
527
528pub struct ColorFrameSource {
529 pub(crate) ptr: *mut IColorFrameSource, }
531
532impl ColorFrameSource {
533 pub(crate) fn new(ptr: *mut IColorFrameSource) -> Self {
534 assert!(!ptr.is_null(), "ColorFrameSource pointer cannot be null");
535 Self { ptr }
536 }
537
538 pub fn subscribe_frame_captured(
539 &self,
540 waitable_handle: &mut WAITABLE_HANDLE,
541 ) -> Result<(), Error> {
542 if self.ptr.is_null() {
543 return Err(Error::from_hresult(E_POINTER));
544 }
545 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
546 let sub_fn = vtbl.SubscribeFrameCaptured.ok_or(E_FAIL)?;
547 let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
548 if hr.is_ok() {
549 Ok(())
550 } else {
551 Err(Error::from_hresult(hr))
552 }
553 }
554
555 pub fn unsubscribe_frame_captured(
556 &self,
557 waitable_handle: WAITABLE_HANDLE,
558 ) -> Result<(), Error> {
559 if self.ptr.is_null() {
560 return Err(Error::from_hresult(E_POINTER));
561 }
562 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
563 let unsub_fn = vtbl.UnsubscribeFrameCaptured.ok_or(E_FAIL)?;
564 let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
565 if hr.is_ok() {
566 Ok(())
567 } else {
568 Err(Error::from_hresult(hr))
569 }
570 }
571
572 pub fn get_frame_captured_event_data(
573 &self,
574 waitable_handle: WAITABLE_HANDLE,
575 ) -> Result<FrameCapturedEventArgs, Error> {
576 if self.ptr.is_null() {
577 return Err(Error::from_hresult(E_POINTER));
578 }
579 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
580 let get_fn = vtbl.GetFrameCapturedEventData.ok_or(E_FAIL)?;
581 let mut args_ptr: *mut IFrameCapturedEventArgs = ptr::null_mut();
582 let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
583 if hr.is_ok() {
584 Ok(FrameCapturedEventArgs::new(args_ptr))
585 } else {
586 Err(Error::from_hresult(hr))
587 }
588 }
589
590 pub fn get_is_active(&self) -> Result<bool, 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.get_IsActive.ok_or(E_FAIL)?;
596 let mut active: BOOLEAN = 0;
597 let hr = unsafe { get_fn(self.ptr, &mut active) };
598 if hr.is_ok() {
599 Ok(active != 0)
600 } else {
601 Err(Error::from_hresult(hr))
602 }
603 }
604
605 pub fn open_reader(&self) -> Result<ColorFrameReader, 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 open_fn = vtbl.OpenReader.ok_or(E_FAIL)?;
611 let mut reader_ptr: *mut IColorFrameReader = ptr::null_mut();
612 let hr = unsafe { open_fn(self.ptr, &mut reader_ptr) };
613 if hr.is_ok() {
614 Ok(ColorFrameReader::new(reader_ptr))
615 } else {
616 Err(Error::from_hresult(hr))
617 }
618 }
619
620 pub fn create_frame_description(
621 &self,
622 format: ColorImageFormat,
623 ) -> Result<FrameDescription, Error> {
624 if self.ptr.is_null() {
625 return Err(Error::from_hresult(E_POINTER));
626 }
627 let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
628 let create_fn = vtbl.CreateFrameDescription.ok_or(E_FAIL)?;
629 let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
630 let hr = unsafe { create_fn(self.ptr, format, &mut desc_ptr) };
631 if hr.is_ok() {
632 Ok(FrameDescription::new(desc_ptr))
633 } else {
634 Err(Error::from_hresult(hr))
635 }
636 }
637
638 pub fn get_frame_description(&self) -> 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 get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
644 let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
645 let hr = unsafe { get_fn(self.ptr, &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_kinect_sensor(&self) -> Result<KinectSensor, 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_KinectSensor.ok_or(E_FAIL)?;
659 let mut sensor_ptr: *mut IKinectSensor = ptr::null_mut();
660 let hr = unsafe { get_fn(self.ptr, &mut sensor_ptr) };
661 if hr.is_ok() {
662 Ok(KinectSensor::new(sensor_ptr))
663 } else {
664 Err(Error::from_hresult(hr))
665 }
666 }
667}
668
669impl Drop for ColorFrameSource {
670 fn drop(&mut self) {
671 if !self.ptr.is_null() {
672 unsafe {
673 let vtbl = (*self.ptr)
674 .lpVtbl
675 .as_ref()
676 .expect("VTable pointer is null in Drop");
677 let release_fn = vtbl
678 .Release
679 .expect("Release function pointer is null in Drop");
680 release_fn(self.ptr);
681 }
682 self.ptr = ptr::null_mut();
683 }
684 }
685}
686
687#[cfg(test)]
689mod tests {
690 use std::{thread, time::Duration};
691
692 use super::*;
693 use crate::{DEFAULT_FRAME_WAIT_TIMEOUT_MS, kinect};
694 use anyhow::Context;
695 use windows::Win32::{
696 Foundation::{WAIT_OBJECT_0, WAIT_TIMEOUT},
697 System::{Com::Urlmon::E_PENDING, Threading::WaitForSingleObject},
698 };
699
700 #[test]
701 fn get_latest_color_frame() -> anyhow::Result<()> {
702 let kinect = kinect::get_default_kinect_sensor()?;
703 kinect.open()?;
704 let color_frame_source = kinect.color_frame_source()?;
705 let color_frame_reader = color_frame_source.open_reader()?;
706
707 let mut frame_count = 0;
708 loop {
709 match color_frame_reader.acquire_latest_frame() {
710 Ok(color_frame) => {
711 let frame_description = color_frame.get_frame_description()?;
712 let width = frame_description.get_width()?;
713 let height = frame_description.get_height()?;
714 assert_eq!(width, 1920);
715 assert_eq!(height, 1080);
716 frame_count += 1;
717
718 if frame_count > 10 {
719 break; }
721 }
722 Err(e) => {
723 if e.code() == E_PENDING {
724 thread::sleep(Duration::from_millis(100));
726 } else {
727 return Err(anyhow::Error::new(e));
729 }
730 }
731 }
732 }
733
734 Ok(())
735 }
736
737 #[test]
738 fn subscribe_color_frame_arrived_event() -> anyhow::Result<()> {
739 let kinect = kinect::get_default_kinect_sensor()?;
740 kinect.open()?;
741 let color_frame_source = kinect.color_frame_source()?;
742 let color_frame_reader = color_frame_source.open_reader()?;
743 let mut waitable_handle: WAITABLE_HANDLE = WAITABLE_HANDLE::default();
744 color_frame_reader.subscribe_frame_arrived(&mut waitable_handle)?;
745 let mut frame_count = 0;
746 let is_active = color_frame_source.get_is_active()?;
747 assert!(is_active, "Color frame source should be active");
748 loop {
749 let result =
750 unsafe { WaitForSingleObject(waitable_handle, DEFAULT_FRAME_WAIT_TIMEOUT_MS) };
751 if WAIT_OBJECT_0 == result {
752 let event_args = color_frame_reader
753 .get_frame_arrived_event_data(waitable_handle)
754 .context("Failed to get frame arrived event data")?;
755
756 let frame_reference = event_args.get_frame_reference()?;
757 let color_frame = frame_reference.acquire_frame()?;
758 let frame_description = color_frame.get_frame_description()?;
759 let width = frame_description.get_width()? as u32;
760 let height = frame_description.get_height()? as u32;
761 let rel_time = frame_reference.get_relative_time()?;
762 let bytes_per_pixel = frame_description.get_bytes_per_pixel()?;
763
764 assert_eq!(width, 1920);
765 assert_eq!(height, 1080);
766 assert!(rel_time > 0);
767 assert_eq!(bytes_per_pixel, 2);
768 let image_format = color_frame.get_raw_color_image_format()?;
769 println!("Color image format: {image_format:?}");
770 let capacity = width * height * bytes_per_pixel;
771 let mut frame_data: Vec<u8> = vec![0; capacity as usize];
772 color_frame
773 .copy_raw_frame_data_to_array(&mut frame_data)
774 .context("Failed to copy raw frame data to array")?;
775 println!("frame_data.len: {:?}", frame_data.len());
776
777 frame_count += 1;
778 if frame_count > 10 {
779 break; }
781 } else if WAIT_TIMEOUT == result {
782 println!("No new color frame available, waiting...");
783 } else {
784 return Err(anyhow::anyhow!(
785 "WaitForSingleObject failed with result: {:?}",
786 result
787 ));
788 }
789 }
790
791 color_frame_reader.unsubscribe_frame_arrived(waitable_handle)?;
793
794 Ok(())
795 }
796
797 }