Refactor in BitrateController module.
- Move condition of 0 bps as max meaning 1gbps from SendSideBandwidthEstimation to BitrateController. - Remove condition on bitrate=0 meaning bandwidth estimation off as that could only happen when no observers existed and in which case the estimation would be ignored. - Add MaybeTriggerOnNetworkChanged which only runs rate allocation if any of the dependent variables has changed thus allowing to remove many of the bool returns that try to indicate if the estimation has changed which would not be aware if the observers have changed. - SendSideBandwidthEstimation now has a UpdateBitrate and has clear code paths to which calls update bitrate. - Changes in enforce_min_bitrate so the 10kbps min is set from the BitrateController and not from the outside this keep valid as observers are changed. R=henrik.lundin@webrtc.org, stefan@webrtc.org BUG=3065 Review URL: https://webrtc-codereview.appspot.com/10189004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5752 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
be7e26d229
commit
07bc734459
@ -132,22 +132,39 @@ void BitrateControllerImpl::SetBitrateObserver(
|
|||||||
// Add new settings.
|
// Add new settings.
|
||||||
bitrate_observers_.push_back(BitrateObserverConfiguration(observer,
|
bitrate_observers_.push_back(BitrateObserverConfiguration(observer,
|
||||||
new BitrateConfiguration(start_bitrate, min_bitrate, max_bitrate)));
|
new BitrateConfiguration(start_bitrate, min_bitrate, max_bitrate)));
|
||||||
|
bitrate_observers_modified_ = true;
|
||||||
|
|
||||||
|
// TODO(andresp): This is a ugly way to set start bitrate.
|
||||||
|
//
|
||||||
|
// Only change start bitrate if we have exactly one observer. By definition
|
||||||
|
// you can only have one start bitrate, once we have our first estimate we
|
||||||
|
// will adapt from there.
|
||||||
|
if (bitrate_observers_.size() == 1) {
|
||||||
|
bandwidth_estimation_.SetSendBitrate(start_bitrate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateMinMaxBitrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateControllerImpl::UpdateMinMaxBitrate() {
|
||||||
uint32_t sum_start_bitrate = 0;
|
uint32_t sum_start_bitrate = 0;
|
||||||
uint32_t sum_min_bitrate = 0;
|
uint32_t sum_min_bitrate = 0;
|
||||||
uint32_t sum_max_bitrate = 0;
|
uint32_t sum_max_bitrate = 0;
|
||||||
|
BitrateObserverConfList::iterator it;
|
||||||
// Summarize all configurations.
|
|
||||||
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
|
||||||
sum_start_bitrate += it->second->start_bitrate_;
|
sum_start_bitrate += it->second->start_bitrate_;
|
||||||
sum_min_bitrate += it->second->min_bitrate_;
|
sum_min_bitrate += it->second->min_bitrate_;
|
||||||
sum_max_bitrate += it->second->max_bitrate_;
|
sum_max_bitrate += it->second->max_bitrate_;
|
||||||
}
|
}
|
||||||
// Only change start bitrate if we have exactly one observer. By definition
|
if (sum_max_bitrate == 0) {
|
||||||
// you can only have one start bitrate, once we have our first estimate we
|
// No max configured use 1Gbit/s.
|
||||||
// will adapt from there.
|
sum_max_bitrate = 1000000000;
|
||||||
if (bitrate_observers_.size() == 1) {
|
}
|
||||||
bandwidth_estimation_.SetSendBitrate(sum_start_bitrate);
|
if (enforce_min_bitrate_ == false) {
|
||||||
|
// If not enforcing min bitrate, allow the bandwidth estimation to
|
||||||
|
// go as low as 10 kbps.
|
||||||
|
sum_min_bitrate = std::min(sum_min_bitrate, 10000u);
|
||||||
}
|
}
|
||||||
bandwidth_estimation_.SetMinMaxBitrate(sum_min_bitrate,
|
bandwidth_estimation_.SetMinMaxBitrate(sum_min_bitrate,
|
||||||
sum_max_bitrate);
|
sum_max_bitrate);
|
||||||
@ -160,30 +177,20 @@ void BitrateControllerImpl::RemoveBitrateObserver(BitrateObserver* observer) {
|
|||||||
if (it != bitrate_observers_.end()) {
|
if (it != bitrate_observers_.end()) {
|
||||||
delete it->second;
|
delete it->second;
|
||||||
bitrate_observers_.erase(it);
|
bitrate_observers_.erase(it);
|
||||||
|
bitrate_observers_modified_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitrateControllerImpl::EnforceMinBitrate(bool enforce_min_bitrate) {
|
void BitrateControllerImpl::EnforceMinBitrate(bool enforce_min_bitrate) {
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
enforce_min_bitrate_ = enforce_min_bitrate;
|
enforce_min_bitrate_ = enforce_min_bitrate;
|
||||||
}
|
UpdateMinMaxBitrate();
|
||||||
|
|
||||||
void BitrateControllerImpl::SetBweMinBitrate(uint32_t min_bitrate) {
|
|
||||||
CriticalSectionScoped cs(critsect_);
|
|
||||||
bandwidth_estimation_.SetMinBitrate(min_bitrate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) {
|
void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) {
|
||||||
uint32_t new_bitrate = 0;
|
|
||||||
uint8_t fraction_lost = 0;
|
|
||||||
uint16_t rtt = 0;
|
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
if (bandwidth_estimation_.UpdateBandwidthEstimate(bitrate,
|
bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
|
||||||
&new_bitrate,
|
MaybeTriggerOnNetworkChanged();
|
||||||
&fraction_lost,
|
|
||||||
&rtt)) {
|
|
||||||
OnNetworkChanged(new_bitrate, fraction_lost, rtt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
|
void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
|
||||||
@ -191,12 +198,27 @@ void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
|
|||||||
const uint32_t rtt,
|
const uint32_t rtt,
|
||||||
const int number_of_packets,
|
const int number_of_packets,
|
||||||
const uint32_t now_ms) {
|
const uint32_t now_ms) {
|
||||||
uint32_t new_bitrate = 0;
|
|
||||||
uint8_t loss = fraction_loss;
|
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
if (bandwidth_estimation_.UpdatePacketLoss(number_of_packets, rtt, now_ms,
|
bandwidth_estimation_.UpdateReceiverBlock(
|
||||||
&loss, &new_bitrate)) {
|
fraction_loss, rtt, number_of_packets, now_ms);
|
||||||
OnNetworkChanged(new_bitrate, loss, rtt);
|
MaybeTriggerOnNetworkChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() {
|
||||||
|
uint32_t bitrate;
|
||||||
|
uint8_t fraction_loss;
|
||||||
|
uint32_t rtt;
|
||||||
|
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
|
||||||
|
|
||||||
|
if (bitrate_observers_modified_ || bitrate != last_bitrate_ ||
|
||||||
|
fraction_loss != last_fraction_loss_ || rtt != last_rtt_ ||
|
||||||
|
last_enforce_min_bitrate_ != enforce_min_bitrate_) {
|
||||||
|
last_bitrate_ = bitrate;
|
||||||
|
last_fraction_loss_ = fraction_loss;
|
||||||
|
last_rtt_ = rtt;
|
||||||
|
last_enforce_min_bitrate_ = enforce_min_bitrate_;
|
||||||
|
bitrate_observers_modified_ = false;
|
||||||
|
OnNetworkChanged(bitrate, fraction_loss, rtt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +311,15 @@ void BitrateControllerImpl::LowRateAllocation(uint32_t bitrate,
|
|||||||
|
|
||||||
bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
|
bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
|
||||||
CriticalSectionScoped cs(critsect_);
|
CriticalSectionScoped cs(critsect_);
|
||||||
return bandwidth_estimation_.AvailableBandwidth(bandwidth);
|
uint32_t bitrate;
|
||||||
|
uint8_t fraction_loss;
|
||||||
|
uint32_t rtt;
|
||||||
|
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
|
||||||
|
if (bitrate) {
|
||||||
|
*bandwidth = bitrate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -45,8 +45,6 @@ class BitrateControllerImpl : public BitrateController {
|
|||||||
|
|
||||||
virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE;
|
virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE;
|
||||||
|
|
||||||
virtual void SetBweMinBitrate(uint32_t min_bitrate) OVERRIDE;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class RtcpBandwidthObserverImpl;
|
class RtcpBandwidthObserverImpl;
|
||||||
|
|
||||||
@ -75,6 +73,7 @@ class BitrateControllerImpl : public BitrateController {
|
|||||||
BitrateObserverConfiguration;
|
BitrateObserverConfiguration;
|
||||||
typedef std::list<BitrateObserverConfiguration> BitrateObserverConfList;
|
typedef std::list<BitrateObserverConfiguration> BitrateObserverConfList;
|
||||||
|
|
||||||
|
void UpdateMinMaxBitrate() EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
||||||
|
|
||||||
// Called by BitrateObserver's direct from the RTCP module.
|
// Called by BitrateObserver's direct from the RTCP module.
|
||||||
void OnReceivedEstimatedBitrate(const uint32_t bitrate);
|
void OnReceivedEstimatedBitrate(const uint32_t bitrate);
|
||||||
@ -84,6 +83,8 @@ class BitrateControllerImpl : public BitrateController {
|
|||||||
const int number_of_packets,
|
const int number_of_packets,
|
||||||
const uint32_t now_ms);
|
const uint32_t now_ms);
|
||||||
|
|
||||||
|
void MaybeTriggerOnNetworkChanged() EXCLUSIVE_LOCKS_REQUIRED(*critsect_);
|
||||||
|
|
||||||
void OnNetworkChanged(const uint32_t bitrate,
|
void OnNetworkChanged(const uint32_t bitrate,
|
||||||
const uint8_t fraction_loss, // 0 - 255.
|
const uint8_t fraction_loss, // 0 - 255.
|
||||||
const uint32_t rtt)
|
const uint32_t rtt)
|
||||||
@ -110,6 +111,11 @@ class BitrateControllerImpl : public BitrateController {
|
|||||||
SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(*critsect_);
|
SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(*critsect_);
|
||||||
BitrateObserverConfList bitrate_observers_ GUARDED_BY(*critsect_);
|
BitrateObserverConfList bitrate_observers_ GUARDED_BY(*critsect_);
|
||||||
bool enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
bool enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
||||||
|
uint32_t last_bitrate_ GUARDED_BY(*critsect_);
|
||||||
|
uint8_t last_fraction_loss_ GUARDED_BY(*critsect_);
|
||||||
|
uint32_t last_rtt_ GUARDED_BY(*critsect_);
|
||||||
|
bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_);
|
||||||
|
bool bitrate_observers_modified_ GUARDED_BY(*critsect_);
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_BITRATE_CONTROLLER_IMPL_H_
|
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_BITRATE_CONTROLLER_IMPL_H_
|
||||||
|
@ -92,9 +92,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
|
|||||||
webrtc::ReportBlockList report_blocks;
|
webrtc::ReportBlockList report_blocks;
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
||||||
EXPECT_EQ(0u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||||
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
EXPECT_EQ(50u, bitrate_observer.last_rtt_);
|
||||||
|
|
||||||
// Test bitrate increase 8% per second.
|
// Test bitrate increase 8% per second.
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
@ -161,9 +161,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {
|
|||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
||||||
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
second_bandwidth_observer->OnReceivedRtcpReceiverReport(
|
||||||
report_blocks, 100, 1);
|
report_blocks, 100, 1);
|
||||||
EXPECT_EQ(0u, bitrate_observer.last_bitrate_);
|
EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
|
||||||
EXPECT_EQ(0u, bitrate_observer.last_rtt_);
|
EXPECT_EQ(100u, bitrate_observer.last_rtt_);
|
||||||
|
|
||||||
// Test bitrate increase 8% per second.
|
// Test bitrate increase 8% per second.
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
@ -323,11 +323,6 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
|||||||
webrtc::ReportBlockList report_blocks;
|
webrtc::ReportBlockList report_blocks;
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
|
||||||
|
|
||||||
// Test bitrate increase 8% per second, distributed equally.
|
|
||||||
report_blocks.clear();
|
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001);
|
|
||||||
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_);
|
EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_);
|
||||||
EXPECT_EQ(50u, bitrate_observer_1.last_rtt_);
|
EXPECT_EQ(50u, bitrate_observer_1.last_rtt_);
|
||||||
@ -336,21 +331,22 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) {
|
|||||||
EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
|
EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
|
||||||
EXPECT_EQ(50u, bitrate_observer_2.last_rtt_);
|
EXPECT_EQ(50u, bitrate_observer_2.last_rtt_);
|
||||||
|
|
||||||
|
// Test bitrate increase 8% per second, distributed equally.
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001);
|
||||||
EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_);
|
EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_);
|
EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_);
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
|
||||||
EXPECT_EQ(126000u, bitrate_observer_1.last_bitrate_);
|
EXPECT_EQ(126000u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(226000u, bitrate_observer_2.last_bitrate_);
|
EXPECT_EQ(226000u, bitrate_observer_2.last_bitrate_);
|
||||||
|
|
||||||
report_blocks.clear();
|
report_blocks.clear();
|
||||||
report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
|
report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
|
||||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001);
|
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001);
|
||||||
EXPECT_EQ(140580u, bitrate_observer_1.last_bitrate_);
|
EXPECT_EQ(140580u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_);
|
EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_);
|
||||||
|
|
||||||
@ -434,8 +430,12 @@ TEST_F(BitrateControllerTestNoEnforceMin, OneBitrateObserver) {
|
|||||||
EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_);
|
EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
|
||||||
// Low REMB.
|
// Low REMB.
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(10000);
|
||||||
EXPECT_EQ(1000u, bitrate_observer_1.last_bitrate_);
|
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
|
||||||
|
// Keeps at least 10 kbps.
|
||||||
|
bandwidth_observer_->OnReceivedEstimatedBitrate(9000);
|
||||||
|
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
|
||||||
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
controller_->RemoveBitrateObserver(&bitrate_observer_1);
|
||||||
}
|
}
|
||||||
@ -469,9 +469,15 @@ TEST_F(BitrateControllerTestNoEnforceMin, ThreeBitrateObservers) {
|
|||||||
EXPECT_EQ(200000u, bitrate_observer_3.last_bitrate_); // Remainder.
|
EXPECT_EQ(200000u, bitrate_observer_3.last_bitrate_); // Remainder.
|
||||||
|
|
||||||
// Low REMB.
|
// Low REMB.
|
||||||
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
|
bandwidth_observer_->OnReceivedEstimatedBitrate(10000);
|
||||||
// Verify that the first observer gets all the rate, and the rest get zero.
|
// Verify that the first observer gets all the rate, and the rest get zero.
|
||||||
EXPECT_EQ(1000u, bitrate_observer_1.last_bitrate_);
|
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
||||||
|
EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_);
|
||||||
|
EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_);
|
||||||
|
|
||||||
|
// Verify it keeps an estimate of at least 10kbps.
|
||||||
|
bandwidth_observer_->OnReceivedEstimatedBitrate(9000);
|
||||||
|
EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_);
|
||||||
EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_);
|
EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_);
|
||||||
EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_);
|
EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_);
|
||||||
|
|
||||||
|
@ -73,10 +73,6 @@ class BitrateController {
|
|||||||
|
|
||||||
// Changes the mode that was set in the constructor.
|
// Changes the mode that was set in the constructor.
|
||||||
virtual void EnforceMinBitrate(bool enforce_min_bitrate) = 0;
|
virtual void EnforceMinBitrate(bool enforce_min_bitrate) = 0;
|
||||||
|
|
||||||
// Changes the minimum configured bitrate of the send-side bandwidth
|
|
||||||
// estimator.
|
|
||||||
virtual void SetBweMinBitrate(uint32_t min_bitrate) = 0;
|
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
#endif // WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_
|
||||||
|
@ -10,11 +10,41 @@
|
|||||||
|
|
||||||
#include "webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h"
|
#include "webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h"
|
||||||
|
|
||||||
#include <math.h> // sqrt()
|
#include <cmath>
|
||||||
|
|
||||||
#include "webrtc/system_wrappers/interface/trace.h"
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
enum { kBweIncreaseIntervalMs = 1000 };
|
||||||
|
enum { kBweDecreaseIntervalMs = 300 };
|
||||||
|
enum { kLimitNumPackets = 20 };
|
||||||
|
enum { kAvgPacketSizeBytes = 1000 };
|
||||||
|
|
||||||
|
// Calculate the rate that TCP-Friendly Rate Control (TFRC) would apply.
|
||||||
|
// The formula in RFC 3448, Section 3.1, is used.
|
||||||
|
uint32_t CalcTfrcBps(uint16_t rtt, uint8_t loss) {
|
||||||
|
if (rtt == 0 || loss == 0) {
|
||||||
|
// Input variables out of range.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
double R = static_cast<double>(rtt) / 1000; // RTT in seconds.
|
||||||
|
int b = 1; // Number of packets acknowledged by a single TCP acknowledgement:
|
||||||
|
// recommended = 1.
|
||||||
|
double t_RTO = 4.0 * R; // TCP retransmission timeout value in seconds
|
||||||
|
// recommended = 4*R.
|
||||||
|
double p = static_cast<double>(loss) / 255; // Packet loss rate in [0, 1).
|
||||||
|
double s = static_cast<double>(kAvgPacketSizeBytes);
|
||||||
|
|
||||||
|
// Calculate send rate in bytes/second.
|
||||||
|
double X =
|
||||||
|
s / (R * std::sqrt(2 * b * p / 3) +
|
||||||
|
(t_RTO * (3 * std::sqrt(3 * b * p / 8) * p * (1 + 32 * p * p))));
|
||||||
|
|
||||||
|
// Convert to bits/second.
|
||||||
|
return (static_cast<uint32_t>(X * 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SendSideBandwidthEstimation::SendSideBandwidthEstimation()
|
SendSideBandwidthEstimation::SendSideBandwidthEstimation()
|
||||||
: accumulate_lost_packets_Q8_(0),
|
: accumulate_lost_packets_Q8_(0),
|
||||||
@ -30,190 +60,121 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation()
|
|||||||
|
|
||||||
SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
|
SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
|
||||||
|
|
||||||
void SendSideBandwidthEstimation::SetSendBitrate(const uint32_t bitrate) {
|
void SendSideBandwidthEstimation::SetSendBitrate(uint32_t bitrate) {
|
||||||
bitrate_ = bitrate;
|
bitrate_ = bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSideBandwidthEstimation::SetMinMaxBitrate(const uint32_t min_bitrate,
|
void SendSideBandwidthEstimation::SetMinMaxBitrate(uint32_t min_bitrate,
|
||||||
const uint32_t max_bitrate) {
|
uint32_t max_bitrate) {
|
||||||
min_bitrate_configured_ = min_bitrate;
|
min_bitrate_configured_ = min_bitrate;
|
||||||
if (max_bitrate == 0) {
|
max_bitrate_configured_ = max_bitrate;
|
||||||
// no max configured use 1Gbit/s
|
|
||||||
max_bitrate_configured_ = 1000000000;
|
|
||||||
} else {
|
|
||||||
max_bitrate_configured_ = max_bitrate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSideBandwidthEstimation::SetMinBitrate(uint32_t min_bitrate) {
|
void SendSideBandwidthEstimation::SetMinBitrate(uint32_t min_bitrate) {
|
||||||
min_bitrate_configured_ = min_bitrate;
|
min_bitrate_configured_ = min_bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SendSideBandwidthEstimation::UpdateBandwidthEstimate(
|
void SendSideBandwidthEstimation::CurrentEstimate(uint32_t* bitrate,
|
||||||
const uint32_t bandwidth,
|
uint8_t* loss,
|
||||||
uint32_t* new_bitrate,
|
uint32_t* rtt) const {
|
||||||
uint8_t* fraction_lost,
|
*bitrate = bitrate_;
|
||||||
uint16_t* rtt) {
|
*loss = last_fraction_loss_;
|
||||||
*new_bitrate = 0;
|
*rtt = last_round_trip_time_;
|
||||||
bwe_incoming_ = bandwidth;
|
|
||||||
|
|
||||||
if (bitrate_ == 0) {
|
|
||||||
// SendSideBandwidthEstimation off
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) {
|
|
||||||
bitrate_ = bwe_incoming_;
|
|
||||||
*new_bitrate = bitrate_;
|
|
||||||
*fraction_lost = last_fraction_loss_;
|
|
||||||
*rtt = last_round_trip_time_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SendSideBandwidthEstimation::UpdatePacketLoss(
|
void SendSideBandwidthEstimation::UpdateReceiverEstimate(uint32_t bandwidth) {
|
||||||
const int number_of_packets,
|
bwe_incoming_ = bandwidth;
|
||||||
const uint32_t rtt,
|
CapBitrateToThresholds();
|
||||||
const uint32_t now_ms,
|
}
|
||||||
uint8_t* loss,
|
|
||||||
uint32_t* new_bitrate) {
|
void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
|
||||||
if (bitrate_ == 0) {
|
uint32_t rtt,
|
||||||
// SendSideBandwidthEstimation off
|
int number_of_packets,
|
||||||
return false;
|
uint32_t now_ms) {
|
||||||
}
|
|
||||||
// Update RTT.
|
// Update RTT.
|
||||||
last_round_trip_time_ = rtt;
|
last_round_trip_time_ = rtt;
|
||||||
|
|
||||||
// Check sequence number diff and weight loss report
|
// Check sequence number diff and weight loss report
|
||||||
if (number_of_packets > 0) {
|
if (number_of_packets > 0) {
|
||||||
// Calculate number of lost packets.
|
// Calculate number of lost packets.
|
||||||
const int num_lost_packets_Q8 = *loss * number_of_packets;
|
const int num_lost_packets_Q8 = fraction_loss * number_of_packets;
|
||||||
// Accumulate reports.
|
// Accumulate reports.
|
||||||
accumulate_lost_packets_Q8_ += num_lost_packets_Q8;
|
accumulate_lost_packets_Q8_ += num_lost_packets_Q8;
|
||||||
accumulate_expected_packets_ += number_of_packets;
|
accumulate_expected_packets_ += number_of_packets;
|
||||||
|
|
||||||
// Report loss if the total report is based on sufficiently many packets.
|
// Report loss if the total report is based on sufficiently many packets.
|
||||||
if (accumulate_expected_packets_ >= kLimitNumPackets) {
|
if (accumulate_expected_packets_ >= kLimitNumPackets) {
|
||||||
*loss = accumulate_lost_packets_Q8_ / accumulate_expected_packets_;
|
last_fraction_loss_ =
|
||||||
|
accumulate_lost_packets_Q8_ / accumulate_expected_packets_;
|
||||||
|
|
||||||
// Reset accumulators
|
// Reset accumulators.
|
||||||
accumulate_lost_packets_Q8_ = 0;
|
accumulate_lost_packets_Q8_ = 0;
|
||||||
accumulate_expected_packets_ = 0;
|
accumulate_expected_packets_ = 0;
|
||||||
} else {
|
} else {
|
||||||
// Report zero loss until we have enough data to estimate
|
// Early return without updating estimate.
|
||||||
// the loss rate.
|
return;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Keep for next time.
|
UpdateEstimate(now_ms);
|
||||||
last_fraction_loss_ = *loss;
|
|
||||||
uint32_t bitrate = 0;
|
|
||||||
if (!ShapeSimple(*loss, rtt, now_ms, &bitrate)) {
|
|
||||||
// No change.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bitrate_ = bitrate;
|
|
||||||
*new_bitrate = bitrate;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SendSideBandwidthEstimation::AvailableBandwidth(
|
void SendSideBandwidthEstimation::UpdateEstimate(uint32_t now_ms) {
|
||||||
uint32_t* bandwidth) const {
|
if (last_fraction_loss_ <= 5) {
|
||||||
if (bitrate_ == 0) {
|
// Loss < 2%: Limit the rate increases to once a kBweIncreaseIntervalMs.
|
||||||
return false;
|
if ((now_ms - time_last_increase_) >= kBweIncreaseIntervalMs) {
|
||||||
}
|
time_last_increase_ = now_ms;
|
||||||
*bandwidth = bitrate_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
// Increase rate by 8%.
|
||||||
* Calculate the rate that TCP-Friendly Rate Control (TFRC) would apply.
|
bitrate_ = static_cast<uint32_t>(bitrate_ * 1.08 + 0.5);
|
||||||
* The formula in RFC 3448, Section 3.1, is used.
|
|
||||||
*/
|
|
||||||
uint32_t SendSideBandwidthEstimation::CalcTFRCbps(uint16_t rtt, uint8_t loss) {
|
|
||||||
if (rtt == 0 || loss == 0) {
|
|
||||||
// input variables out of range
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
double R = static_cast<double>(rtt) / 1000; // RTT in seconds
|
|
||||||
int b = 1; // number of packets acknowledged by a single TCP acknowledgement;
|
|
||||||
// recommended = 1
|
|
||||||
double t_RTO = 4.0 * R; // TCP retransmission timeout value in seconds
|
|
||||||
// recommended = 4*R
|
|
||||||
double p = static_cast<double>(loss) / 255; // packet loss rate in [0, 1)
|
|
||||||
double s = static_cast<double>(kAvgPacketSizeBytes);
|
|
||||||
|
|
||||||
// calculate send rate in bytes/second
|
// Add 1 kbps extra, just to make sure that we do not get stuck
|
||||||
double X = s / (R * sqrt(2 * b * p / 3) +
|
// (gives a little extra increase at low rates, negligible at higher
|
||||||
(t_RTO * (3 * sqrt(3 * b * p / 8) * p * (1 + 32 * p * p))));
|
// rates).
|
||||||
|
bitrate_ += 1000;
|
||||||
return (static_cast<uint32_t>(X * 8)); // bits/second
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SendSideBandwidthEstimation::ShapeSimple(const uint8_t loss,
|
|
||||||
const uint32_t rtt,
|
|
||||||
const uint32_t now_ms,
|
|
||||||
uint32_t* bitrate) {
|
|
||||||
uint32_t new_bitrate = 0;
|
|
||||||
|
|
||||||
// Limit the rate increases to once a kBWEIncreaseIntervalMs.
|
|
||||||
if (loss <= 5) {
|
|
||||||
if ((now_ms - time_last_increase_) < kBWEIncreaseIntervalMs) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
time_last_increase_ = now_ms;
|
|
||||||
}
|
|
||||||
// Limit the rate decreases to once a kBWEDecreaseIntervalMs + rtt.
|
|
||||||
if (loss > 26) {
|
|
||||||
if ((now_ms - time_last_decrease_) < kBWEDecreaseIntervalMs + rtt) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
time_last_decrease_ = now_ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loss > 5 && loss <= 26) {
|
} else if (last_fraction_loss_ <= 26) {
|
||||||
// 2% - 10%
|
// Loss between 2% - 10%: Do nothing.
|
||||||
new_bitrate = bitrate_;
|
|
||||||
} else if (loss > 26) {
|
|
||||||
// 26/256 ~= 10%
|
|
||||||
// reduce rate: newRate = rate * (1 - 0.5*lossRate)
|
|
||||||
// packetLoss = 256*lossRate
|
|
||||||
new_bitrate = static_cast<uint32_t>((bitrate_ *
|
|
||||||
static_cast<double>(512 - loss)) / 512.0);
|
|
||||||
// Calculate what rate TFRC would apply in this situation
|
|
||||||
// scale loss to Q0 (back to [0, 255])
|
|
||||||
uint32_t tfrc_bitrate = CalcTFRCbps(rtt, loss);
|
|
||||||
if (tfrc_bitrate > new_bitrate) {
|
|
||||||
// do not reduce further if rate is below TFRC rate
|
|
||||||
new_bitrate = tfrc_bitrate;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// increase rate by 8%
|
// Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs +
|
||||||
new_bitrate = static_cast<uint32_t>(bitrate_ * 1.08 + 0.5);
|
// rtt.
|
||||||
|
if ((now_ms - time_last_decrease_) >=
|
||||||
|
static_cast<uint32_t>(kBweDecreaseIntervalMs + last_round_trip_time_)) {
|
||||||
|
time_last_decrease_ = now_ms;
|
||||||
|
|
||||||
// add 1 kbps extra, just to make sure that we do not get stuck
|
// Reduce rate:
|
||||||
// (gives a little extra increase at low rates, negligible at higher rates)
|
// newRate = rate * (1 - 0.5*lossRate);
|
||||||
new_bitrate += 1000;
|
// where packetLoss = 256*lossRate;
|
||||||
|
bitrate_ = static_cast<uint32_t>(
|
||||||
|
(bitrate_ * static_cast<double>(512 - last_fraction_loss_)) / 512.0);
|
||||||
|
|
||||||
|
// Calculate what rate TFRC would apply in this situation and to not
|
||||||
|
// reduce further than it.
|
||||||
|
bitrate_ = std::max(
|
||||||
|
bitrate_, CalcTfrcBps(last_round_trip_time_, last_fraction_loss_));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CapBitrateToThresholds(&new_bitrate);
|
|
||||||
*bitrate = new_bitrate;
|
CapBitrateToThresholds();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSideBandwidthEstimation::CapBitrateToThresholds(
|
void SendSideBandwidthEstimation::CapBitrateToThresholds() {
|
||||||
uint32_t* new_bitrate) {
|
if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) {
|
||||||
if (bwe_incoming_ > 0 && *new_bitrate > bwe_incoming_) {
|
bitrate_ = bwe_incoming_;
|
||||||
*new_bitrate = bwe_incoming_;
|
|
||||||
}
|
}
|
||||||
if (*new_bitrate > max_bitrate_configured_) {
|
if (bitrate_ > max_bitrate_configured_) {
|
||||||
*new_bitrate = max_bitrate_configured_;
|
bitrate_ = max_bitrate_configured_;
|
||||||
}
|
}
|
||||||
if (*new_bitrate < min_bitrate_configured_) {
|
if (bitrate_ < min_bitrate_configured_) {
|
||||||
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
|
WEBRTC_TRACE(kTraceWarning,
|
||||||
|
kTraceRtpRtcp,
|
||||||
|
-1,
|
||||||
"The configured min bitrate (%u kbps) is greater than the "
|
"The configured min bitrate (%u kbps) is greater than the "
|
||||||
"estimated available bandwidth (%u kbps).\n",
|
"estimated available bandwidth (%u kbps).\n",
|
||||||
min_bitrate_configured_ / 1000, *new_bitrate / 1000);
|
min_bitrate_configured_ / 1000,
|
||||||
*new_bitrate = min_bitrate_configured_;
|
bitrate_ / 1000);
|
||||||
|
bitrate_ = min_bitrate_configured_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,39 +22,24 @@ class SendSideBandwidthEstimation {
|
|||||||
SendSideBandwidthEstimation();
|
SendSideBandwidthEstimation();
|
||||||
virtual ~SendSideBandwidthEstimation();
|
virtual ~SendSideBandwidthEstimation();
|
||||||
|
|
||||||
// Call when we receive a RTCP message with TMMBR or REMB
|
void CurrentEstimate(uint32_t* bitrate, uint8_t* loss, uint32_t* rtt) const;
|
||||||
// Return true if new_bitrate is valid.
|
|
||||||
bool UpdateBandwidthEstimate(const uint32_t bandwidth,
|
|
||||||
uint32_t* new_bitrate,
|
|
||||||
uint8_t* fraction_lost,
|
|
||||||
uint16_t* rtt);
|
|
||||||
|
|
||||||
// Call when we receive a RTCP message with a ReceiveBlock
|
// Call when we receive a RTCP message with TMMBR or REMB.
|
||||||
// Return true if new_bitrate is valid.
|
void UpdateReceiverEstimate(uint32_t bandwidth);
|
||||||
bool UpdatePacketLoss(const int number_of_packets,
|
|
||||||
const uint32_t rtt,
|
|
||||||
const uint32_t now_ms,
|
|
||||||
uint8_t* loss,
|
|
||||||
uint32_t* new_bitrate);
|
|
||||||
|
|
||||||
// Return false if no bandwidth estimate is available
|
// Call when we receive a RTCP message with a ReceiveBlock.
|
||||||
bool AvailableBandwidth(uint32_t* bandwidth) const;
|
void UpdateReceiverBlock(uint8_t fraction_loss,
|
||||||
void SetSendBitrate(const uint32_t bitrate);
|
uint32_t rtt,
|
||||||
void SetMinMaxBitrate(const uint32_t min_bitrate, const uint32_t max_bitrate);
|
int number_of_packets,
|
||||||
|
uint32_t now_ms);
|
||||||
|
|
||||||
|
void SetSendBitrate(uint32_t bitrate);
|
||||||
|
void SetMinMaxBitrate(uint32_t min_bitrate, uint32_t max_bitrate);
|
||||||
void SetMinBitrate(uint32_t min_bitrate);
|
void SetMinBitrate(uint32_t min_bitrate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ShapeSimple(const uint8_t loss, const uint32_t rtt,
|
void UpdateEstimate(uint32_t now_ms);
|
||||||
const uint32_t now_ms, uint32_t* bitrate);
|
void CapBitrateToThresholds();
|
||||||
|
|
||||||
void CapBitrateToThresholds(uint32_t* bitrate);
|
|
||||||
|
|
||||||
uint32_t CalcTFRCbps(uint16_t rtt, uint8_t loss);
|
|
||||||
|
|
||||||
enum { kBWEIncreaseIntervalMs = 1000 };
|
|
||||||
enum { kBWEDecreaseIntervalMs = 300 };
|
|
||||||
enum { kLimitNumPackets = 20 };
|
|
||||||
enum { kAvgPacketSizeBytes = 1000 };
|
|
||||||
|
|
||||||
// incoming filters
|
// incoming filters
|
||||||
int accumulate_lost_packets_Q8_;
|
int accumulate_lost_packets_Q8_;
|
||||||
|
@ -1159,7 +1159,6 @@ int ViEEncoder::StopDebugRecording() {
|
|||||||
void ViEEncoder::SuspendBelowMinBitrate() {
|
void ViEEncoder::SuspendBelowMinBitrate() {
|
||||||
vcm_.SuspendBelowMinBitrate();
|
vcm_.SuspendBelowMinBitrate();
|
||||||
bitrate_controller_->EnforceMinBitrate(false);
|
bitrate_controller_->EnforceMinBitrate(false);
|
||||||
bitrate_controller_->SetBweMinBitrate(10000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEEncoder::RegisterPreEncodeCallback(
|
void ViEEncoder::RegisterPreEncodeCallback(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user