From a1bf9472aec6932903163eb008dfcb57a892c7b3 Mon Sep 17 00:00:00 2001 From: Valmo Trindade Date: Tue, 24 Jun 2025 19:34:08 -0300 Subject: [PATCH] added static video geoencoding to test KLV data --- src/video_stream.rs | 89 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/src/video_stream.rs b/src/video_stream.rs index e4e34b3..0eac9b6 100644 --- a/src/video_stream.rs +++ b/src/video_stream.rs @@ -1,6 +1,7 @@ use arma_rs::Context; use lazy_static::lazy_static; -use std::process::Command; +use std::io::Write; +use std::process::{Command, Stdio}; use std::sync::mpsc::{self, Receiver, Sender}; use std::sync::Mutex; use std::thread; @@ -27,6 +28,39 @@ fn build_rtsp_url(address: &str, port: &str, stream_path: &str, username: &str, } } +fn generate_klv_packet() -> Vec { + fn encode_u16(value: f64, min: f64, max: f64) -> u16 { + let scale = (value - min) / (max - min); + (scale * u16::MAX as f64).round() as u16 + } + + fn encode_i64(value: f64, min: f64, max: f64) -> i64 { + let scale = (value - min) / (max - min); + (scale * i64::MAX as f64).round() as i64 + } + + let mut pkt = vec![]; + + // Heading (0x02) + pkt.extend([0x02, 0x02]); + pkt.extend(&encode_u16(182.0, 0.0, 360.0).to_be_bytes()); + + // Latitude (0x0D) + pkt.extend([0x0D, 0x08]); + pkt.extend(&encode_i64(-30.123456, -90.0, 90.0).to_be_bytes()); + + // Longitude (0x0E) + pkt.extend([0x0E, 0x08]); + pkt.extend(&encode_i64(-51.123456, -180.0, 180.0).to_be_bytes()); + + // Altitude (0x0F) + pkt.extend([0x0F, 0x04]); + let alt = ((430.0 / 19999.0) * u32::MAX as f64).round() as u32; + pkt.extend(&alt.to_be_bytes()); + + pkt +} + #[cfg(any(target_os = "windows", target_os = "linux"))] fn spawn_ffmpeg( rtsp_url: String, @@ -35,28 +69,50 @@ fn spawn_ffmpeg( ) { thread::spawn(move || { let mut cmd = Command::new("ffmpeg"); + cmd.args(&[ - "-f", - "gdigrab", - "-i", - "desktop", - "-f", - "rtsp", - "-rtsp_transport", - "tcp", + "-f", "gdigrab", + "-i", "desktop", + "-f", "klv", + "-i", "-", + "-map", "0:v", + "-map", "1", + "-c:v", "libx264", + "-metadata:s:1", "handler_name=klv_data", + "-f", "rtsp", + "-rtsp_transport", "tcp", &rtsp_url, ]); #[cfg(target_os = "windows")] - let child_result = cmd.creation_flags(CREATE_NO_WINDOW).spawn(); + let child_result = cmd + .creation_flags(CREATE_NO_WINDOW) + .stdin(Stdio::piped()) + .spawn(); #[cfg(target_os = "linux")] - let child_result = cmd.spawn(); + let child_result = cmd.stdin(Stdio::piped()).spawn(); match child_result { Ok(mut child) => { let _ = status_tx.send(Ok(())); - let _ = stop_rx.recv(); + + if let Some(mut stdin) = child.stdin.take() { + let klv = generate_klv_packet(); + loop { + if stop_rx.try_recv().is_ok() { + break; + } + if stdin.write_all(&klv).is_err() { + break; + } + if stdin.flush().is_err() { + break; + } + thread::sleep(Duration::from_secs(1)); + } + } + let _ = child.kill(); } Err(e) => { @@ -74,8 +130,6 @@ pub fn start_stream( username: String, password: String, ) -> &'static str { - #[cfg(any(target_os = "windows", target_os = "linux"))] - { let (stop_tx, stop_rx) = mpsc::channel(); let (status_tx, status_rx) = mpsc::channel(); @@ -109,13 +163,6 @@ pub fn start_stream( "ffmpeg did not respond" } } - } - - #[cfg(not(any(target_os = "windows", target_os = "linux")))] - { - ctx.callback_null("VIDEO ERROR", "Screen capture is only supported on Windows"); - "unsupported platform" - } } pub fn stop_stream(ctx: Context) -> &'static str {