Skip to content

Commit

Permalink
refactor(streamer): ♻️ Clarify distinction between bitrate and throug…
Browse files Browse the repository at this point in the history
…hput (#2423)
  • Loading branch information
zmerp authored Sep 27, 2024
1 parent 36d7cda commit a1052ed
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 181 deletions.
219 changes: 141 additions & 78 deletions alvr/dashboard/src/dashboard/components/statistics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,16 @@ impl StatisticsTab {
draw_lines(painter, client_fps_points, graph_colors::CLIENT_FPS);
},
|ui, stats| {
ui.colored_label(
graph_colors::SERVER_FPS,
format!("Streamer FPS: {:.2}", stats.server_fps),
);
ui.colored_label(
graph_colors::CLIENT_FPS,
format!("Client FPS: {:.2}", stats.client_fps),
);
Grid::new("fps_tooltip").num_columns(2).show(ui, |ui| {
fn label(ui: &mut Ui, text: &str, value: f32, color: Color32) {
ui.colored_label(color, text);
ui.colored_label(color, format!("{:.2}Hz", value));
ui.end_row();
}

label(ui, "Server FPS", stats.server_fps, graph_colors::SERVER_FPS);
label(ui, "Client FPS", stats.client_fps, graph_colors::CLIENT_FPS);
});
},
);
}
Expand All @@ -264,107 +266,168 @@ impl StatisticsTab {
let mut data = statistics::Data::new(
self.history
.iter()
.map(|stats| stats.actual_bitrate_bps as f64)
.map(|stats| stats.throughput_bps as f64)
.collect::<Vec<_>>(),
);

self.draw_graph(
ui,
available_width,
"Bitrate",
0.0..=(data.quantile(UPPER_QUANTILE) * 2.0) as f32 / 1e6,
"Bitrate and Throughput",
0.0..=(data.quantile(UPPER_QUANTILE) * 1.2) as f32 / 1e6,
|painter, to_screen_trans| {
let mut scaled_calculated = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut decoder_latency_limiter = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut network_latency_limiter = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut encoder_latency_limiter = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut manual_max = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut manual_min = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut requested = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut actual = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut max_throughput = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut min_throughput = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut requested_bitrate = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut recorded_throughput = Vec::with_capacity(GRAPH_HISTORY_SIZE);
let mut recorded_bitrate = Vec::with_capacity(GRAPH_HISTORY_SIZE);
for i in 0..GRAPH_HISTORY_SIZE {
let nom_br = &self.history[i].nominal_bitrate;
let d = &self.history[i].bitrate_directives;

if let Some(value) = nom_br.scaled_calculated_bps {
if let Some(value) = d.scaled_calculated_throughput_bps {
scaled_calculated.push(to_screen_trans * pos2(i as f32, value / 1e6))
}
if let Some(value) = nom_br.decoder_latency_limiter_bps {
if let Some(value) = d.decoder_latency_limiter_bps {
decoder_latency_limiter.push(to_screen_trans * pos2(i as f32, value / 1e6))
}
if let Some(value) = nom_br.network_latency_limiter_bps {
if let Some(value) = d.network_latency_limiter_bps {
network_latency_limiter.push(to_screen_trans * pos2(i as f32, value / 1e6))
}
if let Some(value) = nom_br.encoder_latency_limiter_bps {
if let Some(value) = d.encoder_latency_limiter_bps {
encoder_latency_limiter.push(to_screen_trans * pos2(i as f32, value / 1e6))
}
if let Some(value) = nom_br.manual_max_bps {
manual_max.push(to_screen_trans * pos2(i as f32, value / 1e6))
if let Some(value) = d.manual_max_throughput_bps {
max_throughput.push(to_screen_trans * pos2(i as f32, value / 1e6))
}
if let Some(value) = nom_br.manual_min_bps {
manual_min.push(to_screen_trans * pos2(i as f32, value / 1e6))
if let Some(value) = d.manual_min_throughput_bps {
min_throughput.push(to_screen_trans * pos2(i as f32, value / 1e6))
}
requested.push(to_screen_trans * pos2(i as f32, nom_br.requested_bps / 1e6));
actual.push(
to_screen_trans * pos2(i as f32, self.history[i].actual_bitrate_bps / 1e6),
requested_bitrate
.push(to_screen_trans * pos2(i as f32, d.requested_bitrate_bps / 1e6));
recorded_throughput.push(
to_screen_trans * pos2(i as f32, self.history[i].throughput_bps / 1e6),
);
recorded_bitrate
.push(to_screen_trans * pos2(i as f32, self.history[i].bitrate_bps / 1e6));
}

draw_lines(painter, scaled_calculated, Color32::GRAY);
draw_lines(painter, encoder_latency_limiter, graph_colors::TRANSCODE);
draw_lines(painter, network_latency_limiter, graph_colors::NETWORK);
draw_lines(painter, decoder_latency_limiter, graph_colors::TRANSCODE);
draw_lines(painter, manual_max, graph_colors::RENDER);
draw_lines(painter, manual_min, graph_colors::RENDER);
draw_lines(painter, requested, theme::OK_GREEN);
draw_lines(painter, actual, theme::FG);
},
|ui, stats| {
fn maybe_label(
ui: &mut Ui,
text: &str,
maybe_value_bps: Option<f32>,
color: Color32,
) {
if let Some(value) = maybe_value_bps {
ui.colored_label(color, format!("{text}: {:.2} Mbps", value / 1e6));
}
}

let n = &stats.nominal_bitrate;

maybe_label(
ui,
"Initial calculated",
n.scaled_calculated_bps,
Color32::GRAY,
draw_lines(
painter,
scaled_calculated,
graph_colors::INITIAL_CALCULATED_THROUGHPUT,
);
draw_lines(
painter,
encoder_latency_limiter,
graph_colors::ENCODER_DECODER_LATENCY_LIMITER,
);
draw_lines(
painter,
network_latency_limiter,
graph_colors::NETWORK_LATENCY_LIMITER,
);
maybe_label(
ui,
"Encoder latency limiter",
n.encoder_latency_limiter_bps,
graph_colors::TRANSCODE,
draw_lines(
painter,
decoder_latency_limiter,
graph_colors::ENCODER_DECODER_LATENCY_LIMITER,
);
maybe_label(
ui,
"Network latency limiter",
n.network_latency_limiter_bps,
graph_colors::NETWORK,
draw_lines(
painter,
max_throughput,
graph_colors::MIN_MAX_LATENCY_THROUGHPUT,
);
maybe_label(
ui,
"Decoder latency limiter",
n.decoder_latency_limiter_bps,
graph_colors::TRANSCODE,
draw_lines(
painter,
min_throughput,
graph_colors::MIN_MAX_LATENCY_THROUGHPUT,
);
maybe_label(ui, "Manual max", n.manual_max_bps, graph_colors::RENDER);
maybe_label(ui, "Manual min", n.manual_min_bps, graph_colors::RENDER);
maybe_label(ui, "Requested", Some(n.requested_bps), theme::OK_GREEN);
maybe_label(
ui,
"Actual recorded",
Some(stats.actual_bitrate_bps),
theme::FG,
draw_lines(painter, requested_bitrate, graph_colors::REQUESTED_BITRATE);
draw_lines(
painter,
recorded_throughput,
graph_colors::RECORDED_THROUGHPUT,
);
draw_lines(painter, recorded_bitrate, theme::FG);
},
|ui, stats| {
Grid::new("bitrate_tooltip").num_columns(2).show(ui, |ui| {
fn maybe_label(
ui: &mut Ui,
text: &str,
maybe_value_bps: Option<f32>,
color: Color32,
) {
if let Some(value) = maybe_value_bps {
ui.colored_label(color, text);
ui.colored_label(color, format!("{:.2} Mbps", value / 1e6));
ui.end_row();
}
}

let td = &stats.bitrate_directives;

maybe_label(
ui,
"Initial calculated throughput",
td.scaled_calculated_throughput_bps,
graph_colors::INITIAL_CALCULATED_THROUGHPUT,
);
maybe_label(
ui,
"Encoder latency limiter",
td.encoder_latency_limiter_bps,
graph_colors::ENCODER_DECODER_LATENCY_LIMITER,
);
maybe_label(
ui,
"Network latency limiter",
td.network_latency_limiter_bps,
graph_colors::NETWORK_LATENCY_LIMITER,
);
maybe_label(
ui,
"Decoder latency limiter",
td.decoder_latency_limiter_bps
.filter(|l| *l < stats.throughput_bps),
graph_colors::ENCODER_DECODER_LATENCY_LIMITER,
);
maybe_label(
ui,
"Manual max throughput",
td.manual_max_throughput_bps,
graph_colors::MIN_MAX_LATENCY_THROUGHPUT,
);
maybe_label(
ui,
"Manual min throughput",
td.manual_min_throughput_bps,
graph_colors::MIN_MAX_LATENCY_THROUGHPUT,
);
maybe_label(
ui,
"Requested bitrate",
Some(td.requested_bitrate_bps),
graph_colors::REQUESTED_BITRATE,
);
maybe_label(
ui,
"Recorded throughput",
Some(stats.throughput_bps),
graph_colors::RECORDED_THROUGHPUT,
);
maybe_label(
ui,
"Recorded bitrate",
Some(stats.bitrate_bps),
graph_colors::RECORDED_BITRATE,
);
});

ui.small("Note: throughput is the peak bitrate, packet_size/network_latency.");
},
)
}
Expand Down
15 changes: 8 additions & 7 deletions alvr/events/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ pub struct StatisticsSummary {

// Bitrate statistics minus the empirical output value
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct NominalBitrateStats {
pub scaled_calculated_bps: Option<f32>,
pub struct BitrateDirectives {
pub scaled_calculated_throughput_bps: Option<f32>,
pub decoder_latency_limiter_bps: Option<f32>,
pub network_latency_limiter_bps: Option<f32>,
pub encoder_latency_limiter_bps: Option<f32>,
pub manual_max_bps: Option<f32>,
pub manual_min_bps: Option<f32>,
pub requested_bps: f32,
pub manual_max_throughput_bps: Option<f32>,
pub manual_min_throughput_bps: Option<f32>,
pub requested_bitrate_bps: f32,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
Expand All @@ -47,8 +47,9 @@ pub struct GraphStatistics {
pub vsync_queue_s: f32,
pub client_fps: f32,
pub server_fps: f32,
pub nominal_bitrate: NominalBitrateStats,
pub actual_bitrate_bps: f32,
pub bitrate_directives: BitrateDirectives,
pub throughput_bps: f32,
pub bitrate_bps: f32,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
Expand Down
8 changes: 8 additions & 0 deletions alvr/gui_common/src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ pub mod graph_colors {

pub const SERVER_FPS: Color32 = Color32::LIGHT_BLUE;
pub const CLIENT_FPS: Color32 = Color32::KHAKI;

pub const INITIAL_CALCULATED_THROUGHPUT: Color32 = Color32::GRAY;
pub const ENCODER_DECODER_LATENCY_LIMITER: Color32 = TRANSCODE;
pub const NETWORK_LATENCY_LIMITER: Color32 = NETWORK;
pub const MIN_MAX_LATENCY_THROUGHPUT: Color32 = Color32::RED;
pub const REQUESTED_BITRATE: Color32 = Color32::GREEN;
pub const RECORDED_THROUGHPUT: Color32 = Color32::KHAKI;
pub const RECORDED_BITRATE: Color32 = super::FG;
}

pub fn set_theme(ctx: &Context) {
Expand Down
Loading

0 comments on commit a1052ed

Please sign in to comment.