From b90c934242bbe6480f1d134293e351341d87df4b Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Tue, 12 Sep 2023 22:24:48 -0500 Subject: [PATCH] :shirt: refactor --- src/capture.rs | 2 - src/controller.rs | 124 ++++++++++++++++++++++ src/driver.rs | 148 +++++++++++++++++++++++++++ src/main.rs | 255 ++-------------------------------------------- 4 files changed, 283 insertions(+), 246 deletions(-) create mode 100644 src/controller.rs create mode 100644 src/driver.rs diff --git a/src/capture.rs b/src/capture.rs index 8e19c63..62d7b0a 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -54,8 +54,6 @@ impl Capture return Err (Error::OutputBufferTooSmall); } - // std::thread::sleep (std::time::Duration::from_millis (500)); - Ok (self.stream.dequeue (|view| { let bytesused = usize::try_from (view.bytesused ()).unwrap (); diff --git a/src/controller.rs b/src/controller.rs new file mode 100644 index 0000000..ee964e0 --- /dev/null +++ b/src/controller.rs @@ -0,0 +1,124 @@ +use std:: +{ + time::Instant, +}; + +pub enum MsgFromController +{ + RepaintGui (RgbaFrame), + StartCapture, + StartJpegDecoder (JpegFrame), +} + +#[derive (Clone)] +pub struct JpegFrame +{ + pub data: Vec , + pub capture_time: Instant, +} + +#[derive (Clone)] +pub struct RgbaFrame +{ + pub data: Vec , + pub capture_time: Instant, +} + +pub struct Controller +{ + gui_has_new_frame: bool, + gui_needs_frame: bool, + + capture_is_running: bool, + + jpeg_decoder_is_running: bool, + jpeg_decoder_has_new_frame: bool, + jpeg_decoder_needs_frame: bool, + + rgba_frame: RgbaFrame, + jpeg_frame: JpegFrame, +} + +impl Controller +{ + pub fn new (now: Instant) -> Self + { + Self + { + gui_has_new_frame: false, + gui_needs_frame: false, + + capture_is_running: false, + jpeg_decoder_has_new_frame: false, + jpeg_decoder_is_running: false, + jpeg_decoder_needs_frame: false, + + rgba_frame: RgbaFrame + { + data: Default::default (), + capture_time: now, + }, + jpeg_frame: JpegFrame + { + data: Default::default (), + capture_time: now, + }, + } + } + + pub 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_has_new_frame = false; + self.rgba_frame = frame; + } + + pub fn handle_capture (&mut self, jpeg: JpegFrame) + { + // println! ("handle_capture"); + self.capture_is_running = false; + self.jpeg_frame = jpeg; + self.jpeg_decoder_has_new_frame = true; + } + + pub fn handle_gui_needs_frame (&mut self) + { + // println! ("handle_gui_needs_frame"); + self.gui_needs_frame = true; + } + + pub fn poll (&mut self) -> Option + { + if self.gui_needs_frame && self.gui_has_new_frame + { + self.gui_has_new_frame = false; + self.gui_needs_frame = false; + // println! ("RepaintGui"); + Some (MsgFromController::RepaintGui (self.rgba_frame.clone ())) + } + 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_needs_frame = false; + // println! ("StartJpegDecoder"); + Some (MsgFromController::StartJpegDecoder (self.jpeg_frame.clone ())) + } + else if self.jpeg_decoder_needs_frame && ! self.jpeg_decoder_has_new_frame && ! self.capture_is_running + { + self.capture_is_running = true; + // println! ("StartCapture"); + Some (MsgFromController::StartCapture) + } + else if self.gui_needs_frame && ! self.gui_has_new_frame + { + self.jpeg_decoder_needs_frame = true; + None + } + else + { + None + } + } +} diff --git a/src/driver.rs b/src/driver.rs new file mode 100644 index 0000000..2b3e568 --- /dev/null +++ b/src/driver.rs @@ -0,0 +1,148 @@ +use std:: +{ + sync::mpsc, + time::Instant, +}; + +use eframe::egui; + +use crate:: +{ + capture::Capture, + controller:: + { + Controller, + MsgFromController, + JpegFrame, + RgbaFrame, + }, +}; + +pub enum MsgToDriver +{ + GuiNeedsRgbaFrame, + GotCapture ((Capture, JpegFrame)), + DecodedJpegToRgba (RgbaFrame), +} + +pub enum MsgToGui +{ + NewRgbaFrame (RgbaFrame), +} + +pub struct Driver +{ + send: mpsc::SyncSender , + recv: mpsc::Receiver , + + gui_ctx: egui::Context, + send_to_gui: mpsc::SyncSender , + + capture: Option , + + ctl: Controller, +} + +fn sleep_ms (ms: u64) +{ + std::thread::sleep (std::time::Duration::from_millis (ms)); +} + +impl Driver +{ + pub fn new ( + send: mpsc::SyncSender , + recv: mpsc::Receiver , + gui_ctx: egui::Context, + send_to_gui: mpsc::SyncSender , + ) -> Self + { + Self { + send, + recv, + gui_ctx, + send_to_gui, + capture: Some (Capture::new ().unwrap ()), + ctl: Controller::new (Instant::now ()), + } + } + + pub fn run (&mut self) + { + let pool = rayon::ThreadPoolBuilder::new().build().unwrap (); + + loop + { + match self.recv.recv().unwrap () + { + MsgToDriver::DecodedJpegToRgba (frame) => + { + self.ctl.handle_rgba_frame (frame); + }, + MsgToDriver::GotCapture ((capture, jpeg)) => + { + self.ctl.handle_capture (jpeg); + self.capture = Some (capture); + }, + MsgToDriver::GuiNeedsRgbaFrame => + { + self.ctl.handle_gui_needs_frame (); + }, + } + + while let Some (msg) = self.ctl.poll () + { + match msg + { + MsgFromController::RepaintGui (rgba_frame) => + { + self.send_to_gui.send (MsgToGui::NewRgbaFrame (rgba_frame)).unwrap (); + self.gui_ctx.request_repaint(); + }, + MsgFromController::StartJpegDecoder (jpeg_frame) => + { + let send = self.send.clone (); + pool.spawn (move || + { + // sleep_ms (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)); + + decoder.decode_headers().unwrap (); + let mut rgba = vec![0u8;decoder.output_buffer_size().unwrap ()]; + decoder.decode_into(&mut rgba).unwrap (); + + let rgba = RgbaFrame + { + data: rgba, + capture_time: jpeg_frame.capture_time, + }; + + send.send (MsgToDriver::DecodedJpegToRgba (rgba)).unwrap (); + }); + }, + MsgFromController::StartCapture => + { + let mut capture = self.capture.take ().unwrap (); + let send = self.send.clone (); + + pool.spawn (move || + { + let mut data = vec! [0u8; capture.size_image()]; + capture.wait_for_frame(&mut data).unwrap (); + + let frame = JpegFrame + { + data, + capture_time: Instant::now (), + }; + + // sleep_ms (500); + + send.send (MsgToDriver::GotCapture ((capture, frame))).unwrap (); + }); + } + } + } + } + } +} diff --git a/src/main.rs b/src/main.rs index e8ed03c..10c9d40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,15 @@ use std::{ use eframe::egui; mod capture; +mod controller; +mod driver; + +use driver:: +{ + Driver, + MsgToDriver, + MsgToGui, +}; fn main() -> Result <(), Error> { @@ -56,7 +65,7 @@ struct App { camera_fps: u64, latency: Duration, - send_to_ctl: mpsc::SyncSender , + send_to_ctl: mpsc::SyncSender , recv_at_gui: mpsc::Receiver , driver_thread: thread::JoinHandle <()>, @@ -114,7 +123,7 @@ impl eframe::App for App { if self.requesting_frames { - self.send_to_ctl.send (MsgToController::GuiNeedsRgbaFrame).unwrap (); + self.send_to_ctl.send (MsgToDriver::GuiNeedsRgbaFrame).unwrap (); } while let Ok (msg) = self.recv_at_gui.try_recv() @@ -165,248 +174,6 @@ impl eframe::App for App { } } -enum MsgToController -{ - GuiNeedsRgbaFrame, - GotCapture ((capture::Capture, JpegFrame)), - DecodedJpegToRgba (RgbaFrame), -} - -enum MsgToGui -{ - NewRgbaFrame (RgbaFrame), -} - -enum MsgFromController -{ - RepaintGui (RgbaFrame), - StartCapture, - StartJpegDecoder (JpegFrame), -} - -#[derive (Clone)] -struct JpegFrame -{ - data: Vec , - capture_time: Instant, -} - -#[derive (Clone)] -struct RgbaFrame -{ - data: Vec , - capture_time: Instant, -} - -struct Controller -{ - gui_has_new_frame: bool, - gui_needs_frame: bool, - - capture_is_running: bool, - - jpeg_decoder_is_running: bool, - jpeg_decoder_has_new_frame: bool, - jpeg_decoder_needs_frame: bool, - - rgba_frame: RgbaFrame, - jpeg_frame: JpegFrame, -} - -impl Controller -{ - fn new (now: Instant) -> Self - { - Self - { - gui_has_new_frame: false, - gui_needs_frame: false, - - capture_is_running: false, - jpeg_decoder_has_new_frame: false, - jpeg_decoder_is_running: false, - jpeg_decoder_needs_frame: false, - - rgba_frame: RgbaFrame - { - data: Default::default (), - capture_time: now, - }, - jpeg_frame: JpegFrame - { - data: Default::default (), - capture_time: now, - }, - } - } - - 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_has_new_frame = false; - self.rgba_frame = frame; - } - - fn handle_capture (&mut self, jpeg: JpegFrame) - { - // println! ("handle_capture"); - self.capture_is_running = false; - self.jpeg_frame = jpeg; - self.jpeg_decoder_has_new_frame = true; - } - - fn handle_gui_needs_frame (&mut self) - { - // println! ("handle_gui_needs_frame"); - self.gui_needs_frame = true; - } - - fn poll (&mut self) -> Option - { - if self.gui_needs_frame && self.gui_has_new_frame - { - self.gui_has_new_frame = false; - self.gui_needs_frame = false; - println! ("RepaintGui"); - Some (MsgFromController::RepaintGui (self.rgba_frame.clone ())) - } - 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_needs_frame = false; - println! ("StartJpegDecoder"); - Some (MsgFromController::StartJpegDecoder (self.jpeg_frame.clone ())) - } - else if self.jpeg_decoder_needs_frame && ! self.jpeg_decoder_has_new_frame && ! self.capture_is_running - { - self.capture_is_running = true; - println! ("StartCapture"); - Some (MsgFromController::StartCapture) - } - else if self.gui_needs_frame && ! self.gui_has_new_frame - { - self.jpeg_decoder_needs_frame = true; - None - } - else - { - None - } - } -} - -struct Driver -{ - send: mpsc::SyncSender , - recv: mpsc::Receiver , - - gui_ctx: egui::Context, - send_to_gui: mpsc::SyncSender , - - capture: Option , - - ctl: Controller, -} - -impl Driver -{ - fn new ( - send: mpsc::SyncSender , - recv: mpsc::Receiver , - gui_ctx: egui::Context, - send_to_gui: mpsc::SyncSender , - ) -> Self - { - Self { - send, - recv, - gui_ctx, - send_to_gui, - capture: Some (capture::Capture::new ().unwrap ()), - ctl: Controller::new (Instant::now ()), - } - } - - fn run (&mut self) - { - let pool = rayon::ThreadPoolBuilder::new().build().unwrap (); - - loop - { - match self.recv.recv().unwrap () - { - MsgToController::DecodedJpegToRgba (frame) => - { - self.ctl.handle_rgba_frame (frame); - }, - MsgToController::GotCapture ((capture, jpeg)) => - { - self.ctl.handle_capture (jpeg); - self.capture = Some (capture); - }, - MsgToController::GuiNeedsRgbaFrame => - { - self.ctl.handle_gui_needs_frame (); - }, - } - - while let Some (msg) = self.ctl.poll () - { - match msg - { - MsgFromController::RepaintGui (rgba_frame) => - { - self.send_to_gui.send (MsgToGui::NewRgbaFrame (rgba_frame)).unwrap (); - self.gui_ctx.request_repaint(); - }, - MsgFromController::StartJpegDecoder (jpeg_frame) => - { - let send = self.send.clone (); - 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)); - - decoder.decode_headers().unwrap (); - let mut rgba = vec![0u8;decoder.output_buffer_size().unwrap ()]; - decoder.decode_into(&mut rgba).unwrap (); - - let rgba = RgbaFrame - { - data: rgba, - capture_time: jpeg_frame.capture_time, - }; - - send.send (MsgToController::DecodedJpegToRgba (rgba)).unwrap (); - }); - }, - MsgFromController::StartCapture => - { - let mut capture = self.capture.take ().unwrap (); - let send = self.send.clone (); - - pool.spawn (move || - { - let mut data = vec! [0u8; capture.size_image()]; - capture.wait_for_frame(&mut data).unwrap (); - - let frame = JpegFrame - { - data, - capture_time: Instant::now (), - }; - - send.send (MsgToController::GotCapture ((capture, frame))).unwrap (); - }); - } - } - } - } - } -} - fn main_egui () { let native_options = eframe::NativeOptions::default();