Skip to content

Commit 33cc835

Browse files
perkjWebRTC LUCI CQ
authored andcommitted
Ignore allocated bitrate during initial exponential BWE.
The reason why we want to do this is because audio can allocate a needed bitrate before video when starting a call, which may lead to a race between the first probe result and updating the allocated bitrate. That is the, initial probe will try to probe up to the max configured bitrate. ProbeController::SetFirstProbeToMaxBitrate will allow the first probe to continue up to the max configured bitrate, regardless of of the max allocated bitrate. Bug: webrtc:14928 Change-Id: I6e0ae90e21a78466527f3464951e6033dc846470 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/346760 Reviewed-by: Diep Bui <[email protected]> Commit-Queue: Per Kjellander <[email protected]> Reviewed-by: Erik Språng <[email protected]> Reviewed-by: Per Kjellander <[email protected]> Cr-Commit-Position: refs/heads/main@{#42049}
1 parent 7000b99 commit 33cc835

File tree

6 files changed

+109
-11
lines changed

6 files changed

+109
-11
lines changed

api/transport/network_types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ struct StreamsConfig {
4646
~StreamsConfig();
4747
Timestamp at_time = Timestamp::PlusInfinity();
4848
absl::optional<bool> requests_alr_probing;
49+
// If `initial_probe_to_max_bitrate` is set to true, the first probe
50+
// may probe up to the max configured bitrate and can ignore
51+
// max_total_allocated_bitrate.
52+
absl::optional<bool> initial_probe_to_max_bitrate;
4953
absl::optional<double> pacing_factor;
5054

5155
// TODO(srte): Use BitrateAllocationLimits here.

call/rtp_transport_controller_send.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ void RtpTransportControllerSend::ReconfigureBandwidthEstimation(
262262
RTC_DCHECK_RUN_ON(&sequence_checker_);
263263
bwe_settings_ = settings;
264264

265+
bool allow_probe_without_media = bwe_settings_.allow_probe_without_media &&
266+
packet_router_.SupportsRtxPayloadPadding();
267+
streams_config_.initial_probe_to_max_bitrate = allow_probe_without_media;
268+
pacer_.SetAllowProbeWithoutMediaPacket(allow_probe_without_media);
269+
265270
if (controller_) {
266271
// Recreate the controller and handler.
267272
control_handler_ = nullptr;
@@ -275,9 +280,6 @@ void RtpTransportControllerSend::ReconfigureBandwidthEstimation(
275280
UpdateNetworkAvailability();
276281
}
277282
}
278-
pacer_.SetAllowProbeWithoutMediaPacket(
279-
bwe_settings_.allow_probe_without_media &&
280-
packet_router_.SupportsRtxPayloadPadding());
281283
}
282284

283285
void RtpTransportControllerSend::RegisterTargetTransferRateObserver(

modules/congestion_controller/goog_cc/goog_cc_network_control.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(
218218
probe_controller_->EnablePeriodicAlrProbing(
219219
*initial_config_->stream_based_config.requests_alr_probing);
220220
}
221+
if (initial_config_->stream_based_config.initial_probe_to_max_bitrate) {
222+
probe_controller_->SetFirstProbeToMaxBitrate(
223+
*initial_config_->stream_based_config.initial_probe_to_max_bitrate);
224+
}
221225
absl::optional<DataRate> total_bitrate =
222226
initial_config_->stream_based_config.max_total_allocated_bitrate;
223227
if (total_bitrate) {

modules/congestion_controller/goog_cc/probe_controller.cc

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,22 @@ std::vector<ProbeClusterConfig> ProbeController::OnNetworkAvailability(
272272
return std::vector<ProbeClusterConfig>();
273273
}
274274

275+
void ProbeController::UpdateState(State new_state) {
276+
switch (new_state) {
277+
case State::kInit:
278+
state_ = State::kInit;
279+
break;
280+
case State::kWaitingForProbingResult:
281+
state_ = State::kWaitingForProbingResult;
282+
break;
283+
case State::kProbingComplete:
284+
state_ = State::kProbingComplete;
285+
waiting_for_initial_probe_result_ = false;
286+
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
287+
break;
288+
}
289+
}
290+
275291
std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
276292
Timestamp at_time) {
277293
RTC_DCHECK(network_available_);
@@ -287,6 +303,8 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
287303
probes.push_back(config_.second_exponential_probe_scale.Value() *
288304
start_bitrate_);
289305
}
306+
waiting_for_initial_probe_result_ = true;
307+
290308
return InitiateProbing(at_time, probes, true);
291309
}
292310

@@ -307,6 +325,7 @@ std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
307325
if (config_.abort_further_probe_if_max_lower_than_current &&
308326
(bitrate > max_bitrate_ ||
309327
(!max_total_allocated_bitrate_.IsZero() &&
328+
!(waiting_for_initial_probe_result_ && first_probe_to_max_bitrate_) &&
310329
bitrate > 2 * max_total_allocated_bitrate_))) {
311330
// No need to continue probing.
312331
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
@@ -335,6 +354,11 @@ void ProbeController::EnablePeriodicAlrProbing(bool enable) {
335354
enable_periodic_alr_probing_ = enable;
336355
}
337356

357+
void ProbeController::SetFirstProbeToMaxBitrate(
358+
bool first_probe_to_max_bitrate) {
359+
first_probe_to_max_bitrate_ = first_probe_to_max_bitrate;
360+
}
361+
338362
void ProbeController::SetAlrStartTimeMs(
339363
absl::optional<int64_t> alr_start_time_ms) {
340364
if (alr_start_time_ms) {
@@ -391,6 +415,7 @@ void ProbeController::SetNetworkStateEstimate(
391415
void ProbeController::Reset(Timestamp at_time) {
392416
bandwidth_limited_cause_ = BandwidthLimitedCause::kDelayBasedLimited;
393417
state_ = State::kInit;
418+
waiting_for_initial_probe_result_ = false;
394419
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
395420
time_last_probing_initiated_ = Timestamp::Zero();
396421
estimated_bitrate_ = DataRate::Zero();
@@ -452,8 +477,7 @@ std::vector<ProbeClusterConfig> ProbeController::Process(Timestamp at_time) {
452477
kMaxWaitingTimeForProbingResult) {
453478
if (state_ == State::kWaitingForProbingResult) {
454479
RTC_LOG(LS_INFO) << "kWaitingForProbingResult: timeout";
455-
state_ = State::kProbingComplete;
456-
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
480+
UpdateState(State::kProbingComplete);
457481
}
458482
}
459483
if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) {
@@ -480,14 +504,14 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
480504
: std::min(max_total_allocated_bitrate_, max_bitrate_);
481505
if (std::min(network_estimate, estimated_bitrate_) >
482506
config_.skip_if_estimate_larger_than_fraction_of_max * max_probe_rate) {
483-
state_ = State::kProbingComplete;
484-
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
507+
UpdateState(State::kProbingComplete);
485508
return {};
486509
}
487510
}
488511

489512
DataRate max_probe_bitrate = max_bitrate_;
490-
if (max_total_allocated_bitrate_ > DataRate::Zero()) {
513+
if (max_total_allocated_bitrate_ > DataRate::Zero() &&
514+
!waiting_for_initial_probe_result_) {
491515
// If a max allocated bitrate has been configured, allow probing up to 2x
492516
// that rate. This allows some overhead to account for bursty streams,
493517
// which otherwise would have to ramp up when the overshoot is already in
@@ -555,15 +579,14 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
555579
}
556580
time_last_probing_initiated_ = now;
557581
if (probe_further) {
558-
state_ = State::kWaitingForProbingResult;
582+
UpdateState(State::kWaitingForProbingResult);
559583
// Dont expect probe results to be larger than a fraction of the actual
560584
// probe rate.
561585
min_bitrate_to_probe_further_ =
562586
std::min(estimate_capped_bitrate, (*(bitrates_to_probe.end() - 1))) *
563587
config_.further_probe_threshold;
564588
} else {
565-
state_ = State::kProbingComplete;
566-
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
589+
UpdateState(State::kProbingComplete);
567590
}
568591
return pending_probes;
569592
}

modules/congestion_controller/goog_cc/probe_controller.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ class ProbeController {
121121
Timestamp at_time);
122122

123123
void EnablePeriodicAlrProbing(bool enable);
124+
// The first initial probe ignores allocated bitrate constraints and probe up
125+
// to max configured bitrate configured via SetBitrates.
126+
void SetFirstProbeToMaxBitrate(bool first_probe_to_max_bitrate);
124127

125128
void SetAlrStartTimeMs(absl::optional<int64_t> alr_start_time);
126129
void SetAlrEndedTimeMs(int64_t alr_end_time);
@@ -148,6 +151,7 @@ class ProbeController {
148151
kProbingComplete,
149152
};
150153

154+
void UpdateState(State new_state);
151155
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig>
152156
InitiateExponentialProbing(Timestamp at_time);
153157
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> InitiateProbing(
@@ -158,6 +162,8 @@ class ProbeController {
158162
bool TimeForNetworkStateProbe(Timestamp at_time) const;
159163

160164
bool network_available_;
165+
bool waiting_for_initial_probe_result_ = false;
166+
bool first_probe_to_max_bitrate_ = false;
161167
BandwidthLimitedCause bandwidth_limited_cause_ =
162168
BandwidthLimitedCause::kDelayBasedLimited;
163169
State state_;

modules/congestion_controller/goog_cc/probe_controller_unittest.cc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,32 @@ TEST(ProbeControllerTest, TestExponentialProbing) {
327327
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
328328
}
329329

330+
TEST(ProbeControllerTest, ExponentialProbingStopIfMaxBitrateLow) {
331+
ProbeControllerFixture fixture(
332+
"WebRTC-Bwe-ProbingConfiguration/abort_further:true/");
333+
std::unique_ptr<ProbeController> probe_controller =
334+
fixture.CreateController();
335+
ASSERT_THAT(
336+
probe_controller->OnNetworkAvailability({.network_available = true}),
337+
IsEmpty());
338+
auto probes = probe_controller->SetBitrates(
339+
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
340+
ASSERT_THAT(probes, SizeIs(Gt(0)));
341+
342+
// Repeated probe normally is sent when estimated bitrate climbs above
343+
// 0.7 * 6 * kStartBitrate = 1260. But since max bitrate is low, expect
344+
// exponential probing to stop.
345+
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
346+
/*max_bitrate=*/kStartBitrate,
347+
fixture.CurrentTime());
348+
EXPECT_THAT(probes, IsEmpty());
349+
350+
probes = probe_controller->SetEstimatedBitrate(
351+
DataRate::BitsPerSec(1800), BandwidthLimitedCause::kDelayBasedLimited,
352+
fixture.CurrentTime());
353+
EXPECT_THAT(probes, IsEmpty());
354+
}
355+
330356
TEST(ProbeControllerTest, ExponentialProbingStopIfMaxAllocatedBitrateLow) {
331357
ProbeControllerFixture fixture(
332358
"WebRTC-Bwe-ProbingConfiguration/abort_further:true/");
@@ -352,6 +378,39 @@ TEST(ProbeControllerTest, ExponentialProbingStopIfMaxAllocatedBitrateLow) {
352378
EXPECT_THAT(probes, IsEmpty());
353379
}
354380

381+
TEST(ProbeControllerTest,
382+
InitialProbingIgnoreLowMaxAllocatedbitrateIfSetFirstProbeToMaxBitrate) {
383+
ProbeControllerFixture fixture(
384+
"WebRTC-Bwe-ProbingConfiguration/abort_further:true/");
385+
std::unique_ptr<ProbeController> probe_controller =
386+
fixture.CreateController();
387+
ASSERT_THAT(
388+
probe_controller->OnNetworkAvailability({.network_available = true}),
389+
IsEmpty());
390+
auto probes = probe_controller->SetBitrates(
391+
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
392+
ASSERT_THAT(probes, SizeIs(Gt(0)));
393+
probe_controller->SetFirstProbeToMaxBitrate(true);
394+
395+
// Repeated probe is sent when estimated bitrate climbs above
396+
// 0.7 * 6 * kStartBitrate = 1260. During the initial probe, we ignore the
397+
// allocation limit and probe up to the max.
398+
probes = probe_controller->OnMaxTotalAllocatedBitrate(kStartBitrate,
399+
fixture.CurrentTime());
400+
EXPECT_THAT(probes, IsEmpty());
401+
402+
probes = probe_controller->SetEstimatedBitrate(
403+
DataRate::BitsPerSec(1800), BandwidthLimitedCause::kDelayBasedLimited,
404+
fixture.CurrentTime());
405+
EXPECT_EQ(probes.size(), 1u);
406+
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
407+
408+
probes = probe_controller->SetEstimatedBitrate(
409+
probes[0].target_data_rate, BandwidthLimitedCause::kDelayBasedLimited,
410+
fixture.CurrentTime());
411+
EXPECT_EQ(probes.size(), 1u);
412+
}
413+
355414
TEST(ProbeControllerTest, TestExponentialProbingTimeout) {
356415
ProbeControllerFixture fixture;
357416
std::unique_ptr<ProbeController> probe_controller =

0 commit comments

Comments
 (0)