Add base class NetworkPredictor and NetworkPredictorFactory and wire up.

Add base class NetworkPredictor and NetworkPredictorFactory in /api, make it possible to inject customized NetworkPredictor in PeerConnectionFactory level. The NetworkPredictor object will be pass down to GoogCCNetworkControl and DelayBasedBwe.

Bug: webrtc:10492
Change-Id: Iceeadbe1c9388b11ce4ac01ee56554cb0bf64d04
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130201
Commit-Queue: Ying Wang <yinwa@webrtc.org>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27543}
This commit is contained in:
Ying Wang
2019-04-10 13:48:24 +02:00
committed by Commit Bot
parent c21cf04618
commit 0810a7c25a
37 changed files with 294 additions and 96 deletions

View File

@ -30,6 +30,8 @@ rtc_static_library("goog_cc") {
":probe_controller",
":pushback_controller",
"../..:module_api",
"../../..:webrtc_common",
"../../../api:network_state_predictor_api",
"../../../api/transport:field_trial_based_config",
"../../../api/transport:network_control",
"../../../api/transport:webrtc_key_value_config",
@ -116,6 +118,7 @@ rtc_source_set("estimators") {
]
deps = [
"../../../api:network_state_predictor_api",
"../../../api/transport:webrtc_key_value_config",
"../../../api/units:data_rate",
"../../../logging:rtc_event_bwe",
@ -143,6 +146,7 @@ rtc_source_set("delay_based_bwe") {
deps = [
":estimators",
"../../../api:network_state_predictor_api",
"../../../api/transport:network_control",
"../../../api/transport:webrtc_key_value_config",
"../../../logging:rtc_event_bwe",

View File

@ -83,7 +83,8 @@ DelayBasedBwe::Result::Result(bool probe, DataRate target_bitrate)
DelayBasedBwe::Result::~Result() {}
DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
RtcEventLog* event_log)
RtcEventLog* event_log,
NetworkStatePredictor* network_state_predictor)
: event_log_(event_log),
inter_arrival_(),
delay_detector_(),
@ -100,13 +101,14 @@ DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
prev_state_(BandwidthUsage::kBwNormal),
alr_limited_backoff_enabled_(
key_value_config->Lookup("WebRTC-Bwe-AlrLimitedBackoff")
.find("Enabled") == 0) {
.find("Enabled") == 0),
network_state_predictor_(network_state_predictor) {
RTC_LOG(LS_INFO)
<< "Using Trendline filter for delay change estimation with window size "
<< trendline_window_size_;
delay_detector_.reset(new TrendlineEstimator(trendline_window_size_,
trendline_smoothing_coeff_,
trendline_threshold_gain_));
delay_detector_.reset(new TrendlineEstimator(
trendline_window_size_, trendline_smoothing_coeff_,
trendline_threshold_gain_, network_state_predictor_));
}
DelayBasedBwe::~DelayBasedBwe() {}
@ -169,9 +171,9 @@ void DelayBasedBwe::IncomingPacketFeedback(
inter_arrival_.reset(
new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
kTimestampToMs, true));
delay_detector_.reset(new TrendlineEstimator(trendline_window_size_,
trendline_smoothing_coeff_,
trendline_threshold_gain_));
delay_detector_.reset(new TrendlineEstimator(
trendline_window_size_, trendline_smoothing_coeff_,
trendline_threshold_gain_, network_state_predictor_));
}
last_seen_packet_ = at_time;
@ -189,13 +191,12 @@ void DelayBasedBwe::IncomingPacketFeedback(
uint32_t ts_delta = 0;
int64_t t_delta = 0;
int size_delta = 0;
if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
at_time.ms(), packet_feedback.payload_size,
&ts_delta, &t_delta, &size_delta)) {
double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
delay_detector_->Update(t_delta, ts_delta_ms,
packet_feedback.arrival_time_ms);
}
bool calculated_deltas = inter_arrival_->ComputeDeltas(
timestamp, packet_feedback.arrival_time_ms, at_time.ms(),
packet_feedback.payload_size, &ts_delta, &t_delta, &size_delta);
double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
delay_detector_->Update(t_delta, ts_delta_ms, packet_feedback.send_time_ms,
packet_feedback.arrival_time_ms, calculated_deltas);
}
DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(

View File

@ -17,6 +17,7 @@
#include <vector>
#include "absl/types/optional.h"
#include "api/network_state_predictor.h"
#include "api/transport/webrtc_key_value_config.h"
#include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h"
#include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h"
@ -44,7 +45,8 @@ class DelayBasedBwe {
};
explicit DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
RtcEventLog* event_log);
RtcEventLog* event_log,
NetworkStatePredictor* network_state_predictor);
virtual ~DelayBasedBwe();
Result IncomingPacketFeedbackVector(
@ -88,6 +90,7 @@ class DelayBasedBwe {
DataRate prev_bitrate_;
BandwidthUsage prev_state_;
bool alr_limited_backoff_enabled_;
NetworkStatePredictor* network_state_predictor_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DelayBasedBwe);
};

