The value is today set to 200 which is too low for an audio packet to trigger sending probes. For the initial probing, it would be good if audio packets, that may arrive before the first video frame can trigger sending a probe. Also fix field trial parsing of required number of probes. Bug: webrc:14392 Change-Id: I1f3cebcda38b71446e3602eef9cfa76de61a1ccf Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/275620 Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Per Kjellander <perkj@webrtc.org> Reviewed-by: Diep Bui <diepbp@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38089}
838 lines
35 KiB
C++
838 lines
35 KiB
C++
/*
|
|
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
#include "modules/congestion_controller/goog_cc/probe_controller.h"
|
|
|
|
#include <memory>
|
|
|
|
#include "api/units/data_rate.h"
|
|
#include "api/units/time_delta.h"
|
|
#include "api/units/timestamp.h"
|
|
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
|
|
#include "rtc_base/logging.h"
|
|
#include "system_wrappers/include/clock.h"
|
|
#include "test/explicit_key_value_config.h"
|
|
#include "test/gmock.h"
|
|
#include "test/gtest.h"
|
|
|
|
using ::testing::NiceMock;
|
|
|
|
namespace webrtc {
|
|
namespace test {
|
|
|
|
namespace {
|
|
|
|
constexpr DataRate kMinBitrate = DataRate::BitsPerSec(100);
|
|
constexpr DataRate kStartBitrate = DataRate::BitsPerSec(300);
|
|
constexpr DataRate kMaxBitrate = DataRate::BitsPerSec(10000);
|
|
|
|
constexpr TimeDelta kExponentialProbingTimeout = TimeDelta::Seconds(5);
|
|
|
|
constexpr TimeDelta kAlrProbeInterval = TimeDelta::Seconds(5);
|
|
constexpr TimeDelta kAlrEndedTimeout = TimeDelta::Seconds(3);
|
|
constexpr TimeDelta kBitrateDropTimeout = TimeDelta::Seconds(5);
|
|
} // namespace
|
|
|
|
class ProbeControllerFixture {
|
|
public:
|
|
explicit ProbeControllerFixture(absl::string_view field_trials = "")
|
|
: field_trial_config_(field_trials), clock_(100000000L) {}
|
|
|
|
std::unique_ptr<ProbeController> CreateController() {
|
|
return std::make_unique<ProbeController>(&field_trial_config_,
|
|
&mock_rtc_event_log);
|
|
}
|
|
|
|
Timestamp CurrentTime() { return clock_.CurrentTime(); }
|
|
void AdvanceTime(TimeDelta delta) { clock_.AdvanceTime(delta); }
|
|
|
|
ExplicitKeyValueConfig field_trial_config_;
|
|
SimulatedClock clock_;
|
|
NiceMock<MockRtcEventLog> mock_rtc_event_log;
|
|
};
|
|
|
|
TEST(ProbeControllerTest, InitiatesProbingAtStart) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_GE(probes.size(), 2u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, SetsDefaultTargetDurationAndTargetProbeCount) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
std::vector<ProbeClusterConfig> probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
ASSERT_GE(probes.size(), 2u);
|
|
|
|
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(15));
|
|
EXPECT_EQ(probes[0].target_probe_count, 5);
|
|
}
|
|
|
|
TEST(ProbeControllerTest,
|
|
FieldTrialsOverrideDefaultTargetDurationAndTargetProbeCount) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingBehavior/"
|
|
"min_probe_packets_sent:2,min_probe_duration:123ms/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
std::vector<ProbeClusterConfig> probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
ASSERT_GE(probes.size(), 2u);
|
|
|
|
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(123));
|
|
EXPECT_EQ(probes[0].target_probe_count, 2);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->OnNetworkAvailability(
|
|
{.at_time = fixture.CurrentTime(), .network_available = false});
|
|
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
|
|
kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
probes = probe_controller->OnNetworkAvailability(
|
|
{.at_time = fixture.CurrentTime(), .network_available = true});
|
|
EXPECT_GE(probes.size(), 2u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, CanConfigureInitialProbeRateFactor) {
|
|
ProbeControllerFixture fixture("WebRTC-Bwe-ProbingConfiguration/p1:2,p2:3/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
|
|
EXPECT_EQ(probes[1].target_data_rate, kStartBitrate * 3);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, DisableSecondInitialProbeIfRateFactorZero) {
|
|
ProbeControllerFixture fixture("WebRTC-Bwe-ProbingConfiguration/p1:2,p2:0/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
// Long enough to time out exponential probing.
|
|
fixture.AdvanceTime(kExponentialProbingTimeout);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate + DataRate::BitsPerSec(100),
|
|
fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrate.bps() + 100);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, ProbesOnMaxBitrateIncreaseOnlyWhenInAlr) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kMaxBitrate - DataRate::BitsPerSec(1),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
|
|
// Wait long enough to time out exponential probing.
|
|
fixture.AdvanceTime(kExponentialProbingTimeout);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
|
|
// Probe when in alr.
|
|
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
|
|
probes = probe_controller->OnMaxTotalAllocatedBitrate(
|
|
kMaxBitrate + DataRate::BitsPerSec(1), fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
|
|
// Do not probe when not in alr.
|
|
probe_controller->SetAlrStartTimeMs(absl::nullopt);
|
|
probes = probe_controller->OnMaxTotalAllocatedBitrate(
|
|
kMaxBitrate + DataRate::BitsPerSec(2), fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
}
|
|
|
|
TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
// Long enough to time out exponential probing.
|
|
fixture.AdvanceTime(kExponentialProbingTimeout);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate + DataRate::BitsPerSec(100),
|
|
fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate,
|
|
kMaxBitrate + DataRate::BitsPerSec(100));
|
|
}
|
|
|
|
TEST(ProbeControllerTest, TestExponentialProbing) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
|
|
// Repeated probe should only be sent when estimated bitrate climbs above
|
|
// 0.7 * 6 * kStartBitrate = 1260.
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(1000),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(1800),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, TestExponentialProbingTimeout) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
// Advance far enough to cause a time out in waiting for probing result.
|
|
fixture.AdvanceTime(kExponentialProbingTimeout);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(1800),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, RequestProbeInAlr) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_GE(probes.size(), 2u);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
|
|
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
|
|
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(250),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
probes = probe_controller->RequestProbe(fixture.CurrentTime());
|
|
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
|
|
probe_controller->SetAlrStartTimeMs(absl::nullopt);
|
|
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(250),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
probe_controller->SetAlrEndedTimeMs(fixture.CurrentTime().ms());
|
|
fixture.AdvanceTime(kAlrEndedTimeout - TimeDelta::Millis(1));
|
|
probes = probe_controller->RequestProbe(fixture.CurrentTime());
|
|
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
|
|
probe_controller->SetAlrStartTimeMs(absl::nullopt);
|
|
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(250),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
probe_controller->SetAlrEndedTimeMs(fixture.CurrentTime().ms());
|
|
fixture.AdvanceTime(kAlrEndedTimeout + TimeDelta::Millis(1));
|
|
probes = probe_controller->RequestProbe(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
|
|
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
|
|
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(250),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
fixture.AdvanceTime(kBitrateDropTimeout + TimeDelta::Millis(1));
|
|
probes = probe_controller->RequestProbe(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, PeriodicProbing) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
probe_controller->EnablePeriodicAlrProbing(true);
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
|
|
Timestamp start_time = fixture.CurrentTime();
|
|
|
|
// Expect the controller to send a new probe after 5s has passed.
|
|
probe_controller->SetAlrStartTimeMs(start_time.ms());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), 1000);
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
|
|
// The following probe should be sent at 10s into ALR.
|
|
probe_controller->SetAlrStartTimeMs(start_time.ms());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(4));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
|
|
probe_controller->SetAlrStartTimeMs(start_time.ms());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(1));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, PeriodicProbingAfterReset) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
Timestamp alr_start_time = fixture.CurrentTime();
|
|
|
|
probe_controller->SetAlrStartTimeMs(alr_start_time.ms());
|
|
probe_controller->EnablePeriodicAlrProbing(true);
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probe_controller->Reset(fixture.CurrentTime());
|
|
|
|
fixture.AdvanceTime(TimeDelta::Seconds(10));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
// Since bitrates are not yet set, no probe is sent event though we are in ALR
|
|
// mode.
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
|
|
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
|
|
kMaxBitrate, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
|
|
// Make sure we use `kStartBitrateBps` as the estimated bitrate
|
|
// until SetEstimatedBitrate is called with an updated estimate.
|
|
fixture.AdvanceTime(TimeDelta::Seconds(10));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, TestExponentialProbingOverflow) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
const DataRate kMbpsMultiplier = DataRate::KilobitsPerSec(1000);
|
|
auto probes = probe_controller->SetBitrates(kMinBitrate, 10 * kMbpsMultiplier,
|
|
100 * kMbpsMultiplier,
|
|
fixture.CurrentTime());
|
|
// Verify that probe bitrate is capped at the specified max bitrate.
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
60 * kMbpsMultiplier, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, 100 * kMbpsMultiplier);
|
|
// Verify that repeated probes aren't sent.
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
100 * kMbpsMultiplier, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, TestAllocatedBitrateCap) {
|
|
ProbeControllerFixture fixture;
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
const DataRate kMbpsMultiplier = DataRate::KilobitsPerSec(1000);
|
|
const DataRate kMaxBitrate = 100 * kMbpsMultiplier;
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, 10 * kMbpsMultiplier, kMaxBitrate, fixture.CurrentTime());
|
|
|
|
// Configure ALR for periodic probing.
|
|
probe_controller->EnablePeriodicAlrProbing(true);
|
|
Timestamp alr_start_time = fixture.CurrentTime();
|
|
probe_controller->SetAlrStartTimeMs(alr_start_time.ms());
|
|
|
|
DataRate estimated_bitrate = kMaxBitrate / 10;
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
estimated_bitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
|
|
// Set a max allocated bitrate below the current estimate.
|
|
DataRate max_allocated = estimated_bitrate - 1 * kMbpsMultiplier;
|
|
probes = probe_controller->OnMaxTotalAllocatedBitrate(max_allocated,
|
|
fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty()); // No probe since lower than current max.
|
|
|
|
// Probes such as ALR capped at 2x the max allocation limit.
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, 2 * max_allocated);
|
|
|
|
// Remove allocation limit.
|
|
EXPECT_TRUE(
|
|
probe_controller
|
|
->OnMaxTotalAllocatedBitrate(DataRate::Zero(), fixture.CurrentTime())
|
|
.empty());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, estimated_bitrate * 2);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, ConfigurableProbingFieldTrial) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"p1:2,p2:5,step_size:3,further_probe_threshold:0.8,"
|
|
"alloc_p1:2,alloc_p2,min_probe_packets_sent:2/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
|
|
DataRate::KilobitsPerSec(5000),
|
|
fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 2u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), 600);
|
|
EXPECT_EQ(probes[0].target_probe_count, 2);
|
|
EXPECT_EQ(probes[1].target_data_rate.bps(), 1500);
|
|
EXPECT_EQ(probes[1].target_probe_count, 2);
|
|
|
|
// Repeated probe should only be sent when estimated bitrate climbs above
|
|
// 0.8 * 5 * kStartBitrateBps = 1200.
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(1100),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 0u);
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(1250),
|
|
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), 3 * 1250);
|
|
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
|
|
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
|
|
probes = probe_controller->OnMaxTotalAllocatedBitrate(
|
|
DataRate::KilobitsPerSec(200), fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate.bps(), 400'000);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, LimitAlrProbeWhenLossBasedBweLimited) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"limit_probe_target_rate_to_loss_bwe:true/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
probe_controller->EnablePeriodicAlrProbing(true);
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
// Expect the controller to send a new probe after 5s has passed.
|
|
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss*/ true,
|
|
fixture.CurrentTime());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(6));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, DataRate::BitsPerSec(500));
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(6));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_TRUE(!probes.empty());
|
|
EXPECT_GT(probes[0].target_data_rate, DataRate::BitsPerSec(500));
|
|
}
|
|
|
|
TEST(ProbeControllerTest, PeriodicProbeAtUpperNetworkStateEstimate) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/network_state_interval:5s/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(5000), /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
// Expect the controller to send a new probe after 5s has passed.
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(6);
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
|
|
}
|
|
|
|
TEST(ProbeControllerTest,
|
|
LimitProbeAtUpperNetworkStateEstimateIfLossBasedLimited) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
// Expect the controller to send a new probe after 5s has passed.
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(600);
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/true,
|
|
fixture.CurrentTime());
|
|
// Expect the controller to send a new probe after 5s has passed.
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_TRUE(!probes.empty());
|
|
EXPECT_EQ(probes[0].target_data_rate, DataRate::BitsPerSec(500));
|
|
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_TRUE(!probes.empty());
|
|
EXPECT_GT(probes[0].target_data_rate, DataRate::BitsPerSec(500));
|
|
}
|
|
|
|
TEST(ProbeControllerTest, AlrProbesLimitedByNetworkStateEstimate) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/network_state_interval:5s/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
probe_controller->EnablePeriodicAlrProbing(true);
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::KilobitsPerSec(6), /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
|
|
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, kMaxBitrate);
|
|
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = DataRate::BitsPerSec(8000);
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, CanSetLongerProbeDurationAfterNetworkStateEstimate) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"network_state_interval:5s,network_state_probe_duration:100ms/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
DataRate::KilobitsPerSec(5), /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
ASSERT_FALSE(probes.empty());
|
|
EXPECT_LT(probes[0].target_duration, TimeDelta::Millis(100));
|
|
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(6);
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(100));
|
|
}
|
|
|
|
TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateIncrease) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"network_state_interval:5s,network_state_fast_rampup_rate:2.0/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
// Need to wait at least one second before process can trigger a new probe.
|
|
fixture.AdvanceTime(TimeDelta::Millis(1100));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = kStartBitrate;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
// No probe since NetworkStateEstimate is not higher than the set
|
|
// estimated bitrate.
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
// If NetworkState increase just a bit, dont expect the probe to be sent
|
|
// immediately.
|
|
state_estimate.link_capacity_upper = kStartBitrate * 1.4;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
// If NetworkState increase dramatically, expect a probe to be sent.
|
|
state_estimate.link_capacity_upper = kStartBitrate * 1.4 * 2;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateDrop) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"network_state_interval:5s,network_state_drop_down_rate:0.5/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
// Need to wait at least one second before process can trigger a new probe.
|
|
fixture.AdvanceTime(TimeDelta::Millis(1100));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = kStartBitrate;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
// No probe since NetworkStateEstimate is not lower than the set
|
|
// estimated bitrate.
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
// If NetworkState decrease just a bit, dont expect the probe to be sent
|
|
// immediately.
|
|
state_estimate.link_capacity_upper = kStartBitrate * 0.9;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
// If NetworkState decrease dramatically, expect a probe to be sent.
|
|
state_estimate.link_capacity_upper = kStartBitrate * 0.9 * 0.5;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_EQ(probes.size(), 1u);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateDropLossLimited) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"network_state_interval:5s,network_state_drop_down_rate:0.5,limit_probe_"
|
|
"target_rate_to_loss_bwe:true/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
// Need to wait at least one second before process can trigger a new probe.
|
|
fixture.AdvanceTime(TimeDelta::Millis(1100));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = kStartBitrate;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
// Loss limited.
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
kStartBitrate / 3, /*bwe_limited_due_to_packet_loss=*/true,
|
|
fixture.CurrentTime());
|
|
// If NetworkState decrease dramatically, expect a probe to be sent.
|
|
// But limited to loss based estimate.
|
|
state_estimate.link_capacity_upper = kStartBitrate / 2;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
ASSERT_EQ(probes.size(), 1u);
|
|
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate / 3);
|
|
}
|
|
|
|
TEST(ProbeControllerTest, DontProbeFurtherWhenLossLimited) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
ASSERT_FALSE(probes.empty());
|
|
|
|
// Need to wait at least one second before process can trigger a new probe.
|
|
fixture.AdvanceTime(TimeDelta::Millis(1100));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = 3 * kStartBitrate;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_FALSE(probes.empty());
|
|
EXPECT_LT(probes[0].target_data_rate, state_estimate.link_capacity_upper);
|
|
// Expect that no more probes are sent immediately if BWE is loss limited.
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
probes[0].target_data_rate, /*bwe_limited_due_to_packet_loss=*/true,
|
|
fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
}
|
|
|
|
TEST(ProbeControllerTest, ProbeFurtherWhenDelayBasedLimited) {
|
|
ProbeControllerFixture fixture(
|
|
"WebRTC-Bwe-ProbingConfiguration/"
|
|
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
|
|
std::unique_ptr<ProbeController> probe_controller =
|
|
fixture.CreateController();
|
|
|
|
auto probes = probe_controller->SetBitrates(
|
|
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
|
ASSERT_FALSE(probes.empty());
|
|
|
|
// Need to wait at least one second before process can trigger a new probe.
|
|
fixture.AdvanceTime(TimeDelta::Millis(1100));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_TRUE(probes.empty());
|
|
|
|
NetworkStateEstimate state_estimate;
|
|
state_estimate.link_capacity_upper = 3 * kStartBitrate;
|
|
probe_controller->SetNetworkStateEstimate(state_estimate);
|
|
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
|
probes = probe_controller->Process(fixture.CurrentTime());
|
|
EXPECT_FALSE(probes.empty());
|
|
EXPECT_LT(probes[0].target_data_rate, state_estimate.link_capacity_upper);
|
|
// Since the probe was successfull, expect to continue probing.
|
|
probes = probe_controller->SetEstimatedBitrate(
|
|
probes[0].target_data_rate, /*bwe_limited_due_to_packet_loss=*/false,
|
|
fixture.CurrentTime());
|
|
EXPECT_FALSE(probes.empty());
|
|
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace webrtc
|