LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/call - bitrate_allocator.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 230 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  *
      10             :  */
      11             : 
      12             : #include "webrtc/call/bitrate_allocator.h"
      13             : 
      14             : #include <algorithm>
      15             : #include <utility>
      16             : 
      17             : #include "webrtc/base/checks.h"
      18             : #include "webrtc/base/logging.h"
      19             : #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
      20             : #include "webrtc/system_wrappers/include/clock.h"
      21             : #include "webrtc/system_wrappers/include/metrics.h"
      22             : 
      23             : namespace webrtc {
      24             : 
      25             : // Allow packets to be transmitted in up to 2 times max video bitrate if the
      26             : // bandwidth estimate allows it.
      27             : const int kTransmissionMaxBitrateMultiplier = 2;
      28             : const int kDefaultBitrateBps = 300000;
      29             : 
      30             : // Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
      31             : const double kToggleFactor = 0.1;
      32             : const uint32_t kMinToggleBitrateBps = 20000;
      33             : 
      34             : const int64_t kBweLogIntervalMs = 5000;
      35             : 
      36             : namespace {
      37             : 
      38           0 : double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) {
      39           0 :   RTC_DCHECK_GT(allocated_bitrate, 0);
      40           0 :   if (protection_bitrate == 0)
      41           0 :     return 1.0;
      42             : 
      43           0 :   uint32_t media_bitrate = allocated_bitrate - protection_bitrate;
      44           0 :   return media_bitrate / static_cast<double>(allocated_bitrate);
      45             : }
      46             : }  // namespace
      47             : 
      48           0 : BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
      49             :     : limit_observer_(limit_observer),
      50             :       bitrate_observer_configs_(),
      51             :       last_bitrate_bps_(0),
      52             :       last_non_zero_bitrate_bps_(kDefaultBitrateBps),
      53             :       last_fraction_loss_(0),
      54             :       last_rtt_(0),
      55             :       num_pause_events_(0),
      56           0 :       clock_(Clock::GetRealTimeClock()),
      57           0 :       last_bwe_log_time_(0) {
      58           0 :   sequenced_checker_.Detach();
      59           0 : }
      60             : 
      61           0 : BitrateAllocator::~BitrateAllocator() {
      62           0 :   RTC_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
      63             :                            num_pause_events_);
      64           0 : }
      65             : 
      66           0 : void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
      67             :                                         uint8_t fraction_loss,
      68             :                                         int64_t rtt,
      69             :                                         int64_t probing_interval_ms) {
      70           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
      71           0 :   last_bitrate_bps_ = target_bitrate_bps;
      72           0 :   last_non_zero_bitrate_bps_ =
      73           0 :       target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
      74           0 :   last_fraction_loss_ = fraction_loss;
      75           0 :   last_rtt_ = rtt;
      76           0 :   last_probing_interval_ms_ = probing_interval_ms;
      77             : 
      78             :   // Periodically log the incoming BWE.
      79           0 :   int64_t now = clock_->TimeInMilliseconds();
      80           0 :   if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
      81           0 :     LOG(LS_INFO) << "Current BWE " << target_bitrate_bps;
      82           0 :     last_bwe_log_time_ = now;
      83             :   }
      84             : 
      85           0 :   ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
      86             : 
      87           0 :   for (auto& config : bitrate_observer_configs_) {
      88           0 :     uint32_t allocated_bitrate = allocation[config.observer];
      89           0 :     uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
      90           0 :         allocated_bitrate, last_fraction_loss_, last_rtt_,
      91           0 :         last_probing_interval_ms_);
      92             : 
      93           0 :     if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
      94           0 :       if (target_bitrate_bps > 0)
      95           0 :         ++num_pause_events_;
      96             :       // The protection bitrate is an estimate based on the ratio between media
      97             :       // and protection used before this observer was muted.
      98             :       uint32_t predicted_protection_bps =
      99           0 :           (1.0 - config.media_ratio) * config.min_bitrate_bps;
     100           0 :       LOG(LS_INFO) << "Pausing observer " << config.observer
     101           0 :                    << " with configured min bitrate " << config.min_bitrate_bps
     102           0 :                    << " and current estimate of " << target_bitrate_bps
     103           0 :                    << " and protection bitrate " << predicted_protection_bps;
     104           0 :     } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
     105           0 :       if (target_bitrate_bps > 0)
     106           0 :         ++num_pause_events_;
     107           0 :       LOG(LS_INFO) << "Resuming observer " << config.observer
     108           0 :                    << ", configured min bitrate " << config.min_bitrate_bps
     109           0 :                    << ", current allocation " << allocated_bitrate
     110           0 :                    << " and protection bitrate " << protection_bitrate;
     111             :     }
     112             : 
     113             :     // Only update the media ratio if the observer got an allocation.
     114           0 :     if (allocated_bitrate > 0)
     115           0 :       config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
     116           0 :     config.allocated_bitrate_bps = allocated_bitrate;
     117             :   }
     118           0 : }
     119             : 
     120           0 : void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
     121             :                                    uint32_t min_bitrate_bps,
     122             :                                    uint32_t max_bitrate_bps,
     123             :                                    uint32_t pad_up_bitrate_bps,
     124             :                                    bool enforce_min_bitrate) {
     125           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     126           0 :   auto it = FindObserverConfig(observer);
     127             : 
     128             :   // Update settings if the observer already exists, create a new one otherwise.
     129           0 :   if (it != bitrate_observer_configs_.end()) {
     130           0 :     it->min_bitrate_bps = min_bitrate_bps;
     131           0 :     it->max_bitrate_bps = max_bitrate_bps;
     132           0 :     it->pad_up_bitrate_bps = pad_up_bitrate_bps;
     133           0 :     it->enforce_min_bitrate = enforce_min_bitrate;
     134             :   } else {
     135           0 :     bitrate_observer_configs_.push_back(
     136           0 :         ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
     137           0 :                        pad_up_bitrate_bps, enforce_min_bitrate));
     138             :   }
     139             : 
     140           0 :   ObserverAllocation allocation;
     141           0 :   if (last_bitrate_bps_ > 0) {
     142             :     // Calculate a new allocation and update all observers.
     143           0 :     allocation = AllocateBitrates(last_bitrate_bps_);
     144           0 :     for (auto& config : bitrate_observer_configs_) {
     145           0 :       uint32_t allocated_bitrate = allocation[config.observer];
     146           0 :       uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
     147           0 :           allocated_bitrate, last_fraction_loss_, last_rtt_,
     148           0 :           last_probing_interval_ms_);
     149           0 :       config.allocated_bitrate_bps = allocated_bitrate;
     150           0 :       if (allocated_bitrate > 0)
     151           0 :         config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
     152             :     }
     153             :   } else {
     154             :     // Currently, an encoder is not allowed to produce frames.
     155             :     // But we still have to return the initial config bitrate + let the
     156             :     // observer know that it can not produce frames.
     157           0 :     allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
     158           0 :     observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_,
     159           0 :                                last_probing_interval_ms_);
     160             :   }
     161           0 :   UpdateAllocationLimits();
     162           0 : }
     163             : 
     164           0 : void BitrateAllocator::UpdateAllocationLimits() {
     165           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     166           0 :   uint32_t total_requested_padding_bitrate = 0;
     167           0 :   uint32_t total_requested_min_bitrate = 0;
     168             : 
     169           0 :   for (const auto& config : bitrate_observer_configs_) {
     170           0 :     if (config.enforce_min_bitrate) {
     171           0 :       total_requested_min_bitrate += config.min_bitrate_bps;
     172             :     }
     173           0 :     total_requested_padding_bitrate += config.pad_up_bitrate_bps;
     174             :   }
     175             : 
     176           0 :   LOG(LS_INFO) << "UpdateAllocationLimits : total_requested_min_bitrate: "
     177           0 :                << total_requested_min_bitrate
     178           0 :                << "bps, total_requested_padding_bitrate: "
     179           0 :                << total_requested_padding_bitrate << "bps";
     180           0 :   limit_observer_->OnAllocationLimitsChanged(total_requested_min_bitrate,
     181           0 :                                              total_requested_padding_bitrate);
     182           0 : }
     183             : 
     184           0 : void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
     185           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     186           0 :   auto it = FindObserverConfig(observer);
     187           0 :   if (it != bitrate_observer_configs_.end()) {
     188           0 :     bitrate_observer_configs_.erase(it);
     189             :   }
     190             : 
     191           0 :   UpdateAllocationLimits();
     192           0 : }
     193             : 
     194           0 : int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
     195           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     196           0 :   const auto& it = FindObserverConfig(observer);
     197           0 :   if (it == bitrate_observer_configs_.end()) {
     198             :     // This observer hasn't been added yet, just give it its fair share.
     199           0 :     return last_non_zero_bitrate_bps_ /
     200           0 :            static_cast<int>((bitrate_observer_configs_.size() + 1));
     201           0 :   } else if (it->allocated_bitrate_bps == -1) {
     202             :     // This observer hasn't received an allocation yet, so do the same.
     203           0 :     return last_non_zero_bitrate_bps_ /
     204           0 :            static_cast<int>(bitrate_observer_configs_.size());
     205             :   } else {
     206             :     // This observer already has an allocation.
     207           0 :     return it->allocated_bitrate_bps;
     208             :   }
     209             : }
     210             : 
     211             : BitrateAllocator::ObserverConfigs::iterator
     212           0 : BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) {
     213           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     214           0 :   for (auto it = bitrate_observer_configs_.begin();
     215           0 :        it != bitrate_observer_configs_.end(); ++it) {
     216           0 :     if (it->observer == observer)
     217           0 :       return it;
     218             :   }
     219           0 :   return bitrate_observer_configs_.end();
     220             : }
     221             : 
     222           0 : BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
     223             :     uint32_t bitrate) {
     224           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     225           0 :   if (bitrate_observer_configs_.empty())
     226           0 :     return ObserverAllocation();
     227             : 
     228           0 :   if (bitrate == 0)
     229           0 :     return ZeroRateAllocation();
     230             : 
     231           0 :   uint32_t sum_min_bitrates = 0;
     232           0 :   uint32_t sum_max_bitrates = 0;
     233           0 :   for (const auto& observer_config : bitrate_observer_configs_) {
     234           0 :     sum_min_bitrates += observer_config.min_bitrate_bps;
     235           0 :     sum_max_bitrates += observer_config.max_bitrate_bps;
     236             :   }
     237             : 
     238             :   // Not enough for all observers to get an allocation, allocate according to:
     239             :   // enforced min bitrate -> allocated bitrate previous round -> restart paused
     240             :   // streams.
     241           0 :   if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
     242           0 :     return LowRateAllocation(bitrate);
     243             : 
     244             :   // All observers will get their min bitrate plus an even share of the rest.
     245           0 :   if (bitrate <= sum_max_bitrates)
     246           0 :     return NormalRateAllocation(bitrate, sum_min_bitrates);
     247             : 
     248             :   // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
     249           0 :   return MaxRateAllocation(bitrate, sum_max_bitrates);
     250             : }
     251             : 
     252           0 : BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
     253           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     254           0 :   ObserverAllocation allocation;
     255           0 :   for (const auto& observer_config : bitrate_observer_configs_)
     256           0 :     allocation[observer_config.observer] = 0;
     257           0 :   return allocation;
     258             : }
     259             : 
     260           0 : BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
     261             :     uint32_t bitrate) {
     262           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     263           0 :   ObserverAllocation allocation;
     264             :   // Start by allocating bitrate to observers enforcing a min bitrate, hence
     265             :   // remaining_bitrate might turn negative.
     266           0 :   int64_t remaining_bitrate = bitrate;
     267           0 :   for (const auto& observer_config : bitrate_observer_configs_) {
     268           0 :     int32_t allocated_bitrate = 0;
     269           0 :     if (observer_config.enforce_min_bitrate)
     270           0 :       allocated_bitrate = observer_config.min_bitrate_bps;
     271             : 
     272           0 :     allocation[observer_config.observer] = allocated_bitrate;
     273           0 :     remaining_bitrate -= allocated_bitrate;
     274             :   }
     275             : 
     276             :   // Allocate bitrate to all previously active streams.
     277           0 :   if (remaining_bitrate > 0) {
     278           0 :     for (const auto& observer_config : bitrate_observer_configs_) {
     279           0 :       if (observer_config.enforce_min_bitrate ||
     280           0 :           LastAllocatedBitrate(observer_config) == 0)
     281           0 :         continue;
     282             : 
     283           0 :       uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
     284           0 :       if (remaining_bitrate >= required_bitrate) {
     285           0 :         allocation[observer_config.observer] = required_bitrate;
     286           0 :         remaining_bitrate -= required_bitrate;
     287             :       }
     288             :     }
     289             :   }
     290             : 
     291             :   // Allocate bitrate to previously paused streams.
     292           0 :   if (remaining_bitrate > 0) {
     293           0 :     for (const auto& observer_config : bitrate_observer_configs_) {
     294           0 :       if (LastAllocatedBitrate(observer_config) != 0)
     295           0 :         continue;
     296             : 
     297             :       // Add a hysteresis to avoid toggling.
     298           0 :       uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
     299           0 :       if (remaining_bitrate >= required_bitrate) {
     300           0 :         allocation[observer_config.observer] = required_bitrate;
     301           0 :         remaining_bitrate -= required_bitrate;
     302             :       }
     303             :     }
     304             :   }
     305             : 
     306             :   // Split a possible remainder evenly on all streams with an allocation.
     307           0 :   if (remaining_bitrate > 0)
     308           0 :     DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
     309             : 
     310           0 :   RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
     311           0 :   return allocation;
     312             : }
     313             : 
     314           0 : BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
     315             :     uint32_t bitrate,
     316             :     uint32_t sum_min_bitrates) {
     317           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     318           0 :   ObserverAllocation allocation;
     319           0 :   for (const auto& observer_config : bitrate_observer_configs_)
     320           0 :     allocation[observer_config.observer] = observer_config.min_bitrate_bps;
     321             : 
     322           0 :   bitrate -= sum_min_bitrates;
     323           0 :   if (bitrate > 0)
     324           0 :     DistributeBitrateEvenly(bitrate, true, 1, &allocation);
     325             : 
     326           0 :   return allocation;
     327             : }
     328             : 
     329           0 : BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
     330             :     uint32_t bitrate,
     331             :     uint32_t sum_max_bitrates) {
     332           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     333           0 :   ObserverAllocation allocation;
     334             : 
     335           0 :   for (const auto& observer_config : bitrate_observer_configs_) {
     336           0 :     allocation[observer_config.observer] = observer_config.max_bitrate_bps;
     337           0 :     bitrate -= observer_config.max_bitrate_bps;
     338             :   }
     339             :   DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
     340           0 :                           &allocation);
     341           0 :   return allocation;
     342             : }
     343             : 
     344           0 : uint32_t BitrateAllocator::LastAllocatedBitrate(
     345             :     const ObserverConfig& observer_config) {
     346             :   // Return the configured minimum bitrate for newly added observers, to avoid
     347             :   // requiring an extra high bitrate for the observer to get an allocated
     348             :   // bitrate.
     349           0 :   return observer_config.allocated_bitrate_bps == -1
     350             :              ? observer_config.min_bitrate_bps
     351           0 :              : observer_config.allocated_bitrate_bps;
     352             : }
     353             : 
     354           0 : uint32_t BitrateAllocator::MinBitrateWithHysteresis(
     355             :     const ObserverConfig& observer_config) {
     356           0 :   uint32_t min_bitrate = observer_config.min_bitrate_bps;
     357           0 :   if (LastAllocatedBitrate(observer_config) == 0) {
     358           0 :     min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
     359           0 :                             kMinToggleBitrateBps);
     360             :   }
     361             :   // Account for protection bitrate used by this observer in the previous
     362             :   // allocation.
     363             :   // Note: the ratio will only be updated when the stream is active, meaning a
     364             :   // paused stream won't get any ratio updates. This might lead to waiting a bit
     365             :   // longer than necessary if the network condition improves, but this is to
     366             :   // avoid too much toggling.
     367           0 :   if (observer_config.media_ratio > 0.0 && observer_config.media_ratio < 1.0)
     368           0 :     min_bitrate += min_bitrate * (1.0 - observer_config.media_ratio);
     369             : 
     370           0 :   return min_bitrate;
     371             : }
     372             : 
     373           0 : void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
     374             :                                                bool include_zero_allocations,
     375             :                                                int max_multiplier,
     376             :                                                ObserverAllocation* allocation) {
     377           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     378           0 :   RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
     379             : 
     380           0 :   ObserverSortingMap list_max_bitrates;
     381           0 :   for (const auto& observer_config : bitrate_observer_configs_) {
     382           0 :     if (include_zero_allocations ||
     383           0 :         allocation->at(observer_config.observer) != 0) {
     384           0 :       list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
     385           0 :           observer_config.max_bitrate_bps, &observer_config));
     386             :     }
     387             :   }
     388           0 :   auto it = list_max_bitrates.begin();
     389           0 :   while (it != list_max_bitrates.end()) {
     390           0 :     RTC_DCHECK_GT(bitrate, 0);
     391             :     uint32_t extra_allocation =
     392           0 :         bitrate / static_cast<uint32_t>(list_max_bitrates.size());
     393             :     uint32_t total_allocation =
     394           0 :         extra_allocation + allocation->at(it->second->observer);
     395           0 :     bitrate -= extra_allocation;
     396           0 :     if (total_allocation > max_multiplier * it->first) {
     397             :       // There is more than we can fit for this observer, carry over to the
     398             :       // remaining observers.
     399           0 :       bitrate += total_allocation - max_multiplier * it->first;
     400           0 :       total_allocation = max_multiplier * it->first;
     401             :     }
     402             :     // Finally, update the allocation for this observer.
     403           0 :     allocation->at(it->second->observer) = total_allocation;
     404           0 :     it = list_max_bitrates.erase(it);
     405             :   }
     406           0 : }
     407             : 
     408           0 : bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
     409             :                                                     uint32_t sum_min_bitrates) {
     410           0 :   RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
     411           0 :   if (bitrate < sum_min_bitrates)
     412           0 :     return false;
     413             : 
     414             :   uint32_t extra_bitrate_per_observer =
     415           0 :       (bitrate - sum_min_bitrates) /
     416           0 :       static_cast<uint32_t>(bitrate_observer_configs_.size());
     417           0 :   for (const auto& observer_config : bitrate_observer_configs_) {
     418           0 :     if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
     419           0 :         MinBitrateWithHysteresis(observer_config))
     420           0 :       return false;
     421             :   }
     422           0 :   return true;
     423             : }
     424             : }  // namespace webrtc

Generated by: LCOV version 1.13