Implement periodic bandwidth probing in application-limited region.
Now ProbeController can send periodic bandwidth probes when in application-limited region. This will allow to maintain correct bottleneck bandwidth estimate, even not all bandwidth is being used. The feature is not enabled by default, but can be enabled with a flag. Interval between probes is currently set to 5 seconds. BUG=webrtc:6332 Review-Url: https://codereview.webrtc.org/2504023002 Cr-Commit-Position: refs/heads/master@{#15279}
This commit is contained in:
parent
bf22be902e
commit
80ed35e21c
@ -129,6 +129,9 @@ struct MediaConfig {
|
|||||||
// VideoReceiveStream, where the value is passed on to the
|
// VideoReceiveStream, where the value is passed on to the
|
||||||
// IncomingVideoStream constructor.
|
// IncomingVideoStream constructor.
|
||||||
bool disable_prerenderer_smoothing = false;
|
bool disable_prerenderer_smoothing = false;
|
||||||
|
|
||||||
|
// Enables periodic bandwidth probing in application-limited region.
|
||||||
|
bool periodic_alr_bandwidth_probing = false;
|
||||||
} video;
|
} video;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1102,6 +1102,8 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
|
|||||||
|
|
||||||
webrtc::VideoSendStream::Config config(this);
|
webrtc::VideoSendStream::Config config(this);
|
||||||
config.suspend_below_min_bitrate = video_config_.suspend_below_min_bitrate;
|
config.suspend_below_min_bitrate = video_config_.suspend_below_min_bitrate;
|
||||||
|
config.periodic_alr_bandwidth_probing =
|
||||||
|
video_config_.periodic_alr_bandwidth_probing;
|
||||||
WebRtcVideoSendStream* stream = new WebRtcVideoSendStream(
|
WebRtcVideoSendStream* stream = new WebRtcVideoSendStream(
|
||||||
call_, sp, std::move(config), default_send_options_,
|
call_, sp, std::move(config), default_send_options_,
|
||||||
external_encoder_factory_, video_config_.enable_cpu_overuse_detection,
|
external_encoder_factory_, video_config_.enable_cpu_overuse_detection,
|
||||||
|
|||||||
@ -275,6 +275,10 @@ RateLimiter* CongestionController::GetRetransmissionRateLimiter() {
|
|||||||
return retransmission_rate_limiter_.get();
|
return retransmission_rate_limiter_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CongestionController::EnablePeriodicAlrProbing(bool enable) {
|
||||||
|
probe_controller_->EnablePeriodicAlrProbing(enable);
|
||||||
|
}
|
||||||
|
|
||||||
void CongestionController::SetAllocatedSendBitrateLimits(
|
void CongestionController::SetAllocatedSendBitrateLimits(
|
||||||
int min_send_bitrate_bps,
|
int min_send_bitrate_bps,
|
||||||
int max_padding_bitrate_bps) {
|
int max_padding_bitrate_bps) {
|
||||||
@ -319,6 +323,7 @@ int64_t CongestionController::TimeUntilNextProcess() {
|
|||||||
void CongestionController::Process() {
|
void CongestionController::Process() {
|
||||||
bitrate_controller_->Process();
|
bitrate_controller_->Process();
|
||||||
remote_bitrate_estimator_->Process();
|
remote_bitrate_estimator_->Process();
|
||||||
|
probe_controller_->Process();
|
||||||
MaybeTriggerOnNetworkChanged();
|
MaybeTriggerOnNetworkChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -82,6 +82,7 @@ class CongestionController : public CallStatsObserver, public Module {
|
|||||||
virtual PacketRouter* packet_router() { return packet_router_.get(); }
|
virtual PacketRouter* packet_router() { return packet_router_.get(); }
|
||||||
virtual TransportFeedbackObserver* GetTransportFeedbackObserver();
|
virtual TransportFeedbackObserver* GetTransportFeedbackObserver();
|
||||||
RateLimiter* GetRetransmissionRateLimiter();
|
RateLimiter* GetRetransmissionRateLimiter();
|
||||||
|
void EnablePeriodicAlrProbing(bool enable);
|
||||||
|
|
||||||
// SetAllocatedSendBitrateLimits sets bitrates limits imposed by send codec
|
// SetAllocatedSendBitrateLimits sets bitrates limits imposed by send codec
|
||||||
// settings.
|
// settings.
|
||||||
|
|||||||
@ -38,8 +38,14 @@ constexpr int kExponentialProbingDisabled = 0;
|
|||||||
constexpr int kDefaultMaxProbingBitrateBps = 100000000;
|
constexpr int kDefaultMaxProbingBitrateBps = 100000000;
|
||||||
|
|
||||||
// This is a limit on how often probing can be done when there is a BW
|
// This is a limit on how often probing can be done when there is a BW
|
||||||
// drop detected in ALR region.
|
// drop detected in ALR.
|
||||||
constexpr int kAlrProbingIntervalLimitMs = 5000;
|
constexpr int64_t kAlrProbingIntervalMinMs = 5000;
|
||||||
|
|
||||||
|
// Interval between probes when ALR periodic probing is enabled.
|
||||||
|
constexpr int64_t kAlrPeriodicProbingIntervalMs = 5000;
|
||||||
|
|
||||||
|
// Minimum probe bitrate percentage to probe further for repeated probes.
|
||||||
|
constexpr int kRepeatedProbeMinPercentage = 125;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -53,7 +59,8 @@ ProbeController::ProbeController(PacedSender* pacer, Clock* clock)
|
|||||||
estimated_bitrate_bps_(0),
|
estimated_bitrate_bps_(0),
|
||||||
start_bitrate_bps_(0),
|
start_bitrate_bps_(0),
|
||||||
max_bitrate_bps_(0),
|
max_bitrate_bps_(0),
|
||||||
last_alr_probing_time_(clock_->TimeInMilliseconds()) {}
|
last_alr_probing_time_(clock_->TimeInMilliseconds()),
|
||||||
|
enable_periodic_alr_probing_(false) {}
|
||||||
|
|
||||||
void ProbeController::SetBitrates(int min_bitrate_bps,
|
void ProbeController::SetBitrates(int min_bitrate_bps,
|
||||||
int start_bitrate_bps,
|
int start_bitrate_bps,
|
||||||
@ -83,7 +90,8 @@ void ProbeController::SetBitrates(int min_bitrate_bps,
|
|||||||
if (estimated_bitrate_bps_ != 0 &&
|
if (estimated_bitrate_bps_ != 0 &&
|
||||||
estimated_bitrate_bps_ < old_max_bitrate_bps &&
|
estimated_bitrate_bps_ < old_max_bitrate_bps &&
|
||||||
max_bitrate_bps_ > old_max_bitrate_bps) {
|
max_bitrate_bps_ > old_max_bitrate_bps) {
|
||||||
InitiateProbing({max_bitrate_bps}, kExponentialProbingDisabled);
|
InitiateProbing(clock_->TimeInMilliseconds(), {max_bitrate_bps},
|
||||||
|
kExponentialProbingDisabled);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -103,14 +111,17 @@ void ProbeController::InitiateExponentialProbing() {
|
|||||||
|
|
||||||
// When probing at 1.8 Mbps ( 6x 300), this represents a threshold of
|
// When probing at 1.8 Mbps ( 6x 300), this represents a threshold of
|
||||||
// 1.2 Mbps to continue probing.
|
// 1.2 Mbps to continue probing.
|
||||||
InitiateProbing({3 * start_bitrate_bps_, 6 * start_bitrate_bps_},
|
InitiateProbing(clock_->TimeInMilliseconds(),
|
||||||
|
{3 * start_bitrate_bps_, 6 * start_bitrate_bps_},
|
||||||
4 * start_bitrate_bps_);
|
4 * start_bitrate_bps_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProbeController::SetEstimatedBitrate(int bitrate_bps) {
|
void ProbeController::SetEstimatedBitrate(int bitrate_bps) {
|
||||||
rtc::CritScope cs(&critsect_);
|
rtc::CritScope cs(&critsect_);
|
||||||
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
|
|
||||||
if (state_ == State::kWaitingForProbingResult) {
|
if (state_ == State::kWaitingForProbingResult) {
|
||||||
if ((clock_->TimeInMilliseconds() - time_last_probing_initiated_ms_) >
|
if ((now_ms - time_last_probing_initiated_ms_) >
|
||||||
kMaxWaitingTimeForProbingResultMs) {
|
kMaxWaitingTimeForProbingResultMs) {
|
||||||
LOG(LS_INFO) << "kWaitingForProbingResult: timeout";
|
LOG(LS_INFO) << "kWaitingForProbingResult: timeout";
|
||||||
state_ = State::kProbingComplete;
|
state_ = State::kProbingComplete;
|
||||||
@ -125,38 +136,73 @@ void ProbeController::SetEstimatedBitrate(int bitrate_bps) {
|
|||||||
bitrate_bps > min_bitrate_to_probe_further_bps_) {
|
bitrate_bps > min_bitrate_to_probe_further_bps_) {
|
||||||
// Double the probing bitrate and expect a minimum of 25% gain to
|
// Double the probing bitrate and expect a minimum of 25% gain to
|
||||||
// continue probing.
|
// continue probing.
|
||||||
InitiateProbing({2 * bitrate_bps}, 1.25 * bitrate_bps);
|
InitiateProbing(now_ms, {2 * bitrate_bps},
|
||||||
}
|
bitrate_bps * kRepeatedProbeMinPercentage / 100);
|
||||||
}
|
} else {
|
||||||
} else {
|
// Stop exponential probing.
|
||||||
// A drop in estimated BW when operating in ALR and not already probing.
|
state_ = State::kProbingComplete;
|
||||||
// The current response is to initiate a single probe session at the
|
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
|
||||||
// previous bitrate and immediately use the reported bitrate as the new
|
|
||||||
// bitrate.
|
|
||||||
//
|
|
||||||
// If the probe session fails, the assumption is that this drop was a
|
|
||||||
// real one from a competing flow or something else on the network and
|
|
||||||
// it ramps up from bitrate_bps.
|
|
||||||
if (pacer_->InApplicationLimitedRegion() &&
|
|
||||||
bitrate_bps < 0.5 * estimated_bitrate_bps_) {
|
|
||||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
||||||
if ((now_ms - last_alr_probing_time_) > kAlrProbingIntervalLimitMs) {
|
|
||||||
LOG(LS_INFO) << "Detected big BW drop in ALR, start probe.";
|
|
||||||
// Track how often we probe in response to BW drop in ALR.
|
|
||||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.AlrProbingIntervalInS",
|
|
||||||
(now_ms - last_alr_probing_time_) / 1000);
|
|
||||||
InitiateProbing({estimated_bitrate_bps_}, kExponentialProbingDisabled);
|
|
||||||
last_alr_probing_time_ = now_ms;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect a drop in estimated BW when operating in ALR and not already
|
||||||
|
// probing. The current response is to initiate a single probe session at the
|
||||||
|
// previous bitrate and immediately use the reported bitrate as the new
|
||||||
|
// bitrate.
|
||||||
|
//
|
||||||
|
// If the probe session fails, the assumption is that this drop was a
|
||||||
|
// real one from a competing flow or something else on the network and
|
||||||
|
// it ramps up from bitrate_bps.
|
||||||
|
if (state_ == State::kProbingComplete &&
|
||||||
|
pacer_->GetApplicationLimitedRegionStartTime() &&
|
||||||
|
bitrate_bps < estimated_bitrate_bps_ / 2 &&
|
||||||
|
(now_ms - last_alr_probing_time_) > kAlrProbingIntervalMinMs) {
|
||||||
|
LOG(LS_INFO) << "Detected big BW drop in ALR, start probe.";
|
||||||
|
// Track how often we probe in response to BW drop in ALR.
|
||||||
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.AlrProbingIntervalInS",
|
||||||
|
(now_ms - last_alr_probing_time_) / 1000);
|
||||||
|
InitiateProbing(now_ms, {estimated_bitrate_bps_},
|
||||||
|
kExponentialProbingDisabled);
|
||||||
|
last_alr_probing_time_ = now_ms;
|
||||||
|
|
||||||
// TODO(isheriff): May want to track when we did ALR probing in order
|
// TODO(isheriff): May want to track when we did ALR probing in order
|
||||||
// to reset |last_alr_probing_time_| if we validate that it was a
|
// to reset |last_alr_probing_time_| if we validate that it was a
|
||||||
// drop due to exogenous event.
|
// drop due to exogenous event.
|
||||||
}
|
}
|
||||||
|
|
||||||
estimated_bitrate_bps_ = bitrate_bps;
|
estimated_bitrate_bps_ = bitrate_bps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProbeController::EnablePeriodicAlrProbing(bool enable) {
|
||||||
|
rtc::CritScope cs(&critsect_);
|
||||||
|
enable_periodic_alr_probing_ = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeController::Process() {
|
||||||
|
rtc::CritScope cs(&critsect_);
|
||||||
|
|
||||||
|
if (state_ != State::kProbingComplete || !enable_periodic_alr_probing_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Probe bandwidth periodically when in ALR state.
|
||||||
|
rtc::Optional<int64_t> alr_start_time =
|
||||||
|
pacer_->GetApplicationLimitedRegionStartTime();
|
||||||
|
if (alr_start_time) {
|
||||||
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
|
int64_t next_probe_time_ms =
|
||||||
|
std::max(*alr_start_time, time_last_probing_initiated_ms_) +
|
||||||
|
kAlrPeriodicProbingIntervalMs;
|
||||||
|
if (now_ms >= next_probe_time_ms) {
|
||||||
|
InitiateProbing(
|
||||||
|
now_ms, {estimated_bitrate_bps_ * 2},
|
||||||
|
estimated_bitrate_bps_ * kRepeatedProbeMinPercentage / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProbeController::InitiateProbing(
|
void ProbeController::InitiateProbing(
|
||||||
|
int64_t now_ms,
|
||||||
std::initializer_list<int> bitrates_to_probe,
|
std::initializer_list<int> bitrates_to_probe,
|
||||||
int min_bitrate_to_probe_further_bps) {
|
int min_bitrate_to_probe_further_bps) {
|
||||||
bool first_cluster = true;
|
bool first_cluster = true;
|
||||||
@ -172,7 +218,7 @@ void ProbeController::InitiateProbing(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
min_bitrate_to_probe_further_bps_ = min_bitrate_to_probe_further_bps;
|
min_bitrate_to_probe_further_bps_ = min_bitrate_to_probe_further_bps;
|
||||||
time_last_probing_initiated_ms_ = clock_->TimeInMilliseconds();
|
time_last_probing_initiated_ms_ = now_ms;
|
||||||
if (min_bitrate_to_probe_further_bps == kExponentialProbingDisabled)
|
if (min_bitrate_to_probe_further_bps == kExponentialProbingDisabled)
|
||||||
state_ = State::kProbingComplete;
|
state_ = State::kProbingComplete;
|
||||||
else
|
else
|
||||||
|
|||||||
@ -36,6 +36,9 @@ class ProbeController {
|
|||||||
|
|
||||||
void SetEstimatedBitrate(int bitrate_bps);
|
void SetEstimatedBitrate(int bitrate_bps);
|
||||||
|
|
||||||
|
void EnablePeriodicAlrProbing(bool enable);
|
||||||
|
void Process();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class State {
|
enum class State {
|
||||||
// Initial state where no probing has been triggered yet.
|
// Initial state where no probing has been triggered yet.
|
||||||
@ -47,7 +50,8 @@ class ProbeController {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void InitiateExponentialProbing() EXCLUSIVE_LOCKS_REQUIRED(critsect_);
|
void InitiateExponentialProbing() EXCLUSIVE_LOCKS_REQUIRED(critsect_);
|
||||||
void InitiateProbing(std::initializer_list<int> bitrates_to_probe,
|
void InitiateProbing(int64_t now_ms,
|
||||||
|
std::initializer_list<int> bitrates_to_probe,
|
||||||
int min_bitrate_to_probe_further_bps)
|
int min_bitrate_to_probe_further_bps)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(critsect_);
|
EXCLUSIVE_LOCKS_REQUIRED(critsect_);
|
||||||
|
|
||||||
@ -62,6 +66,7 @@ class ProbeController {
|
|||||||
int start_bitrate_bps_ GUARDED_BY(critsect_);
|
int start_bitrate_bps_ GUARDED_BY(critsect_);
|
||||||
int max_bitrate_bps_ GUARDED_BY(critsect_);
|
int max_bitrate_bps_ GUARDED_BY(critsect_);
|
||||||
int64_t last_alr_probing_time_ GUARDED_BY(critsect_);
|
int64_t last_alr_probing_time_ GUARDED_BY(critsect_);
|
||||||
|
bool enable_periodic_alr_probing_ GUARDED_BY(critsect_);
|
||||||
|
|
||||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ProbeController);
|
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ProbeController);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
using testing::_;
|
using testing::_;
|
||||||
using testing::AtLeast;
|
using testing::AtLeast;
|
||||||
using testing::NiceMock;
|
using testing::NiceMock;
|
||||||
|
using testing::Return;
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
@ -31,11 +32,13 @@ constexpr int kMaxBitrateBps = 10000;
|
|||||||
|
|
||||||
constexpr int kExponentialProbingTimeoutMs = 5000;
|
constexpr int kExponentialProbingTimeoutMs = 5000;
|
||||||
|
|
||||||
|
constexpr int kAlrProbeInterval = 5000;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class ProbeControllerTest : public ::testing::Test {
|
class ProbeControllerTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
ProbeControllerTest() : clock_(0) {
|
ProbeControllerTest() : clock_(100000000L) {
|
||||||
probe_controller_.reset(new ProbeController(&pacer_, &clock_));
|
probe_controller_.reset(new ProbeController(&pacer_, &clock_));
|
||||||
}
|
}
|
||||||
~ProbeControllerTest() override {}
|
~ProbeControllerTest() override {}
|
||||||
@ -79,8 +82,6 @@ TEST_F(ProbeControllerTest, TestExponentialProbing) {
|
|||||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||||
kMaxBitrateBps);
|
kMaxBitrateBps);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXPECT_CALL(pacer_, CreateProbeCluster(2 * 1800, _));
|
EXPECT_CALL(pacer_, CreateProbeCluster(2 * 1800, _));
|
||||||
probe_controller_->SetEstimatedBitrate(1800);
|
probe_controller_->SetEstimatedBitrate(1800);
|
||||||
}
|
}
|
||||||
@ -95,5 +96,59 @@ TEST_F(ProbeControllerTest, TestExponentialProbingTimeout) {
|
|||||||
probe_controller_->SetEstimatedBitrate(1800);
|
probe_controller_->SetEstimatedBitrate(1800);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ProbeControllerTest, ProbeAfterEstimateDropInAlr) {
|
||||||
|
EXPECT_CALL(pacer_, CreateProbeCluster(_, _)).Times(2);
|
||||||
|
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||||
|
kMaxBitrateBps);
|
||||||
|
probe_controller_->SetEstimatedBitrate(500);
|
||||||
|
testing::Mock::VerifyAndClearExpectations(&pacer_);
|
||||||
|
|
||||||
|
// When bandwidth estimate drops the controller should send a probe at the
|
||||||
|
// previous bitrate.
|
||||||
|
EXPECT_CALL(pacer_, CreateProbeCluster(500, _)).Times(1);
|
||||||
|
EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime())
|
||||||
|
.WillRepeatedly(
|
||||||
|
Return(rtc::Optional<int64_t>(clock_.TimeInMilliseconds())));
|
||||||
|
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
|
||||||
|
probe_controller_->SetEstimatedBitrate(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProbeControllerTest, PeriodicProbing) {
|
||||||
|
EXPECT_CALL(pacer_, CreateProbeCluster(_, _)).Times(2);
|
||||||
|
probe_controller_->EnablePeriodicAlrProbing(true);
|
||||||
|
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||||
|
kMaxBitrateBps);
|
||||||
|
probe_controller_->SetEstimatedBitrate(500);
|
||||||
|
testing::Mock::VerifyAndClearExpectations(&pacer_);
|
||||||
|
|
||||||
|
int64_t start_time = clock_.TimeInMilliseconds();
|
||||||
|
|
||||||
|
// Expect the controller to send a new probe after 5s has passed.
|
||||||
|
EXPECT_CALL(pacer_, CreateProbeCluster(1000, _)).Times(1);
|
||||||
|
EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime())
|
||||||
|
.WillRepeatedly(Return(rtc::Optional<int64_t>(start_time)));
|
||||||
|
clock_.AdvanceTimeMilliseconds(5000);
|
||||||
|
probe_controller_->Process();
|
||||||
|
probe_controller_->SetEstimatedBitrate(500);
|
||||||
|
testing::Mock::VerifyAndClearExpectations(&pacer_);
|
||||||
|
|
||||||
|
// The following probe should be sent at 10s into ALR.
|
||||||
|
EXPECT_CALL(pacer_, CreateProbeCluster(_, _)).Times(0);
|
||||||
|
EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime())
|
||||||
|
.WillRepeatedly(Return(rtc::Optional<int64_t>(start_time)));
|
||||||
|
clock_.AdvanceTimeMilliseconds(4000);
|
||||||
|
probe_controller_->Process();
|
||||||
|
probe_controller_->SetEstimatedBitrate(500);
|
||||||
|
testing::Mock::VerifyAndClearExpectations(&pacer_);
|
||||||
|
|
||||||
|
EXPECT_CALL(pacer_, CreateProbeCluster(_, _)).Times(1);
|
||||||
|
EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime())
|
||||||
|
.WillRepeatedly(Return(rtc::Optional<int64_t>(start_time)));
|
||||||
|
clock_.AdvanceTimeMilliseconds(1000);
|
||||||
|
probe_controller_->Process();
|
||||||
|
probe_controller_->SetEstimatedBitrate(500);
|
||||||
|
testing::Mock::VerifyAndClearExpectations(&pacer_);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -44,10 +44,10 @@ void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t now_ms) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
int percentage = static_cast<int>(*rate) * 100 / estimated_bitrate_bps_;
|
int percentage = static_cast<int>(*rate) * 100 / estimated_bitrate_bps_;
|
||||||
if (percentage < kAlrStartUsagePercent && !application_limited_) {
|
if (percentage < kAlrStartUsagePercent && !alr_started_time_ms_) {
|
||||||
application_limited_ = true;
|
alr_started_time_ms_ = rtc::Optional<int64_t>(now_ms);
|
||||||
} else if (percentage > kAlrEndUsagePercent && application_limited_) {
|
} else if (percentage > kAlrEndUsagePercent && alr_started_time_ms_) {
|
||||||
application_limited_ = false;
|
alr_started_time_ms_ = rtc::Optional<int64_t>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +56,9 @@ void AlrDetector::SetEstimatedBitrate(int bitrate_bps) {
|
|||||||
estimated_bitrate_bps_ = bitrate_bps;
|
estimated_bitrate_bps_ = bitrate_bps;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AlrDetector::InApplicationLimitedRegion() const {
|
rtc::Optional<int64_t> AlrDetector::GetApplicationLimitedRegionStartTime()
|
||||||
return application_limited_;
|
const {
|
||||||
|
return alr_started_time_ms_;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -35,13 +35,16 @@ class AlrDetector {
|
|||||||
// Set current estimated bandwidth.
|
// Set current estimated bandwidth.
|
||||||
void SetEstimatedBitrate(int bitrate_bps);
|
void SetEstimatedBitrate(int bitrate_bps);
|
||||||
|
|
||||||
// Returns true if currently in application-limited region.
|
// Returns time in milliseconds when the current application-limited region
|
||||||
bool InApplicationLimitedRegion() const;
|
// started or empty result if the sender is currently not application-limited.
|
||||||
|
rtc::Optional<int64_t> GetApplicationLimitedRegionStartTime() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RateStatistics rate_;
|
RateStatistics rate_;
|
||||||
int estimated_bitrate_bps_ = 0;
|
int estimated_bitrate_bps_ = 0;
|
||||||
bool application_limited_ = false;
|
|
||||||
|
// Non-empty in ALR state.
|
||||||
|
rtc::Optional<int64_t> alr_started_time_ms_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -51,61 +51,61 @@ class AlrDetectorTest : public testing::Test {
|
|||||||
|
|
||||||
TEST_F(AlrDetectorTest, AlrDetection) {
|
TEST_F(AlrDetectorTest, AlrDetection) {
|
||||||
// Start in non-ALR state.
|
// Start in non-ALR state.
|
||||||
EXPECT_FALSE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// Stay in non-ALR state when usage is close to 100%.
|
// Stay in non-ALR state when usage is close to 100%.
|
||||||
SimulateOutgoingTraffic(500, 90);
|
SimulateOutgoingTraffic(500, 90);
|
||||||
EXPECT_FALSE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// Verify that we ALR starts when bitrate drops below 20%.
|
// Verify that we ALR starts when bitrate drops below 20%.
|
||||||
SimulateOutgoingTraffic(500, 20);
|
SimulateOutgoingTraffic(500, 20);
|
||||||
EXPECT_TRUE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// Verify that we remain in ALR state while usage is still below 50%.
|
// Verify that we remain in ALR state while usage is still below 50%.
|
||||||
SimulateOutgoingTraffic(500, 40);
|
SimulateOutgoingTraffic(500, 40);
|
||||||
EXPECT_TRUE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// Verify that ALR ends when usage is above 50%.
|
// Verify that ALR ends when usage is above 50%.
|
||||||
SimulateOutgoingTraffic(500, 60);
|
SimulateOutgoingTraffic(500, 60);
|
||||||
EXPECT_FALSE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AlrDetectorTest, ShortSpike) {
|
TEST_F(AlrDetectorTest, ShortSpike) {
|
||||||
// Start in non-ALR state.
|
// Start in non-ALR state.
|
||||||
EXPECT_FALSE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// Verify that we ALR starts when bitrate drops below 20%.
|
// Verify that we ALR starts when bitrate drops below 20%.
|
||||||
SimulateOutgoingTraffic(500, 20);
|
SimulateOutgoingTraffic(500, 20);
|
||||||
EXPECT_TRUE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// Verify that we stay in ALR region even after a short bitrate spike.
|
// Verify that we stay in ALR region even after a short bitrate spike.
|
||||||
SimulateOutgoingTraffic(100, 150);
|
SimulateOutgoingTraffic(100, 150);
|
||||||
EXPECT_TRUE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
SimulateOutgoingTraffic(200, 20);
|
SimulateOutgoingTraffic(200, 20);
|
||||||
EXPECT_TRUE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// ALR ends when usage is above 50%.
|
// ALR ends when usage is above 50%.
|
||||||
SimulateOutgoingTraffic(500, 60);
|
SimulateOutgoingTraffic(500, 60);
|
||||||
EXPECT_FALSE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AlrDetectorTest, BandwidthEstimateChanges) {
|
TEST_F(AlrDetectorTest, BandwidthEstimateChanges) {
|
||||||
// Start in non-ALR state.
|
// Start in non-ALR state.
|
||||||
EXPECT_FALSE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// ALR starts when bitrate drops below 20%.
|
// ALR starts when bitrate drops below 20%.
|
||||||
SimulateOutgoingTraffic(500, 20);
|
SimulateOutgoingTraffic(500, 20);
|
||||||
EXPECT_TRUE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
|
|
||||||
// When bandwidth estimate drops the detector should stay in ALR mode and quit
|
// When bandwidth estimate drops the detector should stay in ALR mode and quit
|
||||||
// it shortly afterwards as the sender continues sending the same amount of
|
// it shortly afterwards as the sender continues sending the same amount of
|
||||||
// traffic. This is necessary to ensure that ProbeController can still react
|
// traffic. This is necessary to ensure that ProbeController can still react
|
||||||
// to the BWE drop by initiating a new probe.
|
// to the BWE drop by initiating a new probe.
|
||||||
alr_detector_.SetEstimatedBitrate(kEstimatedBitrateBps / 5);
|
alr_detector_.SetEstimatedBitrate(kEstimatedBitrateBps / 5);
|
||||||
EXPECT_TRUE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
SimulateOutgoingTraffic(10, 20);
|
SimulateOutgoingTraffic(10, 20);
|
||||||
EXPECT_FALSE(alr_detector_.InApplicationLimitedRegion());
|
EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -33,6 +33,8 @@ class MockPacedSender : public PacedSender {
|
|||||||
MOCK_CONST_METHOD0(QueueInMs, int64_t());
|
MOCK_CONST_METHOD0(QueueInMs, int64_t());
|
||||||
MOCK_CONST_METHOD0(QueueInPackets, int());
|
MOCK_CONST_METHOD0(QueueInPackets, int());
|
||||||
MOCK_CONST_METHOD0(ExpectedQueueTimeMs, int64_t());
|
MOCK_CONST_METHOD0(ExpectedQueueTimeMs, int64_t());
|
||||||
|
MOCK_CONST_METHOD0(GetApplicationLimitedRegionStartTime,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -343,9 +343,10 @@ int64_t PacedSender::ExpectedQueueTimeMs() const {
|
|||||||
pacing_bitrate_kbps_);
|
pacing_bitrate_kbps_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PacedSender::InApplicationLimitedRegion() const {
|
rtc::Optional<int64_t> PacedSender::GetApplicationLimitedRegionStartTime()
|
||||||
|
const {
|
||||||
CriticalSectionScoped cs(critsect_.get());
|
CriticalSectionScoped cs(critsect_.get());
|
||||||
return alr_detector_->InApplicationLimitedRegion();
|
return alr_detector_->GetApplicationLimitedRegionStartTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PacedSender::QueueSizePackets() const {
|
size_t PacedSender::QueueSizePackets() const {
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include "webrtc/base/optional.h"
|
||||||
#include "webrtc/base/thread_annotations.h"
|
#include "webrtc/base/thread_annotations.h"
|
||||||
#include "webrtc/modules/include/module.h"
|
#include "webrtc/modules/include/module.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
@ -120,12 +121,13 @@ class PacedSender : public Module, public RtpPacketSender {
|
|||||||
// packets in the queue, given the current size and bitrate, ignoring prio.
|
// packets in the queue, given the current size and bitrate, ignoring prio.
|
||||||
virtual int64_t ExpectedQueueTimeMs() const;
|
virtual int64_t ExpectedQueueTimeMs() const;
|
||||||
|
|
||||||
// Application Limited Region refers to operating in a state where the
|
// Returns time in milliseconds when the current application-limited region
|
||||||
|
// started or empty result if the sender is currently not application-limited.
|
||||||
|
//
|
||||||
|
// Application Limited Region (ALR) refers to operating in a state where the
|
||||||
// traffic on network is limited due to application not having enough
|
// traffic on network is limited due to application not having enough
|
||||||
// traffic to meet the current channel capacity.
|
// traffic to meet the current channel capacity.
|
||||||
//
|
virtual rtc::Optional<int64_t> GetApplicationLimitedRegionStartTime() const;
|
||||||
// Returns true if network is currently application-limited.
|
|
||||||
bool InApplicationLimitedRegion() const;
|
|
||||||
|
|
||||||
// Returns the average time since being enqueued, in milliseconds, for all
|
// Returns the average time since being enqueued, in milliseconds, for all
|
||||||
// packets currently in the pacer queue, or 0 if queue is empty.
|
// packets currently in the pacer queue, or 0 if queue is empty.
|
||||||
|
|||||||
@ -748,6 +748,9 @@ VideoSendStreamImpl::VideoSendStreamImpl(
|
|||||||
RTC_DCHECK(congestion_controller_);
|
RTC_DCHECK(congestion_controller_);
|
||||||
RTC_DCHECK(remb_);
|
RTC_DCHECK(remb_);
|
||||||
|
|
||||||
|
congestion_controller_->EnablePeriodicAlrProbing(
|
||||||
|
config_->periodic_alr_bandwidth_probing);
|
||||||
|
|
||||||
// RTP/RTCP initialization.
|
// RTP/RTCP initialization.
|
||||||
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
||||||
congestion_controller_->packet_router()->AddRtpModule(rtp_rtcp);
|
congestion_controller_->packet_router()->AddRtpModule(rtp_rtcp);
|
||||||
|
|||||||
@ -185,6 +185,9 @@ class VideoSendStream {
|
|||||||
// stream may send at a rate higher than the estimated available bitrate.
|
// stream may send at a rate higher than the estimated available bitrate.
|
||||||
bool suspend_below_min_bitrate = false;
|
bool suspend_below_min_bitrate = false;
|
||||||
|
|
||||||
|
// Enables periodic bandwidth probing in application-limited region.
|
||||||
|
bool periodic_alr_bandwidth_probing = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Access to the copy constructor is private to force use of the Copy()
|
// Access to the copy constructor is private to force use of the Copy()
|
||||||
// method for those exceptional cases where we do use it.
|
// method for those exceptional cases where we do use it.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user