use super::state::ProgressState;
use super::tracker::OutputTelemetry;
use std::time::Duration;
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct Progress {
state: ProgressState,
elapsed: Duration,
outputs: Vec<OutputProgress>,
}
impl Progress {
pub(crate) fn new(state: ProgressState, elapsed: Duration, outputs: Vec<OutputProgress>) -> Self {
Self {
state,
elapsed,
outputs,
}
}
pub fn state(&self) -> ProgressState {
self.state
}
pub fn elapsed(&self) -> Duration {
self.elapsed
}
pub fn outputs(&self) -> &[OutputProgress] {
&self.outputs
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct OutputProgress {
output_index: usize,
video_packets: Option<u64>,
fps: Option<f64>,
out_time_us: Option<i64>,
total_size: Option<u64>,
bitrate_kbps: Option<f64>,
speed: Option<f64>,
}
impl OutputProgress {
pub(crate) fn collect(
output_index: usize,
telemetry: &OutputTelemetry,
elapsed: Duration,
) -> Self {
let video_packets = telemetry.video_packets();
let out_time_us = telemetry.out_time_us();
let total_size = telemetry.total_size();
let elapsed_secs = elapsed.as_secs_f64();
let fps = match video_packets {
Some(packets) if elapsed_secs > 0.0 => Some(packets as f64 / elapsed_secs),
_ => None,
};
let bitrate_kbps = match (total_size, out_time_us) {
(Some(bytes), Some(t_us)) if t_us > 0 => {
Some(bytes as f64 * 8.0 * 1000.0 / t_us as f64)
}
_ => None,
};
let speed = match out_time_us {
Some(t_us) if t_us >= 0 && elapsed_secs > 0.0 => {
Some(t_us as f64 / 1_000_000.0 / elapsed_secs)
}
_ => None,
};
Self {
output_index,
video_packets,
fps,
out_time_us,
total_size,
bitrate_kbps,
speed,
}
}
pub fn output_index(&self) -> usize {
self.output_index
}
pub fn video_packets(&self) -> Option<u64> {
self.video_packets
}
pub fn fps(&self) -> Option<f64> {
self.fps
}
pub fn out_time_us(&self) -> Option<i64> {
self.out_time_us
}
pub fn total_size(&self) -> Option<u64> {
self.total_size
}
pub fn bitrate_kbps(&self) -> Option<f64> {
self.bitrate_kbps
}
pub fn speed(&self) -> Option<f64> {
self.speed
}
pub fn percent_of(&self, total_us: i64) -> Option<f64> {
if total_us <= 0 {
return None;
}
let out_time_us = self.out_time_us?;
Some((out_time_us as f64 / total_us as f64 * 100.0).clamp(0.0, 100.0))
}
}