diff options
| author | dyknon dyknonr5fjp | 2025-02-24 18:58:32 +0900 |
|---|---|---|
| committer | dyknon dyknonr5fjp | 2025-02-24 18:58:32 +0900 |
| commit | 6ecbf0d55695335f52d6fcf2b6a22ed45f5e4d99 (patch) | |
| tree | e17bfc8a9b55d5afbfe2f884322a96a54340f25d /src/v4l2abst.rs | |
| parent | 31b60ae28e6aff6d23b378cd77e288c96c7db148 (diff) | |
Remote camera capability.
Diffstat (limited to 'src/v4l2abst.rs')
| -rw-r--r-- | src/v4l2abst.rs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/v4l2abst.rs b/src/v4l2abst.rs new file mode 100644 index 0000000..baefea0 --- /dev/null +++ b/src/v4l2abst.rs @@ -0,0 +1,103 @@ +use anyhow::{anyhow, Result}; +use crate::v4l2; +use chrono::{DateTime, Local}; +use std::io::{Read, Write}; +use std::mem::size_of; + +pub struct Frame<'a>{ + pub format: v4l2::ImageFormat, + pub width: usize, + pub height: usize, + pub stride: usize, + pub buf: &'a [u8], + pub timestamp: DateTime<Local>, +} +impl<'a> Frame<'a>{ + pub fn serialize(&self, dst: &mut impl Write) -> Result<()>{ + dst.write_all(&u32::to_be_bytes(self.format.into()))?; + dst.write_all(&self.timestamp.timestamp_subsec_nanos().to_be_bytes())?; + dst.write_all(&self.timestamp.timestamp().to_be_bytes())?; + dst.write_all(&self.width.to_be_bytes())?; + dst.write_all(&self.height.to_be_bytes())?; + dst.write_all(&self.stride.to_be_bytes())?; + dst.write_all(&self.buf.len().to_be_bytes())?; + dst.write_all(self.buf)?; + Ok(()) + } + pub fn deserialize<'b>(src: &'b mut impl Read, buf: &'a mut Vec<u8>) + -> Result<Self>{ + struct Rh<'c>(&'c mut dyn Read); + impl<'c> Rh<'c>{ + fn u32(&mut self) -> Result<u32>{ + let mut tmp: [u8; 4] = Default::default(); + self.0.read_exact(&mut tmp)?; + Ok(u32::from_be_bytes(tmp)) + } + fn i64(&mut self) -> Result<i64>{ + let mut tmp: [u8; 8] = Default::default(); + self.0.read_exact(&mut tmp)?; + Ok(i64::from_be_bytes(tmp)) + } + fn usize(&mut self) -> Result<usize>{ + let mut tmp: [u8; size_of::<usize>()] = Default::default(); + self.0.read_exact(&mut tmp)?; + Ok(usize::from_be_bytes(tmp)) + } + } + let mut src = Rh(src); + let format = src.u32()?.into(); + let (ns, s) = (src.u32()?, src.i64()?); + let timestamp = DateTime::from_timestamp(s, ns) + .ok_or(anyhow!("Invalid DateTime"))?.into(); + let width = src.usize()?; + let height = src.usize()?; + let stride = src.usize()?; + let len = src.usize()?; + buf.resize(len, 0); + src.0.read_exact(buf)?; + Ok(Frame{ format, width, height, stride, buf, timestamp }) + } +} + +pub trait CaptStream{ + fn next<R>(&mut self, cb: impl FnOnce(Frame) -> R) -> Result<R>; +} + +impl CaptStream for v4l2::CaptStream{ + fn next<R>(&mut self, cb: impl FnOnce(Frame) -> R) -> Result<R>{ + let (width, height) = (self.width(), self.height()); + let stride = self.bytesperline(); + let format = self.pixelformat(); + let mut cb = Some(cb); + loop{ + if let Some(ret) = v4l2::CaptStream::next(self, |buf, attr|{ + if attr.flags.error{ + return None; + } + let timestamp = attr.get_datetime().unwrap(); + Some(cb.take().unwrap()(Frame{ + format, width, height, stride, buf, timestamp + })) + })?{ + return Ok(ret); + } + } + } +} + +pub struct RemoteCam<I: Read + Write>(I); +impl<I: Read + Write> RemoteCam<I>{ + pub fn new(inner: I) -> Self{ + Self(inner) + } +} +impl<I: Read + Write> CaptStream for RemoteCam<I>{ + fn next<R>(&mut self, cb: impl FnOnce(Frame) -> R) -> Result<R>{ + let ack: [u8; 1] = [0x2e]; + let mut buf = Vec::new(); + let frame = Frame::deserialize(&mut self.0, &mut buf)?; + self.0.write_all(&ack)?; + self.0.flush()?; + Ok(cb(frame)) + } +} |
