five_five_five/src/capture.rs

80 lines
1.8 KiB
Rust

/// 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 <Self, Error>
{
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 <usize, Error>
{
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 <bool>
{
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,
}