View File

@ -155,7 +155,8 @@ DelayBasedBweTest::DelayBasedBweTest()
absl::make_unique<AcknowledgedBitrateEstimator>(
&field_trial_config_)),
probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
bitrate_estimator_(new DelayBasedBwe(&field_trial_config_, nullptr)),
bitrate_estimator_(
new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),
stream_generator_(new test::StreamGenerator(1e6, // Capacity.
clock_.TimeInMicroseconds())),
arrival_time_offset_ms_(0),
@ -169,7 +170,8 @@ DelayBasedBweTest::DelayBasedBweTest(const std::string& field_trial_string)
absl::make_unique<AcknowledgedBitrateEstimator>(
&field_trial_config_)),
probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
bitrate_estimator_(new DelayBasedBwe(&field_trial_config_, nullptr)),
bitrate_estimator_(
new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),
stream_generator_(new test::StreamGenerator(1e6, // Capacity.
clock_.TimeInMicroseconds())),
arrival_time_offset_ms_(0),

View File

@ -26,7 +26,9 @@ class DelayIncreaseDetectorInterface {
// between timestamp groups as defined by the InterArrival class.
virtual void Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms) = 0;
int64_t send_time_ms,
int64_t arrival_time_ms,
bool calculated_deltas) = 0;
virtual BandwidthUsage State() const = 0;

View File

@ -17,6 +17,7 @@
#include <memory>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
#include "absl/memory/memory.h"
@ -77,9 +78,11 @@ bool IsNotDisabled(const WebRtcKeyValueConfig* config, absl::string_view key) {
}
} // namespace
GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
NetworkControllerConfig config,
bool feedback_only)
GoogCcNetworkController::GoogCcNetworkController(
RtcEventLog* event_log,
NetworkControllerConfig config,
bool feedback_only,
std::unique_ptr<NetworkStatePredictor> network_state_predictor)
: key_value_config_(config.key_value_config ? config.key_value_config
: &trial_based_config_),
event_log_(event_log),
@ -104,7 +107,9 @@ GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
absl::make_unique<SendSideBandwidthEstimation>(event_log_)),
alr_detector_(absl::make_unique<AlrDetector>()),
probe_bitrate_estimator_(new ProbeBitrateEstimator(event_log)),
delay_based_bwe_(new DelayBasedBwe(key_value_config_, event_log_)),
delay_based_bwe_(new DelayBasedBwe(key_value_config_,
event_log_,
network_state_predictor.get())),
acknowledged_bitrate_estimator_(
absl::make_unique<AcknowledgedBitrateEstimator>(key_value_config_)),
initial_config_(config),
@ -117,7 +122,8 @@ GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
DataRate::Zero())),
max_padding_rate_(config.stream_based_config.max_padding_rate.value_or(
DataRate::Zero())),
max_total_allocated_bitrate_(DataRate::Zero()) {
max_total_allocated_bitrate_(DataRate::Zero()),
network_state_predictor_(std::move(network_state_predictor)) {
RTC_DCHECK(config.constraints.at_time.IsFinite());
ParseFieldTrial(
{&safe_reset_on_route_change_, &safe_reset_acknowledged_rate_},
@ -164,7 +170,8 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
acknowledged_bitrate_estimator_.reset(
new AcknowledgedBitrateEstimator(key_value_config_));
probe_bitrate_estimator_.reset(new ProbeBitrateEstimator(event_log_));
delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_));
delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_,
network_state_predictor_.get()));
bandwidth_estimation_->OnRouteChange();
probe_controller_->Reset(msg.at_time.ms());
NetworkControlUpdate update;

