added static video geoencoding to test KLV data

This commit is contained in:
Valmo Trindade
2025-06-24 19:34:08 -03:00
parent 15129bb344
commit a1bf9472ae

View File

@@ -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<u8> {
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 {