use anyhow::{anyhow, Result}; use std::thread; use std::sync::{Mutex, Condvar}; use crate::v4l2abst::{CaptStream, Frame}; use std::io::{Read, Write}; struct OwnedFrame(Frame<'static>, Vec); impl OwnedFrame{ fn borrow(&self) -> Frame<'_>{ Frame{ format: self.0.format, width: self.0.width, height: self.0.height, stride: self.0.stride, buf: &self.1, timestamp: self.0.timestamp, } } fn from_ref<'a>(src: &Frame<'a>) -> Self{ let r0 = Frame{ format: src.format, width: src.width, height: src.height, stride: src.stride, buf: &[], timestamp: src.timestamp, }; OwnedFrame(r0, src.buf.into()) } } pub fn main(mut cam: impl CaptStream, mut io: impl Read + Write + Send) -> Result<()>{ let frame: Mutex> = Mutex::new(None); let cv = Condvar::new(); thread::scope(|scope|{ let iothread = scope.spawn(|| -> Result<()>{ loop{ let mut frlock = frame.lock().map_err(|e| anyhow!("{}", e))?; while frlock.is_none(){ frlock = cv.wait(frlock).map_err(|e| anyhow!("{}", e))?; } if let Some(fr) = frlock.take(){ drop(frlock); fr.borrow().serialize(&mut io)?; io.flush()?; let mut rb = [0]; io.read_exact(&mut rb)?; if rb[0] != 0x2e{ return Err(anyhow!("protocol error")); } } } }); loop{ cam.next(|fr| -> Result<()>{ let mut frlock = frame.lock().map_err(|e| anyhow!("{}", e))?; *frlock = Some(OwnedFrame::from_ref(&fr)); Ok(()) })??; cv.notify_all(); if iothread.is_finished(){ iothread.join().unwrap()?; break; } } panic!() }) }