Probing: Add support for exponential startup probing
Adds support for exponentially probing the bandwidth at start-up to allow
ramp-up to real capacity of the network.
BUG=webrtc:6332
R=philipel@webrtc.org, stefan@webrtc.org
Review URL: https://codereview.webrtc.org/2235373004 .
Cr-Commit-Position: refs/heads/master@{#14189}
diff --git a/webrtc/modules/BUILD.gn b/webrtc/modules/BUILD.gn
index f997e1e..0c8befc 100644
--- a/webrtc/modules/BUILD.gn
+++ b/webrtc/modules/BUILD.gn
@@ -351,6 +351,7 @@
"congestion_controller/delay_based_bwe_unittest_helper.cc",
"congestion_controller/delay_based_bwe_unittest_helper.h",
"congestion_controller/probe_bitrate_estimator_unittest.cc",
+ "congestion_controller/probe_controller_unittest.cc",
"media_file/media_file_unittest.cc",
"module_common_types_unittest.cc",
"pacing/bitrate_prober_unittest.cc",
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
index 1231c78..e94baa7 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
@@ -31,7 +31,7 @@
}
// Received RTCP REMB or TMMBR.
void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
- owner_->OnReceivedEstimatedBitrate(bitrate);
+ owner_->OnReceiverEstimatedBitrate(bitrate);
}
// Received RTCP receiver block.
void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
@@ -173,7 +173,8 @@
MaybeTriggerOnNetworkChanged();
}
-void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
+// This is called upon reception of REMB or TMMBR.
+void BitrateControllerImpl::OnReceiverEstimatedBitrate(uint32_t bitrate) {
{
rtc::CritScope cs(&critsect_);
bandwidth_estimation_.UpdateReceiverEstimate(clock_->TimeInMilliseconds(),
@@ -182,7 +183,7 @@
MaybeTriggerOnNetworkChanged();
}
-void BitrateControllerImpl::UpdateProbeBitrate(uint32_t bitrate_bps) {
+void BitrateControllerImpl::OnProbeBitrate(uint32_t bitrate_bps) {
{
rtc::CritScope cs(&critsect_);
bandwidth_estimation_.SetSendBitrate(bitrate_bps);
@@ -190,7 +191,10 @@
MaybeTriggerOnNetworkChanged();
}
-void BitrateControllerImpl::UpdateDelayBasedEstimate(uint32_t bitrate_bps) {
+// TODO(isheriff): Perhaps need new interface for invocation from DelayBasedBwe.
+void BitrateControllerImpl::OnReceiveBitrateChanged(
+ const std::vector<uint32_t>& ssrcs,
+ uint32_t bitrate_bps) {
{
rtc::CritScope cs(&critsect_);
bandwidth_estimation_.UpdateDelayBasedEstimate(clock_->TimeInMilliseconds(),
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
index e5f595d..c8bb102 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
@@ -19,6 +19,7 @@
#include <list>
#include <utility>
+#include <vector>
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/criticalsection.h"
@@ -52,7 +53,6 @@
int min_bitrate_bps,
int max_bitrate_bps) override;
- void UpdateDelayBasedEstimate(uint32_t bitrate_bps) override;
void SetReservedBitrate(uint32_t reserved_bitrate_bps) override;
@@ -61,7 +61,10 @@
uint8_t* fraction_loss,
int64_t* rtt) override;
- void UpdateProbeBitrate(uint32_t bitrate_bps) override;
+ // RemoteBitrateObserver overrides.
+ void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
+ uint32_t bitrate_bps) override;
+ void OnProbeBitrate(uint32_t bitrate_bps) override;
int64_t TimeUntilNextProcess() override;
void Process() override;
@@ -70,7 +73,7 @@
class RtcpBandwidthObserverImpl;
// Called by BitrateObserver's direct from the RTCP module.
- void OnReceivedEstimatedBitrate(uint32_t bitrate);
+ void OnReceiverEstimatedBitrate(uint32_t bitrate);
void OnReceivedRtcpReceiverReport(uint8_t fraction_loss,
int64_t rtt,
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
index a70eecf..bfc44ea 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
@@ -170,7 +170,7 @@
EXPECT_EQ(300000, bitrate_observer_.last_bitrate_);
// Test that a low delay-based estimate limits the combined estimate.
- controller_->UpdateDelayBasedEstimate(280000);
+ controller_->OnReceiveBitrateChanged({0}, 280000);
EXPECT_EQ(280000, bitrate_observer_.last_bitrate_);
// Test that a low REMB limits the combined estimate.
diff --git a/webrtc/modules/bitrate_controller/include/bitrate_controller.h b/webrtc/modules/bitrate_controller/include/bitrate_controller.h
index 4c4578a..90b6471 100644
--- a/webrtc/modules/bitrate_controller/include/bitrate_controller.h
+++ b/webrtc/modules/bitrate_controller/include/bitrate_controller.h
@@ -19,6 +19,7 @@
#include "webrtc/modules/include/module.h"
#include "webrtc/modules/pacing/paced_sender.h"
+#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
namespace webrtc {
@@ -43,7 +44,7 @@
virtual ~BitrateObserver() {}
};
-class BitrateController : public Module {
+class BitrateController : public Module, public RemoteBitrateObserver {
// This class collects feedback from all streams sent to a peer (via
// RTCPBandwidthObservers). It does one aggregated send side bandwidth
// estimation and divide the available bitrate between all its registered
@@ -77,10 +78,6 @@
int min_bitrate_bps,
int max_bitrate_bps) = 0;
- virtual void UpdateDelayBasedEstimate(uint32_t bitrate_bps) = 0;
-
- virtual void UpdateProbeBitrate(uint32_t bitrate_bps) = 0;
-
// Gets the available payload bandwidth in bits per second. Note that
// this bandwidth excludes packet headers.
virtual bool AvailableBandwidth(uint32_t* bandwidth) const = 0;
diff --git a/webrtc/modules/congestion_controller/BUILD.gn b/webrtc/modules/congestion_controller/BUILD.gn
index a05f25b..a07acc5 100644
--- a/webrtc/modules/congestion_controller/BUILD.gn
+++ b/webrtc/modules/congestion_controller/BUILD.gn
@@ -16,6 +16,8 @@
"include/congestion_controller.h",
"probe_bitrate_estimator.cc",
"probe_bitrate_estimator.h",
+ "probe_controller.cc",
+ "probe_controller.h",
]
# TODO(jschuh): Bug 1348: fix this warning.
diff --git a/webrtc/modules/congestion_controller/congestion_controller.cc b/webrtc/modules/congestion_controller/congestion_controller.cc
index ae11d93..c0ec3da 100644
--- a/webrtc/modules/congestion_controller/congestion_controller.cc
+++ b/webrtc/modules/congestion_controller/congestion_controller.cc
@@ -22,6 +22,7 @@
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/congestion_controller/delay_based_bwe.h"
+#include "webrtc/modules/congestion_controller/probe_controller.h"
#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
@@ -166,13 +167,13 @@
new WrappingBitrateEstimator(remote_bitrate_observer, clock_)),
bitrate_controller_(
BitrateController::CreateBitrateController(clock_, event_log)),
+ probe_controller_(new ProbeController(pacer_.get(), clock_)),
retransmission_rate_limiter_(
new RateLimiter(clock, kRetransmitWindowSizeMs)),
remote_estimator_proxy_(clock_, packet_router_.get()),
- transport_feedback_adapter_(bitrate_controller_.get(), clock_),
+ transport_feedback_adapter_(clock_),
min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps),
max_bitrate_bps_(0),
- initial_probing_triggered_(false),
last_reported_bitrate_bps_(0),
last_reported_fraction_loss_(0),
last_reported_rtt_(0),
@@ -197,13 +198,13 @@
// construction.
bitrate_controller_(
BitrateController::CreateBitrateController(clock_, event_log)),
+ probe_controller_(new ProbeController(pacer_.get(), clock_)),
retransmission_rate_limiter_(
new RateLimiter(clock, kRetransmitWindowSizeMs)),
remote_estimator_proxy_(clock_, packet_router_.get()),
- transport_feedback_adapter_(bitrate_controller_.get(), clock_),
+ transport_feedback_adapter_(clock_),
min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps),
max_bitrate_bps_(0),
- initial_probing_triggered_(false),
last_reported_bitrate_bps_(0),
last_reported_fraction_loss_(0),
last_reported_rtt_(0),
@@ -215,7 +216,7 @@
void CongestionController::Init() {
transport_feedback_adapter_.SetBitrateEstimator(
- new DelayBasedBwe(&transport_feedback_adapter_, clock_));
+ new DelayBasedBwe(bitrate_controller_.get(), clock_));
transport_feedback_adapter_.GetBitrateEstimator()->SetMinBitrate(
min_bitrate_bps_);
}
@@ -228,25 +229,8 @@
min_bitrate_bps,
max_bitrate_bps);
- {
- rtc::CritScope cs(&critsect_);
- if (!initial_probing_triggered_) {
- pacer_->CreateProbeCluster(start_bitrate_bps * 3, 6);
- pacer_->CreateProbeCluster(start_bitrate_bps * 6, 5);
- initial_probing_triggered_ = true;
- }
-
- // Only do probing if:
- // - we are mid-call, which we consider to be if
- // |last_reported_bitrate_bps_| != 0, and
- // - the current bitrate is lower than the new |max_bitrate_bps|, and
- // - we actually want to increase the |max_bitrate_bps_|.
- if (last_reported_bitrate_bps_ != 0 &&
- last_reported_bitrate_bps_ < static_cast<uint32_t>(max_bitrate_bps) &&
- max_bitrate_bps > max_bitrate_bps_) {
- pacer_->CreateProbeCluster(max_bitrate_bps, 5);
- }
- }
+ probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps,
+ max_bitrate_bps);
max_bitrate_bps_ = max_bitrate_bps;
if (remote_bitrate_estimator_)
@@ -272,8 +256,8 @@
if (remote_bitrate_estimator_)
remote_bitrate_estimator_->SetMinBitrate(min_bitrate_bps);
- RemoteBitrateEstimator* rbe = new DelayBasedBwe(
- &transport_feedback_adapter_, clock_);
+ RemoteBitrateEstimator* rbe =
+ new DelayBasedBwe(bitrate_controller_.get(), clock_);
transport_feedback_adapter_.SetBitrateEstimator(rbe);
rbe->SetMinBitrate(min_bitrate_bps);
// TODO(holmer): Trigger a new probe once mid-call probing is implemented.
@@ -361,6 +345,7 @@
&bitrate_bps, &fraction_loss, &rtt);
if (estimate_changed) {
pacer_->SetEstimatedBitrate(bitrate_bps);
+ probe_controller_->SetEstimatedBitrate(bitrate_bps);
retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
}
diff --git a/webrtc/modules/congestion_controller/congestion_controller.gypi b/webrtc/modules/congestion_controller/congestion_controller.gypi
index c7fdd04..5c7ddf2 100644
--- a/webrtc/modules/congestion_controller/congestion_controller.gypi
+++ b/webrtc/modules/congestion_controller/congestion_controller.gypi
@@ -23,6 +23,8 @@
'include/congestion_controller.h',
'probe_bitrate_estimator.cc',
'probe_bitrate_estimator.h',
+ 'probe_controller.cc',
+ 'probe_controller.h',
],
# TODO(jschuh): Bug 1348: fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
diff --git a/webrtc/modules/congestion_controller/congestion_controller_unittest.cc b/webrtc/modules/congestion_controller/congestion_controller_unittest.cc
index 53ccf3d..79cb2ed 100644
--- a/webrtc/modules/congestion_controller/congestion_controller_unittest.cc
+++ b/webrtc/modules/congestion_controller/congestion_controller_unittest.cc
@@ -12,6 +12,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/call/mock/mock_rtc_event_log.h"
#include "webrtc/modules/pacing/mock/mock_paced_sender.h"
+#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
#include "webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h"
#include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h"
diff --git a/webrtc/modules/congestion_controller/delay_based_bwe.cc b/webrtc/modules/congestion_controller/delay_based_bwe.cc
index bd9f3ee..b7a21be 100644
--- a/webrtc/modules/congestion_controller/delay_based_bwe.cc
+++ b/webrtc/modules/congestion_controller/delay_based_bwe.cc
@@ -18,6 +18,7 @@
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/thread_annotations.h"
+#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
#include "webrtc/modules/pacing/paced_sender.h"
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
@@ -46,7 +47,6 @@
estimator_(),
detector_(OverUseDetectorOptions()),
incoming_bitrate_(kBitrateWindowMs, 8000),
- first_packet_time_ms_(-1),
last_update_ms_(-1),
last_seen_packet_ms_(-1),
uma_recorded_(false) {
@@ -71,11 +71,8 @@
void DelayBasedBwe::IncomingPacketInfo(const PacketInfo& info) {
int64_t now_ms = clock_->TimeInMilliseconds();
- if (first_packet_time_ms_ == -1)
- first_packet_time_ms_ = now_ms;
-
incoming_bitrate_.Update(info.payload_size, info.arrival_time_ms);
- bool update_estimate = false;
+ bool delay_based_bwe_changed = false;
uint32_t target_bitrate_bps = 0;
{
rtc::CritScope lock(&crit_);
@@ -90,15 +87,6 @@
}
last_seen_packet_ms_ = now_ms;
- if (info.probe_cluster_id != PacketInfo::kNotAProbe) {
- int bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info);
- if (bps > 0) {
- remote_rate_.SetEstimate(bps, info.arrival_time_ms);
- observer_->OnProbeBitrate(bps);
- update_estimate = true;
- }
- }
-
uint32_t send_time_24bits =
static_cast<uint32_t>(((static_cast<uint64_t>(info.send_time_ms)
<< kAbsSendTimeFraction) +
@@ -121,41 +109,56 @@
estimator_->num_of_deltas(), info.arrival_time_ms);
}
- if (!update_estimate) {
- // Check if it's time for a periodic update or if we should update because
- // of an over-use.
- if (last_update_ms_ == -1 ||
- now_ms - last_update_ms_ > remote_rate_.GetFeedbackInterval()) {
- update_estimate = true;
- } else if (detector_.State() == kBwOverusing) {
- rtc::Optional<uint32_t> incoming_rate =
- incoming_bitrate_.Rate(info.arrival_time_ms);
- if (incoming_rate &&
- remote_rate_.TimeToReduceFurther(now_ms, *incoming_rate)) {
- update_estimate = true;
- }
- }
+ int probing_bps = 0;
+ if (info.probe_cluster_id != PacketInfo::kNotAProbe) {
+ probing_bps =
+ probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info);
}
- if (update_estimate) {
- // The first overuse should immediately trigger a new estimate.
- // We also have to update the estimate immediately if we are overusing
- // and the target bitrate is too high compared to what we are receiving.
- const RateControlInput input(detector_.State(),
- incoming_bitrate_.Rate(info.arrival_time_ms),
- estimator_->var_noise());
- remote_rate_.Update(&input, now_ms);
- target_bitrate_bps = remote_rate_.UpdateBandwidthEstimate(now_ms);
- update_estimate = remote_rate_.ValidEstimate();
+ // Currently overusing the bandwidth.
+ if (detector_.State() == kBwOverusing) {
+ rtc::Optional<uint32_t> incoming_rate =
+ incoming_bitrate_.Rate(info.arrival_time_ms);
+ if (incoming_rate &&
+ remote_rate_.TimeToReduceFurther(now_ms, *incoming_rate)) {
+ delay_based_bwe_changed =
+ UpdateEstimate(info.arrival_time_ms, now_ms, &target_bitrate_bps);
+ }
+ } else if (probing_bps > 0) {
+ // No overuse, but probing measured a bitrate.
+ remote_rate_.SetEstimate(probing_bps, info.arrival_time_ms);
+ observer_->OnProbeBitrate(probing_bps);
+ delay_based_bwe_changed =
+ UpdateEstimate(info.arrival_time_ms, now_ms, &target_bitrate_bps);
+ }
+ if (!delay_based_bwe_changed &&
+ (last_update_ms_ == -1 ||
+ now_ms - last_update_ms_ > remote_rate_.GetFeedbackInterval())) {
+ delay_based_bwe_changed =
+ UpdateEstimate(info.arrival_time_ms, now_ms, &target_bitrate_bps);
}
}
- if (update_estimate) {
+ if (delay_based_bwe_changed) {
last_update_ms_ = now_ms;
observer_->OnReceiveBitrateChanged({kFixedSsrc}, target_bitrate_bps);
}
}
+bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms,
+ int64_t now_ms,
+ uint32_t* target_bitrate_bps) {
+ // The first overuse should immediately trigger a new estimate.
+ // We also have to update the estimate immediately if we are overusing
+ // and the target bitrate is too high compared to what we are receiving.
+ const RateControlInput input(detector_.State(),
+ incoming_bitrate_.Rate(arrival_time_ms),
+ estimator_->var_noise());
+ remote_rate_.Update(&input, now_ms);
+ *target_bitrate_bps = remote_rate_.UpdateBandwidthEstimate(now_ms);
+ return remote_rate_.ValidEstimate();
+}
+
void DelayBasedBwe::Process() {}
int64_t DelayBasedBwe::TimeUntilNextProcess() {
diff --git a/webrtc/modules/congestion_controller/delay_based_bwe.h b/webrtc/modules/congestion_controller/delay_based_bwe.h
index 19410c6..3e0a014 100644
--- a/webrtc/modules/congestion_controller/delay_based_bwe.h
+++ b/webrtc/modules/congestion_controller/delay_based_bwe.h
@@ -57,6 +57,12 @@
private:
void IncomingPacketInfo(const PacketInfo& info);
+ // Updates the current remote rate estimate and returns true if a valid
+ // estimate exists.
+ bool UpdateEstimate(int64_t packet_arrival_time_ms,
+ int64_t now_ms,
+ uint32_t* target_bitrate_bps)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_);
rtc::ThreadChecker network_thread_;
Clock* const clock_;
@@ -65,7 +71,6 @@
std::unique_ptr<OveruseEstimator> estimator_;
OveruseDetector detector_;
RateStatistics incoming_bitrate_;
- int64_t first_packet_time_ms_;
int64_t last_update_ms_;
int64_t last_seen_packet_ms_;
bool uma_recorded_;
diff --git a/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.cc b/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.cc
index 0ed7816..3469251 100644
--- a/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.cc
+++ b/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.cc
@@ -152,9 +152,8 @@
: clock_(100000000),
bitrate_observer_(new test::TestBitrateObserver),
bitrate_estimator_(new DelayBasedBwe(bitrate_observer_.get(), &clock_)),
- stream_generator_(
- new test::StreamGenerator(1e6, // Capacity.
- clock_.TimeInMicroseconds())),
+ stream_generator_(new test::StreamGenerator(1e6, // Capacity.
+ clock_.TimeInMicroseconds())),
arrival_time_offset_ms_(0) {}
DelayBasedBweTest::~DelayBasedBweTest() {}
diff --git a/webrtc/modules/congestion_controller/include/congestion_controller.h b/webrtc/modules/congestion_controller/include/congestion_controller.h
index 57c2c64..862f2cd 100644
--- a/webrtc/modules/congestion_controller/include/congestion_controller.h
+++ b/webrtc/modules/congestion_controller/include/congestion_controller.h
@@ -30,6 +30,7 @@
class BitrateController;
class Clock;
+class ProbeController;
class ProcessThread;
class RateLimiter;
class RemoteBitrateEstimator;
@@ -120,12 +121,12 @@
const std::unique_ptr<PacedSender> pacer_;
const std::unique_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
const std::unique_ptr<BitrateController> bitrate_controller_;
+ const std::unique_ptr<ProbeController> probe_controller_;
const std::unique_ptr<RateLimiter> retransmission_rate_limiter_;
RemoteEstimatorProxy remote_estimator_proxy_;
TransportFeedbackAdapter transport_feedback_adapter_;
int min_bitrate_bps_;
int max_bitrate_bps_;
- bool initial_probing_triggered_;
rtc::CriticalSection critsect_;
uint32_t last_reported_bitrate_bps_ GUARDED_BY(critsect_);
uint8_t last_reported_fraction_loss_ GUARDED_BY(critsect_);
diff --git a/webrtc/modules/congestion_controller/probe_controller.cc b/webrtc/modules/congestion_controller/probe_controller.cc
new file mode 100644
index 0000000..cf7f3e1
--- /dev/null
+++ b/webrtc/modules/congestion_controller/probe_controller.cc
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016 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 "webrtc/modules/congestion_controller/probe_controller.h"
+
+#include <initializer_list>
+
+#include "webrtc/base/logging.h"
+
+namespace webrtc {
+
+namespace {
+
+// Number of deltas between probes per cluster. On the very first cluster,
+// we will need kProbeDeltasPerCluster + 1 probes, but on a cluster following
+// another, we need kProbeDeltasPerCluster probes.
+constexpr int kProbeDeltasPerCluster = 5;
+
+// Maximum waiting time from the time of initiating probing to getting
+// the measured results back.
+constexpr int64_t kMaxWaitingTimeForProbingResultMs = 1000;
+
+// Value of |min_bitrate_to_probe_further_bps_| that indicates
+// further probing is disabled.
+constexpr int kExponentialProbingDisabled = 0;
+
+} // namespace
+
+ProbeController::ProbeController(PacedSender* pacer, Clock* clock)
+ : pacer_(pacer),
+ clock_(clock),
+ state_(State::kInit),
+ min_bitrate_to_probe_further_bps_(kExponentialProbingDisabled),
+ time_last_probing_initiated_ms_(0),
+ estimated_bitrate_bps_(0),
+ max_bitrate_bps_(0) {}
+
+void ProbeController::SetBitrates(int min_bitrate_bps,
+ int start_bitrate_bps,
+ int max_bitrate_bps) {
+ rtc::CritScope cs(&critsect_);
+ if (state_ == State::kInit) {
+ // When probing at 1.8 Mbps ( 6x 300), this represents a threshold of
+ // 1.2 Mbps to continue probing.
+ InitiateProbing({3 * start_bitrate_bps, 6 * start_bitrate_bps},
+ 4 * start_bitrate_bps);
+ }
+
+ // Only do probing if:
+ // - we are mid-call, which we consider to be if
+ // |estimated_bitrate_bps_| != 0, and
+ // - the current bitrate is lower than the new |max_bitrate_bps|, and
+ // - we actually want to increase the |max_bitrate_bps_|.
+ if (estimated_bitrate_bps_ != 0 && estimated_bitrate_bps_ < max_bitrate_bps &&
+ max_bitrate_bps > max_bitrate_bps_) {
+ InitiateProbing({max_bitrate_bps}, kExponentialProbingDisabled);
+ }
+ max_bitrate_bps_ = max_bitrate_bps;
+}
+
+void ProbeController::SetEstimatedBitrate(int bitrate_bps) {
+ rtc::CritScope cs(&critsect_);
+ if (state_ == State::kWaitingForProbingResult) {
+ if ((clock_->TimeInMilliseconds() - time_last_probing_initiated_ms_) >
+ kMaxWaitingTimeForProbingResultMs) {
+ LOG(LS_INFO) << "kWaitingForProbingResult: timeout";
+ state_ = State::kProbingComplete;
+ min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
+ } else {
+ // Continue probing if probing results indicate channel has greater
+ // capacity.
+ LOG(LS_INFO) << "Measured bitrate: " << bitrate_bps
+ << " Minimum to probe further: "
+ << min_bitrate_to_probe_further_bps_;
+ if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled &&
+ bitrate_bps > min_bitrate_to_probe_further_bps_) {
+ // Double the probing bitrate and expect a minimum of 25% gain to
+ // continue probing.
+ InitiateProbing({2 * bitrate_bps}, 1.25 * bitrate_bps);
+ }
+ }
+ }
+ estimated_bitrate_bps_ = bitrate_bps;
+}
+
+void ProbeController::InitiateProbing(
+ std::initializer_list<int> bitrates_to_probe,
+ int min_bitrate_to_probe_further_bps) {
+ bool first_cluster = true;
+ for (int bitrate : bitrates_to_probe) {
+ if (first_cluster) {
+ pacer_->CreateProbeCluster(bitrate, kProbeDeltasPerCluster + 1);
+ first_cluster = false;
+ } else {
+ pacer_->CreateProbeCluster(bitrate, kProbeDeltasPerCluster);
+ }
+ }
+ min_bitrate_to_probe_further_bps_ = min_bitrate_to_probe_further_bps;
+ time_last_probing_initiated_ms_ = clock_->TimeInMilliseconds();
+ if (min_bitrate_to_probe_further_bps == kExponentialProbingDisabled)
+ state_ = State::kProbingComplete;
+ else
+ state_ = State::kWaitingForProbingResult;
+}
+
+} // namespace webrtc
diff --git a/webrtc/modules/congestion_controller/probe_controller.h b/webrtc/modules/congestion_controller/probe_controller.h
new file mode 100644
index 0000000..4cf34c3
--- /dev/null
+++ b/webrtc/modules/congestion_controller/probe_controller.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016 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 WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_
+#define WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_
+
+#include <initializer_list>
+
+#include "webrtc/base/criticalsection.h"
+#include "webrtc/common_types.h"
+#include "webrtc/modules/pacing/paced_sender.h"
+
+namespace webrtc {
+
+class Clock;
+
+// This class controls initiation of probing to estimate initial channel
+// capacity. There is also support for probing during a session when max
+// bitrate is adjusted by an application.
+class ProbeController {
+ public:
+ ProbeController(PacedSender* pacer, Clock* clock);
+
+ void SetBitrates(int min_bitrate_bps,
+ int start_bitrate_bps,
+ int max_bitrate_bps);
+ void SetEstimatedBitrate(int bitrate_bps);
+
+ private:
+ void InitiateProbing(std::initializer_list<int> bitrates_to_probe,
+ int min_bitrate_to_probe_further_bps)
+ EXCLUSIVE_LOCKS_REQUIRED(critsect_);
+ enum class State {
+ // Initial state where no probing has been triggered yet.
+ kInit,
+ // Waiting for probing results to continue further probing.
+ kWaitingForProbingResult,
+ // Probing is complete.
+ kProbingComplete,
+ };
+ rtc::CriticalSection critsect_;
+ PacedSender* const pacer_;
+ Clock* const clock_;
+ State state_ GUARDED_BY(critsect_);
+ int min_bitrate_to_probe_further_bps_ GUARDED_BY(critsect_);
+ int64_t time_last_probing_initiated_ms_ GUARDED_BY(critsect_);
+ int estimated_bitrate_bps_ GUARDED_BY(critsect_);
+ int max_bitrate_bps_ GUARDED_BY(critsect_);
+
+ RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ProbeController);
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_
diff --git a/webrtc/modules/congestion_controller/probe_controller_unittest.cc b/webrtc/modules/congestion_controller/probe_controller_unittest.cc
new file mode 100644
index 0000000..6932775
--- /dev/null
+++ b/webrtc/modules/congestion_controller/probe_controller_unittest.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 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 <memory>
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/modules/congestion_controller/probe_controller.h"
+#include "webrtc/modules/pacing/mock/mock_paced_sender.h"
+#include "webrtc/system_wrappers/include/clock.h"
+
+using testing::_;
+using testing::AtLeast;
+using testing::NiceMock;
+
+namespace webrtc {
+namespace test {
+
+namespace {
+
+constexpr int kMinBitrateBps = 100;
+constexpr int kStartBitrateBps = 300;
+constexpr int kMaxBitrateBps = 1000;
+
+} // namespace
+
+class ProbeControllerTest : public ::testing::Test {
+ protected:
+ ProbeControllerTest() : clock_(0) {
+ probe_controller_.reset(new ProbeController(&pacer_, &clock_));
+ }
+ ~ProbeControllerTest() override {}
+
+ SimulatedClock clock_;
+ NiceMock<MockPacedSender> pacer_;
+ std::unique_ptr<ProbeController> probe_controller_;
+};
+
+TEST_F(ProbeControllerTest, InitiatesProbingAtStart) {
+ EXPECT_CALL(pacer_, CreateProbeCluster(_, _)).Times(AtLeast(2));
+ probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
+ kMaxBitrateBps);
+}
+
+TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
+ EXPECT_CALL(pacer_, CreateProbeCluster(_, _)).Times(AtLeast(2));
+ probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
+ kMaxBitrateBps);
+ clock_.AdvanceTimeMilliseconds(25);
+
+ probe_controller_->SetEstimatedBitrate(kStartBitrateBps);
+ EXPECT_CALL(pacer_, CreateProbeCluster(kMaxBitrateBps + 100, _));
+ probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
+ kMaxBitrateBps + 100);
+}
+
+TEST_F(ProbeControllerTest, TestExponentialProbing) {
+ probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
+ kMaxBitrateBps);
+ EXPECT_CALL(pacer_, CreateProbeCluster(2 * 1800, _));
+ probe_controller_->SetEstimatedBitrate(1800);
+}
+
+TEST_F(ProbeControllerTest, TestExponentialProbingTimeout) {
+ probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
+ kMaxBitrateBps);
+
+ // Advance far enough to cause a time out in waiting for probing result.
+ clock_.AdvanceTimeMilliseconds(5000);
+ EXPECT_CALL(pacer_, CreateProbeCluster(2 * 1800, _)).Times(0);
+ probe_controller_->SetEstimatedBitrate(1800);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 2b552c0..68149b6 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -275,6 +275,7 @@
'congestion_controller/delay_based_bwe_unittest_helper.cc',
'congestion_controller/delay_based_bwe_unittest_helper.h',
'congestion_controller/probe_bitrate_estimator_unittest.cc',
+ 'congestion_controller/probe_controller_unittest.cc',
'media_file/media_file_unittest.cc',
'module_common_types_unittest.cc',
'pacing/bitrate_prober_unittest.cc',
diff --git a/webrtc/modules/pacing/bitrate_prober.cc b/webrtc/modules/pacing/bitrate_prober.cc
index e2cea73..936be39 100644
--- a/webrtc/modules/pacing/bitrate_prober.cc
+++ b/webrtc/modules/pacing/bitrate_prober.cc
@@ -66,6 +66,7 @@
}
void BitrateProber::CreateProbeCluster(int bitrate_bps, int num_packets) {
+ RTC_DCHECK(probing_state_ != ProbingState::kDisabled);
ProbeCluster cluster;
cluster.max_probe_packets = num_packets;
cluster.probe_bitrate_bps = bitrate_bps;
diff --git a/webrtc/modules/pacing/mock/mock_paced_sender.h b/webrtc/modules/pacing/mock/mock_paced_sender.h
index bd7d7aa..e429962 100644
--- a/webrtc/modules/pacing/mock/mock_paced_sender.h
+++ b/webrtc/modules/pacing/mock/mock_paced_sender.h
@@ -29,6 +29,7 @@
int64_t capture_time_ms,
size_t bytes,
bool retransmission));
+ MOCK_METHOD2(CreateProbeCluster, void(int, int));
MOCK_METHOD1(SetEstimatedBitrate, void(uint32_t));
MOCK_CONST_METHOD0(QueueInMs, int64_t());
MOCK_CONST_METHOD0(QueueInPackets, int());
diff --git a/webrtc/modules/pacing/paced_sender.h b/webrtc/modules/pacing/paced_sender.h
index cb9b849..f74a97a 100644
--- a/webrtc/modules/pacing/paced_sender.h
+++ b/webrtc/modules/pacing/paced_sender.h
@@ -71,7 +71,7 @@
virtual ~PacedSender();
- void CreateProbeCluster(int bitrate_bps, int num_packets);
+ virtual void CreateProbeCluster(int bitrate_bps, int num_packets);
// Temporarily pause all sending.
void Pause();
diff --git a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
index 738570c..dfeedfc 100644
--- a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
+++ b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
@@ -34,7 +34,6 @@
// incoming streams.
virtual void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
uint32_t bitrate) = 0;
-
virtual void OnProbeBitrate(uint32_t bitrate) {}
virtual ~RemoteBitrateObserver() {}
diff --git a/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.cc b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.cc
index d7067b3..66ef7f0 100644
--- a/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.cc
+++ b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.cc
@@ -39,10 +39,8 @@
};
TransportFeedbackAdapter::TransportFeedbackAdapter(
- BitrateController* bitrate_controller,
Clock* clock)
: send_time_history_(clock, kSendTimeHistoryWindowMs),
- bitrate_controller_(bitrate_controller),
clock_(clock),
current_offset_ms_(kNoTimestamp),
last_timestamp_us_(kNoTimestamp) {}
@@ -141,16 +139,6 @@
return last_packet_feedback_vector_;
}
-void TransportFeedbackAdapter::OnReceiveBitrateChanged(
- const std::vector<uint32_t>& ssrcs,
- uint32_t bitrate) {
- bitrate_controller_->UpdateDelayBasedEstimate(bitrate);
-}
-
-void TransportFeedbackAdapter::OnProbeBitrate(uint32_t bitrate) {
- bitrate_controller_->UpdateProbeBitrate(bitrate);
-}
-
void TransportFeedbackAdapter::OnRttUpdate(int64_t avg_rtt_ms,
int64_t max_rtt_ms) {
RTC_DCHECK(bitrate_estimator_.get() != nullptr);
diff --git a/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h
index 525dc71..2db6603 100644
--- a/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h
+++ b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h
@@ -16,7 +16,6 @@
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/thread_annotations.h"
-#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
@@ -24,13 +23,11 @@
namespace webrtc {
class ProcessThread;
-class RemoteBitrateEstimator;
class TransportFeedbackAdapter : public TransportFeedbackObserver,
- public CallStatsObserver,
- public RemoteBitrateObserver {
+ public CallStatsObserver {
public:
- TransportFeedbackAdapter(BitrateController* bitrate_controller, Clock* clock);
+ explicit TransportFeedbackAdapter(Clock* clock);
virtual ~TransportFeedbackAdapter();
void SetBitrateEstimator(RemoteBitrateEstimator* rbe);
@@ -51,18 +48,11 @@
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
private:
- // Implements RemoteBitrateObserver.
- void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
- uint32_t bitrate) override;
-
- void OnProbeBitrate(uint32_t bitrate) override;
-
std::vector<PacketInfo> GetPacketFeedbackVector(
const rtcp::TransportFeedback& feedback);
rtc::CriticalSection lock_;
SendTimeHistory send_time_history_ GUARDED_BY(&lock_);
- BitrateController* bitrate_controller_;
std::unique_ptr<RemoteBitrateEstimator> bitrate_estimator_;
Clock* const clock_;
int64_t current_offset_ms_;
diff --git a/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc
index f9ac8c9..2a60da7 100644
--- a/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc
+++ b/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter_unittest.cc
@@ -40,7 +40,7 @@
virtual ~TransportFeedbackAdapterTest() {}
virtual void SetUp() {
- adapter_.reset(new TransportFeedbackAdapter(&bitrate_controller_, &clock_));
+ adapter_.reset(new TransportFeedbackAdapter(&clock_));
bitrate_estimator_ = new MockRemoteBitrateEstimator();
adapter_->SetBitrateEstimator(bitrate_estimator_);
@@ -60,7 +60,8 @@
~MockBitrateControllerAdapter() override {}
- void UpdateDelayBasedEstimate(uint32_t bitrate_bps) override {
+ void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
+ uint32_t bitrate_bps) override {
owner_->receiver_estimated_bitrate_ = bitrate_bps;
}