- 当接收侧感知到2-10%丢包率,发送端的预测值不变。
- 当实际丢包率超过预测值10%时,新的预测值可更新为As_hat(i)= As_hat(i-1)(1-0.5p),其中p为丢包率。
- 当实际丢包率小于2%时预测时可更新为As_hat(i)= 1.08(As_hat(i-1))+0.5+1000,其中p为丢包率。
- 其中p是rtcp里的丢包率
void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
uint32_t new_bitrate = current_bitrate_bps_;
// We trust the REMB and/or delay-based estimate during the first 2 seconds if
// we haven't had any packet loss reported, to allow startup bitrate probing.
if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {
new_bitrate = std::max(bwe_incoming_, new_bitrate);
new_bitrate = std::max(delay_based_bitrate_bps_, new_bitrate);
if (new_bitrate != current_bitrate_bps_) {
min_bitrate_history_.clear();
min_bitrate_history_.push_back(
std::make_pair(now_ms, current_bitrate_bps_));
CapBitrateToThresholds(now_ms, new_bitrate);
return;
}
}
UpdateMinHistory(now_ms);
if (last_packet_report_ms_ == -1) {
// No feedback received.
CapBitrateToThresholds(now_ms, current_bitrate_bps_);
return;
}
int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;
int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;
if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {
// We only care about loss above a given bitrate threshold.
float loss = last_fraction_loss_ / 256.0f;
// We only make decisions based on loss when the bitrate is above a
// threshold. This is a crude way of handling loss which is uncorrelated
// to congestion.
if (current_bitrate_bps_ < bitrate_threshold_bps_ ||
loss <= low_loss_threshold_) {
// Loss < 2%: Increase rate by 8% of the min bitrate in the last
// kBweIncreaseIntervalMs.
// Note that by remembering the bitrate over the last second one can
// rampup up one second faster than if only allowed to start ramping
// at 8% per second rate now. E.g.:
// If sending a constant 100kbps it can rampup immediatly to 108kbps
// whenever a receiver report is received with lower packet loss.
// If instead one would do: current_bitrate_bps_ *= 1.08^(delta time),
// it would take over one second since the lower packet loss to achieve
// 108kbps.
new_bitrate = static_cast<uint32_t>(
min_bitrate_history_.front().second * 1.08 + 0.5);
// Add 1 kbps extra, just to make sure that we do not get stuck
// (gives a little extra increase at low rates, negligible at higher
// rates).
new_bitrate += 1000;
} else if (current_bitrate_bps_ > bitrate_threshold_bps_) {
if (loss <= high_loss_threshold_) {
// Loss between 2% - 10%: Do nothing.
} else {
// Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs
// + rtt.
if (!has_decreased_since_last_fraction_loss_ &&
(now_ms - time_last_decrease_ms_) >=
(kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {
time_last_decrease_ms_ = now_ms;
// Reduce rate:
// newRate = rate * (1 - 0.5*lossRate);
// where packetLoss = 256*lossRate;
new_bitrate = static_cast<uint32_t>(
(current_bitrate_bps_ *
static_cast<double>(512 - last_fraction_loss_)) /
512.0);
has_decreased_since_last_fraction_loss_ = true;
}
}
}
} else if (time_since_feedback_ms >
kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&
(last_timeout_ms_ == -1 ||
now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {
if (in_timeout_experiment_) {
LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms
<< " ms), reducing bitrate.";
new_bitrate *= 0.8;
// Reset accumulators since we've already acted on missing feedback and
// shouldn't to act again on these old lost packets.
lost_packets_since_last_loss_update_Q8_ = 0;
expected_packets_since_last_loss_update_ = 0;
last_timeout_ms_ = now_ms;
}
}
//其实就是估算current_bitrate_bps_
CapBitrateToThresholds(now_ms, new_bitrate);
}
bitrate_threshold_bps_ 是怎么来的?
SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
: lost_packets_since_last_loss_update_Q8_(0),
expected_packets_since_last_loss_update_(0),
current_bitrate_bps_(0),
min_bitrate_configured_(congestion_controller::GetMinBitrateBps()),
max_bitrate_configured_(kDefaultMaxBitrateBps),
last_low_bitrate_log_ms_(-1),
has_decreased_since_last_fraction_loss_(false),
last_feedback_ms_(-1),
last_packet_report_ms_(-1),
last_timeout_ms_(-1),
last_fraction_loss_(0),
last_logged_fraction_loss_(0),
last_round_trip_time_ms_(0),
bwe_incoming_(0),
delay_based_bitrate_bps_(0),
time_last_decrease_ms_(0),
first_report_time_ms_(-1),
initially_lost_packets_(0),
bitrate_at_2_seconds_kbps_(0),
uma_update_state_(kNoUpdate),
rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
event_log_(event_log),
last_rtc_event_log_ms_(-1),
in_timeout_experiment_(
webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")),
low_loss_threshold_(kDefaultLowLossThreshold),
high_loss_threshold_(kDefaultHighLossThreshold),
bitrate_threshold_bps_(1000 * kDefaultBitrateThresholdKbps) {
RTC_DCHECK(event_log);
if (BweLossExperimentIsEnabled()) {
uint32_t bitrate_threshold_kbps;
if (ReadBweLossExperimentParameters(&low_loss_threshold_,
&high_loss_threshold_,
&bitrate_threshold_kbps)) {
LOG(LS_INFO) << "Enabled BweLossExperiment with parameters "
<< low_loss_threshold_ << ", " << high_loss_threshold_
<< ", " << bitrate_threshold_kbps;
bitrate_threshold_bps_ = bitrate_threshold_kbps * 1000;
}
}
}