• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016 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 "modules/congestion_controller/goog_cc/probe_controller.h"
12 
13 #include <algorithm>
14 #include <initializer_list>
15 #include <memory>
16 #include <string>
17 
18 #include "absl/strings/match.h"
19 #include "absl/types/optional.h"
20 #include "api/units/data_rate.h"
21 #include "api/units/data_size.h"
22 #include "api/units/time_delta.h"
23 #include "api/units/timestamp.h"
24 #include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
25 #include "rtc_base/checks.h"
26 #include "rtc_base/logging.h"
27 #include "system_wrappers/include/metrics.h"
28 
29 namespace webrtc {
30 
31 namespace {
32 // Maximum waiting time from the time of initiating probing to getting
33 // the measured results back.
34 constexpr TimeDelta kMaxWaitingTimeForProbingResult = TimeDelta::Seconds(1);
35 
36 // Default probing bitrate limit. Applied only when the application didn't
37 // specify max bitrate.
38 constexpr DataRate kDefaultMaxProbingBitrate = DataRate::KilobitsPerSec(5000);
39 
40 // If the bitrate drops to a factor `kBitrateDropThreshold` or lower
41 // and we recover within `kBitrateDropTimeoutMs`, then we'll send
42 // a probe at a fraction `kProbeFractionAfterDrop` of the original bitrate.
43 constexpr double kBitrateDropThreshold = 0.66;
44 constexpr TimeDelta kBitrateDropTimeout = TimeDelta::Seconds(5);
45 constexpr double kProbeFractionAfterDrop = 0.85;
46 
47 // Timeout for probing after leaving ALR. If the bitrate drops significantly,
48 // (as determined by the delay based estimator) and we leave ALR, then we will
49 // send a probe if we recover within `kLeftAlrTimeoutMs` ms.
50 constexpr TimeDelta kAlrEndedTimeout = TimeDelta::Seconds(3);
51 
52 // The expected uncertainty of probe result (as a fraction of the target probe
53 // This is a limit on how often probing can be done when there is a BW
54 // drop detected in ALR.
55 constexpr TimeDelta kMinTimeBetweenAlrProbes = TimeDelta::Seconds(5);
56 
57 // bitrate). Used to avoid probing if the probe bitrate is close to our current
58 // estimate.
59 constexpr double kProbeUncertainty = 0.05;
60 
61 // Use probing to recover faster after large bitrate estimate drops.
62 constexpr char kBweRapidRecoveryExperiment[] =
63     "WebRTC-BweRapidRecoveryExperiment";
64 
MaybeLogProbeClusterCreated(RtcEventLog * event_log,const ProbeClusterConfig & probe)65 void MaybeLogProbeClusterCreated(RtcEventLog* event_log,
66                                  const ProbeClusterConfig& probe) {
67   RTC_DCHECK(event_log);
68   if (!event_log) {
69     return;
70   }
71 
72   DataSize min_data_size = probe.target_data_rate * probe.target_duration;
73   event_log->Log(std::make_unique<RtcEventProbeClusterCreated>(
74       probe.id, probe.target_data_rate.bps(), probe.target_probe_count,
75       min_data_size.bytes()));
76 }
77 
78 }  // namespace
79 
ProbeControllerConfig(const FieldTrialsView * key_value_config)80 ProbeControllerConfig::ProbeControllerConfig(
81     const FieldTrialsView* key_value_config)
82     : first_exponential_probe_scale("p1", 3.0),
83       second_exponential_probe_scale("p2", 6.0),
84       further_exponential_probe_scale("step_size", 2),
85       further_probe_threshold("further_probe_threshold", 0.7),
86       alr_probing_interval("alr_interval", TimeDelta::Seconds(5)),
87       alr_probe_scale("alr_scale", 2),
88       network_state_estimate_probing_interval("network_state_interval",
89                                               TimeDelta::PlusInfinity()),
90       probe_if_estimate_lower_than_network_state_estimate_ratio(
91           "est_lower_than_network_ratio",
92           0),
93       estimate_lower_than_network_state_estimate_probing_interval(
94           "est_lower_than_network_interval",
95           TimeDelta::Seconds(3)),
96       network_state_probe_scale("network_state_scale", 1.0),
97       network_state_probe_duration("network_state_probe_duration",
98                                    TimeDelta::Millis(15)),
99 
100       probe_on_max_allocated_bitrate_change("probe_max_allocation", true),
101       first_allocation_probe_scale("alloc_p1", 1),
102       second_allocation_probe_scale("alloc_p2", 2),
103       allocation_allow_further_probing("alloc_probe_further", false),
104       allocation_probe_max("alloc_probe_max", DataRate::PlusInfinity()),
105       min_probe_packets_sent("min_probe_packets_sent", 5),
106       min_probe_duration("min_probe_duration", TimeDelta::Millis(15)),
107       limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe",
108                                           false),
109       loss_limited_probe_scale("loss_limited_scale", 1.5),
110       skip_if_estimate_larger_than_fraction_of_max(
111           "skip_if_est_larger_than_fraction_of_max",
112           0.0) {
113   ParseFieldTrial({&first_exponential_probe_scale,
114                    &second_exponential_probe_scale,
115                    &further_exponential_probe_scale,
116                    &further_probe_threshold,
117                    &alr_probing_interval,
118                    &alr_probe_scale,
119                    &probe_on_max_allocated_bitrate_change,
120                    &first_allocation_probe_scale,
121                    &second_allocation_probe_scale,
122                    &allocation_allow_further_probing,
123                    &min_probe_duration,
124                    &network_state_estimate_probing_interval,
125                    &probe_if_estimate_lower_than_network_state_estimate_ratio,
126                    &estimate_lower_than_network_state_estimate_probing_interval,
127                    &network_state_probe_scale,
128                    &network_state_probe_duration,
129                    &min_probe_packets_sent,
130                    &limit_probe_target_rate_to_loss_bwe,
131                    &loss_limited_probe_scale,
132                    &skip_if_estimate_larger_than_fraction_of_max},
133                   key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration"));
134 
135   // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration
136   ParseFieldTrial(
137       {&first_exponential_probe_scale, &second_exponential_probe_scale},
138       key_value_config->Lookup("WebRTC-Bwe-InitialProbing"));
139   ParseFieldTrial({&further_exponential_probe_scale, &further_probe_threshold},
140                   key_value_config->Lookup("WebRTC-Bwe-ExponentialProbing"));
141   ParseFieldTrial(
142       {&alr_probing_interval, &alr_probe_scale, &loss_limited_probe_scale},
143       key_value_config->Lookup("WebRTC-Bwe-AlrProbing"));
144   ParseFieldTrial(
145       {&first_allocation_probe_scale, &second_allocation_probe_scale,
146        &allocation_allow_further_probing, &allocation_probe_max},
147       key_value_config->Lookup("WebRTC-Bwe-AllocationProbing"));
148   ParseFieldTrial({&min_probe_packets_sent, &min_probe_duration},
149                   key_value_config->Lookup("WebRTC-Bwe-ProbingBehavior"));
150 }
151 
152 ProbeControllerConfig::ProbeControllerConfig(const ProbeControllerConfig&) =
153     default;
154 ProbeControllerConfig::~ProbeControllerConfig() = default;
155 
ProbeController(const FieldTrialsView * key_value_config,RtcEventLog * event_log)156 ProbeController::ProbeController(const FieldTrialsView* key_value_config,
157                                  RtcEventLog* event_log)
158     : enable_periodic_alr_probing_(false),
159       in_rapid_recovery_experiment_(absl::StartsWith(
160           key_value_config->Lookup(kBweRapidRecoveryExperiment),
161           "Enabled")),
162       event_log_(event_log),
163       config_(ProbeControllerConfig(key_value_config)) {
164   Reset(Timestamp::Zero());
165 }
166 
~ProbeController()167 ProbeController::~ProbeController() {}
168 
SetBitrates(DataRate min_bitrate,DataRate start_bitrate,DataRate max_bitrate,Timestamp at_time)169 std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
170     DataRate min_bitrate,
171     DataRate start_bitrate,
172     DataRate max_bitrate,
173     Timestamp at_time) {
174   if (start_bitrate > DataRate::Zero()) {
175     start_bitrate_ = start_bitrate;
176     estimated_bitrate_ = start_bitrate;
177   } else if (start_bitrate_.IsZero()) {
178     start_bitrate_ = min_bitrate;
179   }
180 
181   // The reason we use the variable `old_max_bitrate_pbs` is because we
182   // need to set `max_bitrate_` before we call InitiateProbing.
183   DataRate old_max_bitrate = max_bitrate_;
184   max_bitrate_ =
185       max_bitrate.IsFinite() ? max_bitrate : kDefaultMaxProbingBitrate;
186 
187   switch (state_) {
188     case State::kInit:
189       if (network_available_)
190         return InitiateExponentialProbing(at_time);
191       break;
192 
193     case State::kWaitingForProbingResult:
194       break;
195 
196     case State::kProbingComplete:
197       // If the new max bitrate is higher than both the old max bitrate and the
198       // estimate then initiate probing.
199       if (!estimated_bitrate_.IsZero() && old_max_bitrate < max_bitrate_ &&
200           estimated_bitrate_ < max_bitrate_) {
201         // The assumption is that if we jump more than 20% in the bandwidth
202         // estimate or if the bandwidth estimate is within 90% of the new
203         // max bitrate then the probing attempt was successful.
204         mid_call_probing_succcess_threshold_ =
205             std::min(estimated_bitrate_ * 1.2, max_bitrate_ * 0.9);
206         mid_call_probing_waiting_for_result_ = true;
207         mid_call_probing_bitrate_ = max_bitrate_;
208 
209         RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated",
210                                    max_bitrate_.kbps());
211 
212         return InitiateProbing(at_time, {max_bitrate_}, false);
213       }
214       break;
215   }
216   return std::vector<ProbeClusterConfig>();
217 }
218 
OnMaxTotalAllocatedBitrate(DataRate max_total_allocated_bitrate,Timestamp at_time)219 std::vector<ProbeClusterConfig> ProbeController::OnMaxTotalAllocatedBitrate(
220     DataRate max_total_allocated_bitrate,
221     Timestamp at_time) {
222   const bool in_alr = alr_start_time_.has_value();
223   const bool allow_allocation_probe = in_alr;
224 
225   if (config_.probe_on_max_allocated_bitrate_change &&
226       state_ == State::kProbingComplete &&
227       max_total_allocated_bitrate != max_total_allocated_bitrate_ &&
228       estimated_bitrate_ < max_bitrate_ &&
229       estimated_bitrate_ < max_total_allocated_bitrate &&
230       allow_allocation_probe) {
231     max_total_allocated_bitrate_ = max_total_allocated_bitrate;
232 
233     if (!config_.first_allocation_probe_scale)
234       return std::vector<ProbeClusterConfig>();
235 
236     DataRate first_probe_rate = max_total_allocated_bitrate *
237                                 config_.first_allocation_probe_scale.Value();
238     DataRate probe_cap = config_.allocation_probe_max.Get();
239     first_probe_rate = std::min(first_probe_rate, probe_cap);
240     std::vector<DataRate> probes = {first_probe_rate};
241     if (config_.second_allocation_probe_scale) {
242       DataRate second_probe_rate =
243           max_total_allocated_bitrate *
244           config_.second_allocation_probe_scale.Value();
245       second_probe_rate = std::min(second_probe_rate, probe_cap);
246       if (second_probe_rate > first_probe_rate)
247         probes.push_back(second_probe_rate);
248     }
249     return InitiateProbing(at_time, probes,
250                            config_.allocation_allow_further_probing.Get());
251   }
252   max_total_allocated_bitrate_ = max_total_allocated_bitrate;
253   return std::vector<ProbeClusterConfig>();
254 }
255 
OnNetworkAvailability(NetworkAvailability msg)256 std::vector<ProbeClusterConfig> ProbeController::OnNetworkAvailability(
257     NetworkAvailability msg) {
258   network_available_ = msg.network_available;
259 
260   if (!network_available_ && state_ == State::kWaitingForProbingResult) {
261     state_ = State::kProbingComplete;
262     min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
263   }
264 
265   if (network_available_ && state_ == State::kInit && !start_bitrate_.IsZero())
266     return InitiateExponentialProbing(msg.at_time);
267   return std::vector<ProbeClusterConfig>();
268 }
269 
InitiateExponentialProbing(Timestamp at_time)270 std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
271     Timestamp at_time) {
272   RTC_DCHECK(network_available_);
273   RTC_DCHECK(state_ == State::kInit);
274   RTC_DCHECK_GT(start_bitrate_, DataRate::Zero());
275 
276   // When probing at 1.8 Mbps ( 6x 300), this represents a threshold of
277   // 1.2 Mbps to continue probing.
278   std::vector<DataRate> probes = {config_.first_exponential_probe_scale *
279                                   start_bitrate_};
280   if (config_.second_exponential_probe_scale &&
281       config_.second_exponential_probe_scale.GetOptional().value() > 0) {
282     probes.push_back(config_.second_exponential_probe_scale.Value() *
283                      start_bitrate_);
284   }
285   return InitiateProbing(at_time, probes, true);
286 }
287 
SetEstimatedBitrate(DataRate bitrate,BandwidthLimitedCause bandwidth_limited_cause,Timestamp at_time)288 std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
289     DataRate bitrate,
290     BandwidthLimitedCause bandwidth_limited_cause,
291     Timestamp at_time) {
292   bandwidth_limited_cause_ = bandwidth_limited_cause;
293   if (bitrate < kBitrateDropThreshold * estimated_bitrate_) {
294     time_of_last_large_drop_ = at_time;
295     bitrate_before_last_large_drop_ = estimated_bitrate_;
296   }
297   estimated_bitrate_ = bitrate;
298 
299   if (mid_call_probing_waiting_for_result_ &&
300       bitrate >= mid_call_probing_succcess_threshold_) {
301     RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Success",
302                                mid_call_probing_bitrate_.kbps());
303     RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.ProbedKbps",
304                                bitrate.kbps());
305     mid_call_probing_waiting_for_result_ = false;
306   }
307   if (state_ == State::kWaitingForProbingResult) {
308     // Continue probing if probing results indicate channel has greater
309     // capacity.
310     DataRate network_state_estimate_probe_further_limit =
311         config_.network_state_estimate_probing_interval->IsFinite() &&
312                 network_estimate_
313             ? network_estimate_->link_capacity_upper *
314                   config_.further_probe_threshold
315             : DataRate::PlusInfinity();
316     RTC_LOG(LS_INFO) << "Measured bitrate: " << bitrate
317                      << " Minimum to probe further: "
318                      << min_bitrate_to_probe_further_ << " upper limit: "
319                      << network_state_estimate_probe_further_limit;
320 
321     if (bitrate > min_bitrate_to_probe_further_ &&
322         bitrate <= network_state_estimate_probe_further_limit) {
323       return InitiateProbing(
324           at_time, {config_.further_exponential_probe_scale * bitrate}, true);
325     }
326   }
327   return {};
328 }
329 
EnablePeriodicAlrProbing(bool enable)330 void ProbeController::EnablePeriodicAlrProbing(bool enable) {
331   enable_periodic_alr_probing_ = enable;
332 }
333 
SetAlrStartTimeMs(absl::optional<int64_t> alr_start_time_ms)334 void ProbeController::SetAlrStartTimeMs(
335     absl::optional<int64_t> alr_start_time_ms) {
336   if (alr_start_time_ms) {
337     alr_start_time_ = Timestamp::Millis(*alr_start_time_ms);
338   } else {
339     alr_start_time_ = absl::nullopt;
340   }
341 }
SetAlrEndedTimeMs(int64_t alr_end_time_ms)342 void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) {
343   alr_end_time_.emplace(Timestamp::Millis(alr_end_time_ms));
344 }
345 
RequestProbe(Timestamp at_time)346 std::vector<ProbeClusterConfig> ProbeController::RequestProbe(
347     Timestamp at_time) {
348   // Called once we have returned to normal state after a large drop in
349   // estimated bandwidth. The current response is to initiate a single probe
350   // session (if not already probing) at the previous bitrate.
351   //
352   // If the probe session fails, the assumption is that this drop was a
353   // real one from a competing flow or a network change.
354   bool in_alr = alr_start_time_.has_value();
355   bool alr_ended_recently =
356       (alr_end_time_.has_value() &&
357        at_time - alr_end_time_.value() < kAlrEndedTimeout);
358   if (in_alr || alr_ended_recently || in_rapid_recovery_experiment_) {
359     if (state_ == State::kProbingComplete) {
360       DataRate suggested_probe =
361           kProbeFractionAfterDrop * bitrate_before_last_large_drop_;
362       DataRate min_expected_probe_result =
363           (1 - kProbeUncertainty) * suggested_probe;
364       TimeDelta time_since_drop = at_time - time_of_last_large_drop_;
365       TimeDelta time_since_probe = at_time - last_bwe_drop_probing_time_;
366       if (min_expected_probe_result > estimated_bitrate_ &&
367           time_since_drop < kBitrateDropTimeout &&
368           time_since_probe > kMinTimeBetweenAlrProbes) {
369         RTC_LOG(LS_INFO) << "Detected big bandwidth drop, start probing.";
370         // Track how often we probe in response to bandwidth drop in ALR.
371         RTC_HISTOGRAM_COUNTS_10000(
372             "WebRTC.BWE.BweDropProbingIntervalInS",
373             (at_time - last_bwe_drop_probing_time_).seconds());
374         last_bwe_drop_probing_time_ = at_time;
375         return InitiateProbing(at_time, {suggested_probe}, false);
376       }
377     }
378   }
379   return std::vector<ProbeClusterConfig>();
380 }
381 
SetNetworkStateEstimate(webrtc::NetworkStateEstimate estimate)382 void ProbeController::SetNetworkStateEstimate(
383     webrtc::NetworkStateEstimate estimate) {
384   network_estimate_ = estimate;
385 }
386 
Reset(Timestamp at_time)387 void ProbeController::Reset(Timestamp at_time) {
388   network_available_ = true;
389   bandwidth_limited_cause_ = BandwidthLimitedCause::kDelayBasedLimited;
390   state_ = State::kInit;
391   min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
392   time_last_probing_initiated_ = Timestamp::Zero();
393   estimated_bitrate_ = DataRate::Zero();
394   network_estimate_ = absl::nullopt;
395   start_bitrate_ = DataRate::Zero();
396   max_bitrate_ = kDefaultMaxProbingBitrate;
397   Timestamp now = at_time;
398   last_bwe_drop_probing_time_ = now;
399   alr_end_time_.reset();
400   mid_call_probing_waiting_for_result_ = false;
401   time_of_last_large_drop_ = now;
402   bitrate_before_last_large_drop_ = DataRate::Zero();
403   max_total_allocated_bitrate_ = DataRate::Zero();
404 }
405 
TimeForAlrProbe(Timestamp at_time) const406 bool ProbeController::TimeForAlrProbe(Timestamp at_time) const {
407   if (enable_periodic_alr_probing_ && alr_start_time_) {
408     Timestamp next_probe_time =
409         std::max(*alr_start_time_, time_last_probing_initiated_) +
410         config_.alr_probing_interval;
411     return at_time >= next_probe_time;
412   }
413   return false;
414 }
415 
TimeForNetworkStateProbe(Timestamp at_time) const416 bool ProbeController::TimeForNetworkStateProbe(Timestamp at_time) const {
417   if (!network_estimate_ ||
418       network_estimate_->link_capacity_upper.IsInfinite()) {
419     return false;
420   }
421 
422   bool probe_due_to_low_estimate =
423       bandwidth_limited_cause_ == BandwidthLimitedCause::kDelayBasedLimited &&
424       estimated_bitrate_ <
425           config_.probe_if_estimate_lower_than_network_state_estimate_ratio *
426               network_estimate_->link_capacity_upper;
427   if (probe_due_to_low_estimate &&
428       config_.estimate_lower_than_network_state_estimate_probing_interval
429           ->IsFinite()) {
430     Timestamp next_probe_time =
431         time_last_probing_initiated_ +
432         config_.estimate_lower_than_network_state_estimate_probing_interval;
433     return at_time >= next_probe_time;
434   }
435 
436   bool periodic_probe =
437       estimated_bitrate_ < network_estimate_->link_capacity_upper;
438   if (periodic_probe &&
439       config_.network_state_estimate_probing_interval->IsFinite()) {
440     Timestamp next_probe_time = time_last_probing_initiated_ +
441                                 config_.network_state_estimate_probing_interval;
442     return at_time >= next_probe_time;
443   }
444 
445   return false;
446 }
447 
Process(Timestamp at_time)448 std::vector<ProbeClusterConfig> ProbeController::Process(Timestamp at_time) {
449   if (at_time - time_last_probing_initiated_ >
450       kMaxWaitingTimeForProbingResult) {
451     mid_call_probing_waiting_for_result_ = false;
452 
453     if (state_ == State::kWaitingForProbingResult) {
454       RTC_LOG(LS_INFO) << "kWaitingForProbingResult: timeout";
455       state_ = State::kProbingComplete;
456       min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
457     }
458   }
459   if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) {
460     return {};
461   }
462   if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) {
463     return InitiateProbing(
464         at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true);
465   }
466   return std::vector<ProbeClusterConfig>();
467 }
468 
InitiateProbing(Timestamp now,std::vector<DataRate> bitrates_to_probe,bool probe_further)469 std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
470     Timestamp now,
471     std::vector<DataRate> bitrates_to_probe,
472     bool probe_further) {
473   if (config_.skip_if_estimate_larger_than_fraction_of_max > 0) {
474     DataRate network_estimate = network_estimate_
475                                     ? network_estimate_->link_capacity_upper
476                                     : DataRate::PlusInfinity();
477     DataRate max_probe_rate =
478         max_total_allocated_bitrate_.IsZero()
479             ? max_bitrate_
480             : std::min(max_total_allocated_bitrate_, max_bitrate_);
481     if (std::min(network_estimate, estimated_bitrate_) >
482         config_.skip_if_estimate_larger_than_fraction_of_max * max_probe_rate) {
483       state_ = State::kProbingComplete;
484       min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
485       return {};
486     }
487   }
488 
489   DataRate max_probe_bitrate = max_bitrate_;
490   if (max_total_allocated_bitrate_ > DataRate::Zero()) {
491     // If a max allocated bitrate has been configured, allow probing up to 2x
492     // that rate. This allows some overhead to account for bursty streams,
493     // which otherwise would have to ramp up when the overshoot is already in
494     // progress.
495     // It also avoids minor quality reduction caused by probes often being
496     // received at slightly less than the target probe bitrate.
497     max_probe_bitrate =
498         std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2);
499   }
500 
501   DataRate estimate_capped_bitrate = DataRate::PlusInfinity();
502   if (config_.limit_probe_target_rate_to_loss_bwe) {
503     switch (bandwidth_limited_cause_) {
504       case BandwidthLimitedCause::kLossLimitedBweDecreasing:
505         // If bandwidth estimate is decreasing because of packet loss, do not
506         // send probes.
507         return {};
508       case BandwidthLimitedCause::kLossLimitedBweIncreasing:
509         estimate_capped_bitrate =
510             std::min(max_probe_bitrate,
511                      estimated_bitrate_ * config_.loss_limited_probe_scale);
512         break;
513       case BandwidthLimitedCause::kDelayBasedLimited:
514         break;
515     }
516   }
517   if (config_.network_state_estimate_probing_interval->IsFinite() &&
518       network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) {
519     if (network_estimate_->link_capacity_upper.IsZero()) {
520       RTC_LOG(LS_INFO) << "Not sending probe, Network state estimate is zero";
521       return {};
522     }
523     estimate_capped_bitrate =
524         std::min({estimate_capped_bitrate, max_probe_bitrate,
525                   network_estimate_->link_capacity_upper *
526                       config_.network_state_probe_scale});
527   }
528 
529   std::vector<ProbeClusterConfig> pending_probes;
530   for (DataRate bitrate : bitrates_to_probe) {
531     RTC_DCHECK(!bitrate.IsZero());
532 
533     bitrate = std::min(bitrate, estimate_capped_bitrate);
534     if (bitrate > max_probe_bitrate) {
535       bitrate = max_probe_bitrate;
536       probe_further = false;
537     }
538 
539     ProbeClusterConfig config;
540     config.at_time = now;
541     config.target_data_rate = bitrate;
542     if (network_estimate_ &&
543         config_.network_state_estimate_probing_interval->IsFinite()) {
544       config.target_duration = config_.network_state_probe_duration;
545     } else {
546       config.target_duration = config_.min_probe_duration;
547     }
548 
549     config.target_probe_count = config_.min_probe_packets_sent;
550     config.id = next_probe_cluster_id_;
551     next_probe_cluster_id_++;
552     MaybeLogProbeClusterCreated(event_log_, config);
553     pending_probes.push_back(config);
554   }
555   time_last_probing_initiated_ = now;
556   if (probe_further) {
557     state_ = State::kWaitingForProbingResult;
558     // Dont expect probe results to be larger than a fraction of the actual
559     // probe rate.
560     min_bitrate_to_probe_further_ =
561         std::min(estimate_capped_bitrate, (*(bitrates_to_probe.end() - 1))) *
562         config_.further_probe_threshold;
563   } else {
564     state_ = State::kProbingComplete;
565     min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
566   }
567   return pending_probes;
568 }
569 
570 }  // namespace webrtc
571