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