Adds RTT based backoff trial to SendSideBandwidthEstimation.
Bug: webrtc:9718 Change-Id: Ic94dcd7612524d350f54d1907f843577b890badf Reviewed-on: https://webrtc-review.googlesource.com/c/104122 Commit-Queue: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25048}
This commit is contained in:

committed by
Commit Bot

parent
d2fb1bfeba
commit
2e068e8b6f
@ -35,6 +35,7 @@ rtc_static_library("bitrate_controller") {
|
|||||||
"../../logging:rtc_event_log_api",
|
"../../logging:rtc_event_log_api",
|
||||||
"../../rtc_base:checks",
|
"../../rtc_base:checks",
|
||||||
"../../rtc_base:rtc_base_approved",
|
"../../rtc_base:rtc_base_approved",
|
||||||
|
"../../rtc_base/experiments:field_trial_parser",
|
||||||
"../../system_wrappers",
|
"../../system_wrappers",
|
||||||
"../../system_wrappers:field_trial",
|
"../../system_wrappers:field_trial",
|
||||||
"../../system_wrappers:metrics",
|
"../../system_wrappers:metrics",
|
||||||
|
@ -104,8 +104,21 @@ bool ReadBweLossExperimentParameters(float* low_loss_threshold,
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
RttBasedBackoffConfig::RttBasedBackoffConfig()
|
||||||
|
: rtt_limit("limit", TimeDelta::PlusInfinity()),
|
||||||
|
drop_fraction("fraction", 0.5),
|
||||||
|
drop_interval("interval", TimeDelta::ms(300)) {
|
||||||
|
std::string trial_string =
|
||||||
|
field_trial::FindFullName("WebRTC-Bwe-MaxRttLimit");
|
||||||
|
ParseFieldTrial({&rtt_limit, &drop_fraction, &drop_interval}, trial_string);
|
||||||
|
}
|
||||||
|
RttBasedBackoffConfig::RttBasedBackoffConfig(const RttBasedBackoffConfig&) =
|
||||||
|
default;
|
||||||
|
RttBasedBackoffConfig::~RttBasedBackoffConfig() = default;
|
||||||
|
|
||||||
SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
|
SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
|
||||||
: lost_packets_since_last_loss_update_(0),
|
: rtt_backoff_config_(RttBasedBackoffConfig()),
|
||||||
|
lost_packets_since_last_loss_update_(0),
|
||||||
expected_packets_since_last_loss_update_(0),
|
expected_packets_since_last_loss_update_(0),
|
||||||
current_bitrate_(DataRate::Zero()),
|
current_bitrate_(DataRate::Zero()),
|
||||||
min_bitrate_configured_(
|
min_bitrate_configured_(
|
||||||
@ -119,6 +132,10 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
|
|||||||
last_fraction_loss_(0),
|
last_fraction_loss_(0),
|
||||||
last_logged_fraction_loss_(0),
|
last_logged_fraction_loss_(0),
|
||||||
last_round_trip_time_(TimeDelta::Zero()),
|
last_round_trip_time_(TimeDelta::Zero()),
|
||||||
|
// By initializing this to plus infinity, we make sure that we never
|
||||||
|
// trigger rtt backoff unless packet feedback is enabled.
|
||||||
|
last_propagation_rtt_update_(Timestamp::PlusInfinity()),
|
||||||
|
last_propagation_rtt_(TimeDelta::Zero()),
|
||||||
bwe_incoming_(DataRate::Zero()),
|
bwe_incoming_(DataRate::Zero()),
|
||||||
delay_based_bitrate_(DataRate::Zero()),
|
delay_based_bitrate_(DataRate::Zero()),
|
||||||
time_last_decrease_(Timestamp::MinusInfinity()),
|
time_last_decrease_(Timestamp::MinusInfinity()),
|
||||||
@ -295,6 +312,16 @@ void SendSideBandwidthEstimation::UpdateRtt(TimeDelta rtt, Timestamp at_time) {
|
|||||||
|
|
||||||
void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
|
void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
|
||||||
DataRate new_bitrate = current_bitrate_;
|
DataRate new_bitrate = current_bitrate_;
|
||||||
|
TimeDelta time_since_rtt = at_time - last_propagation_rtt_update_;
|
||||||
|
if (time_since_rtt + last_propagation_rtt_ > rtt_backoff_config_.rtt_limit) {
|
||||||
|
if (at_time - time_last_decrease_ >= rtt_backoff_config_.drop_interval) {
|
||||||
|
time_last_decrease_ = at_time;
|
||||||
|
new_bitrate = current_bitrate_ * rtt_backoff_config_.drop_fraction;
|
||||||
|
}
|
||||||
|
CapBitrateToThresholds(at_time, new_bitrate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We trust the REMB and/or delay-based estimate during the first 2 seconds if
|
// 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.
|
// we haven't had any packet loss reported, to allow startup bitrate probing.
|
||||||
if (last_fraction_loss_ == 0 && IsInStartPhase(at_time)) {
|
if (last_fraction_loss_ == 0 && IsInStartPhase(at_time)) {
|
||||||
@ -382,6 +409,13 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
|
|||||||
CapBitrateToThresholds(at_time, new_bitrate);
|
CapBitrateToThresholds(at_time, new_bitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendSideBandwidthEstimation::UpdatePropagationRtt(
|
||||||
|
Timestamp at_time,
|
||||||
|
TimeDelta propagation_rtt) {
|
||||||
|
last_propagation_rtt_update_ = at_time;
|
||||||
|
last_propagation_rtt_ = propagation_rtt;
|
||||||
|
}
|
||||||
|
|
||||||
bool SendSideBandwidthEstimation::IsInStartPhase(Timestamp at_time) const {
|
bool SendSideBandwidthEstimation::IsInStartPhase(Timestamp at_time) const {
|
||||||
return first_report_time_.IsInfinite() ||
|
return first_report_time_.IsInfinite() ||
|
||||||
at_time - first_report_time_ < kStartPhase;
|
at_time - first_report_time_ < kStartPhase;
|
||||||
|
@ -19,21 +19,35 @@
|
|||||||
|
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
|
#include "rtc_base/experiments/field_trial_parser.h"
|
||||||
|
#include "rtc_base/experiments/field_trial_units.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class RtcEventLog;
|
class RtcEventLog;
|
||||||
|
|
||||||
|
struct RttBasedBackoffConfig {
|
||||||
|
RttBasedBackoffConfig();
|
||||||
|
RttBasedBackoffConfig(const RttBasedBackoffConfig&);
|
||||||
|
RttBasedBackoffConfig& operator=(const RttBasedBackoffConfig&) = default;
|
||||||
|
~RttBasedBackoffConfig();
|
||||||
|
FieldTrialParameter<TimeDelta> rtt_limit;
|
||||||
|
FieldTrialParameter<double> drop_fraction;
|
||||||
|
FieldTrialParameter<TimeDelta> drop_interval;
|
||||||
|
};
|
||||||
|
|
||||||
class SendSideBandwidthEstimation {
|
class SendSideBandwidthEstimation {
|
||||||
public:
|
public:
|
||||||
SendSideBandwidthEstimation() = delete;
|
SendSideBandwidthEstimation() = delete;
|
||||||
explicit SendSideBandwidthEstimation(RtcEventLog* event_log);
|
explicit SendSideBandwidthEstimation(RtcEventLog* event_log);
|
||||||
virtual ~SendSideBandwidthEstimation();
|
~SendSideBandwidthEstimation();
|
||||||
|
|
||||||
void CurrentEstimate(int* bitrate, uint8_t* loss, int64_t* rtt) const;
|
void CurrentEstimate(int* bitrate, uint8_t* loss, int64_t* rtt) const;
|
||||||
|
|
||||||
// Call periodically to update estimate.
|
// Call periodically to update estimate.
|
||||||
void UpdateEstimate(Timestamp at_time);
|
void UpdateEstimate(Timestamp at_time);
|
||||||
|
void OnSentPacket(SentPacket sent_packet);
|
||||||
|
void UpdatePropagationRtt(Timestamp at_time, TimeDelta feedback_rtt);
|
||||||
|
|
||||||
// Call when we receive a RTCP message with TMMBR or REMB.
|
// Call when we receive a RTCP message with TMMBR or REMB.
|
||||||
void UpdateReceiverEstimate(Timestamp at_time, DataRate bandwidth);
|
void UpdateReceiverEstimate(Timestamp at_time, DataRate bandwidth);
|
||||||
@ -79,6 +93,8 @@ class SendSideBandwidthEstimation {
|
|||||||
// set |current_bitrate_| to the capped value and updates the event log.
|
// set |current_bitrate_| to the capped value and updates the event log.
|
||||||
void CapBitrateToThresholds(Timestamp at_time, DataRate bitrate);
|
void CapBitrateToThresholds(Timestamp at_time, DataRate bitrate);
|
||||||
|
|
||||||
|
RttBasedBackoffConfig rtt_backoff_config_;
|
||||||
|
|
||||||
std::deque<std::pair<Timestamp, DataRate> > min_bitrate_history_;
|
std::deque<std::pair<Timestamp, DataRate> > min_bitrate_history_;
|
||||||
|
|
||||||
// incoming filters
|
// incoming filters
|
||||||
@ -98,6 +114,9 @@ class SendSideBandwidthEstimation {
|
|||||||
uint8_t last_logged_fraction_loss_;
|
uint8_t last_logged_fraction_loss_;
|
||||||
TimeDelta last_round_trip_time_;
|
TimeDelta last_round_trip_time_;
|
||||||
|
|
||||||
|
Timestamp last_propagation_rtt_update_;
|
||||||
|
TimeDelta last_propagation_rtt_;
|
||||||
|
|
||||||
DataRate bwe_incoming_;
|
DataRate bwe_incoming_;
|
||||||
DataRate delay_based_bitrate_;
|
DataRate delay_based_bitrate_;
|
||||||
Timestamp time_last_decrease_;
|
Timestamp time_last_decrease_;
|
||||||
|
@ -250,6 +250,13 @@ NetworkControlUpdate GoogCcNetworkController::OnSentPacket(
|
|||||||
SentPacket sent_packet) {
|
SentPacket sent_packet) {
|
||||||
alr_detector_->OnBytesSent(sent_packet.size.bytes(),
|
alr_detector_->OnBytesSent(sent_packet.size.bytes(),
|
||||||
sent_packet.send_time.ms());
|
sent_packet.send_time.ms());
|
||||||
|
if (!first_packet_sent_) {
|
||||||
|
first_packet_sent_ = true;
|
||||||
|
// Initialize feedback time to send time to allow estimation of RTT until
|
||||||
|
// first feedback is received.
|
||||||
|
bandwidth_estimation_->UpdatePropagationRtt(sent_packet.send_time,
|
||||||
|
TimeDelta::Zero());
|
||||||
|
}
|
||||||
return NetworkControlUpdate();
|
return NetworkControlUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,24 +338,30 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport(
|
|||||||
|
|
||||||
NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
|
NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
|
||||||
TransportPacketsFeedback report) {
|
TransportPacketsFeedback report) {
|
||||||
TimeDelta feedback_max_rtt = TimeDelta::MinusInfinity();
|
TimeDelta max_feedback_rtt = TimeDelta::MinusInfinity();
|
||||||
|
TimeDelta min_propagation_rtt = TimeDelta::PlusInfinity();
|
||||||
Timestamp max_recv_time = Timestamp::MinusInfinity();
|
Timestamp max_recv_time = Timestamp::MinusInfinity();
|
||||||
for (const auto& packet_feedback : report.ReceivedWithSendInfo()) {
|
|
||||||
TimeDelta rtt =
|
std::vector<PacketResult> feedbacks = report.ReceivedWithSendInfo();
|
||||||
report.feedback_time - packet_feedback.sent_packet->send_time;
|
for (const auto& feedback : feedbacks)
|
||||||
// max() is used to account for feedback being delayed by the
|
max_recv_time = std::max(max_recv_time, feedback.receive_time);
|
||||||
// receiver.
|
|
||||||
feedback_max_rtt = std::max(feedback_max_rtt, rtt);
|
for (const auto& feedback : feedbacks) {
|
||||||
max_recv_time = std::max(max_recv_time, packet_feedback.receive_time);
|
TimeDelta feedback_rtt =
|
||||||
|
report.feedback_time - feedback.sent_packet->send_time;
|
||||||
|
TimeDelta min_pending_time = feedback.receive_time - max_recv_time;
|
||||||
|
TimeDelta propagation_rtt = feedback_rtt - min_pending_time;
|
||||||
|
max_feedback_rtt = std::max(max_feedback_rtt, feedback_rtt);
|
||||||
|
min_propagation_rtt = std::min(min_propagation_rtt, propagation_rtt);
|
||||||
}
|
}
|
||||||
absl::optional<int64_t> min_feedback_max_rtt_ms;
|
|
||||||
if (feedback_max_rtt.IsFinite()) {
|
if (max_feedback_rtt.IsFinite()) {
|
||||||
feedback_max_rtts_.push_back(feedback_max_rtt.ms());
|
feedback_max_rtts_.push_back(max_feedback_rtt.ms());
|
||||||
const size_t kMaxFeedbackRttWindow = 32;
|
const size_t kMaxFeedbackRttWindow = 32;
|
||||||
if (feedback_max_rtts_.size() > kMaxFeedbackRttWindow)
|
if (feedback_max_rtts_.size() > kMaxFeedbackRttWindow)
|
||||||
feedback_max_rtts_.pop_front();
|
feedback_max_rtts_.pop_front();
|
||||||
min_feedback_max_rtt_ms.emplace(*std::min_element(
|
bandwidth_estimation_->UpdatePropagationRtt(report.feedback_time,
|
||||||
feedback_max_rtts_.begin(), feedback_max_rtts_.end()));
|
min_propagation_rtt);
|
||||||
}
|
}
|
||||||
if (packet_feedback_only_) {
|
if (packet_feedback_only_) {
|
||||||
if (!feedback_max_rtts_.empty()) {
|
if (!feedback_max_rtts_.empty()) {
|
||||||
@ -359,7 +372,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
TimeDelta feedback_min_rtt = TimeDelta::PlusInfinity();
|
TimeDelta feedback_min_rtt = TimeDelta::PlusInfinity();
|
||||||
for (const auto& packet_feedback : report.ReceivedWithSendInfo()) {
|
for (const auto& packet_feedback : feedbacks) {
|
||||||
TimeDelta pending_time = packet_feedback.receive_time - max_recv_time;
|
TimeDelta pending_time = packet_feedback.receive_time - max_recv_time;
|
||||||
TimeDelta rtt = report.feedback_time -
|
TimeDelta rtt = report.feedback_time -
|
||||||
packet_feedback.sent_packet->send_time - pending_time;
|
packet_feedback.sent_packet->send_time - pending_time;
|
||||||
@ -428,10 +441,13 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
|
|||||||
|
|
||||||
// No valid RTT could be because send-side BWE isn't used, in which case
|
// No valid RTT could be because send-side BWE isn't used, in which case
|
||||||
// we don't try to limit the outstanding packets.
|
// we don't try to limit the outstanding packets.
|
||||||
if (in_cwnd_experiment_ && min_feedback_max_rtt_ms) {
|
if (in_cwnd_experiment_ && max_feedback_rtt.IsFinite()) {
|
||||||
|
int64_t min_feedback_max_rtt_ms =
|
||||||
|
*std::min_element(feedback_max_rtts_.begin(), feedback_max_rtts_.end());
|
||||||
|
|
||||||
const DataSize kMinCwnd = DataSize::bytes(2 * 1500);
|
const DataSize kMinCwnd = DataSize::bytes(2 * 1500);
|
||||||
TimeDelta time_window =
|
TimeDelta time_window =
|
||||||
TimeDelta::ms(*min_feedback_max_rtt_ms + accepted_queue_ms_);
|
TimeDelta::ms(min_feedback_max_rtt_ms + accepted_queue_ms_);
|
||||||
DataSize data_window = last_bandwidth_ * time_window;
|
DataSize data_window = last_bandwidth_ * time_window;
|
||||||
if (current_data_window_) {
|
if (current_data_window_) {
|
||||||
data_window =
|
data_window =
|
||||||
@ -440,7 +456,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
|
|||||||
data_window = std::max(kMinCwnd, data_window);
|
data_window = std::max(kMinCwnd, data_window);
|
||||||
}
|
}
|
||||||
current_data_window_ = data_window;
|
current_data_window_ = data_window;
|
||||||
RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_feedback_max_rtt_ms
|
RTC_LOG(LS_INFO) << "Feedback rtt: " << min_feedback_max_rtt_ms
|
||||||
<< " Bitrate: " << last_bandwidth_.bps();
|
<< " Bitrate: " << last_bandwidth_.bps();
|
||||||
}
|
}
|
||||||
update.congestion_window = current_data_window_;
|
update.congestion_window = current_data_window_;
|
||||||
|
@ -73,6 +73,8 @@ class GoogCcNetworkController : public NetworkControllerInterface {
|
|||||||
|
|
||||||
absl::optional<NetworkControllerConfig> initial_config_;
|
absl::optional<NetworkControllerConfig> initial_config_;
|
||||||
|
|
||||||
|
bool first_packet_sent_ = false;
|
||||||
|
|
||||||
Timestamp next_loss_update_ = Timestamp::MinusInfinity();
|
Timestamp next_loss_update_ = Timestamp::MinusInfinity();
|
||||||
int lost_packets_since_last_loss_update_ = 0;
|
int lost_packets_since_last_loss_update_ = 0;
|
||||||
int expected_packets_since_last_loss_update_ = 0;
|
int expected_packets_since_last_loss_update_ = 0;
|
||||||
|
Reference in New Issue
Block a user