use std::{net::SocketAddr, result, sync::Arc, thread::{self, sleep}, time::Duration}; use image::{ImageBuffer, Rgb}; use nokhwa::{pixel_format::RgbFormat, utils::{ApiBackend, RequestedFormat, RequestedFormatType, Resolution}, Camera}; use anyhow::{Context, Ok, Result}; use openh264::{encoder::Encoder, formats::{RgbSliceU8, YUVBuffer}, nal_units}; use tokio::{io::AsyncWriteExt, net::{TcpListener, TcpStream}, runtime::Runtime, sync::{Notify, RwLock}, task::LocalSet}; fn main() -> Result<()>{ let await_frame = Arc::new(Notify::new()); let latest_frame = Arc::new(RwLock::new(YUVBuffer::new(0, 0))); { let runtime = Runtime::new()?; let await_frame = await_frame.clone(); let latest_frame = latest_frame.clone(); thread::spawn(move || { let local = LocalSet::new(); local.block_on(&runtime, camera_manager(await_frame, latest_frame)).unwrap(); }); } { let runtime = Runtime::new()?; let await_frame = await_frame.clone(); let latest_frame = latest_frame.clone(); thread::spawn(move || { let local = LocalSet::new(); local.block_on(&runtime, server(await_frame, latest_frame)).unwrap(); }); } loop {} } async fn camera_manager(await_frame: Arc, latest_frame: Arc>) -> Result<()>{ let cameras = nokhwa::query(ApiBackend::Auto)?; let camera = cameras.get(0).context("no cameras")?; println!("using: {}",camera.human_name()); let requested = RequestedFormat::new::(RequestedFormatType::HighestResolution(Resolution::new(320, 240))); let mut camera = Camera::new(camera.index().clone(), requested)?; camera.open_stream()?; loop { let frame = camera.frame()?; let resolution = frame.resolution(); let frame: ImageBuffer, Vec> = frame.decode_image::()?; let buf = RgbSliceU8::new(frame.as_raw(), (resolution.width_x as usize, resolution.height_y as usize)); let yuv = YUVBuffer::from_rgb8_source(buf); *latest_frame.write().await = yuv; await_frame.notify_waiters(); } } async fn stream_video(await_frame: Arc, latest_frame: Arc>, mut client: TcpStream) -> Result<()>{ let mut encoder = Encoder::new()?; loop { await_frame.notified().await; let data = encoder.encode(&*latest_frame.read().await)?; let data = data.to_vec(); println!("len: {}", data.len()); let len = data.len(); let data2 = data.clone(); drop(data); client.write(&data2).await?; client.write_u32(len as u32).await?; } } async fn server(await_frame: Arc, latest_frame: Arc>) -> Result<()> { let port = 2993; let listener = TcpListener::bind(format!("0.0.0.0:{port}")).await?; println!("listening on {port}"); while let result::Result::Ok((client, addr)) = listener.accept().await { println!("connected to {:?}", addr); tokio::task::spawn_local(stream_video(await_frame.clone(), latest_frame.clone(), client)); } Ok(()) }