👕 refactor: extract Controller again 🥳
							parent
							
								
									d008baa34f
								
							
						
					
					
						commit
						fb5013ef3e
					
				|  | @ -23,6 +23,9 @@ impl Capture | |||
|     { | ||||
|         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))?; | ||||
|         x.set_frame_interval(linuxvideo::Fract::new(1, 30)).unwrap (); | ||||
|         dbg! (x.format ()); | ||||
|  | @ -72,4 +75,4 @@ pub enum Error | |||
|     Io (#[from] std::io::Error), | ||||
|     #[error ("output buffer too small")] | ||||
|     OutputBufferTooSmall, | ||||
| } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										303
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										303
									
								
								src/main.rs
								
								
								
								
							|  | @ -10,7 +10,6 @@ use std::{ | |||
| }; | ||||
| 
 | ||||
| use eframe::egui; | ||||
| use rayon::ThreadPool; | ||||
| 
 | ||||
| mod capture; | ||||
| mod task; | ||||
|  | @ -22,95 +21,25 @@ fn main() -> Result <(), Error> | |||
|     match args.next ().as_deref () | ||||
|     { | ||||
|         None => main_egui (), | ||||
|         Some ("capture") => 
 | ||||
|         Some ("capture") => | ||||
|         { | ||||
|             use std::io::Write; | ||||
|             let mut cap = capture::Capture::new ()?; | ||||
|             let mut buf = vec! [0u8; cap.size_image ()]; | ||||
|             let mut bytesused = 0; | ||||
|             let mut capture = capture::Capture::new ().unwrap (); | ||||
|             let mut buf = vec! [0u8; capture.size_image ()]; | ||||
|             
 | ||||
|             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 (); | ||||
|             for _ in 0..30 | ||||
|             { | ||||
|                 let rc = cap.wait_for_frame (&mut buf); | ||||
|                 bytesused = rc.unwrap (); | ||||
|                 capture.wait_for_frame (&mut buf).unwrap (); | ||||
|             } | ||||
|             let stop = Instant::now (); | ||||
|             
 | ||||
|             let capture_fps = 30_000.0f32 / (stop - start).as_millis () as f32; | ||||
|             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); | ||||
|             println! ("{} ms", (stop - start).as_millis ()); | ||||
|         }, | ||||
|         Some (_) => eprintln! ("Unknown subcommand"), | ||||
|     } | ||||
|  | @ -252,7 +181,9 @@ enum MsgToGui | |||
| 
 | ||||
| enum MsgFromController | ||||
| { | ||||
|     Idle, | ||||
| 	RepaintGui ((Vec <u8>, Instant)), | ||||
| 	StartCapture, | ||||
| 	StartJpegDecoder (JpegFrame), | ||||
| } | ||||
| 
 | ||||
| #[derive (Clone)] | ||||
|  | @ -262,17 +193,12 @@ struct JpegFrame | |||
|     time: Instant, | ||||
| } | ||||
| 
 | ||||
| struct Driver | ||||
| struct Controller | ||||
| { | ||||
|     send: mpsc::SyncSender <MsgToController>, | ||||
|     recv: mpsc::Receiver <MsgToController>, | ||||
|     
 | ||||
|     gui_ctx: egui::Context, | ||||
|     send_to_gui: mpsc::SyncSender <MsgToGui>, | ||||
|     gui_rgba_gen: Instant, | ||||
| 	gui_rgba_gen: Instant, | ||||
|     gui_needs_frame: bool, | ||||
|     
 | ||||
|     capture: task::Task <capture::Capture, ()>, | ||||
|     capture: task::Task <(), ()>, | ||||
|     
 | ||||
|     jpeg_decoder: task::Task <(), Instant>, | ||||
|     jpeg_needs_frame: bool, | ||||
|  | @ -281,27 +207,16 @@ struct Driver | |||
|     jpeg_frame: JpegFrame, | ||||
| } | ||||
| 
 | ||||
| impl Driver | ||||
| impl Controller | ||||
| { | ||||
|     fn new ( | ||||
|         send: mpsc::SyncSender <MsgToController>, | ||||
|         recv: mpsc::Receiver <MsgToController>, | ||||
|         gui_ctx: egui::Context, | ||||
|         send_to_gui: mpsc::SyncSender <MsgToGui>, | ||||
|     ) -> Self | ||||
|     fn new (now: Instant) -> Self | ||||
|     { | ||||
|         let now = Instant::now (); | ||||
|         
 | ||||
|         Self { | ||||
|             send, | ||||
|             recv, | ||||
|             gui_ctx, | ||||
|             send_to_gui, | ||||
|         Self | ||||
|         { | ||||
|             gui_needs_frame: false, | ||||
|             
 | ||||
|             gui_rgba_gen: now, | ||||
|             
 | ||||
|             capture: capture::Capture::new ().unwrap ().into (), | ||||
|             capture: ().into (), | ||||
|             
 | ||||
|             jpeg_decoder: ().into (), | ||||
|             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) | ||||
|     { | ||||
|         let pool = rayon::ThreadPoolBuilder::new().build().unwrap (); | ||||
|  | @ -325,73 +321,62 @@ impl Driver | |||
|             { | ||||
|                 MsgToController::DecodedJpegToRgba ((data, gen)) => | ||||
|                 { | ||||
|                     self.jpeg_decoder.stop (()).unwrap (); | ||||
|                     self.rgba_frame = (data, gen); | ||||
|                     self.ctl.handle_rgba_frame (data, gen); | ||||
|                 }, | ||||
|                 MsgToController::GotCapture ((capture, jpeg)) => | ||||
|                 { | ||||
|                     self.capture.stop (capture).unwrap (); | ||||
|                     self.jpeg_frame = jpeg; | ||||
|                     self.ctl.handle_capture (jpeg); | ||||
|                     self.capture = Some (capture); | ||||
|                 }, | ||||
|                 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 (); | ||||
|                 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 || | ||||
|                 match msg | ||||
|                 { | ||||
|                     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 (); | ||||
|                 }); | ||||
|             } | ||||
|             
 | ||||
|             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 | ||||
|                     MsgFromController::RepaintGui (rgba_frame) => | ||||
|                     { | ||||
|                         data, | ||||
|                         time: Instant::now (), | ||||
|                     }; | ||||
|                     
 | ||||
|                     send.send (MsgToController::GotCapture ((capture, frame))).unwrap (); | ||||
|                 }); | ||||
|                         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 || | ||||
|                         { | ||||
|                             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 (); | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 _
						_