summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bin/usshcamera.rs21
-rw-r--r--src/gtk.rs25
-rw-r--r--src/source.rs3
-rw-r--r--src/v4l2cairo.rs5
4 files changed, 28 insertions, 26 deletions
diff --git a/src/bin/usshcamera.rs b/src/bin/usshcamera.rs
index 6d73e92..ea09a03 100644
--- a/src/bin/usshcamera.rs
+++ b/src/bin/usshcamera.rs
@@ -1,9 +1,9 @@
use anyhow::{anyhow, Result};
use sshcamera::v4l2::{Device as V4l2, Field};
-use sshcamera::v4l2abst::CaptStream;
use sshcamera::io::RWBundle;
+use sshcamera::source;
use std::env;
-use std::io::{self, Read as _, Write as _};
+use std::io;
fn main() -> Result<()>{
let mut args = env::args();
@@ -20,7 +20,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)
@@ -28,17 +28,6 @@ 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)
}
diff --git a/src/gtk.rs b/src/gtk.rs
index 6ebd992..91b772f 100644
--- a/src/gtk.rs
+++ b/src/gtk.rs
@@ -7,7 +7,7 @@ use glib::{clone, spawn_future_local};
use std::thread;
use std::sync::{Arc, Mutex};
use std::rc::Rc;
-use std::cell::RefCell;
+use std::cell::Cell;
use crate::sync::Signal;
use std::future::poll_fn;
use std::task::Poll;
@@ -107,41 +107,54 @@ fn activate<Attr: Overlay>(app: &gtk::Application, apps: Arc<AppState<Attr>>){
let draw = gtk::DrawingArea::new();
let overlay = Attr::empty().unwrap();
- let frame_cache: Rc<RefCell<Option<cairo::ImageSurface>>>
- = Rc::new(RefCell::new(None));
+ let frame_cache: Rc<Cell<Option<cairo::ImageSurface>>>
+ = Rc::new(Cell::new(None));
+ let attr_cache: Rc<Cell<Option<Attr>>> = Rc::new(Cell::new(None));
draw.set_draw_func(clone!{
#[strong] frame_cache,
move |_draw, ctx, canvas_w, canvas_h|{
ctx.set_source_rgb(0., 0., 0.);
ctx.paint().unwrap();
- if let Some(image) = frame_cache.borrow_mut().clone(){
+ if let Some(image) = frame_cache.take(){
let ipat = cairo::SurfacePattern::create(&image);
let scale = ((canvas_w as f64) / (image.width() as f64)).min(
(canvas_h as f64) / (image.height() as f64));
ctx.scale(scale, scale);
ctx.set_source(&ipat).unwrap();
ctx.paint().unwrap();
+ frame_cache.replace(Some(image));
}
}
});
+ overlay.add_tick_callback(clone!{
+ #[strong] attr_cache,
+ move |overlay, _clock|{
+ if let Some(attr) = attr_cache.take(){
+ attr.update(overlay).unwrap();
+ attr_cache.replace(Some(attr));
+ }
+ glib::ControlFlow::Continue
+ }
+ });
spawn_future_local(poll_fn(clone!{
#[strong] apps,
#[strong] draw,
#[strong] frame_cache,
+ #[strong] attr_cache,
#[strong] overlay,
move |ctx|{
loop{
match apps.update.lock().unwrap().poll(ctx){
Poll::Ready(_) => {
if let Some(newfb) = apps.next.lock().unwrap().take(){
- let mut frame_cache = frame_cache.borrow_mut();
if let Some(lastframe) = frame_cache.take(){
apps.fbpool.lock().unwrap()
.put(lastframe.take_data().unwrap());
}
- *frame_cache = Some(newfb.image.into_inner());
+ frame_cache.replace(Some(newfb.image.into_inner()));
newfb.attr.update(&overlay).unwrap();
+ attr_cache.replace(Some(newfb.attr));
}
draw.queue_draw();
},
diff --git a/src/source.rs b/src/source.rs
index a99bcd2..2563a99 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -38,11 +38,9 @@ pub fn main(mut cam: impl CaptStream, mut io: impl Read + Write + Send)
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()?;
@@ -58,7 +56,6 @@ pub fn main(mut cam: impl CaptStream, mut io: impl Read + Write + Send)
loop{
cam.next(|fr| -> Result<()>{
let mut frlock = frame.lock().map_err(|e| anyhow!("{}", e))?;
- eprintln!("fset");
*frlock = Some(OwnedFrame::from_ref(&fr));
Ok(())
})??;
diff --git a/src/v4l2cairo.rs b/src/v4l2cairo.rs
index de89df8..795575b 100644
--- a/src/v4l2cairo.rs
+++ b/src/v4l2cairo.rs
@@ -125,8 +125,11 @@ impl cgtk::Overlay for Overlay{
Ok(())
}
fn update(&self, widget: &gtk::Label) -> Result<()>{
+ let delay = Local::now() - &self.timestamp;
widget.set_label(
- &self.timestamp.format("%Y/%m/%d %H:%M:%S%.3f").to_string());
+ &format!("{} (delay={}ms)",
+ self.timestamp.format("%Y/%m/%d %H:%M:%S%.3f"),
+ delay.num_milliseconds()));
Ok(())
}
}