Simplified throughput estimator

Add interface for AcknowledgedBitrateEstimator
Add simplified throughput estimator, implementing the same interface.
The choice of estimator implementation can be controlled by a field trial.

Bug: webrtc:10274
Change-Id: I6bef090a8a6a1783f3f5750a2ee56189f562a9c8
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158892
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29761}
This commit is contained in:
Björn Terelius 2019-11-11 21:00:18 +01:00 committed by Commit Bot
parent 62a19d0798
commit 251b0dcc4f
12 changed files with 512 additions and 22 deletions

View File

@ -106,6 +106,8 @@ rtc_library("estimators") {
sources = [
"acknowledged_bitrate_estimator.cc",
"acknowledged_bitrate_estimator.h",
"acknowledged_bitrate_estimator_interface.cc",
"acknowledged_bitrate_estimator_interface.h",
"bitrate_estimator.cc",
"bitrate_estimator.h",
"delay_increase_detector_interface.h",
@ -113,6 +115,8 @@ rtc_library("estimators") {
"median_slope_estimator.h",
"probe_bitrate_estimator.cc",
"probe_bitrate_estimator.h",
"robust_throughput_estimator.cc",
"robust_throughput_estimator.h",
"trendline_estimator.cc",
"trendline_estimator.h",
]
@ -249,6 +253,7 @@ if (rtc_include_tests) {
"median_slope_estimator_unittest.cc",
"probe_bitrate_estimator_unittest.cc",
"probe_controller_unittest.cc",
"robust_throughput_estimator_unittest.cc",
"send_side_bandwidth_estimation_unittest.cc",
"trendline_estimator_unittest.cc",
]

View File

@ -18,11 +18,13 @@
#include "api/transport/network_types.h"
#include "api/transport/webrtc_key_value_config.h"
#include "api/units/data_rate.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h"
#include "modules/congestion_controller/goog_cc/bitrate_estimator.h"
namespace webrtc {
class AcknowledgedBitrateEstimator {
class AcknowledgedBitrateEstimator
: public AcknowledgedBitrateEstimatorInterface {
public:
AcknowledgedBitrateEstimator(
const WebRtcKeyValueConfig* key_value_config,
@ -30,14 +32,14 @@ class AcknowledgedBitrateEstimator {
explicit AcknowledgedBitrateEstimator(
const WebRtcKeyValueConfig* key_value_config);
~AcknowledgedBitrateEstimator();
~AcknowledgedBitrateEstimator() override;
void IncomingPacketFeedbackVector(
const std::vector<PacketResult>& packet_feedback_vector);
absl::optional<DataRate> bitrate() const;
absl::optional<DataRate> PeekRate() const;
void SetAlr(bool in_alr);
void SetAlrEndedTime(Timestamp alr_ended_time);
const std::vector<PacketResult>& packet_feedback_vector) override;
absl::optional<DataRate> bitrate() const override;
absl::optional<DataRate> PeekRate() const override;
void SetAlr(bool in_alr) override;
void SetAlrEndedTime(Timestamp alr_ended_time) override;
private:
absl::optional<Timestamp> alr_ended_time_;

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/goog_cc/robust_throughput_estimator.h"
#include "rtc_base/logging.h"
namespace webrtc {
constexpr char RobustThroughputEstimatorSettings::kKey[];
RobustThroughputEstimatorSettings::RobustThroughputEstimatorSettings(
const WebRtcKeyValueConfig* key_value_config) {
Parser()->Parse(
key_value_config->Lookup(RobustThroughputEstimatorSettings::kKey));
if (min_packets < 10 || kMaxPackets < min_packets) {
RTC_LOG(LS_WARNING) << "Window size must be between 10 and " << kMaxPackets
<< " packets";
min_packets = 20;
}
if (window_duration < TimeDelta::ms(100) ||
TimeDelta::ms(2000) < window_duration) {
RTC_LOG(LS_WARNING) << "Window duration must be between 100 and 2000 ms";
window_duration = TimeDelta::ms(500);
}
}
std::unique_ptr<StructParametersParser>
RobustThroughputEstimatorSettings::Parser() {
return StructParametersParser::Create("enabled", &enabled, //
"reduce_bias", &reduce_bias, //
"assume_shared_link",
&assume_shared_link, //
"min_packets", &min_packets, //
"window_duration", &window_duration);
}
AcknowledgedBitrateEstimatorInterface::
~AcknowledgedBitrateEstimatorInterface() {}
std::unique_ptr<AcknowledgedBitrateEstimatorInterface>
AcknowledgedBitrateEstimatorInterface::Create(
const WebRtcKeyValueConfig* key_value_config) {
RobustThroughputEstimatorSettings simplified_estimator_settings(
key_value_config);
if (simplified_estimator_settings.enabled) {
return std::make_unique<RobustThroughputEstimator>(
simplified_estimator_settings);
}
return std::make_unique<AcknowledgedBitrateEstimator>(key_value_config);
}
} // namespace webrtc

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_ACKNOWLEDGED_BITRATE_ESTIMATOR_INTERFACE_H_
#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_ACKNOWLEDGED_BITRATE_ESTIMATOR_INTERFACE_H_
#include <memory>
#include <vector>
#include "absl/types/optional.h"
#include "api/transport/network_types.h"
#include "api/transport/webrtc_key_value_config.h"
#include "api/units/data_rate.h"
#include "rtc_base/experiments/struct_parameters_parser.h"
namespace webrtc {
struct RobustThroughputEstimatorSettings {
static constexpr char kKey[] = "WebRTC-Bwe-RobustThroughputEstimatorSettings";
static constexpr size_t kMaxPackets = 500;
RobustThroughputEstimatorSettings() = delete;
explicit RobustThroughputEstimatorSettings(
const WebRtcKeyValueConfig* key_value_config);
bool enabled = false; // Set to true to use RobustThroughputEstimator.
// The estimator handles delay spikes by removing the largest receive time
// gap, but this introduces some bias that may lead to overestimation when
// there isn't any delay spike. If |reduce_bias| is true, we instead replace
// the largest receive time gap by the second largest. This reduces the bias
// at the cost of not completely removing the genuine delay spikes.
bool reduce_bias = true;
// If |assume_shared_link| is false, we ignore the size of the first packet
// when computing the receive rate. Otherwise, we remove half of the first
// and last packet's sizes.
bool assume_shared_link = false;
// The estimator window keeps at least |min_packets| packets and up to
// kMaxPackets received during the last |window_duration|.
unsigned min_packets = 20;
TimeDelta window_duration = TimeDelta::ms(500);
std::unique_ptr<StructParametersParser> Parser();
};
class AcknowledgedBitrateEstimatorInterface {
public:
static std::unique_ptr<AcknowledgedBitrateEstimatorInterface> Create(
const WebRtcKeyValueConfig* key_value_config);
virtual ~AcknowledgedBitrateEstimatorInterface();
virtual void IncomingPacketFeedbackVector(
const std::vector<PacketResult>& packet_feedback_vector) = 0;
virtual absl::optional<DataRate> bitrate() const = 0;
virtual absl::optional<DataRate> PeekRate() const = 0;
virtual void SetAlr(bool in_alr) = 0;
virtual void SetAlrEndedTime(Timestamp alr_ended_time) = 0;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_ACKNOWLEDGED_BITRATE_ESTIMATOR_INTERFACE_H_

View File

@ -149,7 +149,7 @@ DelayBasedBweTest::DelayBasedBweTest()
: field_trial(),
clock_(100000000),
acknowledged_bitrate_estimator_(
std::make_unique<AcknowledgedBitrateEstimator>(&field_trial_config_)),
AcknowledgedBitrateEstimatorInterface::Create(&field_trial_config_)),
probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
bitrate_estimator_(
new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),
@ -163,7 +163,7 @@ DelayBasedBweTest::DelayBasedBweTest(const std::string& field_trial_string)
std::make_unique<test::ScopedFieldTrials>(field_trial_string)),
clock_(100000000),
acknowledged_bitrate_estimator_(
std::make_unique<AcknowledgedBitrateEstimator>(&field_trial_config_)),
AcknowledgedBitrateEstimatorInterface::Create(&field_trial_config_)),
probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
bitrate_estimator_(
new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),

View File

@ -169,7 +169,8 @@ class DelayBasedBweTest : public ::testing::Test {
field_trial; // Must be initialized first.
SimulatedClock clock_; // Time at the receiver.
test::TestBitrateObserver bitrate_observer_;
std::unique_ptr<AcknowledgedBitrateEstimator> acknowledged_bitrate_estimator_;
std::unique_ptr<AcknowledgedBitrateEstimatorInterface>
acknowledged_bitrate_estimator_;
const std::unique_ptr<ProbeBitrateEstimator> probe_bitrate_estimator_;
std::unique_ptr<DelayBasedBwe> bitrate_estimator_;
std::unique_ptr<test::StreamGenerator> stream_generator_;

View File

@ -23,7 +23,6 @@
#include "api/units/time_delta.h"
#include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/goog_cc/alr_detector.h"
#include "modules/congestion_controller/goog_cc/probe_controller.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
@ -32,6 +31,7 @@
#include "rtc_base/logging.h"
namespace webrtc {
namespace {
// From RTCPSender video report interval.
constexpr TimeDelta kLossUpdateInterval = TimeDelta::Millis<1000>();
@ -96,7 +96,7 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config,
event_log_,
network_state_predictor_.get())),
acknowledged_bitrate_estimator_(
std::make_unique<AcknowledgedBitrateEstimator>(key_value_config_)),
AcknowledgedBitrateEstimatorInterface::Create(key_value_config_)),
initial_config_(config),
last_loss_based_target_rate_(*config.constraints.starting_rate),
last_pushback_target_rate_(last_loss_based_target_rate_),
@ -146,8 +146,8 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
}
}
acknowledged_bitrate_estimator_.reset(
new AcknowledgedBitrateEstimator(key_value_config_));
acknowledged_bitrate_estimator_ =
AcknowledgedBitrateEstimatorInterface::Create(key_value_config_);
probe_bitrate_estimator_.reset(new ProbeBitrateEstimator(event_log_));
if (network_estimator_)
network_estimator_->OnRouteChange(msg);

View File

@ -27,7 +27,7 @@
#include "api/units/data_rate.h"
#include "api/units/data_size.h"
#include "api/units/timestamp.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h"
#include "modules/congestion_controller/goog_cc/alr_detector.h"
#include "modules/congestion_controller/goog_cc/congestion_window_pushback_controller.h"
#include "modules/congestion_controller/goog_cc/delay_based_bwe.h"
@ -100,7 +100,8 @@ class GoogCcNetworkController : public NetworkControllerInterface {
std::unique_ptr<NetworkStateEstimator> network_estimator_;
std::unique_ptr<NetworkStatePredictor> network_state_predictor_;
std::unique_ptr<DelayBasedBwe> delay_based_bwe_;
std::unique_ptr<AcknowledgedBitrateEstimator> acknowledged_bitrate_estimator_;
std::unique_ptr<AcknowledgedBitrateEstimatorInterface>
acknowledged_bitrate_estimator_;
absl::optional<NetworkControllerConfig> initial_config_;

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/congestion_controller/goog_cc/robust_throughput_estimator.h"
#include <stddef.h>
#include <algorithm>
#include <utility>
#include "rtc_base/checks.h"
namespace webrtc {
RobustThroughputEstimator::RobustThroughputEstimator(
const RobustThroughputEstimatorSettings& settings)
: settings_(settings) {
RTC_DCHECK(settings.enabled);
}
RobustThroughputEstimator::~RobustThroughputEstimator() {}
void RobustThroughputEstimator::IncomingPacketFeedbackVector(
const std::vector<PacketResult>& packet_feedback_vector) {
RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(),
packet_feedback_vector.end(),
PacketResult::ReceiveTimeOrder()));
for (const auto& packet : packet_feedback_vector) {
// Insert the new packet.
window_.push_back(packet);
// In most cases, receive timestamps should already be in order, but in the
// rare case where feedback packets have been reordered, we do some swaps to
// ensure that the window is sorted.
for (size_t i = window_.size() - 1;
i > 0 && window_[i].receive_time < window_[i - 1].receive_time; i--) {
std::swap(window_[i], window_[i - 1]);
}
// Remove old packets.
while (window_.size() > settings_.kMaxPackets ||
(window_.size() > settings_.min_packets &&
packet.receive_time - window_.front().receive_time >
settings_.window_duration)) {
window_.pop_front();
}
}
}
absl::optional<DataRate> RobustThroughputEstimator::bitrate() const {
if (window_.size() < settings_.min_packets)
return absl::nullopt;
TimeDelta largest_recv_gap(TimeDelta::ms(0));
TimeDelta second_largest_recv_gap(TimeDelta::ms(0));
for (size_t i = 1; i < window_.size(); i++) {
// Find receive time gaps
TimeDelta gap = window_[i].receive_time - window_[i - 1].receive_time;
if (gap > largest_recv_gap) {
second_largest_recv_gap = largest_recv_gap;
largest_recv_gap = gap;
} else if (gap > second_largest_recv_gap) {
second_largest_recv_gap = gap;
}
}
Timestamp min_send_time = window_[0].sent_packet.send_time;
Timestamp max_send_time = window_[0].sent_packet.send_time;
Timestamp min_recv_time = window_[0].receive_time;
Timestamp max_recv_time = window_[0].receive_time;
DataSize data_size = DataSize::bytes(0);
for (const auto& packet : window_) {
min_send_time = std::min(min_send_time, packet.sent_packet.send_time);
max_send_time = std::max(max_send_time, packet.sent_packet.send_time);
min_recv_time = std::min(min_recv_time, packet.receive_time);
max_recv_time = std::max(max_recv_time, packet.receive_time);
data_size += packet.sent_packet.size;
data_size += packet.sent_packet.prior_unacked_data;
}
// Suppose a packet of size S is sent every T milliseconds.
// A window of N packets would contain N*S bytes, but the time difference
// between the first and the last packet would only be (N-1)*T. Thus, we
// need to remove one packet.
DataSize recv_size = data_size;
DataSize send_size = data_size;
if (settings_.assume_shared_link) {
// Depending on how the bottleneck queue is implemented, a large packet
// may delay sending of sebsequent packets, so the delay between packets
// i and i+1 depends on the size of both packets. In this case we minimize
// the maximum error by removing half of both the first and last packet
// size.
DataSize first_last_average_size =
(window_.front().sent_packet.size +
window_.front().sent_packet.prior_unacked_data +
window_.back().sent_packet.size +
window_.back().sent_packet.prior_unacked_data) /
2;
recv_size -= first_last_average_size;
send_size -= first_last_average_size;
} else {
// In the simpler case where the delay between packets i and i+1 only
// depends on the size of packet i+1, the first packet doesn't give us
// any information. Analogously, we assume that the start send time
// for the last packet doesn't depend on the size of the packet.
recv_size -= (window_.front().sent_packet.size +
window_.front().sent_packet.prior_unacked_data);
send_size -= (window_.back().sent_packet.size +
window_.back().sent_packet.prior_unacked_data);
}
// Remove the largest gap by replacing it by the second largest gap
// or the average gap.
TimeDelta send_duration = max_send_time - min_send_time;
TimeDelta recv_duration = (max_recv_time - min_recv_time) - largest_recv_gap;
if (settings_.reduce_bias) {
recv_duration += second_largest_recv_gap;
} else {
recv_duration += recv_duration / (window_.size() - 2);
}
send_duration = std::max(send_duration, TimeDelta::ms(1));
recv_duration = std::max(recv_duration, TimeDelta::ms(1));
return std::min(send_size / send_duration, recv_size / recv_duration);
}
} // namespace webrtc

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_ROBUST_THROUGHPUT_ESTIMATOR_H_
#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_ROBUST_THROUGHPUT_ESTIMATOR_H_
#include <deque>
#include <memory>
#include <vector>
#include "absl/types/optional.h"
#include "api/transport/network_types.h"
#include "api/transport/webrtc_key_value_config.h"
#include "api/units/data_rate.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h"
namespace webrtc {
class RobustThroughputEstimator : public AcknowledgedBitrateEstimatorInterface {
public:
explicit RobustThroughputEstimator(
const RobustThroughputEstimatorSettings& settings);
~RobustThroughputEstimator() override;
void IncomingPacketFeedbackVector(
const std::vector<PacketResult>& packet_feedback_vector) override;
absl::optional<DataRate> bitrate() const override;
absl::optional<DataRate> PeekRate() const override { return bitrate(); }
void SetAlr(bool /*in_alr*/) override {}
void SetAlrEndedTime(Timestamp /*alr_ended_time*/) override {}
private:
const RobustThroughputEstimatorSettings settings_;
std::deque<PacketResult> window_;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_ROBUST_THROUGHPUT_ESTIMATOR_H_

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/congestion_controller/goog_cc/robust_throughput_estimator.h"
#include "api/transport/field_trial_based_config.h"
#include "test/field_trial.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
std::vector<PacketResult> CreateFeedbackVector(size_t number_of_packets,
DataSize packet_size,
TimeDelta send_increment,
TimeDelta recv_increment,
Timestamp* send_clock,
Timestamp* recv_clock,
uint16_t* sequence_number) {
std::vector<PacketResult> packet_feedback_vector(number_of_packets);
for (size_t i = 0; i < number_of_packets; i++) {
packet_feedback_vector[i].receive_time = *recv_clock;
packet_feedback_vector[i].sent_packet.send_time = *send_clock;
packet_feedback_vector[i].sent_packet.sequence_number = *sequence_number;
packet_feedback_vector[i].sent_packet.size = packet_size;
*send_clock += send_increment;
*recv_clock += recv_increment;
*sequence_number += 1;
}
return packet_feedback_vector;
}
} // anonymous namespace
TEST(RobustThroughputEstimatorTest, SteadyRate) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Bwe-RobustThroughputEstimatorSettings/"
"enabled:true,assume_shared_link:false,reduce_bias:true,min_packets:10,"
"window_duration:100ms/");
FieldTrialBasedConfig field_trial_config;
RobustThroughputEstimatorSettings settings(&field_trial_config);
RobustThroughputEstimator throughput_estimator(settings);
DataSize packet_size(DataSize::bytes(1000));
Timestamp send_clock(Timestamp::ms(100000));
Timestamp recv_clock(Timestamp::ms(10000));
TimeDelta send_increment(TimeDelta::ms(10));
TimeDelta recv_increment(TimeDelta::ms(10));
uint16_t sequence_number = 100;
std::vector<PacketResult> packet_feedback =
CreateFeedbackVector(9, packet_size, send_increment, recv_increment,
&send_clock, &recv_clock, &sequence_number);
throughput_estimator.IncomingPacketFeedbackVector(packet_feedback);
EXPECT_FALSE(throughput_estimator.bitrate().has_value());
packet_feedback =
CreateFeedbackVector(11, packet_size, send_increment, recv_increment,
&send_clock, &recv_clock, &sequence_number);
throughput_estimator.IncomingPacketFeedbackVector(packet_feedback);
auto throughput = throughput_estimator.bitrate();
EXPECT_TRUE(throughput.has_value());
EXPECT_NEAR(throughput.value().bytes_per_sec<double>(), 100 * 1000.0,
0.05 * 100 * 1000.0); // Allow 5% error
}
TEST(RobustThroughputEstimatorTest, DelaySpike) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Bwe-RobustThroughputEstimatorSettings/"
"enabled:true,assume_shared_link:false,reduce_bias:true,min_packets:10,"
"window_duration:100ms/");
FieldTrialBasedConfig field_trial_config;
RobustThroughputEstimatorSettings settings(&field_trial_config);
RobustThroughputEstimator throughput_estimator(settings);
DataSize packet_size(DataSize::bytes(1000));
Timestamp send_clock(Timestamp::ms(100000));
Timestamp recv_clock(Timestamp::ms(10000));
TimeDelta send_increment(TimeDelta::ms(10));
TimeDelta recv_increment(TimeDelta::ms(10));
uint16_t sequence_number = 100;
std::vector<PacketResult> packet_feedback =
CreateFeedbackVector(20, packet_size, send_increment, recv_increment,
&send_clock, &recv_clock, &sequence_number);
throughput_estimator.IncomingPacketFeedbackVector(packet_feedback);
auto throughput = throughput_estimator.bitrate();
EXPECT_TRUE(throughput.has_value());
EXPECT_NEAR(throughput.value().bytes_per_sec<double>(), 100 * 1000.0,
0.05 * 100 * 1000.0); // Allow 5% error
// Delay spike
recv_clock += TimeDelta::ms(40);
// Faster delivery after the gap
recv_increment = TimeDelta::ms(2);
packet_feedback =
CreateFeedbackVector(5, packet_size, send_increment, recv_increment,
&send_clock, &recv_clock, &sequence_number);
throughput_estimator.IncomingPacketFeedbackVector(packet_feedback);
throughput = throughput_estimator.bitrate();
EXPECT_TRUE(throughput.has_value());
EXPECT_NEAR(throughput.value().bytes_per_sec<double>(), 100 * 1000.0,
0.05 * 100 * 1000.0); // Allow 5% error
// Delivery at normal rate. This will be capped by the send rate.
recv_increment = TimeDelta::ms(10);
packet_feedback =
CreateFeedbackVector(5, packet_size, send_increment, recv_increment,
&send_clock, &recv_clock, &sequence_number);
throughput_estimator.IncomingPacketFeedbackVector(packet_feedback);
throughput = throughput_estimator.bitrate();
EXPECT_TRUE(throughput.has_value());
EXPECT_NEAR(throughput.value().bytes_per_sec<double>(), 100 * 1000.0,
0.05 * 100 * 1000.0); // Allow 5% error
}
TEST(RobustThroughputEstimatorTest, CappedByReceiveRate) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Bwe-RobustThroughputEstimatorSettings/"
"enabled:true,assume_shared_link:false,reduce_bias:true,min_packets:10,"
"window_duration:100ms/");
FieldTrialBasedConfig field_trial_config;
RobustThroughputEstimatorSettings settings(&field_trial_config);
RobustThroughputEstimator throughput_estimator(settings);
DataSize packet_size(DataSize::bytes(1000));
Timestamp send_clock(Timestamp::ms(100000));
Timestamp recv_clock(Timestamp::ms(10000));
TimeDelta send_increment(TimeDelta::ms(10));
TimeDelta recv_increment(TimeDelta::ms(40));
uint16_t sequence_number = 100;
std::vector<PacketResult> packet_feedback =
CreateFeedbackVector(20, packet_size, send_increment, recv_increment,
&send_clock, &recv_clock, &sequence_number);
throughput_estimator.IncomingPacketFeedbackVector(packet_feedback);
auto throughput = throughput_estimator.bitrate();
EXPECT_TRUE(throughput.has_value());
EXPECT_NEAR(throughput.value().bytes_per_sec<double>(), 25 * 1000.0,
0.05 * 25 * 1000.0); // Allow 5% error
}
TEST(RobustThroughputEstimatorTest, CappedBySendRate) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Bwe-RobustThroughputEstimatorSettings/"
"enabled:true,assume_shared_link:false,reduce_bias:true,min_packets:10,"
"window_duration:100ms/");
FieldTrialBasedConfig field_trial_config;
RobustThroughputEstimatorSettings settings(&field_trial_config);
RobustThroughputEstimator throughput_estimator(settings);
DataSize packet_size(DataSize::bytes(1000));
Timestamp send_clock(Timestamp::ms(100000));
Timestamp recv_clock(Timestamp::ms(10000));
TimeDelta send_increment(TimeDelta::ms(20));
TimeDelta recv_increment(TimeDelta::ms(10));
uint16_t sequence_number = 100;
std::vector<PacketResult> packet_feedback =
CreateFeedbackVector(20, packet_size, send_increment, recv_increment,
&send_clock, &recv_clock, &sequence_number);
throughput_estimator.IncomingPacketFeedbackVector(packet_feedback);
auto throughput = throughput_estimator.bitrate();
EXPECT_TRUE(throughput.has_value());
EXPECT_NEAR(throughput.value().bytes_per_sec<double>(), 50 * 1000.0,
0.05 * 50 * 1000.0); // Allow 5% error
}
} // namespace webrtc*/

