summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc')
-rw-r--r--chromium/third_party/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc287
1 files changed, 166 insertions, 121 deletions
diff --git a/chromium/third_party/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/chromium/third_party/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
index c2c8616559b..cff5dd18545 100644
--- a/chromium/third_party/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
+++ b/chromium/third_party/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
@@ -18,7 +18,8 @@
namespace webrtc {
-class RtcpBandwidthObserverImpl : public RtcpBandwidthObserver {
+class BitrateControllerImpl::RtcpBandwidthObserverImpl
+ : public RtcpBandwidthObserver {
public:
explicit RtcpBandwidthObserverImpl(BitrateControllerImpl* owner)
: owner_(owner) {
@@ -76,94 +77,29 @@ class RtcpBandwidthObserverImpl : public RtcpBandwidthObserver {
BitrateControllerImpl* owner_;
};
-class LowRateStrategy {
- public:
- LowRateStrategy(
- SendSideBandwidthEstimation* bandwidth_estimation,
- BitrateControllerImpl::BitrateObserverConfList* bitrate_observers)
- : bandwidth_estimation_(bandwidth_estimation),
- bitrate_observers_(bitrate_observers) {}
-
- virtual ~LowRateStrategy() {}
-
- virtual void LowRateAllocation(uint32_t bitrate,
- uint8_t fraction_loss,
- uint32_t rtt,
- uint32_t sum_min_bitrates) = 0;
-
- protected:
- SendSideBandwidthEstimation* bandwidth_estimation_;
- BitrateControllerImpl::BitrateObserverConfList* bitrate_observers_;
-};
-
-class EnforceMinRateStrategy : public LowRateStrategy {
- public:
- EnforceMinRateStrategy(
- SendSideBandwidthEstimation* bandwidth_estimation,
- BitrateControllerImpl::BitrateObserverConfList* bitrate_observers)
- : LowRateStrategy(bandwidth_estimation, bitrate_observers) {}
-
- void LowRateAllocation(uint32_t bitrate,
- uint8_t fraction_loss,
- uint32_t rtt,
- uint32_t sum_min_bitrates) {
- // Min bitrate to all observers.
- BitrateControllerImpl::BitrateObserverConfList::iterator it;
- for (it = bitrate_observers_->begin(); it != bitrate_observers_->end();
- ++it) {
- it->first->OnNetworkChanged(it->second->min_bitrate_, fraction_loss,
- rtt);
- }
- // Set sum of min to current send bitrate.
- bandwidth_estimation_->SetSendBitrate(sum_min_bitrates);
- }
-};
-
-class NoEnforceMinRateStrategy : public LowRateStrategy {
- public:
- NoEnforceMinRateStrategy(
- SendSideBandwidthEstimation* bandwidth_estimation,
- BitrateControllerImpl::BitrateObserverConfList* bitrate_observers)
- : LowRateStrategy(bandwidth_estimation, bitrate_observers) {}
-
- void LowRateAllocation(uint32_t bitrate,
- uint8_t fraction_loss,
- uint32_t rtt,
- uint32_t sum_min_bitrates) {
- // Allocate up to |min_bitrate_| to one observer at a time, until
- // |bitrate| is depleted.
- uint32_t remainder = bitrate;
- BitrateControllerImpl::BitrateObserverConfList::iterator it;
- for (it = bitrate_observers_->begin(); it != bitrate_observers_->end();
- ++it) {
- uint32_t allocation = std::min(remainder, it->second->min_bitrate_);
- it->first->OnNetworkChanged(allocation, fraction_loss, rtt);
- remainder -= allocation;
- }
- // Set |bitrate| to current send bitrate.
- bandwidth_estimation_->SetSendBitrate(bitrate);
- }
-};
-
BitrateController* BitrateController::CreateBitrateController(
+ Clock* clock,
bool enforce_min_bitrate) {
- return new BitrateControllerImpl(enforce_min_bitrate);
+ return new BitrateControllerImpl(clock, enforce_min_bitrate);
}
-BitrateControllerImpl::BitrateControllerImpl(bool enforce_min_bitrate)
- : critsect_(CriticalSectionWrapper::CreateCriticalSection()) {
- if (enforce_min_bitrate) {
- low_rate_strategy_.reset(new EnforceMinRateStrategy(
- &bandwidth_estimation_, &bitrate_observers_));
- } else {
- low_rate_strategy_.reset(new NoEnforceMinRateStrategy(
- &bandwidth_estimation_, &bitrate_observers_));
- }
-}
+BitrateControllerImpl::BitrateControllerImpl(Clock* clock, bool enforce_min_bitrate)
+ : clock_(clock),
+ last_bitrate_update_ms_(clock_->TimeInMilliseconds()),
+ critsect_(CriticalSectionWrapper::CreateCriticalSection()),
+ bandwidth_estimation_(),
+ bitrate_observers_(),
+ enforce_min_bitrate_(enforce_min_bitrate),
+ reserved_bitrate_bps_(0),
+ last_bitrate_bps_(0),
+ last_fraction_loss_(0),
+ last_rtt_ms_(0),
+ last_enforce_min_bitrate_(!enforce_min_bitrate_),
+ bitrate_observers_modified_(false),
+ last_reserved_bitrate_bps_(0) {}
BitrateControllerImpl::~BitrateControllerImpl() {
- BitrateObserverConfList::iterator it =
- bitrate_observers_.begin();
+ BitrateObserverConfList::iterator it = bitrate_observers_.begin();
while (it != bitrate_observers_.end()) {
delete it->second;
bitrate_observers_.erase(it);
@@ -203,26 +139,56 @@ void BitrateControllerImpl::SetBitrateObserver(
it->second->start_bitrate_ = start_bitrate;
it->second->min_bitrate_ = min_bitrate;
it->second->max_bitrate_ = max_bitrate;
+ // Set the send-side bandwidth to the max of the sum of start bitrates and
+ // the current estimate, so that if the user wants to immediately use more
+ // bandwidth, that can be enforced.
+ uint32_t sum_start_bitrate = 0;
+ BitrateObserverConfList::iterator it;
+ for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
+ ++it) {
+ sum_start_bitrate += it->second->start_bitrate_;
+ }
+ uint32_t current_estimate;
+ uint8_t loss;
+ uint32_t rtt;
+ bandwidth_estimation_.CurrentEstimate(&current_estimate, &loss, &rtt);
+ bandwidth_estimation_.SetSendBitrate(std::max(sum_start_bitrate,
+ current_estimate));
} else {
// Add new settings.
bitrate_observers_.push_back(BitrateObserverConfiguration(observer,
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);
+ }
}
- uint32_t sum_start_bitrate = 0;
+
+ UpdateMinMaxBitrate();
+}
+
+void BitrateControllerImpl::UpdateMinMaxBitrate() {
uint32_t sum_min_bitrate = 0;
uint32_t sum_max_bitrate = 0;
-
- // Summarize all configurations.
+ BitrateObserverConfList::iterator it;
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
- sum_start_bitrate += it->second->start_bitrate_;
sum_min_bitrate += it->second->min_bitrate_;
sum_max_bitrate += it->second->max_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(sum_start_bitrate);
+ if (sum_max_bitrate == 0) {
+ // No max configured use 1Gbit/s.
+ sum_max_bitrate = 1000000000;
+ }
+ 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,
sum_max_bitrate);
@@ -235,31 +201,46 @@ void BitrateControllerImpl::RemoveBitrateObserver(BitrateObserver* observer) {
if (it != bitrate_observers_.end()) {
delete it->second;
bitrate_observers_.erase(it);
+ bitrate_observers_modified_ = true;
}
}
void BitrateControllerImpl::EnforceMinBitrate(bool enforce_min_bitrate) {
CriticalSectionScoped cs(critsect_);
- if (enforce_min_bitrate) {
- low_rate_strategy_.reset(new EnforceMinRateStrategy(
- &bandwidth_estimation_, &bitrate_observers_));
- } else {
- low_rate_strategy_.reset(new NoEnforceMinRateStrategy(
- &bandwidth_estimation_, &bitrate_observers_));
- }
+ enforce_min_bitrate_ = enforce_min_bitrate;
+ UpdateMinMaxBitrate();
+}
+
+void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
+ CriticalSectionScoped cs(critsect_);
+ reserved_bitrate_bps_ = reserved_bitrate_bps;
+ MaybeTriggerOnNetworkChanged();
}
void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) {
- uint32_t new_bitrate = 0;
- uint8_t fraction_lost = 0;
- uint16_t rtt = 0;
CriticalSectionScoped cs(critsect_);
- if (bandwidth_estimation_.UpdateBandwidthEstimate(bitrate,
- &new_bitrate,
- &fraction_lost,
- &rtt)) {
- OnNetworkChanged(new_bitrate, fraction_lost, rtt);
+ bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
+ MaybeTriggerOnNetworkChanged();
+}
+
+int32_t BitrateControllerImpl::TimeUntilNextProcess() {
+ enum { kBitrateControllerUpdateIntervalMs = 25 };
+ CriticalSectionScoped cs(critsect_);
+ int time_since_update_ms =
+ clock_->TimeInMilliseconds() - last_bitrate_update_ms_;
+ return std::max(0, kBitrateControllerUpdateIntervalMs - time_since_update_ms);
+}
+
+int32_t BitrateControllerImpl::Process() {
+ if (TimeUntilNextProcess() > 0)
+ return 0;
+ {
+ CriticalSectionScoped cs(critsect_);
+ bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds());
+ MaybeTriggerOnNetworkChanged();
}
+ last_bitrate_update_ms_ = clock_->TimeInMilliseconds();
+ return 0;
}
void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
@@ -267,37 +248,63 @@ void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
const uint32_t rtt,
const int number_of_packets,
const uint32_t now_ms) {
- uint32_t new_bitrate = 0;
- uint8_t loss = fraction_loss;
CriticalSectionScoped cs(critsect_);
- if (bandwidth_estimation_.UpdatePacketLoss(number_of_packets, rtt, now_ms,
- &loss, &new_bitrate)) {
- OnNetworkChanged(new_bitrate, loss, rtt);
+ bandwidth_estimation_.UpdateReceiverBlock(
+ fraction_loss, rtt, number_of_packets, now_ms);
+ MaybeTriggerOnNetworkChanged();
+}
+
+void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() {
+ uint32_t bitrate;
+ uint8_t fraction_loss;
+ uint32_t rtt;
+ bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
+ bitrate -= std::min(bitrate, reserved_bitrate_bps_);
+
+ if (bitrate_observers_modified_ ||
+ bitrate != last_bitrate_bps_ ||
+ fraction_loss != last_fraction_loss_ ||
+ rtt != last_rtt_ms_ ||
+ last_enforce_min_bitrate_ != enforce_min_bitrate_ ||
+ last_reserved_bitrate_bps_ != reserved_bitrate_bps_) {
+ last_bitrate_bps_ = bitrate;
+ last_fraction_loss_ = fraction_loss;
+ last_rtt_ms_ = rtt;
+ last_enforce_min_bitrate_ = enforce_min_bitrate_;
+ last_reserved_bitrate_bps_ = reserved_bitrate_bps_;
+ bitrate_observers_modified_ = false;
+ OnNetworkChanged(bitrate, fraction_loss, rtt);
}
}
-// We have the lock here.
void BitrateControllerImpl::OnNetworkChanged(const uint32_t bitrate,
const uint8_t fraction_loss,
const uint32_t rtt) {
// Sanity check.
- uint32_t number_of_observers = bitrate_observers_.size();
- if (number_of_observers == 0) {
+ if (bitrate_observers_.empty())
return;
- }
+
uint32_t sum_min_bitrates = 0;
BitrateObserverConfList::iterator it;
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
sum_min_bitrates += it->second->min_bitrate_;
}
- if (bitrate <= sum_min_bitrates) {
- return low_rate_strategy_->LowRateAllocation(bitrate, fraction_loss, rtt,
- sum_min_bitrates);
- }
+ if (bitrate <= sum_min_bitrates)
+ return LowRateAllocation(bitrate, fraction_loss, rtt, sum_min_bitrates);
+ else
+ return NormalRateAllocation(bitrate, fraction_loss, rtt, sum_min_bitrates);
+}
+
+void BitrateControllerImpl::NormalRateAllocation(uint32_t bitrate,
+ uint8_t fraction_loss,
+ uint32_t rtt,
+ uint32_t sum_min_bitrates) {
+ uint32_t number_of_observers = bitrate_observers_.size();
uint32_t bitrate_per_observer = (bitrate - sum_min_bitrates) /
number_of_observers;
// Use map to sort list based on max bitrate.
ObserverSortingMap list_max_bitrates;
+ BitrateObserverConfList::iterator it;
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
list_max_bitrates.insert(std::pair<uint32_t, ObserverConfiguration*>(
it->second->max_bitrate_,
@@ -328,8 +335,46 @@ void BitrateControllerImpl::OnNetworkChanged(const uint32_t bitrate,
}
}
+void BitrateControllerImpl::LowRateAllocation(uint32_t bitrate,
+ uint8_t fraction_loss,
+ uint32_t rtt,
+ uint32_t sum_min_bitrates) {
+ if (enforce_min_bitrate_) {
+ // Min bitrate to all observers.
+ BitrateControllerImpl::BitrateObserverConfList::iterator it;
+ for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
+ ++it) {
+ it->first->OnNetworkChanged(it->second->min_bitrate_, fraction_loss, rtt);
+ }
+ // Set sum of min to current send bitrate.
+ bandwidth_estimation_.SetSendBitrate(sum_min_bitrates);
+ } else {
+ // Allocate up to |min_bitrate_| to one observer at a time, until
+ // |bitrate| is depleted.
+ uint32_t remainder = bitrate;
+ BitrateControllerImpl::BitrateObserverConfList::iterator it;
+ for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
+ ++it) {
+ uint32_t allocation = std::min(remainder, it->second->min_bitrate_);
+ it->first->OnNetworkChanged(allocation, fraction_loss, rtt);
+ remainder -= allocation;
+ }
+ // Set |bitrate| to current send bitrate.
+ bandwidth_estimation_.SetSendBitrate(bitrate);
+ }
+}
+
bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
- return bandwidth_estimation_.AvailableBandwidth(bandwidth);
+ CriticalSectionScoped cs(critsect_);
+ uint32_t bitrate;
+ uint8_t fraction_loss;
+ uint32_t rtt;
+ bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
+ if (bitrate) {
+ *bandwidth = bitrate - std::min(bitrate, reserved_bitrate_bps_);
+ return true;
+ }
+ return false;
}
} // namespace webrtc