Break out allocation from BitrateController into a BitrateAllocator.
This also refactors some of the padding and allocation code in ViEEncoder, and
makes ChannelGroup a simple forwarder from BitrateController to
BitrateAllocator.
This CL is part of a bigger picture, see https://review.webrtc.org/35319004/ for
details.
BUG=4323
R=mflodman@webrtc.org, pbos@webrtc.org, sprang@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/44399004
Cr-Commit-Position: refs/heads/master@{#8595}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8595 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
index acfeb59..586d8da 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
@@ -79,35 +79,26 @@
BitrateController* BitrateController::CreateBitrateController(
Clock* clock,
- bool enforce_min_bitrate) {
- return new BitrateControllerImpl(clock, enforce_min_bitrate);
+ BitrateObserver* observer) {
+ return new BitrateControllerImpl(clock, observer);
}
BitrateControllerImpl::BitrateControllerImpl(Clock* clock,
- bool enforce_min_bitrate)
+ BitrateObserver* observer)
: clock_(clock),
+ observer_(observer),
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),
remb_suppressor_(new RembSuppressor(clock)) {
}
BitrateControllerImpl::~BitrateControllerImpl() {
- BitrateObserverConfList::iterator it = bitrate_observers_.begin();
- while (it != bitrate_observers_.end()) {
- delete it->second;
- bitrate_observers_.erase(it);
- it = bitrate_observers_.begin();
- }
delete critsect_;
}
@@ -115,117 +106,33 @@
return new RtcpBandwidthObserverImpl(this);
}
-BitrateControllerImpl::BitrateObserverConfList::iterator
-BitrateControllerImpl::FindObserverConfigurationPair(const BitrateObserver*
- observer) {
- BitrateObserverConfList::iterator it = bitrate_observers_.begin();
- for (; it != bitrate_observers_.end(); ++it) {
- if (it->first == observer) {
- return it;
- }
- }
- return bitrate_observers_.end();
-}
-
-void BitrateControllerImpl::SetBitrateObserver(
- BitrateObserver* observer,
- uint32_t start_bitrate,
- uint32_t min_bitrate,
- uint32_t max_bitrate) {
+void BitrateControllerImpl::SetStartBitrate(int start_bitrate_bps) {
CriticalSectionScoped cs(critsect_);
-
- BitrateObserverConfList::iterator it = FindObserverConfigurationPair(
- observer);
-
- if (it != bitrate_observers_.end()) {
- // Update current configuration.
- 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;
- int64_t rtt;
- bandwidth_estimation_.CurrentEstimate(¤t_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);
- }
- }
-
- UpdateMinMaxBitrate();
+ bandwidth_estimation_.SetSendBitrate(start_bitrate_bps);
}
-void BitrateControllerImpl::UpdateMinMaxBitrate() {
- uint32_t sum_min_bitrate = 0;
- uint32_t sum_max_bitrate = 0;
- BitrateObserverConfList::iterator it;
- for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
- sum_min_bitrate += it->second->min_bitrate_;
- sum_max_bitrate += it->second->max_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);
-}
-
-void BitrateControllerImpl::RemoveBitrateObserver(BitrateObserver* observer) {
+void BitrateControllerImpl::SetMinMaxBitrate(int min_bitrate_bps,
+ int max_bitrate_bps) {
CriticalSectionScoped cs(critsect_);
- BitrateObserverConfList::iterator it = FindObserverConfigurationPair(
- 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_);
- enforce_min_bitrate_ = enforce_min_bitrate;
- UpdateMinMaxBitrate();
+ bandwidth_estimation_.SetMinMaxBitrate(min_bitrate_bps, max_bitrate_bps);
}
void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
- CriticalSectionScoped cs(critsect_);
- reserved_bitrate_bps_ = reserved_bitrate_bps;
+ {
+ CriticalSectionScoped cs(critsect_);
+ reserved_bitrate_bps_ = reserved_bitrate_bps;
+ }
MaybeTriggerOnNetworkChanged();
}
void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
- CriticalSectionScoped cs(critsect_);
- if (remb_suppressor_->SuppresNewRemb(bitrate)) {
- return;
+ {
+ CriticalSectionScoped cs(critsect_);
+ if (remb_suppressor_->SuppresNewRemb(bitrate)) {
+ return;
+ }
+ bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
}
- bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
MaybeTriggerOnNetworkChanged();
}
@@ -244,8 +151,8 @@
{
CriticalSectionScoped cs(critsect_);
bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds());
- MaybeTriggerOnNetworkChanged();
}
+ MaybeTriggerOnNetworkChanged();
last_bitrate_update_ms_ = clock_->TimeInMilliseconds();
return 0;
}
@@ -255,9 +162,11 @@
int64_t rtt,
int number_of_packets,
int64_t now_ms) {
- CriticalSectionScoped cs(critsect_);
- bandwidth_estimation_.UpdateReceiverBlock(
- fraction_loss, rtt, number_of_packets, now_ms);
+ {
+ CriticalSectionScoped cs(critsect_);
+ bandwidth_estimation_.UpdateReceiverBlock(fraction_loss, rtt,
+ number_of_packets, now_ms);
+ }
MaybeTriggerOnNetworkChanged();
}
@@ -265,110 +174,25 @@
uint32_t bitrate;
uint8_t fraction_loss;
int64_t rtt;
- bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
- bitrate -= std::min(bitrate, reserved_bitrate_bps_);
+ bool new_bitrate = false;
+ {
+ CriticalSectionScoped cs(critsect_);
+ bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
+ bitrate -= std::min(bitrate, reserved_bitrate_bps_);
+ bitrate = std::max(bitrate, bandwidth_estimation_.GetMinBitrate());
- 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);
- }
-}
-
-void BitrateControllerImpl::OnNetworkChanged(uint32_t bitrate,
- uint8_t fraction_loss,
- int64_t rtt) {
- // Sanity check.
- 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 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,
- int64_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_,
- new ObserverConfiguration(it->first, it->second->min_bitrate_)));
- }
- ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
- while (max_it != list_max_bitrates.end()) {
- number_of_observers--;
- uint32_t observer_allowance = max_it->second->min_bitrate_ +
- bitrate_per_observer;
- if (max_it->first < observer_allowance) {
- // We have more than enough for this observer.
- // Carry the remainder forward.
- uint32_t remainder = observer_allowance - max_it->first;
- if (number_of_observers != 0) {
- bitrate_per_observer += remainder / number_of_observers;
- }
- max_it->second->observer_->OnNetworkChanged(max_it->first, fraction_loss,
- rtt);
- } else {
- max_it->second->observer_->OnNetworkChanged(observer_allowance,
- fraction_loss, rtt);
+ if (bitrate != last_bitrate_bps_ || fraction_loss != last_fraction_loss_ ||
+ rtt != last_rtt_ms_ ||
+ last_reserved_bitrate_bps_ != reserved_bitrate_bps_) {
+ last_bitrate_bps_ = bitrate;
+ last_fraction_loss_ = fraction_loss;
+ last_rtt_ms_ = rtt;
+ last_reserved_bitrate_bps_ = reserved_bitrate_bps_;
+ new_bitrate = true;
}
- delete max_it->second;
- list_max_bitrates.erase(max_it);
- // Prepare next iteration.
- max_it = list_max_bitrates.begin();
}
-}
-
-void BitrateControllerImpl::LowRateAllocation(uint32_t bitrate,
- uint8_t fraction_loss,
- int64_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);
- }
+ if (new_bitrate)
+ observer_->OnNetworkChanged(bitrate, fraction_loss, rtt);
}
bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
@@ -379,6 +203,7 @@
bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
if (bitrate) {
*bandwidth = bitrate - std::min(bitrate, reserved_bitrate_bps_);
+ *bandwidth = std::max(*bandwidth, bandwidth_estimation_.GetMinBitrate());
return true;
}
return false;