197 lines
4.2 KiB
Rust
197 lines
4.2 KiB
Rust
use anyhow::{Context, Result, bail};
|
|
use gstreamer as gst;
|
|
use gstreamer::prelude::*;
|
|
use gstreamer_app as gst_app;
|
|
use lesavka_common::lesavka::{AudioPacket, OutputDelayProbeRequest, VideoPacket};
|
|
use serde::Serialize;
|
|
use std::f64::consts::TAU;
|
|
use std::sync::Arc;
|
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
|
|
use crate::audio::Voice;
|
|
use crate::camera::{CameraCodec, CameraConfig};
|
|
use crate::video::CameraRelay;
|
|
|
|
const DEFAULT_DURATION_SECONDS: u32 = 20;
|
|
const DEFAULT_WARMUP_SECONDS: u32 = 4;
|
|
const DEFAULT_PULSE_PERIOD_MS: u32 = 1_000;
|
|
const DEFAULT_PULSE_WIDTH_MS: u32 = 120;
|
|
const DEFAULT_EVENT_WIDTH_CODES: &[u32] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
|
const AUDIO_SAMPLE_RATE: u32 = 48_000;
|
|
const AUDIO_CHANNELS: usize = 2;
|
|
const AUDIO_CHUNK_MS: u64 = 10;
|
|
const AUDIO_AMPLITUDE: f64 = 24_000.0;
|
|
const AUDIO_PILOT_AMPLITUDE: f64 = 700.0;
|
|
const AUDIO_PILOT_FREQUENCY_HZ: f64 = 180.0;
|
|
const DARK_FRAME_RGB: Rgb = Rgb { r: 4, g: 8, b: 12 };
|
|
const VIDEO_CONTINUITY_BLOCKS: usize = 20;
|
|
const VIDEO_CONTINUITY_DATA_BITS: usize = 16;
|
|
const EVENT_COLORS: [Rgb; 16] = [
|
|
Rgb {
|
|
r: 255,
|
|
g: 45,
|
|
b: 45,
|
|
},
|
|
Rgb {
|
|
r: 0,
|
|
g: 230,
|
|
b: 118,
|
|
},
|
|
Rgb {
|
|
r: 41,
|
|
g: 121,
|
|
b: 255,
|
|
},
|
|
Rgb {
|
|
r: 255,
|
|
g: 179,
|
|
b: 0,
|
|
},
|
|
Rgb {
|
|
r: 216,
|
|
g: 27,
|
|
b: 96,
|
|
},
|
|
Rgb {
|
|
r: 0,
|
|
g: 188,
|
|
b: 212,
|
|
},
|
|
Rgb {
|
|
r: 205,
|
|
g: 220,
|
|
b: 57,
|
|
},
|
|
Rgb {
|
|
r: 126,
|
|
g: 87,
|
|
b: 194,
|
|
},
|
|
Rgb {
|
|
r: 255,
|
|
g: 112,
|
|
b: 67,
|
|
},
|
|
Rgb {
|
|
r: 38,
|
|
g: 166,
|
|
b: 154,
|
|
},
|
|
Rgb {
|
|
r: 255,
|
|
g: 64,
|
|
b: 129,
|
|
},
|
|
Rgb {
|
|
r: 92,
|
|
g: 107,
|
|
b: 192,
|
|
},
|
|
Rgb {
|
|
r: 255,
|
|
g: 235,
|
|
b: 59,
|
|
},
|
|
Rgb {
|
|
r: 105,
|
|
g: 240,
|
|
b: 174,
|
|
},
|
|
Rgb {
|
|
r: 171,
|
|
g: 71,
|
|
b: 188,
|
|
},
|
|
Rgb {
|
|
r: 3,
|
|
g: 169,
|
|
b: 244,
|
|
},
|
|
];
|
|
const EVENT_FREQUENCIES_HZ: [f64; 16] = [
|
|
620.0, 780.0, 940.0, 1_120.0, 1_320.0, 1_540.0, 1_780.0, 2_040.0, 2_320.0, 2_620.0, 2_960.0,
|
|
3_340.0, 3_760.0, 4_220.0, 4_740.0, 5_320.0,
|
|
];
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
struct Rgb {
|
|
r: u8,
|
|
g: u8,
|
|
b: u8,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
struct ProbeConfig {
|
|
duration: Duration,
|
|
warmup: Duration,
|
|
pulse_period: Duration,
|
|
pulse_width: Duration,
|
|
event_width_codes: Vec<u32>,
|
|
audio_delay: Duration,
|
|
video_delay: Duration,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct OutputDelayProbeSummary {
|
|
pub video_frames: u64,
|
|
pub audio_packets: u64,
|
|
pub event_count: u64,
|
|
pub timeline_json: String,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
struct ProbeEventSlot {
|
|
event_id: usize,
|
|
code: u32,
|
|
planned_start_us: u64,
|
|
planned_end_us: u64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
struct OutputDelayProbeTimeline {
|
|
schema: &'static str,
|
|
origin: &'static str,
|
|
media_path: &'static str,
|
|
injection_scope: &'static str,
|
|
server_pipeline_reference: &'static str,
|
|
sink_handoff_path: &'static str,
|
|
client_uplink_included: bool,
|
|
camera_width: u32,
|
|
camera_height: u32,
|
|
camera_fps: u32,
|
|
audio_sample_rate: u32,
|
|
audio_channels: usize,
|
|
audio_chunk_ms: u64,
|
|
audio_delay_us: u64,
|
|
video_delay_us: u64,
|
|
server_start_unix_ns: u128,
|
|
pulse_period_ms: u64,
|
|
pulse_width_ms: u64,
|
|
warmup_us: u64,
|
|
duration_us: u64,
|
|
events: Vec<OutputDelayProbeEventTimeline>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
struct OutputDelayProbeEventTimeline {
|
|
event_id: usize,
|
|
code: u32,
|
|
planned_start_us: u64,
|
|
planned_end_us: u64,
|
|
video_seq: Option<u64>,
|
|
audio_seq: Option<u64>,
|
|
video_feed_monotonic_us: Option<u64>,
|
|
audio_push_monotonic_us: Option<u64>,
|
|
video_feed_unix_ns: Option<u128>,
|
|
audio_push_unix_ns: Option<u128>,
|
|
server_feed_delta_ms: Option<f64>,
|
|
}
|
|
|
|
include!("output_delay_probe/timeline_config.rs");
|
|
include!("output_delay_probe/probe_runtime.rs");
|
|
include!("output_delay_probe/media_encoding.rs");
|
|
|
|
#[cfg(test)]
|
|
#[path = "output_delay_probe/tests/mod.rs"]
|
|
mod tests;
|