👕 refactor: extract Controller again 🥳

main
_ 2023-09-12 21:20:14 -05:00
parent d008baa34f
commit fb5013ef3e
2 changed files with 148 additions and 160 deletions

View File

@ -23,6 +23,9 @@ impl Capture
{ {
let x = Device::open ("/dev/video0")?; let x = Device::open ("/dev/video0")?;
// sudo apt install v4l-utils
// v4l2-ctl -d /dev/video0 --list-formats-ext
let x = x.video_capture (PixFormat::new (1280, 720, PixelFormat::MJPG))?; let x = x.video_capture (PixFormat::new (1280, 720, PixelFormat::MJPG))?;
x.set_frame_interval(linuxvideo::Fract::new(1, 30)).unwrap (); x.set_frame_interval(linuxvideo::Fract::new(1, 30)).unwrap ();
dbg! (x.format ()); dbg! (x.format ());
@ -72,4 +75,4 @@ pub enum Error
Io (#[from] std::io::Error), Io (#[from] std::io::Error),
#[error ("output buffer too small")] #[error ("output buffer too small")]
OutputBufferTooSmall, OutputBufferTooSmall,
} }

View File

@ -10,7 +10,6 @@ use std::{
}; };
use eframe::egui; use eframe::egui;
use rayon::ThreadPool;
mod capture; mod capture;
mod task; mod task;
@ -22,95 +21,25 @@ fn main() -> Result <(), Error>
match args.next ().as_deref () match args.next ().as_deref ()
{ {
None => main_egui (), None => main_egui (),
Some ("capture") => Some ("capture") =>
{ {
use std::io::Write; let mut capture = capture::Capture::new ().unwrap ();
let mut cap = capture::Capture::new ()?; let mut buf = vec! [0u8; capture.size_image ()];
let mut buf = vec! [0u8; cap.size_image ()];
let mut bytesused = 0;
for _ in 0..30 for _ in 0..10
{ {
cap.wait_for_frame (&mut buf).unwrap (); capture.wait_for_frame (&mut buf).unwrap ();
} }
println! ("Measuring...");
let start = Instant::now (); let start = Instant::now ();
for _ in 0..30 for _ in 0..30
{ {
let rc = cap.wait_for_frame (&mut buf); capture.wait_for_frame (&mut buf).unwrap ();
bytesused = rc.unwrap ();
} }
let stop = Instant::now (); let stop = Instant::now ();
let capture_fps = 30_000.0f32 / (stop - start).as_millis () as f32; println! ("{} ms", (stop - start).as_millis ());
dbg! (capture_fps);
let buf = &buf [0..bytesused];
let mut f = std::fs::File::create ("data.jpeg").unwrap ();
f.write_all (buf).unwrap ();
let start = Instant::now ();
let mut pixels = vec! [];
for _ in 0..30
{
let mut decoder = zune_jpeg::JpegDecoder::new_with_options
(
buf,
zune_core::options::DecoderOptions::new_fast ().jpeg_set_out_colorspace (zune_core::colorspace::ColorSpace::YCbCr),
);
decoder.decode_headers ().unwrap ();
pixels.resize (decoder.output_buffer_size ().unwrap (), 0);
decoder.decode_into (&mut pixels).unwrap ();
}
let stop = Instant::now ();
let decode_mpf = (stop - start).as_millis () as f32 / 30.0f32;
dbg! (decode_mpf);
let mut f = std::fs::File::create ("data.raw").unwrap ();
f.write_all (&pixels).unwrap ();
},
Some ("decode") =>
{
let jpeg = std::fs::read ("data.jpeg").unwrap ();
let start = Instant::now ();
let mut pixels = vec! [];
for _ in 0..30
{
let mut decoder = zune_jpeg::JpegDecoder::new_with_options
(
&jpeg,
zune_core::options::DecoderOptions::new_fast ().jpeg_set_out_colorspace (zune_core::colorspace::ColorSpace::YCbCr),
);
decoder.decode_headers ().unwrap ();
pixels.resize (decoder.output_buffer_size ().unwrap (), 0);
decoder.decode_into (&mut pixels).unwrap ();
}
let stop = Instant::now ();
let mpf_ycbcr = (stop - start).as_millis () as f32 / 30.0f32;
dbg! (mpf_ycbcr);
std::fs::write ("raw.data", &pixels).unwrap ();
let start = Instant::now ();
let mut pixels = vec! [];
for _ in 0..30
{
let mut decoder = zune_jpeg::JpegDecoder::new_with_options
(
&jpeg,
zune_core::options::DecoderOptions::new_fast ().jpeg_set_out_colorspace (zune_core::colorspace::ColorSpace::RGB),
);
decoder.decode_headers ().unwrap ();
pixels.resize (decoder.output_buffer_size ().unwrap (), 0);
decoder.decode_into (&mut pixels).unwrap ();
}
let stop = Instant::now ();
let mpf_rgb = (stop - start).as_millis () as f32 / 30.0f32;
dbg! (mpf_rgb);
}, },
Some (_) => eprintln! ("Unknown subcommand"), Some (_) => eprintln! ("Unknown subcommand"),
} }
@ -252,7 +181,9 @@ enum MsgToGui
enum MsgFromController enum MsgFromController
{ {
Idle, RepaintGui ((Vec <u8>, Instant)),
StartCapture,
StartJpegDecoder (JpegFrame),
} }
#[derive (Clone)] #[derive (Clone)]
@ -262,17 +193,12 @@ struct JpegFrame
time: Instant, time: Instant,
} }
struct Driver struct Controller
{ {
send: mpsc::SyncSender <MsgToController>, gui_rgba_gen: Instant,
recv: mpsc::Receiver <MsgToController>,
gui_ctx: egui::Context,
send_to_gui: mpsc::SyncSender <MsgToGui>,
gui_rgba_gen: Instant,
gui_needs_frame: bool, gui_needs_frame: bool,
capture: task::Task <capture::Capture, ()>, capture: task::Task <(), ()>,
jpeg_decoder: task::Task <(), Instant>, jpeg_decoder: task::Task <(), Instant>,
jpeg_needs_frame: bool, jpeg_needs_frame: bool,
@ -281,27 +207,16 @@ struct Driver
jpeg_frame: JpegFrame, jpeg_frame: JpegFrame,
} }
impl Driver impl Controller
{ {
fn new ( fn new (now: Instant) -> Self
send: mpsc::SyncSender <MsgToController>,
recv: mpsc::Receiver <MsgToController>,
gui_ctx: egui::Context,
send_to_gui: mpsc::SyncSender <MsgToGui>,
) -> Self
{ {
let now = Instant::now (); Self
{
Self {
send,
recv,
gui_ctx,
send_to_gui,
gui_needs_frame: false, gui_needs_frame: false,
gui_rgba_gen: now, gui_rgba_gen: now,
capture: capture::Capture::new ().unwrap ().into (), capture: ().into (),
jpeg_decoder: ().into (), jpeg_decoder: ().into (),
jpeg_needs_frame: false, jpeg_needs_frame: false,
@ -315,6 +230,87 @@ impl Driver
} }
} }
fn handle_rgba_frame (&mut self, data: Vec <u8>, gen: Instant)
{
self.jpeg_decoder.stop (()).unwrap ();
self.rgba_frame = (data, gen);
}
fn handle_capture (&mut self, jpeg: JpegFrame)
{
self.capture.stop (()).unwrap ();
self.jpeg_frame = jpeg;
}
fn handle_gui_needs_frame (&mut self)
{
self.gui_needs_frame = true;
}
fn poll (&mut self) -> Option <MsgFromController>
{
if self.gui_needs_frame && self.rgba_frame.1 > self.gui_rgba_gen
{
self.gui_needs_frame = false;
self.gui_rgba_gen = self.rgba_frame.1;
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
{
self.jpeg_decoder.start (self.jpeg_frame.time).unwrap ();
self.jpeg_needs_frame = false;
Some (MsgFromController::StartJpegDecoder (self.jpeg_frame.clone ()))
}
else if self.jpeg_needs_frame && ! self.capture.is_running ()
{
self.capture.start (()).unwrap ();
Some (MsgFromController::StartCapture)
}
else if self.gui_needs_frame && self.jpeg_frame.time == self.rgba_frame.1
{
self.jpeg_needs_frame = true;
None
}
else
{
None
}
}
}
struct Driver
{
send: mpsc::SyncSender <MsgToController>,
recv: mpsc::Receiver <MsgToController>,
gui_ctx: egui::Context,
send_to_gui: mpsc::SyncSender <MsgToGui>,
capture: Option <capture::Capture>,
ctl: Controller,
}
impl Driver
{
fn new (
send: mpsc::SyncSender <MsgToController>,
recv: mpsc::Receiver <MsgToController>,
gui_ctx: egui::Context,
send_to_gui: mpsc::SyncSender <MsgToGui>,
) -> Self
{
Self {
send,
recv,
gui_ctx,
send_to_gui,
capture: Some (capture::Capture::new ().unwrap ()),
ctl: Controller::new (Instant::now ()),
}
}
fn run (&mut self) fn run (&mut self)
{ {
let pool = rayon::ThreadPoolBuilder::new().build().unwrap (); let pool = rayon::ThreadPoolBuilder::new().build().unwrap ();
@ -325,73 +321,62 @@ impl Driver
{ {
MsgToController::DecodedJpegToRgba ((data, gen)) => MsgToController::DecodedJpegToRgba ((data, gen)) =>
{ {
self.jpeg_decoder.stop (()).unwrap (); self.ctl.handle_rgba_frame (data, gen);
self.rgba_frame = (data, gen);
}, },
MsgToController::GotCapture ((capture, jpeg)) => MsgToController::GotCapture ((capture, jpeg)) =>
{ {
self.capture.stop (capture).unwrap (); self.ctl.handle_capture (jpeg);
self.jpeg_frame = jpeg; self.capture = Some (capture);
}, },
MsgToController::GuiNeedsRgbaFrame => MsgToController::GuiNeedsRgbaFrame =>
{ {
self.gui_needs_frame = true; self.ctl.handle_gui_needs_frame ();
}, },
} }
if self.gui_needs_frame && self.rgba_frame.1 > self.gui_rgba_gen while let Some (msg) = self.ctl.poll ()
{ {
self.send_to_gui.send (MsgToGui::NewRgbaFrame (self.rgba_frame.clone ())).unwrap (); match msg
self.gui_needs_frame = false;
self.gui_rgba_gen = self.rgba_frame.1;
self.gui_ctx.request_repaint();
}
if
self.gui_needs_frame &&
! self.jpeg_decoder.is_running () &&
self.jpeg_frame.time > self.rgba_frame.1
{
let send = self.send.clone ();
let jpeg_frame = self.jpeg_frame.clone ();
self.jpeg_decoder.start(jpeg_frame.time).unwrap ();
self.jpeg_needs_frame = false;
pool.spawn (move ||
{ {
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)); MsgFromController::RepaintGui (rgba_frame) =>
decoder.decode_headers().unwrap ();
let mut rgba = vec![0u8;decoder.output_buffer_size().unwrap ()];
decoder.decode_into(&mut rgba).unwrap ();
send.send (MsgToController::DecodedJpegToRgba ((rgba, jpeg_frame.time))).unwrap ();
});
}
if self.gui_needs_frame && self.jpeg_frame.time == self.rgba_frame.1
{
self.jpeg_needs_frame = true;
}
if self.jpeg_needs_frame && ! self.capture.is_running()
{
let mut capture = self.capture.start (()).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, self.send_to_gui.send (MsgToGui::NewRgbaFrame (rgba_frame)).unwrap ();
time: Instant::now (), self.gui_ctx.request_repaint();
}; },
MsgFromController::StartJpegDecoder (jpeg_frame) =>
send.send (MsgToController::GotCapture ((capture, frame))).unwrap (); {
}); let send = self.send.clone ();
pool.spawn (move ||
{
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 ();
send.send (MsgToController::DecodedJpegToRgba ((rgba, jpeg_frame.time))).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,
time: Instant::now (),
};
send.send (MsgToController::GotCapture ((capture, frame))).unwrap ();
});
}
}
} }
} }
} }