camera core add

This commit is contained in:
Brad Stein 2025-07-03 16:08:30 -05:00
parent 2fdfa7e597
commit 9fc17478b2
2 changed files with 15 additions and 23 deletions

View File

@ -138,18 +138,14 @@ impl LesavkaClientApp {
tokio::spawn(Self::audio_loop(ep_audio, audio_out)); tokio::spawn(Self::audio_loop(ep_audio, audio_out));
/*────────── microphone gRPC pusher ───────────*/ /*────────── camera & mic tasks ───────────────*/
let mic = Arc::new(MicrophoneCapture::new()?); let cam = Arc::new(CameraCapture::new(
let ep_mic = vid_ep.clone(); std::env::var("LESAVKA_CAM_SOURCE").ok().as_deref()
tokio::spawn(Self::mic_loop(ep_mic, mic)); )?);
tokio::spawn(Self::cam_loop(vid_ep.clone(), cam));
/*────────── webcam gRPC pusher ───────────────*/ let mic = Arc::new(MicrophoneCapture::new()?);
if !std::env::var("LESAVKA_CAM_DISABLE").is_ok() { tokio::spawn(Self::mic_loop(vid_ep.clone(), mic));
let cam = Arc::new(CameraCapture::new(
std::env::var("LESAVKA_CAM_SOURCE").ok().as_deref()
)?);
tokio::spawn(Self::cam_loop(vid_ep.clone(), cam));
}
/*────────── central reactor ───────────────────*/ /*────────── central reactor ───────────────────*/
tokio::select! { tokio::select! {
@ -318,9 +314,8 @@ impl LesavkaClientApp {
async fn cam_loop(ep: Channel, cam: Arc<CameraCapture>) { async fn cam_loop(ep: Channel, cam: Arc<CameraCapture>) {
loop { loop {
let mut cli = RelayClient::new(ep.clone()); let mut cli = RelayClient::new(ep.clone());
let (tx, rx) = tokio::sync::mpsc::channel::<VideoPacket>(256);
// pull frames in a real thread so we dont block async scheduler
let (tx_pkt, rx_pkt) = tokio::sync::mpsc::channel::<VideoPacket>(256);
std::thread::spawn({ std::thread::spawn({
let cam = cam.clone(); let cam = cam.clone();
move || { move || {
@ -332,17 +327,14 @@ impl LesavkaClientApp {
if n < 10 || n % 120 == 0 { if n < 10 || n % 120 == 0 {
tracing::trace!("📸 cli frame#{n} {} B", pkt.data.len()); tracing::trace!("📸 cli frame#{n} {} B", pkt.data.len());
} }
let _ = tx_pkt.blocking_send(pkt); let _ = tx.blocking_send(pkt);
} }
} }
}); });
let outbound = tokio_stream::wrappers::ReceiverStream::new(rx_pkt); let outbound = tokio_stream::wrappers::ReceiverStream::new(rx);
match cli.stream_camera(Request::new(outbound)).await { if let Err(e) = cli.stream_camera(Request::new(outbound)).await {
Ok(mut resp) => { tracing::warn!("❌📸 connect failed: {e}");
while resp.get_mut().message().await.transpose().is_some() {}
}
Err(e) => tracing::warn!("❌📸 connect failed: {e}"),
} }
tokio::time::sleep(Duration::from_secs(1)).await; tokio::time::sleep(Duration::from_secs(1)).await;
} }

View File

@ -181,7 +181,7 @@ pub async fn eye_ball(
trace!(target:"lesavka_server::video", trace!(target:"lesavka_server::video",
eye = %eye, eye = %eye,
size = size, size = size,
"📤 sent"); "🎥📤 sent");
} }
Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => { Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => {
static DROP_CNT: std::sync::atomic::AtomicU64 = static DROP_CNT: std::sync::atomic::AtomicU64 =
@ -191,7 +191,7 @@ pub async fn eye_ball(
debug!(target:"lesavka_server::video", debug!(target:"lesavka_server::video",
eye = %eye, eye = %eye,
dropped = c, dropped = c,
"⏳ channel full - dropping frames"); "🎥⏳ channel full - dropping frames");
} }
} }
Err(e) => error!("mpsc send err: {e}"), Err(e) => error!("mpsc send err: {e}"),
@ -293,7 +293,7 @@ impl CameraRelay {
tracing::trace!(target:"lesavka_server::video", tracing::trace!(target:"lesavka_server::video",
cam_id = self.id, cam_id = self.id,
bytes = pkt.data.len(), bytes = pkt.data.len(),
"📥 srv pkt"); "📸📥 srv pkt");
} }
self.sink.push(pkt); self.sink.push(pkt);
} }