View File

@ -17,6 +17,7 @@
#include <vector>
#include "absl/types/optional.h"
#include "api/network_state_predictor.h"
#include "api/transport/field_trial_based_config.h"
#include "api/transport/network_control.h"
#include "api/transport/network_types.h"
@ -40,9 +41,11 @@ namespace webrtc {
class GoogCcNetworkController : public NetworkControllerInterface {
public:
GoogCcNetworkController(RtcEventLog* event_log,
NetworkControllerConfig config,
bool feedback_only);
GoogCcNetworkController(
RtcEventLog* event_log,
NetworkControllerConfig config,
bool feedback_only,
std::unique_ptr<NetworkStatePredictor> network_state_predictor);
~GoogCcNetworkController() override;
// NetworkControllerInterface
@ -121,6 +124,8 @@ class GoogCcNetworkController : public NetworkControllerInterface {
absl::optional<DataSize> current_data_window_;
std::unique_ptr<NetworkStatePredictor> network_state_predictor_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GoogCcNetworkController);
};

View File

@ -110,7 +110,7 @@ void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") {
class GoogCcNetworkControllerTest : public ::testing::Test {
protected:
GoogCcNetworkControllerTest()
: current_time_(Timestamp::ms(123456)), factory_(&event_log_) {}
: current_time_(Timestamp::ms(123456)), factory_(&event_log_, nullptr) {}
~GoogCcNetworkControllerTest() override {}
void SetUp() override {

View File

@ -60,7 +60,7 @@ NetworkControlUpdate GoogCcStatePrinter::GetState(Timestamp at_time) const {
GoogCcDebugFactory::GoogCcDebugFactory(RtcEventLog* event_log,
GoogCcStatePrinter* printer)
: GoogCcNetworkControllerFactory(event_log), printer_(printer) {}
: GoogCcNetworkControllerFactory(event_log, nullptr), printer_(printer) {}
std::unique_ptr<NetworkControllerInterface> GoogCcDebugFactory::Create(
NetworkControllerConfig config) {

View File

@ -15,6 +15,7 @@
#include <algorithm>
#include "absl/types/optional.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"
@ -53,9 +54,11 @@ constexpr int kDeltaCounterMax = 1000;
} // namespace
TrendlineEstimator::TrendlineEstimator(size_t window_size,
double smoothing_coef,
double threshold_gain)
TrendlineEstimator::TrendlineEstimator(
size_t window_size,
double smoothing_coef,
double threshold_gain,
NetworkStatePredictor* network_state_predictor)
: window_size_(window_size),
smoothing_coef_(smoothing_coef),
threshold_gain_(threshold_gain),
@ -73,51 +76,61 @@ TrendlineEstimator::TrendlineEstimator(size_t window_size,
prev_trend_(0.0),
time_over_using_(-1),
overuse_counter_(0),
hypothesis_(BandwidthUsage::kBwNormal) {}
hypothesis_(BandwidthUsage::kBwNormal),
hypothesis_predicted_(BandwidthUsage::kBwNormal),
network_state_predictor_(network_state_predictor) {}
TrendlineEstimator::~TrendlineEstimator() {}
void TrendlineEstimator::Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms) {
const double delta_ms = recv_delta_ms - send_delta_ms;
++num_of_deltas_;
num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax);
if (first_arrival_time_ms_ == -1)
first_arrival_time_ms_ = arrival_time_ms;
int64_t send_time_ms,
int64_t arrival_time_ms,
bool calculated_deltas) {
if (calculated_deltas) {
const double delta_ms = recv_delta_ms - send_delta_ms;
++num_of_deltas_;
num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax);
if (first_arrival_time_ms_ == -1)
first_arrival_time_ms_ = arrival_time_ms;
// Exponential backoff filter.
accumulated_delay_ += delta_ms;
BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
accumulated_delay_);
smoothed_delay_ = smoothing_coef_ * smoothed_delay_ +
(1 - smoothing_coef_) * accumulated_delay_;
BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms,
smoothed_delay_);
// Exponential backoff filter.
accumulated_delay_ += delta_ms;
BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
accumulated_delay_);
smoothed_delay_ = smoothing_coef_ * smoothed_delay_ +
(1 - smoothing_coef_) * accumulated_delay_;
BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms,
smoothed_delay_);
// Simple linear regression.
delay_hist_.push_back(std::make_pair(
static_cast<double>(arrival_time_ms - first_arrival_time_ms_),
smoothed_delay_));
if (delay_hist_.size() > window_size_)
delay_hist_.pop_front();
double trend = prev_trend_;
if (delay_hist_.size() == window_size_) {
// Update trend_ if it is possible to fit a line to the data. The delay
// trend can be seen as an estimate of (send_rate - capacity)/capacity.
// 0 < trend < 1 -> the delay increases, queues are filling up
// trend == 0 -> the delay does not change
// trend < 0 -> the delay decreases, queues are being emptied
trend = LinearFitSlope(delay_hist_).value_or(trend);
// Simple linear regression.
delay_hist_.push_back(std::make_pair(
static_cast<double>(arrival_time_ms - first_arrival_time_ms_),
smoothed_delay_));
if (delay_hist_.size() > window_size_)
delay_hist_.pop_front();
double trend = prev_trend_;
if (delay_hist_.size() == window_size_) {
// Update trend_ if it is possible to fit a line to the data. The delay
// trend can be seen as an estimate of (send_rate - capacity)/capacity.
// 0 < trend < 1 -> the delay increases, queues are filling up
// trend == 0 -> the delay does not change
// trend < 0 -> the delay decreases, queues are being emptied
trend = LinearFitSlope(delay_hist_).value_or(trend);
}
BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend);
Detect(trend, send_delta_ms, arrival_time_ms);
}
if (network_state_predictor_) {
hypothesis_predicted_ = network_state_predictor_->Update(
send_time_ms, arrival_time_ms, hypothesis_);
}
BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend);
Detect(trend, send_delta_ms, arrival_time_ms);
}
BandwidthUsage TrendlineEstimator::State() const {
return hypothesis_;
return network_state_predictor_ ? hypothesis_predicted_ : hypothesis_;
}
void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) {

View File

@ -15,6 +15,7 @@
#include <deque>
#include <utility>
#include "api/network_state_predictor.h"
#include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "rtc_base/constructor_magic.h"
@ -28,10 +29,12 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface {
// the trend line. |threshold_gain| is used to scale the trendline slope for
// comparison to the old threshold. Once the old estimator has been removed
// (or the thresholds been merged into the estimators), we can just set the
// threshold instead of setting a gain.
// threshold instead of setting a gain.|network_state_predictor| is used to
// bettter predict network state.
TrendlineEstimator(size_t window_size,
double smoothing_coef,
double threshold_gain);
double threshold_gain,
NetworkStatePredictor* network_state_predictor);
~TrendlineEstimator() override;
@ -39,7 +42,9 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface {
// between timestamp groups as defined by the InterArrival class.
void Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms) override;
int64_t send_time_ms,
int64_t arrival_time_ms,
bool calculated_deltas) override;
BandwidthUsage State() const override;
@ -78,6 +83,8 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface {
double time_over_using_;
int overuse_counter_;
BandwidthUsage hypothesis_;
BandwidthUsage hypothesis_predicted_;
NetworkStatePredictor* network_state_predictor_;
RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator);
};

View File

@ -26,7 +26,7 @@ class TrendlineEstimatorForTest : public TrendlineEstimator {
using TrendlineEstimator::modified_trend;
};
void TestEstimator(double slope, double jitter_stddev, double tolerance) {
TrendlineEstimatorForTest estimator(kWindowSize, kSmoothing, kGain);
TrendlineEstimatorForTest estimator(kWindowSize, kSmoothing, kGain, nullptr);
Random random(0x1234567);
int64_t send_times[kPacketCount];
int64_t recv_times[kPacketCount];
@ -41,7 +41,7 @@ void TestEstimator(double slope, double jitter_stddev, double tolerance) {
for (size_t i = 1; i < kPacketCount; ++i) {
double recv_delta = recv_times[i] - recv_times[i - 1];
double send_delta = send_times[i] - send_times[i - 1];
estimator.Update(recv_delta, send_delta, recv_times[i]);
estimator.Update(recv_delta, send_delta, 0, recv_times[i], true);
if (i < kWindowSize)
EXPECT_NEAR(estimator.modified_trend(), 0, 0.001);
else