use crate::{
base::{Rs2Extrinsics, Rs2Intrinsics, Rs2MotionDeviceIntrinsics},
check_rs2_error,
kind::{Rs2Exception, Rs2Format, Rs2StreamKind},
};
use anyhow::Result;
use num_traits::FromPrimitive;
use realsense_sys as sys;
use std::{convert::TryFrom, mem::MaybeUninit, ptr::NonNull};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum StreamConstructionError {
#[error("Could not retrieve stream data. Type: {0}; Reason: {1}")]
CouldNotRetrieveStreamData(Rs2Exception, String),
#[error("Could not determine if this is the default stream. Type: {0}; Reason: {1}")]
CouldNotDetermineIsDefault(Rs2Exception, String),
#[error("Could not get the stream profile from a stream profile list. Type: {0}; Reason: {1}")]
CouldNotGetProfileFromList(Rs2Exception, String),
#[error("Could not clone the stream profile after getting it from the profile list. Type: {0}; Reason: {1}")]
CouldNotCloneProfile(Rs2Exception, String),
}
#[derive(Error, Debug)]
pub enum DataError {
#[error("Could not get extrinsics. Type: {0}; Reason: {1}")]
CouldNotGetExtrinsics(Rs2Exception, String),
#[error("Could not set extrinsics. Type: {0}; Reason: {1}")]
CouldNotSetExtrinsics(Rs2Exception, String),
#[error("Stream does not have video intrinsics")]
StreamDoesNotHaveVideoIntrinsics,
#[error("Stream does not have motion intrinsics")]
StreamDoesNotHaveMotionIntrinsics,
#[error("Could not get video intrinsics. Type: {0}; Reason: {1}")]
CouldNotGetIntrinsics(Rs2Exception, String),
#[error("Could not get motion intrinsics. Type: {0}; Reason: {1}")]
CouldNotGetMotionIntrinsics(Rs2Exception, String),
}
#[derive(Debug)]
pub struct StreamProfile {
ptr: NonNull<sys::rs2_stream_profile>,
stream: Rs2StreamKind,
format: Rs2Format,
index: usize,
unique_id: i32,
framerate: i32,
is_default: bool,
should_drop: bool,
}
impl TryFrom<NonNull<sys::rs2_stream_profile>> for StreamProfile {
type Error = StreamConstructionError;
fn try_from(stream_profile_ptr: NonNull<sys::rs2_stream_profile>) -> Result<Self, Self::Error> {
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let mut stream = MaybeUninit::uninit();
let mut format = MaybeUninit::uninit();
let mut index = MaybeUninit::uninit();
let mut unique_id = MaybeUninit::uninit();
let mut framerate = MaybeUninit::uninit();
sys::rs2_get_stream_profile_data(
stream_profile_ptr.as_ptr(),
stream.as_mut_ptr(),
format.as_mut_ptr(),
index.as_mut_ptr(),
unique_id.as_mut_ptr(),
framerate.as_mut_ptr(),
&mut err,
);
check_rs2_error!(err, StreamConstructionError::CouldNotRetrieveStreamData)?;
let is_default =
sys::rs2_is_stream_profile_default(stream_profile_ptr.as_ptr(), &mut err);
check_rs2_error!(err, StreamConstructionError::CouldNotDetermineIsDefault)?;
Ok(StreamProfile {
ptr: stream_profile_ptr,
stream: Rs2StreamKind::from_i32(stream.assume_init() as i32).unwrap(),
format: Rs2Format::from_i32(format.assume_init() as i32).unwrap(),
index: index.assume_init() as usize,
unique_id: unique_id.assume_init(),
framerate: framerate.assume_init(),
is_default: is_default != 0,
should_drop: false,
})
}
}
}
impl Drop for StreamProfile {
fn drop(&mut self) {
unsafe {
if self.should_drop {
sys::rs2_delete_stream_profile(self.ptr.as_ptr());
}
}
}
}
impl StreamProfile {
pub(crate) fn try_create(
profiles: &NonNull<sys::rs2_stream_profile_list>,
index: i32,
) -> Result<Self, StreamConstructionError> {
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let profile_ptr = sys::rs2_get_stream_profile(profiles.as_ptr(), index, &mut err);
check_rs2_error!(err, StreamConstructionError::CouldNotGetProfileFromList)?;
let mut stream = MaybeUninit::uninit();
let mut format = MaybeUninit::uninit();
let mut index = MaybeUninit::uninit();
let mut unique_id = MaybeUninit::uninit();
let mut framerate = MaybeUninit::uninit();
sys::rs2_get_stream_profile_data(
profile_ptr,
stream.as_mut_ptr(),
format.as_mut_ptr(),
index.as_mut_ptr(),
unique_id.as_mut_ptr(),
framerate.as_mut_ptr(),
&mut err,
);
check_rs2_error!(err, StreamConstructionError::CouldNotRetrieveStreamData)?;
let profile_ptr = sys::rs2_clone_stream_profile(
profile_ptr,
stream.assume_init(),
index.assume_init(),
format.assume_init(),
&mut err,
);
check_rs2_error!(err, StreamConstructionError::CouldNotCloneProfile)?;
let nonnull_profile_ptr = NonNull::new(profile_ptr).unwrap();
let mut stream_profile = Self::try_from(nonnull_profile_ptr)?;
stream_profile.should_drop = true;
Ok(stream_profile)
}
}
#[inline]
pub fn is_default(&self) -> bool {
self.is_default
}
#[inline]
pub fn kind(&self) -> Rs2StreamKind {
self.stream
}
#[inline]
pub fn format(&self) -> Rs2Format {
self.format
}
#[inline]
pub fn index(&self) -> usize {
self.index
}
#[inline]
pub fn unique_id(&self) -> i32 {
self.unique_id
}
#[inline]
pub fn framerate(&self) -> i32 {
self.framerate
}
pub fn extrinsics(&self, to_profile: &StreamProfile) -> Result<Rs2Extrinsics, DataError> {
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let mut extrinsics = MaybeUninit::<sys::rs2_extrinsics>::uninit();
sys::rs2_get_extrinsics(
self.ptr.as_ptr(),
to_profile.ptr.as_ptr(),
extrinsics.as_mut_ptr(),
&mut err,
);
check_rs2_error!(err, DataError::CouldNotGetExtrinsics)?;
Ok(Rs2Extrinsics(extrinsics.assume_init()))
}
}
pub fn set_extrinsics(
&self,
to_profile: &StreamProfile,
extrinsics: Rs2Extrinsics,
) -> Result<(), DataError> {
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
sys::rs2_register_extrinsics(
self.ptr.as_ptr(),
to_profile.ptr.as_ptr(),
extrinsics.0,
&mut err,
);
check_rs2_error!(err, DataError::CouldNotSetExtrinsics)?;
Ok(())
}
}
pub fn intrinsics(&self) -> Result<Rs2Intrinsics, DataError> {
match self.stream {
Rs2StreamKind::Depth => (),
Rs2StreamKind::Color => (),
Rs2StreamKind::Infrared => (),
Rs2StreamKind::Fisheye => (),
_ => {
return Err(DataError::StreamDoesNotHaveVideoIntrinsics);
}
}
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let mut intrinsics = MaybeUninit::<sys::rs2_intrinsics>::uninit();
sys::rs2_get_video_stream_intrinsics(
self.ptr.as_ptr(),
intrinsics.as_mut_ptr(),
&mut err,
);
check_rs2_error!(err, DataError::CouldNotGetIntrinsics)?;
Ok(Rs2Intrinsics(intrinsics.assume_init()))
}
}
pub fn motion_intrinsics(&self) -> Result<Rs2MotionDeviceIntrinsics, DataError> {
match self.stream {
Rs2StreamKind::Gyro => (),
Rs2StreamKind::Accel => (),
_ => {
return Err(DataError::StreamDoesNotHaveMotionIntrinsics);
}
}
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let mut intrinsics = MaybeUninit::<sys::rs2_motion_device_intrinsic>::uninit();
sys::rs2_get_motion_intrinsics(self.ptr.as_ptr(), intrinsics.as_mut_ptr(), &mut err);
check_rs2_error!(err, DataError::CouldNotGetMotionIntrinsics)?;
Ok(Rs2MotionDeviceIntrinsics(intrinsics.assume_init()))
}
}
}