summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/sshcamera.rs22
-rw-r--r--src/lib.rs1
-rw-r--r--src/source.rs73
-rw-r--r--src/v4l2abst.rs12
4 files changed, 92 insertions, 16 deletions
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<ExitCode>{
@@ -21,7 +22,7 @@ fn main() -> Result<ExitCode>{
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<ExitCode>{
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<u8>);
+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<Option<OwnedFrame>> = 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<u8>)
+ -> 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<u8>)
-> Result<Self>{
struct Rh<'c>(&'c mut dyn Read);