View File

@ -1269,14 +1269,14 @@ void EventLogAnalyzer::CreateSendSideBweSimulationGraph(Plot* plot) {
FieldTrialBasedConfig field_trial_config_;
// The event_log_visualizer should normally not be compiled with
// BWE_TEST_LOGGING_COMPILE_TIME_ENABLE since the normal plots won't work.
// However, compiling with BWE_TEST_LOGGING, running with --plot_sendside_bwe
// However, compiling with BWE_TEST_LOGGING, running with --plot=sendside_bwe
// and piping the output to plot_dynamics.py can be used as a hack to get the
// internal state of various BWE components. In this case, it is important
// we don't instantiate the AcknowledgedBitrateEstimator both here and in
// GoogCcNetworkController since that would lead to duplicate outputs.
AcknowledgedBitrateEstimator acknowledged_bitrate_estimator(
&field_trial_config_,
std::make_unique<BitrateEstimator>(&field_trial_config_));
std::unique_ptr<AcknowledgedBitrateEstimatorInterface>
acknowledged_bitrate_estimator(
AcknowledgedBitrateEstimatorInterface::Create(&field_trial_config_));
#endif // !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
int64_t time_us =
std::min({NextRtpTime(), NextRtcpTime(), NextProcessTime()});
@ -1321,7 +1321,8 @@ void EventLogAnalyzer::CreateSendSideBweSimulationGraph(Plot* plot) {
feedback_msg->SortedByReceiveTime();
if (!feedback.empty()) {
#if !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
acknowledged_bitrate_estimator.IncomingPacketFeedbackVector(feedback);
acknowledged_bitrate_estimator->IncomingPacketFeedbackVector(
feedback);
#endif // !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
for (const PacketResult& packet : feedback)
acked_bitrate.Update(packet.sent_packet.size.bytes(),
@ -1334,7 +1335,7 @@ void EventLogAnalyzer::CreateSendSideBweSimulationGraph(Plot* plot) {
float y = bitrate_bps.value_or(0) / 1000;
acked_time_series.points.emplace_back(x, y);
#if !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
y = acknowledged_bitrate_estimator.bitrate()
y = acknowledged_bitrate_estimator->bitrate()
.value_or(DataRate::Zero())
.kbps();
acked_estimate_time_series.points.emplace_back(x, y);