From 55cae3e208dcc5579470f90d16a49ad7331b6b23 Mon Sep 17 00:00:00 2001 From: dyknon Date: Fri, 28 Feb 2025 01:26:55 +0900 Subject: make less delay (but not works correctly) --- src/bin/sshcamera.rs | 22 +++++----------- src/lib.rs | 1 + src/source.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/v4l2abst.rs | 12 +++++++++ 4 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 src/source.rs diff --git a/src/bin/sshcamera.rs b/src/bin/sshcamera.rs index 270700a..1add8cd 100644 --- a/src/bin/sshcamera.rs +++ b/src/bin/sshcamera.rs @@ -2,11 +2,12 @@ use anyhow::{anyhow, Result}; use sshcamera::v4l2::{Device as V4l2, Field}; use sshcamera::v4l2cairo::V4l2Cairo; use sshcamera::gtk; -use sshcamera::v4l2abst::{CaptStream, RemoteCam}; +use sshcamera::v4l2abst::RemoteCam; use sshcamera::io::RWBundle; +use sshcamera::source; use gtk4::glib::ExitCode; use std::env; -use std::io::{self, Read as _, Write as _}; +use std::io; use std::process::{Command, Stdio}; fn main() -> Result{ @@ -21,7 +22,7 @@ fn main() -> Result{ let v = V4l2::open(arg1)?; // TODO: It should be better. - let mut c = v.captstream_builder()? + let c = v.captstream_builder()? .set_pixelformat("MJPG".into()) //.set_pixelformat("YUYV".into()) .set_field(Field::None) @@ -29,19 +30,8 @@ fn main() -> Result{ assert!(["YUYV", "MJPG"].contains(&c.pixelformat().as_str())); assert!(c.field() == Field::None); - let mut io = RWBundle(io::stdin(), io::stdout()); - loop{ - CaptStream::next(&mut c, |frame|{ - frame.serialize(&mut io)?; - io.flush()?; - let mut rb = [0]; - io.read_exact(&mut rb)?; - if rb[0] != 0x2e{ - return Err(anyhow!("protocol error")); - } - Ok(()) - })??; - } + let io = RWBundle(io::stdin(), io::stdout()); + source::main(c, io).and(Ok(ExitCode::SUCCESS)) }else{ let child = Command::new(arg1) .args(args) diff --git a/src/lib.rs b/src/lib.rs index 61a1e4f..13be706 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,3 +5,4 @@ pub mod v4l2; pub mod v4l2abst; pub mod v4l2cairo; pub mod gtk; +pub mod source; diff --git a/src/source.rs b/src/source.rs new file mode 100644 index 0000000..a99bcd2 --- /dev/null +++ b/src/source.rs @@ -0,0 +1,73 @@ +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(){ + eprintln!("is none"); + frlock = cv.wait(frlock).map_err(|e| anyhow!("{}", e))?; + } + if let Some(fr) = frlock.take(){ + eprintln!("fgot"); + 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))?; + eprintln!("fset"); + *frlock = Some(OwnedFrame::from_ref(&fr)); + Ok(()) + })??; + cv.notify_all(); + if iothread.is_finished(){ + iothread.join().unwrap()?; + break; + } + } + panic!() + }) +} diff --git a/src/v4l2abst.rs b/src/v4l2abst.rs index 03983bc..a4103fc 100644 --- a/src/v4l2abst.rs +++ b/src/v4l2abst.rs @@ -23,6 +23,18 @@ impl<'a> Frame<'a>{ dst.write_all(self.buf)?; Ok(()) } + pub fn clone_in<'b, 'c>(&'b self, buf: &'c mut Vec) + -> Frame<'c>{ + *buf = self.buf.into(); + Frame{ + format: self.format, + width: self.width, + height: self.height, + stride: self.stride, + buf, + timestamp: self.timestamp, + } + } pub fn deserialize<'b>(src: &'b mut impl Read, buf: &'a mut Vec) -> Result{ struct Rh<'c>(&'c mut dyn Read); -- cgit v1.2.3