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}
This commit is contained in:
parent
a421ddd60e
commit
b2540bb99f
@ -351,6 +351,7 @@ if (rtc_include_tests) {
|
||||
"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",
|
||||
|
||||
@ -31,7 +31,7 @@ class BitrateControllerImpl::RtcpBandwidthObserverImpl
|
||||
}
|
||||
// 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 @@ void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
|
||||
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 @@ void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
|
||||
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 @@ void BitrateControllerImpl::UpdateProbeBitrate(uint32_t bitrate_bps) {
|
||||
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(),
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
@ -52,7 +53,6 @@ class BitrateControllerImpl : public BitrateController {
|
||||
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 @@ class BitrateControllerImpl : public BitrateController {
|
||||
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 BitrateControllerImpl : public BitrateController {
|
||||
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,
|
||||
|
||||
@ -170,7 +170,7 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
||||
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.
|
||||
|
||||
@ -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 @@ class BitrateObserver {
|
||||
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 @@ class BitrateController : public Module {
|
||||
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;
|
||||
|
||||
@ -16,6 +16,8 @@ rtc_source_set("congestion_controller") {
|
||||
"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.
|
||||
|
||||
@ -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 @@ CongestionController::CongestionController(
|
||||
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 @@ CongestionController::CongestionController(
|
||||
// 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 @@ CongestionController::~CongestionController() {}
|
||||
|
||||
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 @@ void CongestionController::SetBweBitrates(int min_bitrate_bps,
|
||||
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 @@ void CongestionController::ResetBweAndBitrates(int bitrate_bps,
|
||||
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 @@ void CongestionController::MaybeTriggerOnNetworkChanged() {
|
||||
&bitrate_bps, &fraction_loss, &rtt);
|
||||
if (estimate_changed) {
|
||||
pacer_->SetEstimatedBitrate(bitrate_bps);
|
||||
probe_controller_->SetEstimatedBitrate(bitrate_bps);
|
||||
retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
|
||||
}
|
||||
|
||||
|
||||
@ -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, ],
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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 @@ DelayBasedBwe::DelayBasedBwe(RemoteBitrateObserver* observer, Clock* clock)
|
||||
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::IncomingPacketFeedbackVector(
|
||||
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 @@ void DelayBasedBwe::IncomingPacketInfo(const PacketInfo& info) {
|
||||
}
|
||||
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 @@ void DelayBasedBwe::IncomingPacketInfo(const PacketInfo& info) {
|
||||
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() {
|
||||
|
||||
@ -57,6 +57,12 @@ class DelayBasedBwe : public RemoteBitrateEstimator {
|
||||
|
||||
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 @@ class DelayBasedBwe : public RemoteBitrateEstimator {
|
||||
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_;
|
||||
|
||||
@ -152,9 +152,8 @@ DelayBasedBweTest::DelayBasedBweTest()
|
||||
: 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() {}
|
||||
|
||||
@ -30,6 +30,7 @@ namespace webrtc {
|
||||
|
||||
class BitrateController;
|
||||
class Clock;
|
||||
class ProbeController;
|
||||
class ProcessThread;
|
||||
class RateLimiter;
|
||||
class RemoteBitrateEstimator;
|
||||
@ -120,12 +121,12 @@ class CongestionController : public CallStatsObserver, public Module {
|
||||
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_);
|
||||
|
||||
113
webrtc/modules/congestion_controller/probe_controller.cc
Normal file
113
webrtc/modules/congestion_controller/probe_controller.cc
Normal file
@ -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
|
||||
62
webrtc/modules/congestion_controller/probe_controller.h
Normal file
62
webrtc/modules/congestion_controller/probe_controller.h
Normal file
@ -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_
|
||||
@ -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
|
||||
@ -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',
|
||||
|
||||
@ -66,6 +66,7 @@ void BitrateProber::OnIncomingPacket(size_t packet_size) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -29,6 +29,7 @@ class MockPacedSender : public PacedSender {
|
||||
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());
|
||||
|
||||
@ -71,7 +71,7 @@ class PacedSender : public Module, public RtpPacketSender {
|
||||
|
||||
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();
|
||||
|
||||
@ -34,7 +34,6 @@ class RemoteBitrateObserver {
|
||||
// incoming streams.
|
||||
virtual void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
|
||||
uint32_t bitrate) = 0;
|
||||
|
||||
virtual void OnProbeBitrate(uint32_t bitrate) {}
|
||||
|
||||
virtual ~RemoteBitrateObserver() {}
|
||||
|
||||
@ -39,10 +39,8 @@ class PacketInfoComparator {
|
||||
};
|
||||
|
||||
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 @@ std::vector<PacketInfo> TransportFeedbackAdapter::GetTransportFeedbackVector()
|
||||
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);
|
||||
|
||||
@ -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 @@ class TransportFeedbackAdapter : public TransportFeedbackObserver,
|
||||
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_;
|
||||
|
||||
@ -40,7 +40,7 @@ class TransportFeedbackAdapterTest : public ::testing::Test {
|
||||
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 @@ class TransportFeedbackAdapterTest : public ::testing::Test {
|
||||
|
||||
~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;
|
||||
}
|
||||
|
||||
|
||||
@ -1008,7 +1008,7 @@ void EventLogAnalyzer::CreateNetworkDelayFeedbackGraph(Plot* plot) {
|
||||
}
|
||||
|
||||
SimulatedClock clock(0);
|
||||
TransportFeedbackAdapter feedback_adapter(nullptr, &clock);
|
||||
TransportFeedbackAdapter feedback_adapter(&clock);
|
||||
|
||||
TimeSeries time_series;
|
||||
time_series.label = "Network Delay Change";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user