use std::ptr::NonNull;
use std::slice;
use crate::error::{Error, Result};
use crate::formats::FrameFormat;
use uvc_sys::*;
unsafe impl Send for Frame {}
unsafe impl Sync for Frame {}
#[derive(Debug)]
pub struct Frame {
frame: NonNull<uvc_frame>,
}
impl Frame {
pub(crate) unsafe fn from_raw(frame: *mut uvc_frame) -> Frame {
Frame {
frame: NonNull::new(frame).unwrap(),
}
}
unsafe fn new_with_dimensions(width: u32, height: u32, components: u32) -> Self {
let frame = uvc_allocate_frame((width * height * components) as _);
Frame {
frame: NonNull::new(frame).unwrap(),
}
}
pub fn to_rgb(&self) -> Result<Frame> {
let new_frame = unsafe { Frame::new_with_dimensions(self.width(), self.height(), 3) };
let err = unsafe {
match self.format() {
FrameFormat::MJPEG => uvc_mjpeg2rgb(self.frame.as_ptr(), new_frame.frame.as_ptr()),
FrameFormat::YUYV => uvc_yuyv2rgb(self.frame.as_ptr(), new_frame.frame.as_ptr()),
FrameFormat::UYVY => uvc_uyvy2rgb(self.frame.as_ptr(), new_frame.frame.as_ptr()),
FrameFormat::Any => uvc_any2rgb(self.frame.as_ptr(), new_frame.frame.as_ptr()),
_ => uvc_any2rgb(self.frame.as_ptr(), new_frame.frame.as_ptr()),
}
}
.into();
if err == Error::Success {
Ok(new_frame)
} else {
Err(err)
}
}
pub fn to_bgr(&self) -> Result<Frame> {
let new_frame = unsafe { Frame::new_with_dimensions(self.width(), self.height(), 3) };
let err = unsafe {
match self.format() {
FrameFormat::YUYV => uvc_yuyv2bgr(self.frame.as_ptr(), new_frame.frame.as_ptr()),
FrameFormat::UYVY => uvc_uyvy2bgr(self.frame.as_ptr(), new_frame.frame.as_ptr()),
FrameFormat::Any => uvc_any2bgr(self.frame.as_ptr(), new_frame.frame.as_ptr()),
_ => uvc_any2bgr(self.frame.as_ptr(), new_frame.frame.as_ptr()),
}
}
.into();
if err == Error::Success {
Ok(new_frame)
} else {
Err(err)
}
}
#[must_use]
pub fn to_bytes(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
(*self.frame.as_ptr()).data as *const u8,
(*self.frame.as_ptr()).data_bytes as _,
)
}
}
#[must_use]
pub fn width(&self) -> u32 {
unsafe { *self.frame.as_ptr() }.width
}
#[must_use]
pub fn height(&self) -> u32 {
unsafe { *self.frame.as_ptr() }.height
}
#[must_use]
pub fn format(&self) -> FrameFormat {
unsafe { *self.frame.as_ptr() }.frame_format.into()
}
#[must_use]
pub fn sequence(&self) -> u32 {
unsafe { (*self.frame.as_ptr()).sequence }
}
pub fn duplicate(&self) -> Result<Frame> {
unsafe {
let mut new_frame = Frame::from_raw(uvc_allocate_frame(0));
let err = uvc_duplicate_frame(self.frame.as_ptr(), new_frame.frame.as_mut()).into();
if err != Error::Success {
return Err(err);
}
Ok(new_frame)
}
}
}
impl Drop for Frame {
fn drop(&mut self) {
unsafe { uvc_free_frame(self.frame.as_ptr()) }
}
}