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

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2012 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             : #include "webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h"
      12             : 
      13             : #include <algorithm>
      14             : #include <cmath>
      15             : 
      16             : #include "webrtc/base/checks.h"
      17             : #include "webrtc/base/logging.h"
      18             : #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
      19             : #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h"
      20             : #include "webrtc/system_wrappers/include/field_trial.h"
      21             : #include "webrtc/system_wrappers/include/metrics.h"
      22             : 
      23             : namespace webrtc {
      24             : namespace {
      25             : const int64_t kBweIncreaseIntervalMs = 1000;
      26             : const int64_t kBweDecreaseIntervalMs = 300;
      27             : const int64_t kStartPhaseMs = 2000;
      28             : const int64_t kBweConverganceTimeMs = 20000;
      29             : const int kLimitNumPackets = 20;
      30             : const int kDefaultMaxBitrateBps = 1000000000;
      31             : const int64_t kLowBitrateLogPeriodMs = 10000;
      32             : const int64_t kRtcEventLogPeriodMs = 5000;
      33             : // Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals.
      34             : const int64_t kFeedbackIntervalMs = 1500;
      35             : const int64_t kFeedbackTimeoutIntervals = 3;
      36             : const int64_t kTimeoutIntervalMs = 1000;
      37             : 
      38             : struct UmaRampUpMetric {
      39             :   const char* metric_name;
      40             :   int bitrate_kbps;
      41             : };
      42             : 
      43             : const UmaRampUpMetric kUmaRampupMetrics[] = {
      44             :     {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500},
      45             :     {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000},
      46             :     {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}};
      47             : const size_t kNumUmaRampupMetrics =
      48             :     sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]);
      49             : 
      50             : }  // namespace
      51             : 
      52           0 : SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
      53             :     : lost_packets_since_last_loss_update_Q8_(0),
      54             :       expected_packets_since_last_loss_update_(0),
      55             :       bitrate_(0),
      56           0 :       min_bitrate_configured_(congestion_controller::GetMinBitrateBps()),
      57             :       max_bitrate_configured_(kDefaultMaxBitrateBps),
      58             :       last_low_bitrate_log_ms_(-1),
      59             :       has_decreased_since_last_fraction_loss_(false),
      60             :       last_feedback_ms_(-1),
      61             :       last_packet_report_ms_(-1),
      62             :       last_timeout_ms_(-1),
      63             :       last_fraction_loss_(0),
      64             :       last_logged_fraction_loss_(0),
      65             :       last_round_trip_time_ms_(0),
      66             :       bwe_incoming_(0),
      67             :       delay_based_bitrate_bps_(0),
      68             :       time_last_decrease_ms_(0),
      69             :       first_report_time_ms_(-1),
      70             :       initially_lost_packets_(0),
      71             :       bitrate_at_2_seconds_kbps_(0),
      72             :       uma_update_state_(kNoUpdate),
      73             :       rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
      74             :       event_log_(event_log),
      75             :       last_rtc_event_log_ms_(-1),
      76           0 :       in_timeout_experiment_(webrtc::field_trial::FindFullName(
      77           0 :                                  "WebRTC-FeedbackTimeout") == "Enabled") {
      78           0 :   RTC_DCHECK(event_log);
      79           0 : }
      80             : 
      81           0 : SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
      82             : 
      83           0 : void SendSideBandwidthEstimation::SetBitrates(int send_bitrate,
      84             :                                               int min_bitrate,
      85             :                                               int max_bitrate) {
      86           0 :   if (send_bitrate > 0)
      87           0 :     SetSendBitrate(send_bitrate);
      88           0 :   SetMinMaxBitrate(min_bitrate, max_bitrate);
      89           0 : }
      90             : 
      91           0 : void SendSideBandwidthEstimation::SetSendBitrate(int bitrate) {
      92           0 :   RTC_DCHECK_GT(bitrate, 0);
      93           0 :   bitrate_ = bitrate;
      94             : 
      95             :   // Clear last sent bitrate history so the new value can be used directly
      96             :   // and not capped.
      97           0 :   min_bitrate_history_.clear();
      98           0 : }
      99             : 
     100           0 : void SendSideBandwidthEstimation::SetMinMaxBitrate(int min_bitrate,
     101             :                                                    int max_bitrate) {
     102           0 :   RTC_DCHECK_GE(min_bitrate, 0);
     103           0 :   min_bitrate_configured_ =
     104           0 :       std::max(min_bitrate, congestion_controller::GetMinBitrateBps());
     105           0 :   if (max_bitrate > 0) {
     106           0 :     max_bitrate_configured_ =
     107           0 :         std::max<uint32_t>(min_bitrate_configured_, max_bitrate);
     108             :   } else {
     109           0 :     max_bitrate_configured_ = kDefaultMaxBitrateBps;
     110             :   }
     111           0 : }
     112             : 
     113           0 : int SendSideBandwidthEstimation::GetMinBitrate() const {
     114           0 :   return min_bitrate_configured_;
     115             : }
     116             : 
     117           0 : void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate,
     118             :                                                   uint8_t* loss,
     119             :                                                   int64_t* rtt) const {
     120           0 :   *bitrate = bitrate_;
     121           0 :   *loss = last_fraction_loss_;
     122           0 :   *rtt = last_round_trip_time_ms_;
     123           0 : }
     124             : 
     125           0 : void SendSideBandwidthEstimation::UpdateReceiverEstimate(
     126             :     int64_t now_ms, uint32_t bandwidth) {
     127           0 :   bwe_incoming_ = bandwidth;
     128           0 :   bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);
     129           0 : }
     130             : 
     131           0 : void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(
     132             :     int64_t now_ms,
     133             :     uint32_t bitrate_bps) {
     134           0 :   delay_based_bitrate_bps_ = bitrate_bps;
     135           0 :   bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);
     136           0 : }
     137             : 
     138           0 : void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
     139             :                                                       int64_t rtt,
     140             :                                                       int number_of_packets,
     141             :                                                       int64_t now_ms) {
     142           0 :   last_feedback_ms_ = now_ms;
     143           0 :   if (first_report_time_ms_ == -1)
     144           0 :     first_report_time_ms_ = now_ms;
     145             : 
     146             :   // Update RTT.
     147           0 :   last_round_trip_time_ms_ = rtt;
     148             : 
     149             :   // Check sequence number diff and weight loss report
     150           0 :   if (number_of_packets > 0) {
     151             :     // Calculate number of lost packets.
     152           0 :     const int num_lost_packets_Q8 = fraction_loss * number_of_packets;
     153             :     // Accumulate reports.
     154           0 :     lost_packets_since_last_loss_update_Q8_ += num_lost_packets_Q8;
     155           0 :     expected_packets_since_last_loss_update_ += number_of_packets;
     156             : 
     157             :     // Don't generate a loss rate until it can be based on enough packets.
     158           0 :     if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
     159           0 :       return;
     160             : 
     161           0 :     has_decreased_since_last_fraction_loss_ = false;
     162           0 :     last_fraction_loss_ = lost_packets_since_last_loss_update_Q8_ /
     163           0 :                           expected_packets_since_last_loss_update_;
     164             : 
     165             :     // Reset accumulators.
     166           0 :     lost_packets_since_last_loss_update_Q8_ = 0;
     167           0 :     expected_packets_since_last_loss_update_ = 0;
     168           0 :     last_packet_report_ms_ = now_ms;
     169           0 :     UpdateEstimate(now_ms);
     170             :   }
     171           0 :   UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8);
     172             : }
     173             : 
     174           0 : void SendSideBandwidthEstimation::UpdateUmaStats(int64_t now_ms,
     175             :                                                  int64_t rtt,
     176             :                                                  int lost_packets) {
     177           0 :   int bitrate_kbps = static_cast<int>((bitrate_ + 500) / 1000);
     178           0 :   for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
     179           0 :     if (!rampup_uma_stats_updated_[i] &&
     180           0 :         bitrate_kbps >= kUmaRampupMetrics[i].bitrate_kbps) {
     181           0 :       RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
     182             :                                    now_ms - first_report_time_ms_);
     183           0 :       rampup_uma_stats_updated_[i] = true;
     184             :     }
     185             :   }
     186           0 :   if (IsInStartPhase(now_ms)) {
     187           0 :     initially_lost_packets_ += lost_packets;
     188           0 :   } else if (uma_update_state_ == kNoUpdate) {
     189           0 :     uma_update_state_ = kFirstDone;
     190           0 :     bitrate_at_2_seconds_kbps_ = bitrate_kbps;
     191           0 :     RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
     192             :                          initially_lost_packets_, 0, 100, 50);
     193           0 :     RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast<int>(rtt), 0,
     194             :                          2000, 50);
     195           0 :     RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
     196             :                          bitrate_at_2_seconds_kbps_, 0, 2000, 50);
     197           0 :   } else if (uma_update_state_ == kFirstDone &&
     198           0 :              now_ms - first_report_time_ms_ >= kBweConverganceTimeMs) {
     199           0 :     uma_update_state_ = kDone;
     200             :     int bitrate_diff_kbps =
     201           0 :         std::max(bitrate_at_2_seconds_kbps_ - bitrate_kbps, 0);
     202           0 :     RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
     203             :                          0, 2000, 50);
     204             :   }
     205           0 : }
     206             : 
     207           0 : void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
     208             :   // We trust the REMB and/or delay-based estimate during the first 2 seconds if
     209             :   // we haven't had any packet loss reported, to allow startup bitrate probing.
     210           0 :   if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {
     211           0 :     uint32_t prev_bitrate = bitrate_;
     212           0 :     if (bwe_incoming_ > bitrate_)
     213           0 :       bitrate_ = CapBitrateToThresholds(now_ms, bwe_incoming_);
     214           0 :     if (delay_based_bitrate_bps_ > bitrate_) {
     215           0 :       bitrate_ = CapBitrateToThresholds(now_ms, delay_based_bitrate_bps_);
     216             :     }
     217           0 :     if (bitrate_ != prev_bitrate) {
     218           0 :       min_bitrate_history_.clear();
     219           0 :       min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_));
     220           0 :       return;
     221             :     }
     222             :   }
     223           0 :   UpdateMinHistory(now_ms);
     224           0 :   if (last_packet_report_ms_ == -1) {
     225             :     // No feedback received.
     226           0 :     bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);
     227           0 :     return;
     228             :   }
     229           0 :   int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;
     230           0 :   int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;
     231           0 :   if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {
     232           0 :     if (last_fraction_loss_ <= 5) {
     233             :       // Loss < 2%: Increase rate by 8% of the min bitrate in the last
     234             :       // kBweIncreaseIntervalMs.
     235             :       // Note that by remembering the bitrate over the last second one can
     236             :       // rampup up one second faster than if only allowed to start ramping
     237             :       // at 8% per second rate now. E.g.:
     238             :       //   If sending a constant 100kbps it can rampup immediatly to 108kbps
     239             :       //   whenever a receiver report is received with lower packet loss.
     240             :       //   If instead one would do: bitrate_ *= 1.08^(delta time), it would
     241             :       //   take over one second since the lower packet loss to achieve
     242             :       //   108kbps.
     243           0 :       bitrate_ = static_cast<uint32_t>(
     244           0 :           min_bitrate_history_.front().second * 1.08 + 0.5);
     245             : 
     246             :       // Add 1 kbps extra, just to make sure that we do not get stuck
     247             :       // (gives a little extra increase at low rates, negligible at higher
     248             :       // rates).
     249           0 :       bitrate_ += 1000;
     250           0 :     } else if (last_fraction_loss_ <= 26) {
     251             :       // Loss between 2% - 10%: Do nothing.
     252             :     } else {
     253             :       // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs
     254             :       // + rtt.
     255           0 :       if (!has_decreased_since_last_fraction_loss_ &&
     256           0 :           (now_ms - time_last_decrease_ms_) >=
     257           0 :               (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {
     258           0 :         time_last_decrease_ms_ = now_ms;
     259             : 
     260             :         // Reduce rate:
     261             :         //   newRate = rate * (1 - 0.5*lossRate);
     262             :         //   where packetLoss = 256*lossRate;
     263           0 :         bitrate_ = static_cast<uint32_t>(
     264           0 :             (bitrate_ * static_cast<double>(512 - last_fraction_loss_)) /
     265             :             512.0);
     266           0 :         has_decreased_since_last_fraction_loss_ = true;
     267             :       }
     268             :     }
     269           0 :   } else if (time_since_feedback_ms >
     270           0 :                  kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&
     271           0 :              (last_timeout_ms_ == -1 ||
     272           0 :               now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {
     273           0 :     if (in_timeout_experiment_) {
     274           0 :       LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms
     275           0 :                       << " ms), reducing bitrate.";
     276           0 :       bitrate_ *= 0.8;
     277             :       // Reset accumulators since we've already acted on missing feedback and
     278             :       // shouldn't to act again on these old lost packets.
     279           0 :       lost_packets_since_last_loss_update_Q8_ = 0;
     280           0 :       expected_packets_since_last_loss_update_ = 0;
     281           0 :       last_timeout_ms_ = now_ms;
     282             :     }
     283             :   }
     284           0 :   uint32_t capped_bitrate = CapBitrateToThresholds(now_ms, bitrate_);
     285           0 :   if (capped_bitrate != bitrate_ ||
     286           0 :       last_fraction_loss_ != last_logged_fraction_loss_ ||
     287           0 :       last_rtc_event_log_ms_ == -1 ||
     288           0 :       now_ms - last_rtc_event_log_ms_ > kRtcEventLogPeriodMs) {
     289           0 :     event_log_->LogBwePacketLossEvent(capped_bitrate, last_fraction_loss_,
     290           0 :                                       expected_packets_since_last_loss_update_);
     291           0 :     last_logged_fraction_loss_ = last_fraction_loss_;
     292           0 :     last_rtc_event_log_ms_ = now_ms;
     293             :   }
     294           0 :   bitrate_ = capped_bitrate;
     295             : }
     296             : 
     297           0 : bool SendSideBandwidthEstimation::IsInStartPhase(int64_t now_ms) const {
     298           0 :   return first_report_time_ms_ == -1 ||
     299           0 :          now_ms - first_report_time_ms_ < kStartPhaseMs;
     300             : }
     301             : 
     302           0 : void SendSideBandwidthEstimation::UpdateMinHistory(int64_t now_ms) {
     303             :   // Remove old data points from history.
     304             :   // Since history precision is in ms, add one so it is able to increase
     305             :   // bitrate if it is off by as little as 0.5ms.
     306           0 :   while (!min_bitrate_history_.empty() &&
     307           0 :          now_ms - min_bitrate_history_.front().first + 1 >
     308             :              kBweIncreaseIntervalMs) {
     309           0 :     min_bitrate_history_.pop_front();
     310             :   }
     311             : 
     312             :   // Typical minimum sliding-window algorithm: Pop values higher than current
     313             :   // bitrate before pushing it.
     314           0 :   while (!min_bitrate_history_.empty() &&
     315           0 :          bitrate_ <= min_bitrate_history_.back().second) {
     316           0 :     min_bitrate_history_.pop_back();
     317             :   }
     318             : 
     319           0 :   min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_));
     320           0 : }
     321             : 
     322           0 : uint32_t SendSideBandwidthEstimation::CapBitrateToThresholds(
     323             :     int64_t now_ms, uint32_t bitrate) {
     324           0 :   if (bwe_incoming_ > 0 && bitrate > bwe_incoming_) {
     325           0 :     bitrate = bwe_incoming_;
     326             :   }
     327           0 :   if (delay_based_bitrate_bps_ > 0 && bitrate > delay_based_bitrate_bps_) {
     328           0 :     bitrate = delay_based_bitrate_bps_;
     329             :   }
     330           0 :   if (bitrate > max_bitrate_configured_) {
     331           0 :     bitrate = max_bitrate_configured_;
     332             :   }
     333           0 :   if (bitrate < min_bitrate_configured_) {
     334           0 :     if (last_low_bitrate_log_ms_ == -1 ||
     335           0 :         now_ms - last_low_bitrate_log_ms_ > kLowBitrateLogPeriodMs) {
     336           0 :       LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate / 1000
     337           0 :                       << " kbps is below configured min bitrate "
     338           0 :                       << min_bitrate_configured_ / 1000 << " kbps.";
     339           0 :       last_low_bitrate_log_ms_ = now_ms;
     340             :     }
     341           0 :     bitrate = min_bitrate_configured_;
     342             :   }
     343           0 :   return bitrate;
     344             : }
     345             : }  // namespace webrtc

Generated by: LCOV version 1.13