#[cfg(feature = "with-image")]
use crate::base::Rs2Image;
use crate::{
base::{PoseData, Resolution, StreamProfileData},
common::*,
error::{ErrorChecker, Result},
frame_kind,
kind::{Format, FrameMetaDataValue, StreamKind, TimestampDomain},
sensor::{AnySensor, DepthSensor},
stream_profile::{AnyStreamProfile, StreamProfile},
};
pub trait GenericFrameEx
where
Self: Sized,
{
fn metadata(&self, kind: FrameMetaDataValue) -> Result<u64> {
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_get_frame_metadata(
self.ptr().as_ptr(),
kind as sys::rs2_frame_metadata_value,
checker.inner_mut_ptr(),
);
checker.check()?;
Ok(val as u64)
}
}
fn number(&self) -> Result<u64> {
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_get_frame_number(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as u64)
}
}
fn data_size(&self) -> Result<usize> {
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_get_frame_data_size(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as usize)
}
}
fn timestamp(&self) -> Result<f64> {
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_get_frame_timestamp(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as f64)
}
}
fn timestamp_domain(&self) -> Result<TimestampDomain> {
let val = unsafe {
let mut checker = ErrorChecker::new();
let val =
sys::rs2_get_frame_timestamp_domain(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
val
};
let domain = TimestampDomain::from_u32(val).unwrap();
Ok(domain)
}
fn data(&self) -> Result<&[u8]> {
let size = self.data_size()?;
let slice = unsafe {
let mut checker = ErrorChecker::new();
let ptr = sys::rs2_get_frame_data(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
slice::from_raw_parts::<u8>(ptr.cast::<u8>(), size)
};
Ok(slice)
}
fn sensor(&self) -> Result<AnySensor> {
let sensor = unsafe {
let mut checker = ErrorChecker::new();
let ptr = sys::rs2_get_frame_sensor(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
AnySensor::from_raw(ptr)
};
Ok(sensor)
}
fn stream_profile(&self) -> Result<AnyStreamProfile> {
let profile = unsafe {
let mut checker = ErrorChecker::new();
let ptr =
sys::rs2_get_frame_stream_profile(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
StreamProfile::from_raw_parts(ptr as *mut _, false)
};
Ok(profile)
}
fn try_clone(&self) -> Result<Self> {
unsafe {
let mut checker = ErrorChecker::new();
sys::rs2_frame_add_ref(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(Self::from_raw(self.ptr().as_ptr()))
}
}
#[doc(hidden)]
fn ptr(&self) -> NonNull<sys::rs2_frame>;
fn into_raw(self) -> *mut sys::rs2_frame;
unsafe fn from_raw(ptr: *mut sys::rs2_frame) -> Self;
}
pub trait VideoFrameEx
where
Self: GenericFrameEx,
{
fn resolution(&self) -> Result<Resolution> {
let width = self.width()?;
let height = self.height()?;
let resolution = Resolution { width, height };
Ok(resolution)
}
fn width(&self) -> Result<usize> {
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_get_frame_width(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as usize)
}
}
fn height(&self) -> Result<usize> {
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_get_frame_height(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as usize)
}
}
fn stride_in_bytes(&self) -> Result<usize> {
unsafe {
let mut checker = ErrorChecker::new();
let val =
sys::rs2_get_frame_stride_in_bytes(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as usize)
}
}
fn bits_per_pixel(&self) -> Result<usize> {
unsafe {
let mut checker = ErrorChecker::new();
let val =
sys::rs2_get_frame_bits_per_pixel(self.ptr().as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as usize)
}
}
#[cfg(feature = "with-image")]
fn ref_image(&self) -> Result<Rs2Image> {
let StreamProfileData { format, .. } = self.stream_profile()?.get_data()?;
let raw_data = self.data()?;
let Resolution { width, height } = self.resolution()?;
let stride_in_bytes = self.stride_in_bytes()?;
debug_assert_eq!(raw_data.len() % stride_in_bytes, 0, "please report bug");
let image = match format {
Format::Bgr8 => {
let channels = 3;
let sample_size = mem::size_of::<u8>();
debug_assert_eq!(stride_in_bytes % sample_size, 0, "please report bug");
let stride_in_samples = stride_in_bytes / sample_size;
debug_assert_eq!(
raw_data.len(),
stride_in_samples * height,
"please report bug"
);
debug_assert!(width * channels <= stride_in_samples, "please report bug");
let flat = FlatSamples {
samples: raw_data,
layout: SampleLayout {
channels: channels as u8,
width: width as u32,
height: height as u32,
channel_stride: 1,
width_stride: channels,
height_stride: stride_in_samples,
},
color_hint: Some(ColorType::Bgr8),
};
let image = flat.try_into_buffer().unwrap();
Rs2Image::Bgr8(image)
}
Format::Bgra8 => {
let channels = 4;
let sample_size = mem::size_of::<u8>();
debug_assert_eq!(stride_in_bytes % sample_size, 0, "please report bug");
let stride_in_samples = stride_in_bytes / sample_size;
debug_assert_eq!(
raw_data.len(),
stride_in_samples * height,
"please report bug"
);
debug_assert!(width * channels <= stride_in_samples, "please report bug");
let flat = FlatSamples {
samples: raw_data,
layout: SampleLayout {
channels: channels as u8,
width: width as u32,
height: height as u32,
channel_stride: 1,
width_stride: channels,
height_stride: stride_in_samples,
},
color_hint: Some(ColorType::Bgra8),
};
let image = flat.try_into_buffer().unwrap();
Rs2Image::Bgra8(image)
}
Format::Rgb8 => {
let channels = 3;
let sample_size = mem::size_of::<u8>();
debug_assert_eq!(stride_in_bytes % sample_size, 0, "please report bug");
let stride_in_samples = stride_in_bytes / sample_size;
debug_assert_eq!(
raw_data.len(),
stride_in_samples * height,
"please report bug"
);
debug_assert!(width * channels <= stride_in_samples, "please report bug");
let flat = FlatSamples {
samples: raw_data,
layout: SampleLayout {
channels: channels as u8,
width: width as u32,
height: height as u32,
channel_stride: 1,
width_stride: channels,
height_stride: stride_in_samples,
},
color_hint: Some(ColorType::Rgb8),
};
let image = flat.try_into_buffer().unwrap();
Rs2Image::Rgb8(image)
}
Format::Rgba8 => {
let channels = 4;
let sample_size = mem::size_of::<u8>();
debug_assert_eq!(stride_in_bytes % sample_size, 0, "please report bug");
let stride_in_samples = stride_in_bytes / sample_size;
debug_assert_eq!(
raw_data.len(),
stride_in_samples * height,
"please report bug"
);
debug_assert!(width * channels <= stride_in_samples, "please report bug");
let flat = FlatSamples {
samples: raw_data,
layout: SampleLayout {
channels: channels as u8,
width: width as u32,
height: height as u32,
channel_stride: 1,
width_stride: channels,
height_stride: stride_in_samples,
},
color_hint: Some(ColorType::Rgba8),
};
let image = flat.try_into_buffer().unwrap();
Rs2Image::Rgba8(image)
}
Format::Z16 => {
let sample_size = mem::size_of::<u16>();
debug_assert_eq!(stride_in_bytes % sample_size, 0, "please report bug");
let depth_data: &[u16] =
safe_transmute::transmute_many::<u16, PedanticGuard>(raw_data).unwrap();
let stride_in_samples = stride_in_bytes / sample_size;
debug_assert_eq!(
depth_data.len(),
stride_in_samples * height,
"please report bug"
);
debug_assert!(width <= stride_in_samples, "please report bug");
let flat = FlatSamples {
samples: depth_data,
layout: SampleLayout {
channels: 1,
width: width as u32,
height: height as u32,
channel_stride: 1,
width_stride: 1,
height_stride: stride_in_bytes / sample_size,
},
color_hint: Some(ColorType::L16),
};
let image = flat.try_into_buffer().unwrap();
Rs2Image::Luma16(image)
}
_ => unreachable!("unsupported format. please report bug"),
};
Ok(image)
}
#[cfg(feature = "with-image")]
fn owned_image(&self) -> Result<DynamicImage> {
Ok(self.ref_image()?.into())
}
}
pub trait DepthFrameEx
where
Self: VideoFrameEx,
{
fn distance(&self, x: usize, y: usize) -> Result<f32> {
let distance = unsafe {
let mut checker = ErrorChecker::new();
let distance = sys::rs2_depth_frame_get_distance(
self.ptr().as_ptr(),
x as c_int,
y as c_int,
checker.inner_mut_ptr(),
);
checker.check()?;
distance
};
Ok(distance)
}
fn depth_units(&self) -> Result<f32> {
let sensor = self.sensor()?;
let sensor: DepthSensor = sensor.try_extend_to()?.unwrap();
let depth_units = sensor.depth_units()?;
Ok(depth_units)
}
}
pub trait DisparityFrameEx
where
Self: DepthFrameEx,
{
fn baseline(&self) -> Result<f32> {
unsafe {
let mut checker = ErrorChecker::new();
let baseline = sys::rs2_depth_stereo_frame_get_baseline(
self.ptr().as_ptr(),
checker.inner_mut_ptr(),
);
checker.check()?;
Ok(baseline)
}
}
}
#[derive(Debug)]
pub enum ExtendedFrame {
Points(PointsFrame),
Composite(CompositeFrame),
Video(VideoFrame),
Depth(DepthFrame),
Disparity(DisparityFrame),
Motion(MotionFrame),
Pose(PoseFrame),
Other(AnyFrame),
}
pub type PointsFrame = Frame<frame_kind::Points>;
pub type CompositeFrame = Frame<frame_kind::Composite>;
pub type VideoFrame = Frame<frame_kind::Video>;
pub type DepthFrame = Frame<frame_kind::Depth>;
pub type DisparityFrame = Frame<frame_kind::Disparity>;
pub type MotionFrame = Frame<frame_kind::Motion>;
pub type PoseFrame = Frame<frame_kind::Pose>;
pub type AnyFrame = Frame<frame_kind::Any>;
#[derive(Debug)]
pub struct Frame<Kind>
where
Kind: frame_kind::FrameKind,
{
pub(crate) ptr: NonNull<sys::rs2_frame>,
_phantom: PhantomData<Kind>,
}
impl<Kind> GenericFrameEx for Frame<Kind>
where
Kind: frame_kind::FrameKind,
{
fn ptr(&self) -> NonNull<sys::rs2_frame> {
self.ptr
}
fn into_raw(self) -> *mut sys::rs2_frame {
let ptr = self.ptr;
mem::forget(self);
ptr.as_ptr()
}
unsafe fn from_raw(ptr: *mut sys::rs2_frame) -> Self {
Self {
ptr: NonNull::new(ptr).unwrap(),
_phantom: PhantomData,
}
}
}
impl VideoFrameEx for VideoFrame {}
impl VideoFrameEx for DepthFrame {}
impl DepthFrameEx for DepthFrame {}
impl VideoFrameEx for DisparityFrame {}
impl DepthFrameEx for DisparityFrame {}
impl DisparityFrameEx for DisparityFrame {}
impl<Kind> Frame<Kind> where Kind: frame_kind::FrameKind {}
impl AnyFrame {
pub fn is_extendable_to<Kind>(&self) -> Result<bool>
where
Kind: frame_kind::NonAnyFrameKind,
{
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_is_frame_extendable_to(
self.ptr.as_ptr(),
Kind::EXTENSION as sys::rs2_extension,
checker.inner_mut_ptr(),
);
checker.check()?;
Ok(val != 0)
}
}
pub fn try_extend_to<Kind>(self) -> Result<result::Result<Frame<Kind>, Self>>
where
Kind: frame_kind::NonAnyFrameKind,
{
let is_extendable = self.is_extendable_to::<Kind>()?;
if is_extendable {
let ptr = self.into_raw();
let frame = Frame {
ptr: NonNull::new(ptr).unwrap(),
_phantom: PhantomData,
};
Ok(Ok(frame))
} else {
Ok(Err(self))
}
}
pub fn try_extend(self) -> Result<ExtendedFrame> {
let frame_any = self;
let frame_any = match frame_any.try_extend_to::<frame_kind::Points>()? {
Ok(frame) => return Ok(ExtendedFrame::Points(frame)),
Err(frame) => frame,
};
let frame_any = match frame_any.try_extend_to::<frame_kind::Composite>()? {
Ok(frame) => return Ok(ExtendedFrame::Composite(frame)),
Err(frame) => frame,
};
let frame_any = match frame_any.try_extend_to::<frame_kind::Motion>()? {
Ok(frame) => return Ok(ExtendedFrame::Motion(frame)),
Err(frame) => frame,
};
let frame_any = match frame_any.try_extend_to::<frame_kind::Pose>()? {
Ok(frame) => return Ok(ExtendedFrame::Pose(frame)),
Err(frame) => frame,
};
let frame_any = match frame_any.try_extend_to::<frame_kind::Disparity>()? {
Ok(frame) => return Ok(ExtendedFrame::Disparity(frame)),
Err(frame) => frame,
};
let frame_any = match frame_any.try_extend_to::<frame_kind::Depth>()? {
Ok(frame) => return Ok(ExtendedFrame::Depth(frame)),
Err(frame) => frame,
};
let frame_any = match frame_any.try_extend_to::<frame_kind::Video>()? {
Ok(frame) => return Ok(ExtendedFrame::Video(frame)),
Err(frame) => frame,
};
Ok(ExtendedFrame::Other(frame_any))
}
}
impl CompositeFrame {
pub fn len(&self) -> Result<usize> {
let len = unsafe {
let mut checker = ErrorChecker::new();
let len = sys::rs2_embedded_frames_count(self.ptr.as_ptr(), checker.inner_mut_ptr());
checker.check()?;
len as usize
};
Ok(len)
}
pub fn is_empty(&self) -> Result<bool> {
Ok(self.len()? == 0)
}
pub fn get(&self, index: usize) -> Result<Option<AnyFrame>> {
let len = self.len()?;
if index >= len {
return Ok(None);
}
let frame = unsafe {
let mut checker = ErrorChecker::new();
let ptr =
sys::rs2_extract_frame(self.ptr.as_ptr(), index as c_int, checker.inner_mut_ptr());
checker.check()?;
Frame::from_raw(ptr)
};
Ok(Some(frame))
}
pub fn try_into_iter(self) -> Result<CompositeFrameIntoIter> {
let len = self.len()?;
let ptr = self.into_raw();
let iter = CompositeFrameIntoIter {
index: 0,
len,
ptr: NonNull::new(ptr).unwrap(),
fused: len == 0,
};
Ok(iter)
}
pub fn try_iter(&self) -> Result<CompositeFrameIter> {
let len = self.len()?;
let iter = CompositeFrameIter {
index: 0,
len,
ptr: self.ptr,
fused: len == 0,
};
Ok(iter)
}
pub fn first_of<Kind>(&self, stream: StreamKind) -> Result<Option<Frame<Kind>>>
where
Kind: frame_kind::NonAnyFrameKind,
{
for result in self.try_iter()? {
let frame_any = result?;
if let Ok(frame) = frame_any.try_extend_to::<Kind>()? {
if frame.stream_profile()?.get_data()?.stream == stream {
return Ok(Some(frame));
}
}
}
Ok(None)
}
pub fn color_frame(&self) -> Result<Option<VideoFrame>> {
self.first_of::<frame_kind::Video>(StreamKind::Color)
}
pub fn depth_frame(&self) -> Result<Option<DepthFrame>> {
self.first_of::<frame_kind::Depth>(StreamKind::Depth)
}
pub fn pose_frame(&self) -> Result<Option<PoseFrame>> {
self.first_of::<frame_kind::Pose>(StreamKind::Pose)
}
}
impl PoseFrame {
pub fn pose(&self) -> Result<PoseData> {
let pose_data = unsafe {
let mut checker = ErrorChecker::new();
let mut pose_data = MaybeUninit::uninit();
sys::rs2_pose_frame_get_pose_data(
self.ptr.as_ptr(),
pose_data.as_mut_ptr(),
checker.inner_mut_ptr(),
);
checker.check()?;
pose_data.assume_init()
};
let pose = PoseData(pose_data);
Ok(pose)
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct TextureCoordinate {
pub u: f32,
pub v: f32,
}
unsafe impl safe_transmute::TriviallyTransmutable for TextureCoordinate {}
impl PointsFrame {
pub fn vertices<'a>(&'a self) -> Result<&'a [sys::rs2_vertex]> {
let n_points = self.points_count()?;
unsafe {
let mut checker = ErrorChecker::new();
let ptr = sys::rs2_get_frame_vertices(self.ptr.as_ptr(), checker.inner_mut_ptr());
checker.check()?;
let slice = slice::from_raw_parts::<sys::rs2_vertex>(ptr, n_points);
Ok(slice)
}
}
pub fn texture_coordinates<'a>(&'a self) -> Result<&'a [TextureCoordinate]> {
unsafe {
let n_points = self.points_count()?;
let mut checker = ErrorChecker::new();
let ptr =
sys::rs2_get_frame_texture_coordinates(self.ptr.as_ptr(), checker.inner_mut_ptr());
checker.check()?;
let slice = slice::from_raw_parts::<sys::rs2_pixel>(ptr, n_points);
let bytes =
slice::from_raw_parts::<u8>(slice.as_ptr() as *const u8, mem::size_of_val(slice));
let tcs =
safe_transmute::transmute_many::<TextureCoordinate, PedanticGuard>(bytes).unwrap();
debug_assert_eq!(tcs.len(), n_points);
Ok(tcs)
}
}
pub fn points_count(&self) -> Result<usize> {
unsafe {
let mut checker = ErrorChecker::new();
let val = sys::rs2_get_frame_points_count(self.ptr.as_ptr(), checker.inner_mut_ptr());
checker.check()?;
Ok(val as usize)
}
}
}
impl MotionFrame {
pub fn motion(&self) -> Result<[f32; 3]> {
let slice = safe_transmute::transmute_many::<f32, PedanticGuard>(self.data()?).unwrap();
match *slice {
[x, y, z] => Ok([x, y, z]),
_ => unreachable!("please report bug"),
}
}
}
impl IntoIterator for CompositeFrame {
type Item = Result<AnyFrame>;
type IntoIter = CompositeFrameIntoIter;
fn into_iter(self) -> Self::IntoIter {
self.try_into_iter().unwrap()
}
}
impl<Kind> Clone for Frame<Kind>
where
Kind: frame_kind::FrameKind,
{
fn clone(&self) -> Self {
self.try_clone().unwrap()
}
}
impl<Kind> Drop for Frame<Kind>
where
Kind: frame_kind::FrameKind,
{
fn drop(&mut self) {
unsafe {
sys::rs2_release_frame(self.ptr.as_ptr());
}
}
}
unsafe impl<Kind> Send for Frame<Kind> where Kind: frame_kind::FrameKind {}
unsafe impl<Kind> Sync for Frame<Kind> where Kind: frame_kind::FrameKind {}
#[derive(Debug)]
pub struct CompositeFrameIntoIter {
len: usize,
index: usize,
ptr: NonNull<sys::rs2_frame>,
fused: bool,
}
impl Iterator for CompositeFrameIntoIter {
type Item = Result<AnyFrame>;
fn next(&mut self) -> Option<Self::Item> {
if self.fused {
return None;
}
let ptr = unsafe {
let mut checker = ErrorChecker::new();
let ptr = sys::rs2_extract_frame(
self.ptr.as_ptr(),
self.index as c_int,
checker.inner_mut_ptr(),
);
if let Err(err) = checker.check() {
self.fused = true;
return Some(Err(err));
}
ptr
};
self.index += 1;
if self.index >= self.len {
self.fused = true;
}
let frame = unsafe { Frame::from_raw(ptr) };
Some(Ok(frame))
}
}
impl FusedIterator for CompositeFrameIntoIter {}
impl Drop for CompositeFrameIntoIter {
fn drop(&mut self) {
unsafe {
sys::rs2_release_frame(self.ptr.as_ptr());
}
}
}
#[derive(Debug)]
pub struct CompositeFrameIter {
len: usize,
index: usize,
ptr: NonNull<sys::rs2_frame>,
fused: bool,
}
impl Iterator for CompositeFrameIter {
type Item = Result<AnyFrame>;
fn next(&mut self) -> Option<Self::Item> {
if self.fused {
return None;
}
let ptr = unsafe {
let mut checker = ErrorChecker::new();
let ptr = sys::rs2_extract_frame(
self.ptr.as_ptr(),
self.index as c_int,
checker.inner_mut_ptr(),
);
if let Err(err) = checker.check() {
self.fused = true;
return Some(Err(err));
}
ptr
};
self.index += 1;
if self.index >= self.len {
self.fused = true;
}
let frame = unsafe { Frame::from_raw(ptr) };
Some(Ok(frame))
}
}
impl FusedIterator for CompositeFrameIter {}