diff options
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.cc | 287 |
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(¤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); + } } - 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 |