increased cam logging
This commit is contained in:
parent
1c095a95d1
commit
6c3942cd2c
@ -2,6 +2,7 @@
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::Context;
|
||||
use gstreamer as gst;
|
||||
use gstreamer_app as gst_app;
|
||||
use gst::prelude::*;
|
||||
@ -22,7 +23,7 @@ impl CameraCapture {
|
||||
.unwrap_or_else(|| "/dev/video0".into());
|
||||
|
||||
let desc = format!(
|
||||
"v4l2src device={dev} io-mode=dmabuf-do-timestamp=true ! \
|
||||
"v4l2src device={dev} io-mode=dmabuf do-timestamp=true ! \
|
||||
videoconvert ! videoscale ! video/x-raw,width=1280,height=720 ! \
|
||||
v4l2h264enc key-int-max=30 \
|
||||
extra-controls=\"encode,frame_level_rate_control_enable=1,h264_profile=4\" ! \
|
||||
@ -30,12 +31,13 @@ impl CameraCapture {
|
||||
appsink name=asink emit-signals=true max-buffers=60 drop=true"
|
||||
);
|
||||
|
||||
// --- NEW: propagate the Result and down‑cast with `?`
|
||||
let pipeline: gst::Pipeline = gst::parse::launch(&desc)?
|
||||
tracing::debug!("📸 pipeline‑desc:\n{desc}");
|
||||
let pipeline: gst::Pipeline = gst::parse::launch(&desc)
|
||||
.context("gst parse_launch(cam)")?
|
||||
.downcast::<gst::Pipeline>()
|
||||
.expect("not a pipeline");
|
||||
|
||||
// --- NEW: the lookup already returns the concrete AppSink → just unwrap with `?`
|
||||
tracing::debug!("📸 pipeline built OK – setting PLAYING…");
|
||||
let sink: gst_app::AppSink = pipeline
|
||||
.by_name("asink")
|
||||
.expect("appsink element not found")
|
||||
@ -43,6 +45,7 @@ impl CameraCapture {
|
||||
.expect("appsink down‑cast");
|
||||
|
||||
pipeline.set_state(gst::State::Playing)?;
|
||||
tracing::info!("📸 webcam pipeline ▶️ device={dev}");
|
||||
|
||||
Ok(Self { pipeline, sink })
|
||||
}
|
||||
@ -72,14 +75,11 @@ impl CameraCapture {
|
||||
/// Cheap stub used when the web‑cam is disabled
|
||||
pub fn new_stub() -> Self {
|
||||
let pipeline = gst::Pipeline::new();
|
||||
|
||||
// --- NEW: AppSink factory helper (AppSink::new() does not exist)
|
||||
let sink: gst_app::AppSink = gst::ElementFactory::make("appsink")
|
||||
.build()
|
||||
.expect("make appsink")
|
||||
.expect("appsink")
|
||||
.downcast::<gst_app::AppSink>()
|
||||
.expect("appsink down‑cast");
|
||||
|
||||
.unwrap();
|
||||
Self { pipeline, sink }
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,9 +93,22 @@ impl InputAggregator {
|
||||
}
|
||||
|
||||
// Auto‑select webcam (may be toggled later through magic chord)
|
||||
self.camera = match CameraCapture::new(std::env::var("LESAVKA_CAM_SOURCE").ok().as_deref()) {
|
||||
Ok(cam) => { info!("📸 webcam enabled"); Some(cam) }
|
||||
Err(e) => { warn!("📸 webcam disabled: {e}"); None }
|
||||
let cam_src_env = std::env::var("LESAVKA_CAM_SOURCE").ok();
|
||||
self.camera = match cam_src_env.as_deref()
|
||||
// .or(device_fragment) // <- if you later wire CLI arg
|
||||
.map(|s| CameraCapture::new(Some(s))) {
|
||||
Some(Ok(c)) => {
|
||||
info!("📸 webcam enabled (device fragment = {:?})", cam_src_env);
|
||||
Some(c)
|
||||
}
|
||||
Some(Err(e)) => {
|
||||
warn!("📸 webcam disabled: {e:#}");
|
||||
Some(CameraCapture::new_stub()) // keep stub so call‑sites compile
|
||||
}
|
||||
None => {
|
||||
info!("📸 webcam disabled (no CAM_SOURCE set)");
|
||||
None // or Stub – your choice
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
@ -135,6 +148,12 @@ impl InputAggregator {
|
||||
mouse.process_events();
|
||||
}
|
||||
|
||||
if let Some(cam) = &self.camera {
|
||||
debug!("📸 CameraCapture present – first pull() will block until a frame arrives");
|
||||
} else {
|
||||
debug!("📸 No camera pipeline active");
|
||||
}
|
||||
|
||||
self.magic_active = magic_now;
|
||||
tick.tick().await;
|
||||
}
|
||||
|
||||
@ -114,7 +114,6 @@ echo 32 >"$U/req_number" 2>/dev/null || true
|
||||
|
||||
# ----------------------- UVC function (usb‑video) ------------------
|
||||
mkdir -p "$G/functions/uvc.usb0"
|
||||
# Mandatory control interface strings
|
||||
mkdir -p "$G/functions/uvc.usb0/control/strings/0x409"
|
||||
echo "Lesavka UVC" >"$G/functions/uvc.usb0/control/strings/0x409/label"
|
||||
# Simple 720p MJPEG + 720p H.264 alt‑setting
|
||||
@ -152,6 +151,6 @@ ln -s $G/functions/uvc.usb0 $G/configs/c.1/
|
||||
# 4. Bind gadget
|
||||
#──────────────────────────────────────────────────
|
||||
echo "$UDC" >"$G/UDC"
|
||||
log "🎉 gadget bound on $UDC (hidg0, hidg1, UAC2 L+R)"
|
||||
log "🎉 gadget bound on $UDC (hidg0, hidg1, UAC2 L+R, UVC)"
|
||||
|
||||
exit 0
|
||||
|
||||
@ -122,7 +122,7 @@ After=network.target lesavka-core.service
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/lesavka-server
|
||||
Restart=always
|
||||
Environment=RUST_LOG=lesavka_server=info,lesavka_server::audio=info,lesavka_server::video=info,lesavka_server::gadget=info
|
||||
Environment=RUST_LOG=lesavka_server=info,lesavka_server::audio=info,lesavka_server::video=trace,lesavka_server::gadget=info
|
||||
Environment=RUST_BACKTRACE=1
|
||||
Environment=GST_DEBUG="*:2,alsasink:6,alsasrc:6"
|
||||
Restart=always
|
||||
|
||||
@ -212,11 +212,28 @@ impl Relay for Handler {
|
||||
|
||||
async fn stream_camera(
|
||||
&self,
|
||||
_req: Request<tonic::Streaming<VideoPacket>>,
|
||||
req: Request<tonic::Streaming<VideoPacket>>,
|
||||
) -> Result<Response<Self::StreamCameraStream>, Status> {
|
||||
// Simply consume the inbound stream and discard; echo back a single Empty.
|
||||
// map gRPC camera id → UVC device
|
||||
let uvc = std::env::var("LESAVKA_UVC_DEV")
|
||||
.unwrap_or_else(|_| "/dev/video4".into());
|
||||
|
||||
// build once
|
||||
let relay = video::CameraRelay::new(0, &uvc)
|
||||
.map_err(|e| Status::internal(format!("{e:#}")))?;
|
||||
|
||||
// dummy outbound (same pattern as other streams)
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(1);
|
||||
tx.send(Ok(Empty {})).await.ok();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut s = req.into_inner();
|
||||
while let Some(pkt) = s.next().await.transpose()? {
|
||||
relay.feed(pkt); // ← all logging inside video.rs
|
||||
}
|
||||
tx.send(Ok(Empty {})).await.ok();
|
||||
Ok::<(), Status>(())
|
||||
});
|
||||
|
||||
Ok(Response::new(ReceiverStream::new(rx)))
|
||||
}
|
||||
|
||||
|
||||
@ -259,3 +259,37 @@ impl WebcamSink {
|
||||
let _ = self.appsrc.push_buffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*─────────────────────────────────*/
|
||||
/* gRPC → WebcamSink relay */
|
||||
/*─────────────────────────────────*/
|
||||
|
||||
pub struct CameraRelay {
|
||||
sink: WebcamSink, // the v4l2sink pipeline (or stub)
|
||||
id: u32, // gRPC “id” (for future multi‑cam)
|
||||
frames: std::sync::atomic::AtomicU64,
|
||||
}
|
||||
|
||||
impl CameraRelay {
|
||||
pub fn new(id: u32, uvc_dev: &str) -> anyhow::Result<Self> {
|
||||
Ok(Self {
|
||||
sink: WebcamSink::new(uvc_dev)?,
|
||||
id,
|
||||
frames: std::sync::atomic::AtomicU64::new(0),
|
||||
})
|
||||
}
|
||||
|
||||
/// Push one VideoPacket coming from the client
|
||||
pub fn feed(&self, pkt: VideoPacket) {
|
||||
let n = self.frames.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
if n < 10 || n % 300 == 0 {
|
||||
tracing::debug!(target:"lesavka_server::video",
|
||||
cam_id = self.id,
|
||||
frame = n,
|
||||
bytes = pkt.data.len(),
|
||||
pts = pkt.pts,
|
||||
"📸 srv webcam frame");
|
||||
}
|
||||
self.sink.push(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user