Skip to content

Commit a51ceca

Browse files
fix(dgw): fix adaptive frame skipping during EOF waits in session shadowing
Fixes playback failures in session shadowing where adaptive frame skipping permanently stalls video streaming after EOF retry waits. The ratio used for adaptive frame skip decisions (media_time / wall_time) was corrupted by time spent waiting for the recording file to grow during EOF retries. A 20-second EOF wait would result in a ratio of ~0.006, far below the 1.0 threshold, causing all subsequent frames to be decode-only with no encoded output reaching the player. The fix changes the ratio to only measure active processing time (media_time / accumulated_processing_time) instead of total wall time, excluding idle waits. Additionally, EOF waits now time out after 3 seconds to limit the maximum stall duration. Issue: DGW-XXX
1 parent aad097b commit a51ceca

2 files changed

Lines changed: 16 additions & 6 deletions

File tree

crates/video-streamer/src/streamer/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub fn webm_stream(
9999
}
100100
}
101101

102-
const MAX_RETRY_COUNT: usize = 3;
102+
const MAX_RETRY_COUNT: usize = 25;
103103
// To make sure we don't retry forever
104104
// Retry is set to 0 when we successfully read a tag
105105
let mut retry_count = 0;
@@ -190,6 +190,10 @@ pub fn webm_stream(
190190
},
191191
_ = stop_notifier.notified() => {
192192
let _ = tx.send(WhenEofControlFlow::Break);
193+
},
194+
_ = tokio::time::sleep(std::time::Duration::from_secs(3)) => {
195+
info!("EOF wait timed out, retrying");
196+
let _ = tx.send(WhenEofControlFlow::Continue);
193197
}
194198
}
195199
});

crates/video-streamer/src/streamer/tag_writers.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::time::Instant;
1+
use std::time::{Duration, Instant};
22

33
use anyhow::Context;
44
use cadeau::xmf::vpx::{VpxCodec, VpxDecoder, VpxEncoder};
@@ -14,7 +14,7 @@ use crate::debug::mastroka_spec_name;
1414
const VPX_EFLAG_FORCE_KF: u32 = 0x00000001;
1515

1616
#[cfg(feature = "perf-diagnostics")]
17-
fn duration_as_millis_u64(duration: std::time::Duration) -> u64 {
17+
fn duration_as_millis_u64(duration: Duration) -> u64 {
1818
u64::try_from(duration.as_millis()).unwrap_or(u64::MAX)
1919
}
2020

@@ -105,7 +105,9 @@ where
105105
last_encoded_abs_time: Option<u64>,
106106

107107
// Adaptive frame skipping state
108+
#[cfg(feature = "perf-diagnostics")]
108109
stream_start: Instant,
110+
processing_time: Duration,
109111
last_ratio: f64,
110112
frames_since_last_encode: u32,
111113
adaptive_frame_skip: bool,
@@ -192,7 +194,9 @@ where
192194
decoder,
193195
cut_block_state: CutBlockState::HaventMet,
194196
last_encoded_abs_time: None,
197+
#[cfg(feature = "perf-diagnostics")]
195198
stream_start: Instant::now(),
199+
processing_time: Duration::ZERO,
196200
last_ratio: 1.0,
197201
frames_since_last_encode: 0,
198202
adaptive_frame_skip: config.adaptive_frame_skip,
@@ -263,7 +267,9 @@ where
263267
"VideoBlock created"
264268
);
265269

270+
let processing_started = Instant::now();
266271
self.process_current_block(&video_block)?;
272+
self.processing_time += processing_started.elapsed();
267273

268274
Ok(WriterResult::Continue)
269275
}
@@ -371,11 +377,11 @@ where
371377

372378
fn current_realtime_ratio(&self, media_advanced_ms: u64) -> f64 {
373379
#[allow(clippy::cast_possible_truncation)] // u64 max is ~584 million years in ms; no real truncation risk
374-
let wall_ms = self.stream_start.elapsed().as_millis() as u64;
375-
if wall_ms == 0 {
380+
let processing_ms = self.processing_time.as_millis() as u64;
381+
if processing_ms == 0 {
376382
1.0
377383
} else {
378-
media_advanced_ms as f64 / wall_ms as f64
384+
media_advanced_ms as f64 / processing_ms as f64
379385
}
380386
}
381387

0 commit comments

Comments
 (0)