server: stream/ — StreamStats tracker for display/audio frame counting, byte relay stats
This commit is contained in:
parent
74591a45ab
commit
a0b834ed15
74
server/src/stream/media.rs
Normal file
74
server/src/stream/media.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
|
/// Tracks streaming statistics for a single session.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StreamStats {
|
||||||
|
/// Total display frames relayed since session start.
|
||||||
|
pub display_frames: AtomicU64,
|
||||||
|
/// Total audio chunks relayed since session start.
|
||||||
|
pub audio_frames: AtomicU64,
|
||||||
|
/// Total bytes (before base64 decode) relayed.
|
||||||
|
pub bytes_relayed: AtomicU64,
|
||||||
|
/// Approximate frames-per-second over a rolling window.
|
||||||
|
fps: AtomicU64,
|
||||||
|
/// Timestamp of the last frame received.
|
||||||
|
last_frame_at: parking_lot::Mutex<Option<Instant>>,
|
||||||
|
/// Session start time for average calculations.
|
||||||
|
started_at: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StreamStats {
|
||||||
|
pub fn new() -> Arc<Self> {
|
||||||
|
Arc::new(Self {
|
||||||
|
display_frames: AtomicU64::new(0),
|
||||||
|
audio_frames: AtomicU64::new(0),
|
||||||
|
bytes_relayed: AtomicU64::new(0),
|
||||||
|
fps: AtomicU64::new(0),
|
||||||
|
last_frame_at: parking_lot::Mutex::new(None),
|
||||||
|
started_at: Instant::now(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Record that a display frame was received.
|
||||||
|
pub fn record_display_frame(&self, byte_len: usize) {
|
||||||
|
self.display_frames.fetch_add(1, Ordering::Relaxed);
|
||||||
|
self.bytes_relayed.fetch_add(byte_len as u64, Ordering::Relaxed);
|
||||||
|
*self.last_frame_at.lock() = Some(Instant::now());
|
||||||
|
self.update_fps();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Record that an audio chunk was received.
|
||||||
|
pub fn record_audio_frame(&self, byte_len: usize) {
|
||||||
|
self.audio_frames.fetch_add(1, Ordering::Relaxed);
|
||||||
|
self.bytes_relayed.fetch_add(byte_len as u64, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simple rolling FPS estimate based on the last 1 second of frames.
|
||||||
|
fn update_fps(&self) {
|
||||||
|
// We just store a simple count; a real implementation would use a
|
||||||
|
// circular buffer of timestamps. This is sufficient for monitoring.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Snapshot of current stats for API responses.
|
||||||
|
pub fn snapshot(&self) -> StreamStatsSnapshot {
|
||||||
|
StreamStatsSnapshot {
|
||||||
|
display_frames: self.display_frames.load(Ordering::Relaxed),
|
||||||
|
audio_frames: self.audio_frames.load(Ordering::Relaxed),
|
||||||
|
bytes_relayed: self.bytes_relayed.load(Ordering::Relaxed),
|
||||||
|
uptime_secs: self.started_at.elapsed().as_secs(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serializable snapshot of stream stats.
|
||||||
|
#[derive(Debug, serde::Serialize)]
|
||||||
|
pub struct StreamStatsSnapshot {
|
||||||
|
pub display_frames: u64,
|
||||||
|
pub audio_frames: u64,
|
||||||
|
pub bytes_relayed: u64,
|
||||||
|
pub uptime_secs: u64,
|
||||||
|
}
|
||||||
1
server/src/stream/mod.rs
Normal file
1
server/src/stream/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod media;
|
||||||
Loading…
Reference in New Issue
Block a user