realsense_rust/frame/
composite.rs

1//! Composite frame type containing all other potential frame types.
2//!
3//! Each Pipeline produces a synchronized collection of frames for all streams
4//! configured for its allocated device. These frames will be presented to the user as
5//! a collection via the Composite Frame type.
6//!
7//! This is typically what is delivered from the pipeline.
8
9use super::prelude::FrameCategory;
10use crate::kind::Rs2StreamKind;
11use realsense_sys as sys;
12use std::{
13    convert::{TryFrom, TryInto},
14    ptr::NonNull,
15};
16
17/// Holds the raw data pointer from an RS2 Composite frame type.
18#[derive(Debug)]
19pub struct CompositeFrame {
20    /// The raw data pointer from the original rs2 frame
21    frame: Option<NonNull<sys::rs2_frame>>,
22}
23
24unsafe impl Send for CompositeFrame {}
25
26impl Drop for CompositeFrame {
27    /// Drop the raw pointer stored with this struct whenever it goes out of scope.
28    fn drop(&mut self) {
29        if let Some(frame) = self.frame {
30            unsafe {
31                sys::rs2_release_frame(frame.as_ptr());
32            }
33        }
34    }
35}
36
37impl From<NonNull<sys::rs2_frame>> for CompositeFrame {
38    fn from(frame: NonNull<sys::rs2_frame>) -> Self {
39        Self { frame: Some(frame) }
40    }
41}
42
43impl CompositeFrame {
44    /// Gets the number of individual frames included in the composite frame.
45    pub fn count(&self) -> usize {
46        unsafe {
47            let mut err: *mut sys::rs2_error = std::ptr::null_mut::<sys::rs2_error>();
48            let frame = self.frame.as_ref().unwrap();
49            let count = sys::rs2_embedded_frames_count(frame.as_ptr(), &mut err);
50            if err.as_ref().is_none() {
51                count as usize
52            } else {
53                sys::rs2_free_error(err);
54                0
55            }
56        }
57    }
58
59    /// Checks if the Composite frame collection is empty.
60    pub fn is_empty(&self) -> bool {
61        self.count() == 0
62    }
63
64    /// Retrieves all frames in the Composite frame collection of a given type.
65    ///
66    /// # Generic Arguments
67    ///
68    /// `F` must implement [`FrameCategory`]. Some examples of good types to use for this are:
69    ///
70    /// * [`ColorFrame`](crate::frame::ColorFrame)
71    /// * [`DepthFrame`](crate::frame::DepthFrame)
72    /// * [`DisparityFrame`](crate::frame::DisparityFrame)
73    /// * [`PoseFrame`](crate::frame::PoseFrame)
74    /// * [`PointsFrame`](crate::frame::PointsFrame)
75    ///
76    pub fn frames_of_type<F>(&self) -> Vec<F>
77    where
78        F: TryFrom<NonNull<sys::rs2_frame>> + FrameCategory,
79    {
80        let mut frames = Vec::new();
81        for i in 0..self.count() {
82            unsafe {
83                let frame = self.frame.as_ref().unwrap();
84                let mut err = std::ptr::null_mut::<sys::rs2_error>();
85                let frame_ptr =
86                    sys::rs2_extract_frame(frame.as_ptr(), i as std::os::raw::c_int, &mut err);
87
88                if err.as_ref().is_some() {
89                    sys::rs2_free_error(err);
90                    continue;
91                }
92
93                let nonnull_frame_ptr = NonNull::new(frame_ptr).unwrap();
94
95                let is_extendable_to = sys::rs2_is_frame_extendable_to(
96                    nonnull_frame_ptr.as_ptr(),
97                    #[allow(clippy::useless_conversion)]
98                    (F::extension() as i32).try_into().unwrap(),
99                    &mut err,
100                );
101
102                if err.as_ref().is_none() {
103                    if is_extendable_to != 0 {
104                        if let Ok(f) = F::try_from(nonnull_frame_ptr) {
105                            let kind_for_frame = F::kind();
106
107                            if kind_for_frame == Rs2StreamKind::Any || f.has_correct_kind() {
108                                frames.push(f);
109                            }
110                            // This continue is to skip releasing the frame at the end of the loop.
111                            // If the call to try_from above is successful and we can push, then
112                            // the frame is owned by the type `E` and we should not release it.
113                            continue;
114                        }
115                    }
116                } else {
117                    sys::rs2_free_error(err);
118                }
119                sys::rs2_release_frame(nonnull_frame_ptr.as_ptr());
120            }
121        }
122        frames
123    }
124
125    /// Get (and own) the underlying frame pointer for this frame.
126    ///
127    /// This is primarily useful for passing this frame forward to a processing block or blocks
128    /// (either via frame queue, directly, callback, etc).
129    ///
130    /// # Safety
131    ///
132    /// This does not destroy the underlying frame pointer once self
133    /// goes out of scope. Instead, the program expects that whatever
134    /// object was assigned to by this function now manages the lifetime.
135    pub unsafe fn get_owned_raw(mut self) -> NonNull<sys::rs2_frame> {
136        std::mem::take(&mut self.frame).unwrap()
137    }
138}