👕 refactor
parent
cd0a0883c8
commit
99bb54b26e
|
@ -54,6 +54,8 @@ impl Capture
|
||||||
return Err (Error::OutputBufferTooSmall);
|
return Err (Error::OutputBufferTooSmall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// std::thread::sleep (std::time::Duration::from_millis (500));
|
||||||
|
|
||||||
Ok (self.stream.dequeue (|view|
|
Ok (self.stream.dequeue (|view|
|
||||||
{
|
{
|
||||||
let bytesused = usize::try_from (view.bytesused ()).unwrap ();
|
let bytesused = usize::try_from (view.bytesused ()).unwrap ();
|
||||||
|
|
89
src/main.rs
89
src/main.rs
|
@ -1,6 +1,4 @@
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
|
||||||
marker::Send,
|
|
||||||
sync::mpsc,
|
sync::mpsc,
|
||||||
thread,
|
thread,
|
||||||
time::{
|
time::{
|
||||||
|
@ -12,7 +10,6 @@ use std::{
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
|
|
||||||
mod capture;
|
mod capture;
|
||||||
mod task;
|
|
||||||
|
|
||||||
fn main() -> Result <(), Error>
|
fn main() -> Result <(), Error>
|
||||||
{
|
{
|
||||||
|
@ -124,11 +121,11 @@ impl eframe::App for App {
|
||||||
{
|
{
|
||||||
match msg
|
match msg
|
||||||
{
|
{
|
||||||
MsgToGui::NewRgbaFrame ((data, gen)) =>
|
MsgToGui::NewRgbaFrame (frame) =>
|
||||||
{
|
{
|
||||||
self.latency = Instant::now () - gen;
|
texture.set (egui::ColorImage::from_rgba_premultiplied([1280,720], &frame.data), Default::default ());
|
||||||
|
self.latency = Instant::now () - frame.capture_time;
|
||||||
self.camera_frames += 1;
|
self.camera_frames += 1;
|
||||||
texture.set (egui::ColorImage::from_rgba_premultiplied([1280,720], &data), Default::default ());
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,17 +169,17 @@ enum MsgToController
|
||||||
{
|
{
|
||||||
GuiNeedsRgbaFrame,
|
GuiNeedsRgbaFrame,
|
||||||
GotCapture ((capture::Capture, JpegFrame)),
|
GotCapture ((capture::Capture, JpegFrame)),
|
||||||
DecodedJpegToRgba ((Vec <u8>, Instant)),
|
DecodedJpegToRgba (RgbaFrame),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MsgToGui
|
enum MsgToGui
|
||||||
{
|
{
|
||||||
NewRgbaFrame ((Vec <u8>, Instant)),
|
NewRgbaFrame (RgbaFrame),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MsgFromController
|
enum MsgFromController
|
||||||
{
|
{
|
||||||
RepaintGui ((Vec <u8>, Instant)),
|
RepaintGui (RgbaFrame),
|
||||||
StartCapture,
|
StartCapture,
|
||||||
StartJpegDecoder (JpegFrame),
|
StartJpegDecoder (JpegFrame),
|
||||||
}
|
}
|
||||||
|
@ -191,20 +188,28 @@ enum MsgFromController
|
||||||
struct JpegFrame
|
struct JpegFrame
|
||||||
{
|
{
|
||||||
data: Vec <u8>,
|
data: Vec <u8>,
|
||||||
time: Instant,
|
capture_time: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive (Clone)]
|
||||||
|
struct RgbaFrame
|
||||||
|
{
|
||||||
|
data: Vec <u8>,
|
||||||
|
capture_time: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Controller
|
struct Controller
|
||||||
{
|
{
|
||||||
gui_rgba_gen: Instant,
|
gui_has_new_frame: bool,
|
||||||
gui_needs_frame: bool,
|
gui_needs_frame: bool,
|
||||||
|
|
||||||
capture_is_running: bool,
|
capture_is_running: bool,
|
||||||
|
|
||||||
jpeg_decoder_is_running: bool,
|
jpeg_decoder_is_running: bool,
|
||||||
jpeg_needs_frame: bool,
|
jpeg_decoder_has_new_frame: bool,
|
||||||
|
jpeg_decoder_needs_frame: bool,
|
||||||
|
|
||||||
rgba_frame: (Vec <u8>, Instant),
|
rgba_frame: RgbaFrame,
|
||||||
jpeg_frame: JpegFrame,
|
jpeg_frame: JpegFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,62 +219,75 @@ impl Controller
|
||||||
{
|
{
|
||||||
Self
|
Self
|
||||||
{
|
{
|
||||||
|
gui_has_new_frame: false,
|
||||||
gui_needs_frame: false,
|
gui_needs_frame: false,
|
||||||
gui_rgba_gen: now,
|
|
||||||
|
|
||||||
capture_is_running: false,
|
capture_is_running: false,
|
||||||
|
jpeg_decoder_has_new_frame: false,
|
||||||
jpeg_decoder_is_running: false,
|
jpeg_decoder_is_running: false,
|
||||||
jpeg_needs_frame: false,
|
jpeg_decoder_needs_frame: false,
|
||||||
|
|
||||||
rgba_frame: (Default::default (), now),
|
rgba_frame: RgbaFrame
|
||||||
|
{
|
||||||
|
data: Default::default (),
|
||||||
|
capture_time: now,
|
||||||
|
},
|
||||||
jpeg_frame: JpegFrame
|
jpeg_frame: JpegFrame
|
||||||
{
|
{
|
||||||
data: Default::default (),
|
data: Default::default (),
|
||||||
time: now,
|
capture_time: now,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_rgba_frame (&mut self, data: Vec <u8>, gen: Instant)
|
fn handle_rgba_frame (&mut self, frame: RgbaFrame)
|
||||||
{
|
{
|
||||||
|
// println! ("handle_rgba_frame");
|
||||||
|
self.gui_has_new_frame = true;
|
||||||
self.jpeg_decoder_is_running = false;
|
self.jpeg_decoder_is_running = false;
|
||||||
self.rgba_frame = (data, gen);
|
self.jpeg_decoder_has_new_frame = false;
|
||||||
|
self.rgba_frame = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_capture (&mut self, jpeg: JpegFrame)
|
fn handle_capture (&mut self, jpeg: JpegFrame)
|
||||||
{
|
{
|
||||||
|
// println! ("handle_capture");
|
||||||
self.capture_is_running = false;
|
self.capture_is_running = false;
|
||||||
self.jpeg_frame = jpeg;
|
self.jpeg_frame = jpeg;
|
||||||
|
self.jpeg_decoder_has_new_frame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_gui_needs_frame (&mut self)
|
fn handle_gui_needs_frame (&mut self)
|
||||||
{
|
{
|
||||||
|
// println! ("handle_gui_needs_frame");
|
||||||
self.gui_needs_frame = true;
|
self.gui_needs_frame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll (&mut self) -> Option <MsgFromController>
|
fn poll (&mut self) -> Option <MsgFromController>
|
||||||
{
|
{
|
||||||
if self.gui_needs_frame && self.rgba_frame.1 > self.gui_rgba_gen
|
if self.gui_needs_frame && self.gui_has_new_frame
|
||||||
{
|
{
|
||||||
|
self.gui_has_new_frame = false;
|
||||||
self.gui_needs_frame = false;
|
self.gui_needs_frame = false;
|
||||||
self.gui_rgba_gen = self.rgba_frame.1;
|
println! ("RepaintGui");
|
||||||
|
|
||||||
Some (MsgFromController::RepaintGui (self.rgba_frame.clone ()))
|
Some (MsgFromController::RepaintGui (self.rgba_frame.clone ()))
|
||||||
}
|
}
|
||||||
else if self.gui_needs_frame && ! self.jpeg_decoder_is_running && self.jpeg_frame.time > self.rgba_frame.1
|
else if self.jpeg_decoder_has_new_frame && ! self.jpeg_decoder_is_running && self.jpeg_decoder_needs_frame
|
||||||
{
|
{
|
||||||
self.jpeg_decoder_is_running = true;
|
self.jpeg_decoder_is_running = true;
|
||||||
self.jpeg_needs_frame = false;
|
self.jpeg_decoder_needs_frame = false;
|
||||||
|
println! ("StartJpegDecoder");
|
||||||
Some (MsgFromController::StartJpegDecoder (self.jpeg_frame.clone ()))
|
Some (MsgFromController::StartJpegDecoder (self.jpeg_frame.clone ()))
|
||||||
}
|
}
|
||||||
else if self.jpeg_needs_frame && ! self.capture_is_running
|
else if self.jpeg_decoder_needs_frame && ! self.jpeg_decoder_has_new_frame && ! self.capture_is_running
|
||||||
{
|
{
|
||||||
self.capture_is_running = true;
|
self.capture_is_running = true;
|
||||||
|
println! ("StartCapture");
|
||||||
Some (MsgFromController::StartCapture)
|
Some (MsgFromController::StartCapture)
|
||||||
}
|
}
|
||||||
else if self.gui_needs_frame && self.jpeg_frame.time == self.rgba_frame.1
|
else if self.gui_needs_frame && ! self.gui_has_new_frame
|
||||||
{
|
{
|
||||||
self.jpeg_needs_frame = true;
|
self.jpeg_decoder_needs_frame = true;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -319,9 +337,9 @@ impl Driver
|
||||||
{
|
{
|
||||||
match self.recv.recv().unwrap ()
|
match self.recv.recv().unwrap ()
|
||||||
{
|
{
|
||||||
MsgToController::DecodedJpegToRgba ((data, gen)) =>
|
MsgToController::DecodedJpegToRgba (frame) =>
|
||||||
{
|
{
|
||||||
self.ctl.handle_rgba_frame (data, gen);
|
self.ctl.handle_rgba_frame (frame);
|
||||||
},
|
},
|
||||||
MsgToController::GotCapture ((capture, jpeg)) =>
|
MsgToController::GotCapture ((capture, jpeg)) =>
|
||||||
{
|
{
|
||||||
|
@ -348,13 +366,20 @@ impl Driver
|
||||||
let send = self.send.clone ();
|
let send = self.send.clone ();
|
||||||
pool.spawn (move ||
|
pool.spawn (move ||
|
||||||
{
|
{
|
||||||
|
// std::thread::sleep (std::time::Duration::from_millis (500));
|
||||||
let mut decoder = zune_jpeg::JpegDecoder::new_with_options (&jpeg_frame.data, zune_core::options::DecoderOptions::new_fast().jpeg_set_out_colorspace(zune_core::colorspace::ColorSpace::RGBA));
|
let mut decoder = zune_jpeg::JpegDecoder::new_with_options (&jpeg_frame.data, zune_core::options::DecoderOptions::new_fast().jpeg_set_out_colorspace(zune_core::colorspace::ColorSpace::RGBA));
|
||||||
|
|
||||||
decoder.decode_headers().unwrap ();
|
decoder.decode_headers().unwrap ();
|
||||||
let mut rgba = vec![0u8;decoder.output_buffer_size().unwrap ()];
|
let mut rgba = vec![0u8;decoder.output_buffer_size().unwrap ()];
|
||||||
decoder.decode_into(&mut rgba).unwrap ();
|
decoder.decode_into(&mut rgba).unwrap ();
|
||||||
|
|
||||||
send.send (MsgToController::DecodedJpegToRgba ((rgba, jpeg_frame.time))).unwrap ();
|
let rgba = RgbaFrame
|
||||||
|
{
|
||||||
|
data: rgba,
|
||||||
|
capture_time: jpeg_frame.capture_time,
|
||||||
|
};
|
||||||
|
|
||||||
|
send.send (MsgToController::DecodedJpegToRgba (rgba)).unwrap ();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
MsgFromController::StartCapture =>
|
MsgFromController::StartCapture =>
|
||||||
|
@ -370,7 +395,7 @@ impl Driver
|
||||||
let frame = JpegFrame
|
let frame = JpegFrame
|
||||||
{
|
{
|
||||||
data,
|
data,
|
||||||
time: Instant::now (),
|
capture_time: Instant::now (),
|
||||||
};
|
};
|
||||||
|
|
||||||
send.send (MsgToController::GotCapture ((capture, frame))).unwrap ();
|
send.send (MsgToController::GotCapture ((capture, frame))).unwrap ();
|
||||||
|
@ -394,6 +419,4 @@ enum Error
|
||||||
{
|
{
|
||||||
#[error ("capture")]
|
#[error ("capture")]
|
||||||
Capture (#[from] capture::Error),
|
Capture (#[from] capture::Error),
|
||||||
#[error ("task")]
|
|
||||||
Task (#[from] task::Error),
|
|
||||||
}
|
}
|
||||||
|
|
74
src/task.rs
74
src/task.rs
|
@ -1,74 +0,0 @@
|
||||||
/// This is probably just a fancy Cell or something.
|
|
||||||
|
|
||||||
pub enum Task <S, R>
|
|
||||||
{
|
|
||||||
Stopped (S),
|
|
||||||
Running (R),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive (Debug, thiserror::Error)]
|
|
||||||
pub enum Error
|
|
||||||
{
|
|
||||||
#[error ("tried to start already-running task")]
|
|
||||||
AlreadyRunning,
|
|
||||||
#[error ("tried to stop already-stopped task")]
|
|
||||||
AlreadyStopped,
|
|
||||||
#[error ("cannot access a task's inner object while it's running")]
|
|
||||||
CantAccessWhileRunning,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl <S, R> From <S> for Task <S, R>
|
|
||||||
{
|
|
||||||
fn from (x: S) -> Self
|
|
||||||
{
|
|
||||||
Self::Stopped (x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl <S, R> Task <S, R>
|
|
||||||
{
|
|
||||||
pub fn is_running (&self) -> bool
|
|
||||||
{
|
|
||||||
match self
|
|
||||||
{
|
|
||||||
Self::Running (_) => true,
|
|
||||||
Self::Stopped (_) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_inner (&self) -> Result <&S, Error>
|
|
||||||
{
|
|
||||||
match self
|
|
||||||
{
|
|
||||||
Self::Running (_) => Err (Error::CantAccessWhileRunning),
|
|
||||||
Self::Stopped (x) => Ok (x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_inner_mut (&mut self) -> Result <&mut S, Error>
|
|
||||||
{
|
|
||||||
match self
|
|
||||||
{
|
|
||||||
Self::Running (_) => Err (Error::CantAccessWhileRunning),
|
|
||||||
Self::Stopped (x) => Ok (x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start (&mut self, x: R) -> Result <S, Error>
|
|
||||||
{
|
|
||||||
match std::mem::replace (self, Self::Running (x))
|
|
||||||
{
|
|
||||||
Self::Running (_) => Err (Error::AlreadyRunning),
|
|
||||||
Self::Stopped (x) => Ok (x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stop (&mut self, x: S) -> Result <R, Error>
|
|
||||||
{
|
|
||||||
match std::mem::replace (self, Self::Stopped (x))
|
|
||||||
{
|
|
||||||
Self::Stopped (_) => Err (Error::AlreadyStopped),
|
|
||||||
Self::Running (x) => Ok (x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue