use anyhow::{anyhow, Result}; use crate::v4l2; use chrono::{DateTime, Local}; use std::io::{Read, Write}; pub struct Frame<'a>{ pub format: v4l2::ImageFormat, pub width: usize, pub height: usize, pub stride: usize, pub buf: &'a [u8], pub timestamp: DateTime, } 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 as u64).to_be_bytes())?; dst.write_all(&(self.height as u64).to_be_bytes())?; dst.write_all(&(self.stride as u64).to_be_bytes())?; dst.write_all(&(self.buf.len() as u64).to_be_bytes())?; dst.write_all(self.buf)?; Ok(()) } pub fn deserialize<'b>(src: &'b mut impl Read, buf: &'a mut Vec) -> Result{ struct Rh<'c>(&'c mut dyn Read); impl<'c> Rh<'c>{ fn u32(&mut self) -> Result{ let mut tmp: [u8; 4] = Default::default(); self.0.read_exact(&mut tmp)?; Ok(u32::from_be_bytes(tmp)) } fn i64(&mut self) -> Result{ let mut tmp: [u8; 8] = Default::default(); self.0.read_exact(&mut tmp)?; Ok(i64::from_be_bytes(tmp)) } fn usize(&mut self) -> Result{ let mut tmp: [u8; 8] = Default::default(); self.0.read_exact(&mut tmp)?; Ok(u64::from_be_bytes(tmp) as usize) } } // XXX: limit allocation length? 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(&mut self, cb: impl FnOnce(Frame) -> R) -> Result; } impl CaptStream for v4l2::CaptStream{ fn next(&mut self, cb: impl FnOnce(Frame) -> R) -> Result{ 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); impl RemoteCam{ pub fn new(inner: I) -> Self{ Self(inner) } } impl CaptStream for RemoteCam{ fn next(&mut self, cb: impl FnOnce(Frame) -> R) -> Result{ 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)) } }