/// Wraps non-thread-safe capture device like a v4l webcam use linuxvideo:: { format:: { PixFormat, PixelFormat, }, Device, stream::ReadStream, }; pub struct Capture { size_image: usize, stream: ReadStream, } impl Capture { pub fn new () -> Result { let x = Device::open ("/dev/video0")?; // sudo apt install v4l-utils // v4l2-ctl -d /dev/video0 --list-formats-ext let x = x.video_capture (PixFormat::new (1280, 720, PixelFormat::MJPG))?; let interval = x.set_frame_interval(linuxvideo::Fract::new(1, 30)).unwrap (); dbg! (interval); dbg! (x.format ()); let size_image = usize::try_from (x.format ().size_image ()).unwrap (); let stream = x.into_stream ()?; Ok (Self { size_image, stream, }) } pub fn size_image (&self) -> usize { self.size_image } /// Blocks until the capture device gets us a frame pub fn wait_for_frame (&mut self, output: &mut [u8]) -> Result { if output.len () < self.size_image () { return Err (Error::OutputBufferTooSmall); } Ok (self.stream.dequeue (|view| { let bytesused = usize::try_from (view.bytesused ()).unwrap (); let input = &view [0..bytesused]; let _ = &mut output [0..bytesused].copy_from_slice (&input); Ok (input.len ()) })?) } pub fn will_block (&self) -> std::io::Result { self.stream.will_block () } } #[derive (Debug, thiserror::Error)] pub enum Error { #[error ("I/O")] Io (#[from] std::io::Error), #[error ("output buffer too small")] OutputBufferTooSmall, }