diff --git a/src/bwe.rs b/src/bwe.rs index 90d856aa..e2ba6bba 100644 --- a/src/bwe.rs +++ b/src/bwe.rs @@ -82,4 +82,16 @@ impl<'a> Bwe<'a> { pub fn set_desired_bitrate(&mut self, desired_bitrate: Bitrate) { self.0.session.set_bwe_desired_bitrate(desired_bitrate); } + + /// Reset the BWE with a new init_bitrate + /// + /// # Example + /// + /// This method is useful when you initially start with only an audio stream. In this case, the BWE will report a very low estimated bitrate. + /// Later, when you start a video stream, the estimated bitrate will be affected by the previous low bitrate, resulting in a very low estimated bitrate, which can cause poor video stream quality. + /// To avoid this, you need to warm up the video stream for a while then calling reset with a provided init_bitrate. + /// + pub fn reset(&mut self, init_bitrate: Bitrate) { + self.0.session.reset_bwe(init_bitrate); + } } diff --git a/src/packet/bwe/acked_bitrate_estimator.rs b/src/packet/bwe/acked_bitrate_estimator.rs index 37448de6..9c4ff37b 100644 --- a/src/packet/bwe/acked_bitrate_estimator.rs +++ b/src/packet/bwe/acked_bitrate_estimator.rs @@ -73,8 +73,7 @@ impl AckedBitrateEstimator { // current estimate. With low values of uncertainty_symmetry_cap_ we add more // uncertainty to increases than to decreases. For higher values we approach // symmetry. - let sample_uncertainty = - scale * (estimate_bps - sample_estimate_bps).abs() / (estimate_bps.max(25_000.0)); + let sample_uncertainty = scale * (estimate_bps - sample_estimate_bps).abs() / estimate_bps; let sample_var = sample_uncertainty.powf(2.0); // Update a bayesian estimate of the rate, weighting it lower if the sample @@ -85,6 +84,7 @@ impl AckedBitrateEstimator { let mut new_estimate = (sample_var * estimate_bps + pred_bitrate_estimate_var * sample_estimate_bps) / (sample_var + pred_bitrate_estimate_var); + new_estimate = new_estimate.max(ESTIMATE_FLOOR.as_f64()); self.estimate = Some(Bitrate::bps(new_estimate.ceil() as u64)); self.estimate_var = @@ -136,7 +136,7 @@ impl AckedBitrateEstimator { self.sum += packet_size; - estimate.map(|e| (e, false)) + estimate.map(|e| (e, is_small)) } } @@ -200,7 +200,7 @@ mod test { assert_eq!( estimate.as_u64(), - 99530, + 108320, "AckedBitrateEstiamtor should produce the correct bitrate" ); } diff --git a/src/session.rs b/src/session.rs index 91ac400f..ce13b2ea 100644 --- a/src/session.rs +++ b/src/session.rs @@ -796,6 +796,12 @@ impl Session { } } + pub fn reset_bwe(&mut self, init_bitrate: Bitrate) { + if let Some(bwe) = self.bwe.as_mut() { + bwe.reset(init_bitrate); + } + } + pub fn line_count(&self) -> usize { self.medias.len() + if self.app.is_some() { 1 } else { 0 } } @@ -898,6 +904,10 @@ impl Bwe { self.bwe.handle_timeout(now); } + pub fn reset(&mut self, init_bitrate: Bitrate) { + self.bwe = SendSideBandwithEstimator::new(init_bitrate); + } + pub fn update<'t>( &mut self, records: impl Iterator,