69 lines
1.6 KiB
Rust
69 lines
1.6 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")?;
|
|
dbg! (x.formats (linuxvideo::BufType::VIDEO_CAPTURE).collect::<Vec <_>> ());
|
|
let x = x.video_capture (PixFormat::new (u32::MAX, u32::MAX, PixelFormat::MJPG))?;
|
|
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];
|
|
&mut output [0..bytesused].copy_from_slice (&input);
|
|
Ok (input.len ())
|
|
})?)
|
|
}
|
|
}
|
|
|
|
#[derive (Debug, thiserror::Error)]
|
|
pub enum Error
|
|
{
|
|
#[error ("I/O")]
|
|
Io (#[from] std::io::Error),
|
|
#[error ("output buffer too small")]
|
|
OutputBufferTooSmall,
|
|
} |