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    pub ptr: NonNull<sys::rs2_frame>,
22}
23
24impl Drop for CompositeFrame {
25    /// Drop the raw pointer stored with this struct whenever it goes out of scope.
26    fn drop(&mut self) {
27        unsafe {
28            sys::rs2_release_frame(self.ptr.as_ptr());
29        }
30    }
31}
32
33impl From<NonNull<sys::rs2_frame>> for CompositeFrame {
34    fn from(frame_ptr: NonNull<sys::rs2_frame>) -> Self {
35        Self { ptr: frame_ptr }
36    }
37}
38
39impl CompositeFrame {
40    /// Gets the number of individual frames included in the composite frame.
41    pub fn count(&self) -> usize {
42        unsafe {
43            let mut err: *mut sys::rs2_error = std::ptr::null_mut::<sys::rs2_error>();
44            let count = sys::rs2_embedded_frames_count(self.ptr.as_ptr(), &mut err);
45            if err.as_ref().is_none() {
46                count as usize
47            } else {
48                sys::rs2_free_error(err);
49                0
50            }
51        }
52    }
53
54    /// Checks if the Composite frame collection is empty.
55    pub fn is_empty(&self) -> bool {
56        self.count() == 0
57    }
58
59    /// Retrieves all frames in the Composite frame collection of a given type.
60    ///
61    /// # Generic Arguments
62    ///
63    /// `F` must implement [`FrameCategory`](super::prelude::FrameCategory). Some examples of good
64    /// types to use for this are:
65    ///
66    /// * [`ColorFrame`](crate::frame::ColorFrame)
67    /// * [`DepthFrame`](crate::frame::DepthFrame)
68    /// * [`DisparityFrame`](crate::frame::DisparityFrame)
69    /// * [`PoseFrame`](crate::frame::PoseFrame)
70    /// * [`PointsFrame`](crate::frame::PointsFrame)
71    ///
72    pub fn frames_of_type<F>(&self) -> Vec<F>
73    where
74        F: TryFrom<NonNull<sys::rs2_frame>> + FrameCategory,
75    {
76        let mut frames = Vec::new();
77        for i in 0..self.count() {
78            unsafe {
79                let mut err = std::ptr::null_mut::<sys::rs2_error>();
80                let frame_ptr =
81                    sys::rs2_extract_frame(self.ptr.as_ptr(), i as std::os::raw::c_int, &mut err);
82
83                if err.as_ref().is_some() {
84                    sys::rs2_free_error(err);
85                    continue;
86                }
87
88                let nonnull_frame_ptr = NonNull::new(frame_ptr).unwrap();
89
90                let is_extendable_to = sys::rs2_is_frame_extendable_to(
91                    nonnull_frame_ptr.as_ptr(),
92                    #[allow(clippy::useless_conversion)]
93                    (F::extension() as i32).try_into().unwrap(),
94                    &mut err,
95                );
96
97                if err.as_ref().is_none() {
98                    if is_extendable_to != 0 {
99                        if let Ok(f) = F::try_from(nonnull_frame_ptr) {
100                            let kind_for_frame = F::kind();
101
102                            if kind_for_frame == Rs2StreamKind::Any || f.has_correct_kind() {
103                                frames.push(f);
104                            }
105                            // This continue is to skip releasing the frame at the end of the loop.
106                            // If the call to try_from above is successful and we can push, then
107                            // the frame is owned by the type `E` and we should not release it.
108                            continue;
109                        }
110                    }
111                } else {
112                    sys::rs2_free_error(err);
113                }
114                sys::rs2_release_frame(nonnull_frame_ptr.as_ptr());
115            }
116        }
117        frames
118    }
119}