Replaces redundant congestion controller components

This CL replaces components in the congestion controller module
that are identical to equivalent components in the rtp and goog_cc
subfolder. Some redundant components are left as they were not
trivial to replace.

Bug: webrtc:8415
Change-Id: I86a1f164d7b100b8ec8ba7dbc1c9bda2128a4f37
Reviewed-on: https://webrtc-review.googlesource.com/78521
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23384}
This commit is contained in:
Sebastian Jansson
2018-05-24 14:17:06 +02:00
committed by Commit Bot
parent ec2eb2218f
commit 172fd8536e
51 changed files with 22 additions and 2037 deletions

View File

@ -40,7 +40,6 @@ rtc_static_library("congestion_controller") {
deps = [
":delay_based_bwe",
":estimators",
":transport_feedback",
"..:module_api",
"../..:webrtc_common",
@ -54,6 +53,7 @@ rtc_static_library("congestion_controller") {
"../pacing",
"../remote_bitrate_estimator",
"../rtp_rtcp:rtp_rtcp_format",
"goog_cc:estimators",
]
if (!build_with_mozilla) {
@ -64,8 +64,6 @@ rtc_static_library("congestion_controller") {
rtc_static_library("transport_feedback") {
visibility = [ "*" ]
sources = [
"send_time_history.cc",
"send_time_history.h",
"transport_feedback_adapter.cc",
"transport_feedback_adapter.h",
]
@ -76,45 +74,7 @@ rtc_static_library("transport_feedback") {
"../../rtc_base:rtc_base_approved",
"../../system_wrappers:system_wrappers",
"../rtp_rtcp:rtp_rtcp_format",
]
}
rtc_source_set("estimators") {
configs += [ ":bwe_test_logging" ]
sources = [
"acknowledged_bitrate_estimator.cc",
"acknowledged_bitrate_estimator.h",
"bitrate_estimator.cc",
"bitrate_estimator.h",
"delay_increase_detector_interface.h",
"median_slope_estimator.cc",
"median_slope_estimator.h",
"probe_bitrate_estimator.cc",
"probe_bitrate_estimator.h",
"trendline_estimator.cc",
"trendline_estimator.h",
]
# TODO(jschuh): Bug 1348: fix this warning.
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
if (!build_with_chromium && is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
}
deps = [
"../../api:optional",
"../../logging:rtc_event_bwe",
"../../logging:rtc_event_log_api",
"../../rtc_base:checks",
"../../rtc_base:rtc_base_approved",
"../../rtc_base:rtc_numerics",
"../../rtc_base:safe_minmax",
"../../system_wrappers:field_trial_api",
"../../system_wrappers:metrics_api",
"../remote_bitrate_estimator:remote_bitrate_estimator",
"../rtp_rtcp:rtp_rtcp_format",
"rtp:transport_feedback",
]
}
@ -125,7 +85,6 @@ rtc_source_set("delay_based_bwe") {
"delay_based_bwe.h",
]
deps = [
":estimators",
"../../:typedefs",
"../../logging:rtc_event_bwe",
"../../logging:rtc_event_log_api",
@ -135,6 +94,7 @@ rtc_source_set("delay_based_bwe") {
"../../system_wrappers:metrics_api",
"../pacing",
"../remote_bitrate_estimator",
"goog_cc:estimators",
]
if (!build_with_chromium && is_clang) {
@ -148,25 +108,17 @@ if (rtc_include_tests) {
testonly = true
sources = [
"acknowledged_bitrate_estimator_unittest.cc",
"congestion_controller_unittests_helper.cc",
"congestion_controller_unittests_helper.h",
"delay_based_bwe_unittest.cc",
"delay_based_bwe_unittest_helper.cc",
"delay_based_bwe_unittest_helper.h",
"median_slope_estimator_unittest.cc",
"probe_bitrate_estimator_unittest.cc",
"probe_controller_unittest.cc",
"receive_side_congestion_controller_unittest.cc",
"send_side_congestion_controller_unittest.cc",
"send_time_history_unittest.cc",
"transport_feedback_adapter_unittest.cc",
"trendline_estimator_unittest.cc",
]
deps = [
":congestion_controller",
":delay_based_bwe",
":estimators",
":mock_congestion_controller",
":transport_feedback",
"../../logging:mocks",
@ -184,6 +136,7 @@ if (rtc_include_tests) {
"../remote_bitrate_estimator:remote_bitrate_estimator",
"../rtp_rtcp:rtp_rtcp_format",
"bbr:bbr_unittests",
"goog_cc:estimators",
"goog_cc:goog_cc_unittests",
"rtp:congestion_controller_unittests",
]

View File

@ -1,65 +0,0 @@
/*
* Copyright (c) 2017 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/acknowledged_bitrate_estimator.h"
#include <utility>
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/ptr_util.h"
namespace webrtc {
namespace {
bool IsInSendTimeHistory(const PacketFeedback& packet) {
return packet.send_time_ms != PacketFeedback::kNoSendTime;
}
} // namespace
AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator()
: AcknowledgedBitrateEstimator(rtc::MakeUnique<BitrateEstimator>()) {}
AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator(
std::unique_ptr<BitrateEstimator> bitrate_estimator)
: bitrate_estimator_(std::move(bitrate_estimator)) {}
void AcknowledgedBitrateEstimator::IncomingPacketFeedbackVector(
const std::vector<PacketFeedback>& packet_feedback_vector) {
RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(),
packet_feedback_vector.end(),
PacketFeedbackComparator()));
for (const auto& packet : packet_feedback_vector) {
if (IsInSendTimeHistory(packet)) {
MaybeExpectFastRateChange(packet.send_time_ms);
bitrate_estimator_->Update(packet.arrival_time_ms,
rtc::dchecked_cast<int>(packet.payload_size));
}
}
}
rtc::Optional<uint32_t> AcknowledgedBitrateEstimator::bitrate_bps() const {
return bitrate_estimator_->bitrate_bps();
}
void AcknowledgedBitrateEstimator::SetAlrEndedTimeMs(
int64_t alr_ended_time_ms) {
alr_ended_time_ms_.emplace(alr_ended_time_ms);
}
void AcknowledgedBitrateEstimator::MaybeExpectFastRateChange(
int64_t packet_send_time_ms) {
if (alr_ended_time_ms_ && packet_send_time_ms > *alr_ended_time_ms_) {
bitrate_estimator_->ExpectFastRateChange();
alr_ended_time_ms_.reset();
}
}
} // namespace webrtc

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2017 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGED_BITRATE_ESTIMATOR_H_
#define MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGED_BITRATE_ESTIMATOR_H_
#include <memory>
#include <vector>
#include "api/optional.h"
#include "modules/congestion_controller/bitrate_estimator.h"
namespace webrtc {
struct PacketFeedback;
class AcknowledgedBitrateEstimator {
public:
explicit AcknowledgedBitrateEstimator(
std::unique_ptr<BitrateEstimator> bitrate_estimator);
AcknowledgedBitrateEstimator();
void IncomingPacketFeedbackVector(
const std::vector<PacketFeedback>& packet_feedback_vector);
rtc::Optional<uint32_t> bitrate_bps() const;
void SetAlrEndedTimeMs(int64_t alr_ended_time_ms);
private:
void MaybeExpectFastRateChange(int64_t packet_arrival_time_ms);
rtc::Optional<int64_t> alr_ended_time_ms_;
std::unique_ptr<BitrateEstimator> bitrate_estimator_;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGED_BITRATE_ESTIMATOR_H_

View File

@ -1,135 +0,0 @@
/*
* Copyright (c) 2017 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/acknowledged_bitrate_estimator.h"
#include <utility>
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "rtc_base/fakeclock.h"
#include "rtc_base/ptr_util.h"
#include "test/gmock.h"
#include "test/gtest.h"
using testing::_;
using testing::NiceMock;
using testing::InSequence;
using testing::Return;
namespace webrtc {
namespace {
constexpr int64_t kFirstArrivalTimeMs = 10;
constexpr int64_t kFirstSendTimeMs = 10;
constexpr uint16_t kSequenceNumber = 1;
constexpr size_t kPayloadSize = 10;
class MockBitrateEstimator : public BitrateEstimator {
public:
MOCK_METHOD2(Update, void(int64_t now_ms, int bytes));
MOCK_CONST_METHOD0(bitrate_bps, rtc::Optional<uint32_t>());
MOCK_METHOD0(ExpectFastRateChange, void());
};
struct AcknowledgedBitrateEstimatorTestStates {
std::unique_ptr<AcknowledgedBitrateEstimator> acknowledged_bitrate_estimator;
MockBitrateEstimator* mock_bitrate_estimator;
};
AcknowledgedBitrateEstimatorTestStates CreateTestStates() {
AcknowledgedBitrateEstimatorTestStates states;
auto mock_bitrate_estimator = rtc::MakeUnique<MockBitrateEstimator>();
states.mock_bitrate_estimator = mock_bitrate_estimator.get();
states.acknowledged_bitrate_estimator =
rtc::MakeUnique<AcknowledgedBitrateEstimator>(
std::move(mock_bitrate_estimator));
return states;
}
std::vector<PacketFeedback> CreateFeedbackVector() {
std::vector<PacketFeedback> packet_feedback_vector;
const PacedPacketInfo pacing_info;
packet_feedback_vector.push_back(
PacketFeedback(kFirstArrivalTimeMs, kFirstSendTimeMs, kSequenceNumber,
kPayloadSize, pacing_info));
packet_feedback_vector.push_back(
PacketFeedback(kFirstArrivalTimeMs + 10, kFirstSendTimeMs + 10,
kSequenceNumber, kPayloadSize + 10, pacing_info));
return packet_feedback_vector;
}
} // anonymous namespace
TEST(LegacyTestAcknowledgedBitrateEstimator,
DontAddPacketsWhichAreNotInSendHistory) {
auto states = CreateTestStates();
std::vector<PacketFeedback> packet_feedback_vector;
packet_feedback_vector.push_back(
PacketFeedback(kFirstArrivalTimeMs, kSequenceNumber));
EXPECT_CALL(*states.mock_bitrate_estimator, Update(_, _)).Times(0);
states.acknowledged_bitrate_estimator->IncomingPacketFeedbackVector(
packet_feedback_vector);
}
TEST(LegacyTestAcknowledgedBitrateEstimator, UpdateBandwith) {
auto states = CreateTestStates();
auto packet_feedback_vector = CreateFeedbackVector();
{
InSequence dummy;
EXPECT_CALL(
*states.mock_bitrate_estimator,
Update(packet_feedback_vector[0].arrival_time_ms,
static_cast<int>(packet_feedback_vector[0].payload_size)))
.Times(1);
EXPECT_CALL(
*states.mock_bitrate_estimator,
Update(packet_feedback_vector[1].arrival_time_ms,
static_cast<int>(packet_feedback_vector[1].payload_size)))
.Times(1);
}
states.acknowledged_bitrate_estimator->IncomingPacketFeedbackVector(
packet_feedback_vector);
}
TEST(LegacyTestAcknowledgedBitrateEstimator, ExpectFastRateChangeWhenLeftAlr) {
auto states = CreateTestStates();
auto packet_feedback_vector = CreateFeedbackVector();
{
InSequence dummy;
EXPECT_CALL(
*states.mock_bitrate_estimator,
Update(packet_feedback_vector[0].arrival_time_ms,
static_cast<int>(packet_feedback_vector[0].payload_size)))
.Times(1);
EXPECT_CALL(*states.mock_bitrate_estimator, ExpectFastRateChange())
.Times(1);
EXPECT_CALL(
*states.mock_bitrate_estimator,
Update(packet_feedback_vector[1].arrival_time_ms,
static_cast<int>(packet_feedback_vector[1].payload_size)))
.Times(1);
}
states.acknowledged_bitrate_estimator->SetAlrEndedTimeMs(kFirstArrivalTimeMs +
1);
states.acknowledged_bitrate_estimator->IncomingPacketFeedbackVector(
packet_feedback_vector);
}
TEST(LegacyTestAcknowledgedBitrateEstimator, ReturnBitrate) {
auto states = CreateTestStates();
rtc::Optional<uint32_t> return_value(42);
EXPECT_CALL(*states.mock_bitrate_estimator, bitrate_bps())
.Times(1)
.WillOnce(Return(return_value));
EXPECT_EQ(return_value, states.acknowledged_bitrate_estimator->bitrate_bps());
}
} // namespace webrtc*/

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 2017 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/bitrate_estimator.h"
#include <cmath>
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
namespace webrtc {
namespace {
constexpr int kInitialRateWindowMs = 500;
constexpr int kRateWindowMs = 150;
} // namespace
BitrateEstimator::BitrateEstimator()
: sum_(0),
current_win_ms_(0),
prev_time_ms_(-1),
bitrate_estimate_(-1.0f),
bitrate_estimate_var_(50.0f) {}
BitrateEstimator::~BitrateEstimator() = default;
void BitrateEstimator::Update(int64_t now_ms, int bytes) {
int rate_window_ms = kRateWindowMs;
// We use a larger window at the beginning to get a more stable sample that
// we can use to initialize the estimate.
if (bitrate_estimate_ < 0.f)
rate_window_ms = kInitialRateWindowMs;
float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms);
if (bitrate_sample < 0.0f)
return;
if (bitrate_estimate_ < 0.0f) {
// This is the very first sample we get. Use it to initialize the estimate.
bitrate_estimate_ = bitrate_sample;
return;
}
// Define the sample uncertainty as a function of how far away it is from the
// current estimate.
float sample_uncertainty =
10.0f * std::abs(bitrate_estimate_ - bitrate_sample) / bitrate_estimate_;
float sample_var = sample_uncertainty * sample_uncertainty;
// Update a bayesian estimate of the rate, weighting it lower if the sample
// uncertainty is large.
// The bitrate estimate uncertainty is increased with each update to model
// that the bitrate changes over time.
float pred_bitrate_estimate_var = bitrate_estimate_var_ + 5.f;
bitrate_estimate_ = (sample_var * bitrate_estimate_ +
pred_bitrate_estimate_var * bitrate_sample) /
(sample_var + pred_bitrate_estimate_var);
bitrate_estimate_var_ = sample_var * pred_bitrate_estimate_var /
(sample_var + pred_bitrate_estimate_var);
BWE_TEST_LOGGING_PLOT(1, "acknowledged_bitrate", now_ms,
bitrate_estimate_ * 1000);
}
float BitrateEstimator::UpdateWindow(int64_t now_ms,
int bytes,
int rate_window_ms) {
// Reset if time moves backwards.
if (now_ms < prev_time_ms_) {
prev_time_ms_ = -1;
sum_ = 0;
current_win_ms_ = 0;
}
if (prev_time_ms_ >= 0) {
current_win_ms_ += now_ms - prev_time_ms_;
// Reset if nothing has been received for more than a full window.
if (now_ms - prev_time_ms_ > rate_window_ms) {
sum_ = 0;
current_win_ms_ %= rate_window_ms;
}
}
prev_time_ms_ = now_ms;
float bitrate_sample = -1.0f;
if (current_win_ms_ >= rate_window_ms) {
bitrate_sample = 8.0f * sum_ / static_cast<float>(rate_window_ms);
current_win_ms_ -= rate_window_ms;
sum_ = 0;
}
sum_ += bytes;
return bitrate_sample;
}
rtc::Optional<uint32_t> BitrateEstimator::bitrate_bps() const {
if (bitrate_estimate_ < 0.f)
return rtc::nullopt;
return bitrate_estimate_ * 1000;
}
void BitrateEstimator::ExpectFastRateChange() {
// By setting the bitrate-estimate variance to a higher value we allow the
// bitrate to change fast for the next few samples.
bitrate_estimate_var_ += 200;
}
} // namespace webrtc

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2017 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_BITRATE_ESTIMATOR_H_
#define MODULES_CONGESTION_CONTROLLER_BITRATE_ESTIMATOR_H_
#include <vector>
#include "api/optional.h"
namespace webrtc {
// Computes a bayesian estimate of the throughput given acks containing
// the arrival time and payload size. Samples which are far from the current
// estimate or are based on few packets are given a smaller weight, as they
// are considered to be more likely to have been caused by, e.g., delay spikes
// unrelated to congestion.
class BitrateEstimator {
public:
BitrateEstimator();
virtual ~BitrateEstimator();
virtual void Update(int64_t now_ms, int bytes);
virtual rtc::Optional<uint32_t> bitrate_bps() const;
virtual void ExpectFastRateChange();
private:
float UpdateWindow(int64_t now_ms, int bytes, int rate_window_ms);
int sum_;
int64_t current_win_ms_;
int64_t prev_time_ms_;
float bitrate_estimate_;
float bitrate_estimate_var_;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_BITRATE_ESTIMATOR_H_

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2017 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/congestion_controller_unittests_helper.h"
#include "rtc_base/checks.h"
#include "test/gtest.h"
namespace webrtc {
void ComparePacketFeedbackVectors(const std::vector<PacketFeedback>& truth,
const std::vector<PacketFeedback>& input) {
ASSERT_EQ(truth.size(), input.size());
size_t len = truth.size();
// truth contains the input data for the test, and input is what will be
// sent to the bandwidth estimator. truth.arrival_tims_ms is used to
// populate the transport feedback messages. As these times may be changed
// (because of resolution limits in the packets, and because of the time
// base adjustment performed by the TransportFeedbackAdapter at the first
// packet, the truth[x].arrival_time and input[x].arrival_time may not be
// equal. However, the difference must be the same for all x.
int64_t arrival_time_delta =
truth[0].arrival_time_ms - input[0].arrival_time_ms;
for (size_t i = 0; i < len; ++i) {
RTC_CHECK(truth[i].arrival_time_ms != PacketFeedback::kNotReceived);
if (input[i].arrival_time_ms != PacketFeedback::kNotReceived) {
EXPECT_EQ(truth[i].arrival_time_ms,
input[i].arrival_time_ms + arrival_time_delta);
}
EXPECT_EQ(truth[i].send_time_ms, input[i].send_time_ms);
EXPECT_EQ(truth[i].sequence_number, input[i].sequence_number);
EXPECT_EQ(truth[i].payload_size, input[i].payload_size);
EXPECT_EQ(truth[i].pacing_info, input[i].pacing_info);
}
}
} // namespace webrtc

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 2017 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_CONGESTION_CONTROLLER_UNITTESTS_HELPER_H_
#define MODULES_CONGESTION_CONTROLLER_CONGESTION_CONTROLLER_UNITTESTS_HELPER_H_
#include <vector>
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
namespace webrtc {
void ComparePacketFeedbackVectors(const std::vector<PacketFeedback>& truth,
const std::vector<PacketFeedback>& input);
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_CONGESTION_CONTROLLER_UNITTESTS_HELPER_H_

View File

@ -17,7 +17,7 @@
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "modules/congestion_controller/trendline_estimator.h"
#include "modules/congestion_controller/goog_cc/trendline_estimator.h"
#include "modules/pacing/paced_sender.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"

View File

@ -15,8 +15,8 @@
#include <utility>
#include <vector>
#include "modules/congestion_controller/delay_increase_detector_interface.h"
#include "modules/congestion_controller/probe_bitrate_estimator.h"
#include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h"
#include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/aimd_rate_control.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/inter_arrival.h"

View File

@ -17,8 +17,8 @@
#include <utility>
#include <vector>
#include "modules/congestion_controller/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/delay_based_bwe.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "rtc_base/constructormagic.h"
#include "system_wrappers/include/clock.h"

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2018 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_DELAY_INCREASE_DETECTOR_INTERFACE_H_
#define MODULES_CONGESTION_CONTROLLER_DELAY_INCREASE_DETECTOR_INTERFACE_H_
#include <stdint.h>
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "rtc_base/constructormagic.h"
namespace webrtc {
class DelayIncreaseDetectorInterface {
public:
DelayIncreaseDetectorInterface() {}
virtual ~DelayIncreaseDetectorInterface() {}
// Update the detector with a new sample. The deltas should represent deltas
// between timestamp groups as defined by the InterArrival class.
virtual void Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms) = 0;
virtual BandwidthUsage State() const = 0;
RTC_DISALLOW_COPY_AND_ASSIGN(DelayIncreaseDetectorInterface);
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_DELAY_INCREASE_DETECTOR_INTERFACE_H_

View File

@ -17,7 +17,6 @@
#include "rtc_base/ptr_util.h"
namespace webrtc {
namespace webrtc_cc {
namespace {
bool IsInSendTimeHistory(const PacketFeedback& packet) {
@ -65,5 +64,4 @@ void AcknowledgedBitrateEstimator::MaybeExpectFastRateChange(
}
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -21,8 +21,6 @@ namespace webrtc {
struct PacketFeedback;
namespace webrtc_cc {
class AcknowledgedBitrateEstimator {
public:
explicit AcknowledgedBitrateEstimator(
@ -42,7 +40,6 @@ class AcknowledgedBitrateEstimator {
std::unique_ptr<BitrateEstimator> bitrate_estimator_;
};
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_ACKNOWLEDGED_BITRATE_ESTIMATOR_H_

View File

@ -24,7 +24,6 @@ using testing::InSequence;
using testing::Return;
namespace webrtc {
namespace webrtc_cc {
namespace {
@ -132,5 +131,4 @@ TEST(TestAcknowledgedBitrateEstimator, ReturnBitrate) {
EXPECT_EQ(return_value, states.acknowledged_bitrate_estimator->bitrate_bps());
}
} // namespace webrtc_cc
} // namespace webrtc*/

View File

@ -16,7 +16,6 @@
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
namespace webrtc {
namespace webrtc_cc {
namespace {
constexpr int kInitialRateWindowMs = 500;
@ -105,5 +104,4 @@ void BitrateEstimator::ExpectFastRateChange() {
bitrate_estimate_var_ += 200;
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -16,7 +16,6 @@
#include "api/optional.h"
namespace webrtc {
namespace webrtc_cc {
// Computes a bayesian estimate of the throughput given acks containing
// the arrival time and payload size. Samples which are far from the current
@ -42,7 +41,6 @@ class BitrateEstimator {
float bitrate_estimate_var_;
};
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_BITRATE_ESTIMATOR_H_

View File

@ -16,7 +16,6 @@
#include "rtc_base/constructormagic.h"
namespace webrtc {
namespace webrtc_cc {
class DelayIncreaseDetectorInterface {
public:
@ -33,7 +32,7 @@ class DelayIncreaseDetectorInterface {
RTC_DISALLOW_COPY_AND_ASSIGN(DelayIncreaseDetectorInterface);
};
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_DELAY_INCREASE_DETECTOR_INTERFACE_H_

View File

@ -18,7 +18,6 @@
#include "rtc_base/logging.h"
namespace webrtc {
namespace webrtc_cc {
constexpr unsigned int kDeltaCounterMax = 1000;
@ -91,5 +90,4 @@ void MedianSlopeEstimator::Update(double recv_delta_ms,
BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trendline_);
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -20,7 +20,6 @@
#include "rtc_base/numerics/percentile_filter.h"
namespace webrtc {
namespace webrtc_cc {
class MedianSlopeEstimator {
public:
@ -68,7 +67,7 @@ class MedianSlopeEstimator {
RTC_DISALLOW_COPY_AND_ASSIGN(MedianSlopeEstimator);
};
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_

View File

@ -13,7 +13,6 @@
#include "test/gtest.h"
namespace webrtc {
namespace webrtc_cc {
namespace {
constexpr size_t kWindowSize = 20;
@ -70,5 +69,4 @@ TEST(MedianSlopeEstimator, JitteryLineSlopeZero) {
TestEstimator(0, kAvgTimeBetweenPackets / 3.0, 0.02);
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -53,7 +53,6 @@ constexpr int kMaxProbeIntervalMs = 1000;
} // namespace
namespace webrtc {
namespace webrtc_cc {
ProbeBitrateEstimator::ProbeBitrateEstimator(RtcEventLog* event_log)
: event_log_(event_log) {}
@ -187,5 +186,4 @@ void ProbeBitrateEstimator::EraseOldClusters(int64_t timestamp_ms) {
}
}
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -18,7 +18,6 @@
namespace webrtc {
class RtcEventLog;
namespace webrtc_cc {
class ProbeBitrateEstimator {
public:
@ -51,7 +50,6 @@ class ProbeBitrateEstimator {
rtc::Optional<int> estimated_bitrate_bps_;
};
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_PROBE_BITRATE_ESTIMATOR_H_

View File

@ -18,7 +18,6 @@
#include "test/gtest.h"
namespace webrtc {
namespace webrtc_cc {
namespace {
constexpr int kInvalidBitrate = -1;
@ -219,5 +218,4 @@ TEST_F(TestProbeBitrateEstimator, FetchLastEstimatedBitrateBps) {
EXPECT_FALSE(probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps());
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -20,7 +20,6 @@
#include "rtc_base/numerics/safe_minmax.h"
namespace webrtc {
namespace webrtc_cc {
namespace {
rtc::Optional<double> LinearFitSlope(
@ -181,5 +180,4 @@ void TrendlineEstimator::UpdateThreshold(double modified_offset,
last_update_ms_ = now_ms;
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -20,7 +20,6 @@
#include "rtc_base/constructormagic.h"
namespace webrtc {
namespace webrtc_cc {
class TrendlineEstimator : public DelayIncreaseDetectorInterface {
public:
@ -88,7 +87,6 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface {
RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator);
};
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_

View File

@ -13,7 +13,6 @@
#include "test/gtest.h"
namespace webrtc {
namespace webrtc_cc {
namespace {
constexpr size_t kWindowSize = 20;
@ -71,5 +70,4 @@ TEST(TrendlineEstimator, JitteryLineSlopeZero) {
TestEstimator(0, kAvgTimeBetweenPackets / 3.0, 0.02);
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -1,93 +0,0 @@
/*
* 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/median_slope_estimator.h"
#include <algorithm>
#include <vector>
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "rtc_base/logging.h"
namespace webrtc {
constexpr unsigned int kDeltaCounterMax = 1000;
MedianSlopeEstimator::MedianSlopeEstimator(size_t window_size,
double threshold_gain)
: window_size_(window_size),
threshold_gain_(threshold_gain),
num_of_deltas_(0),
accumulated_delay_(0),
delay_hist_(),
median_filter_(0.5),
trendline_(0) {}
MedianSlopeEstimator::~MedianSlopeEstimator() {}
MedianSlopeEstimator::DelayInfo::DelayInfo(int64_t time,
double delay,
size_t slope_count)
: time(time), delay(delay) {
slopes.reserve(slope_count);
}
MedianSlopeEstimator::DelayInfo::~DelayInfo() = default;
void MedianSlopeEstimator::Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms) {
const double delta_ms = recv_delta_ms - send_delta_ms;
++num_of_deltas_;
if (num_of_deltas_ > kDeltaCounterMax)
num_of_deltas_ = kDeltaCounterMax;
accumulated_delay_ += delta_ms;
BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
accumulated_delay_);
// If the window is full, remove the |window_size_| - 1 slopes that belong to
// the oldest point.
if (delay_hist_.size() == window_size_) {
for (double slope : delay_hist_.front().slopes) {
const bool success = median_filter_.Erase(slope);
RTC_CHECK(success);
}
delay_hist_.pop_front();
}
// Add |window_size_| - 1 new slopes.
for (auto& old_delay : delay_hist_) {
if (arrival_time_ms - old_delay.time != 0) {
// The C99 standard explicitly states that casts and assignments must
// perform the associated conversions. This means that |slope| will be
// a 64-bit double even if the division is computed using, e.g., 80-bit
// extended precision. I believe this also holds in C++ even though the
// C++11 standard isn't as explicit. Furthermore, there are good reasons
// to believe that compilers couldn't perform optimizations that break
// this assumption even if they wanted to.
double slope = (accumulated_delay_ - old_delay.delay) /
static_cast<double>(arrival_time_ms - old_delay.time);
median_filter_.Insert(slope);
// We want to avoid issues with different rounding mode / precision
// which we might get if we recomputed the slope when we remove it.
old_delay.slopes.push_back(slope);
}
}
delay_hist_.emplace_back(arrival_time_ms, accumulated_delay_,
window_size_ - 1);
// Recompute the median slope.
if (delay_hist_.size() == window_size_)
trendline_ = median_filter_.GetPercentileValue();
BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trendline_);
}
} // namespace webrtc

View File

@ -1,72 +0,0 @@
/*
* 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_MEDIAN_SLOPE_ESTIMATOR_H_
#define MODULES_CONGESTION_CONTROLLER_MEDIAN_SLOPE_ESTIMATOR_H_
#include <stddef.h>
#include <stdint.h>
#include <deque>
#include <vector>
#include "rtc_base/constructormagic.h"
#include "rtc_base/numerics/percentile_filter.h"
namespace webrtc {
class MedianSlopeEstimator {
public:
// |window_size| is the number of points required to compute a trend line.
// |threshold_gain| is used to scale the trendline slope for comparison to
// the old threshold. Once the old estimator has been removed (or the
// thresholds been merged into the estimators), we can just set the
// threshold instead of setting a gain.
MedianSlopeEstimator(size_t window_size, double threshold_gain);
~MedianSlopeEstimator();
// Update the estimator with a new sample. The deltas should represent deltas
// between timestamp groups as defined by the InterArrival class.
void Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms);
// Returns the estimated trend k multiplied by some gain.
// 0 < k < 1 -> the delay increases, queues are filling up
// k == 0 -> the delay does not change
// k < 0 -> the delay decreases, queues are being emptied
double trendline_slope() const { return trendline_ * threshold_gain_; }
// Returns the number of deltas which the current estimator state is based on.
unsigned int num_of_deltas() const { return num_of_deltas_; }
private:
struct DelayInfo {
DelayInfo(int64_t time, double delay, size_t slope_count);
~DelayInfo();
int64_t time;
double delay;
std::vector<double> slopes;
};
// Parameters.
const size_t window_size_;
const double threshold_gain_;
// Used by the existing threshold.
unsigned int num_of_deltas_;
// Theil-Sen robust line fitting
double accumulated_delay_;
std::deque<DelayInfo> delay_hist_;
PercentileFilter<double> median_filter_;
double trendline_;
RTC_DISALLOW_COPY_AND_ASSIGN(MedianSlopeEstimator);
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_MEDIAN_SLOPE_ESTIMATOR_H_

View File

@ -1,72 +0,0 @@
/*
* 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/median_slope_estimator.h"
#include "rtc_base/random.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
constexpr size_t kWindowSize = 20;
constexpr double kGain = 1;
constexpr int64_t kAvgTimeBetweenPackets = 10;
constexpr size_t kPacketCount = 2 * kWindowSize + 1;
void TestEstimator(double slope, double jitter_stddev, double tolerance) {
MedianSlopeEstimator estimator(kWindowSize, kGain);
Random random(0x1234567);
int64_t send_times[kPacketCount];
int64_t recv_times[kPacketCount];
int64_t send_start_time = random.Rand(1000000);
int64_t recv_start_time = random.Rand(1000000);
for (size_t i = 0; i < kPacketCount; ++i) {
send_times[i] = send_start_time + i * kAvgTimeBetweenPackets;
double latency = i * kAvgTimeBetweenPackets / (1 - slope);
double jitter = random.Gaussian(0, jitter_stddev);
recv_times[i] = recv_start_time + latency + jitter;
}
for (size_t i = 1; i < kPacketCount; ++i) {
double recv_delta = recv_times[i] - recv_times[i - 1];
double send_delta = send_times[i] - send_times[i - 1];
estimator.Update(recv_delta, send_delta, recv_times[i]);
if (i < kWindowSize)
EXPECT_NEAR(estimator.trendline_slope(), 0, 0.001);
else
EXPECT_NEAR(estimator.trendline_slope(), slope, tolerance);
}
}
} // namespace
TEST(DeprecatedMedianSlopeEstimator, PerfectLineSlopeOneHalf) {
TestEstimator(0.5, 0, 0.001);
}
TEST(DeprecatedMedianSlopeEstimator, PerfectLineSlopeMinusOne) {
TestEstimator(-1, 0, 0.001);
}
TEST(DeprecatedMedianSlopeEstimator, PerfectLineSlopeZero) {
TestEstimator(0, 0, 0.001);
}
TEST(DeprecatedMedianSlopeEstimator, JitteryLineSlopeOneHalf) {
TestEstimator(0.5, kAvgTimeBetweenPackets / 3.0, 0.01);
}
TEST(DeprecatedMedianSlopeEstimator, JitteryLineSlopeMinusOne) {
TestEstimator(-1, kAvgTimeBetweenPackets / 3.0, 0.05);
}
TEST(DeprecatedMedianSlopeEstimator, JitteryLineSlopeZero) {
TestEstimator(0, kAvgTimeBetweenPackets / 3.0, 0.02);
}
} // namespace webrtc

View File

@ -1,189 +0,0 @@
/*
* 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/probe_bitrate_estimator.h"
#include <algorithm>
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/ptr_util.h"
namespace {
// The minumum number of probes we need to receive feedback about in percent
// in order to have a valid estimate.
constexpr int kMinReceivedProbesPercent = 80;
// The minumum number of bytes we need to receive feedback about in percent
// in order to have a valid estimate.
constexpr int kMinReceivedBytesPercent = 80;
// The maximum |receive rate| / |send rate| ratio for a valid estimate.
constexpr float kMaxValidRatio = 2.0f;
// The minimum |receive rate| / |send rate| ratio assuming that the link is
// not saturated, i.e. we assume that we will receive at least
// kMinRatioForUnsaturatedLink * |send rate| if |send rate| is less than the
// link capacity.
constexpr float kMinRatioForUnsaturatedLink = 0.9f;
// The target utilization of the link. If we know true link capacity
// we'd like to send at 95% of that rate.
constexpr float kTargetUtilizationFraction = 0.95f;
// The maximum time period over which the cluster history is retained.
// This is also the maximum time period beyond which a probing burst is not
// expected to last.
constexpr int kMaxClusterHistoryMs = 1000;
// The maximum time interval between first and the last probe on a cluster
// on the sender side as well as the receive side.
constexpr int kMaxProbeIntervalMs = 1000;
} // namespace
namespace webrtc {
ProbeBitrateEstimator::ProbeBitrateEstimator(RtcEventLog* event_log)
: event_log_(event_log) {}
ProbeBitrateEstimator::~ProbeBitrateEstimator() = default;
int ProbeBitrateEstimator::HandleProbeAndEstimateBitrate(
const PacketFeedback& packet_feedback) {
int cluster_id = packet_feedback.pacing_info.probe_cluster_id;
RTC_DCHECK_NE(cluster_id, PacedPacketInfo::kNotAProbe);
EraseOldClusters(packet_feedback.arrival_time_ms - kMaxClusterHistoryMs);
int payload_size_bits = rtc::dchecked_cast<int>(
packet_feedback.payload_size * 8);
AggregatedCluster* cluster = &clusters_[cluster_id];
if (packet_feedback.send_time_ms < cluster->first_send_ms) {
cluster->first_send_ms = packet_feedback.send_time_ms;
}
if (packet_feedback.send_time_ms > cluster->last_send_ms) {
cluster->last_send_ms = packet_feedback.send_time_ms;
cluster->size_last_send = payload_size_bits;
}
if (packet_feedback.arrival_time_ms < cluster->first_receive_ms) {
cluster->first_receive_ms = packet_feedback.arrival_time_ms;
cluster->size_first_receive = payload_size_bits;
}
if (packet_feedback.arrival_time_ms > cluster->last_receive_ms) {
cluster->last_receive_ms = packet_feedback.arrival_time_ms;
}
cluster->size_total += payload_size_bits;
cluster->num_probes += 1;
RTC_DCHECK_GT(packet_feedback.pacing_info.probe_cluster_min_probes, 0);
RTC_DCHECK_GT(packet_feedback.pacing_info.probe_cluster_min_bytes, 0);
int min_probes = packet_feedback.pacing_info.probe_cluster_min_probes *
kMinReceivedProbesPercent / 100;
int min_bytes = packet_feedback.pacing_info.probe_cluster_min_bytes *
kMinReceivedBytesPercent / 100;
if (cluster->num_probes < min_probes || cluster->size_total < min_bytes * 8)
return -1;
float send_interval_ms = cluster->last_send_ms - cluster->first_send_ms;
float receive_interval_ms =
cluster->last_receive_ms - cluster->first_receive_ms;
if (send_interval_ms <= 0 || send_interval_ms > kMaxProbeIntervalMs ||
receive_interval_ms <= 0 || receive_interval_ms > kMaxProbeIntervalMs) {
RTC_LOG(LS_INFO) << "Probing unsuccessful, invalid send/receive interval"
<< " [cluster id: " << cluster_id
<< "] [send interval: " << send_interval_ms << " ms]"
<< " [receive interval: " << receive_interval_ms << " ms]";
if (event_log_) {
event_log_->Log(rtc::MakeUnique<RtcEventProbeResultFailure>(
cluster_id, ProbeFailureReason::kInvalidSendReceiveInterval));
}
return -1;
}
// Since the |send_interval_ms| does not include the time it takes to actually
// send the last packet the size of the last sent packet should not be
// included when calculating the send bitrate.
RTC_DCHECK_GT(cluster->size_total, cluster->size_last_send);
float send_size = cluster->size_total - cluster->size_last_send;
float send_bps = send_size / send_interval_ms * 1000;
// Since the |receive_interval_ms| does not include the time it takes to
// actually receive the first packet the size of the first received packet
// should not be included when calculating the receive bitrate.
RTC_DCHECK_GT(cluster->size_total, cluster->size_first_receive);
float receive_size = cluster->size_total - cluster->size_first_receive;
float receive_bps = receive_size / receive_interval_ms * 1000;
float ratio = receive_bps / send_bps;
if (ratio > kMaxValidRatio) {
RTC_LOG(LS_INFO) << "Probing unsuccessful, receive/send ratio too high"
<< " [cluster id: " << cluster_id
<< "] [send: " << send_size << " bytes / "
<< send_interval_ms << " ms = " << send_bps / 1000
<< " kb/s]"
<< " [receive: " << receive_size << " bytes / "
<< receive_interval_ms << " ms = " << receive_bps / 1000
<< " kb/s]"
<< " [ratio: " << receive_bps / 1000 << " / "
<< send_bps / 1000 << " = " << ratio
<< " > kMaxValidRatio (" << kMaxValidRatio << ")]";
if (event_log_) {
event_log_->Log(rtc::MakeUnique<RtcEventProbeResultFailure>(
cluster_id, ProbeFailureReason::kInvalidSendReceiveRatio));
}
return -1;
}
RTC_LOG(LS_INFO) << "Probing successful"
<< " [cluster id: " << cluster_id << "] [send: " << send_size
<< " bytes / " << send_interval_ms
<< " ms = " << send_bps / 1000 << " kb/s]"
<< " [receive: " << receive_size << " bytes / "
<< receive_interval_ms << " ms = " << receive_bps / 1000
<< " kb/s]";
float res = std::min(send_bps, receive_bps);
// If we're receiving at significantly lower bitrate than we were sending at,
// it suggests that we've found the true capacity of the link. In this case,
// set the target bitrate slightly lower to not immediately overuse.
if (receive_bps < kMinRatioForUnsaturatedLink * send_bps) {
RTC_DCHECK_GT(send_bps, receive_bps);
res = kTargetUtilizationFraction * receive_bps;
}
if (event_log_) {
event_log_->Log(
rtc::MakeUnique<RtcEventProbeResultSuccess>(cluster_id, res));
}
estimated_bitrate_bps_ = res;
return *estimated_bitrate_bps_;
}
rtc::Optional<int>
ProbeBitrateEstimator::FetchAndResetLastEstimatedBitrateBps() {
rtc::Optional<int> estimated_bitrate_bps = estimated_bitrate_bps_;
estimated_bitrate_bps_.reset();
return estimated_bitrate_bps;
}
void ProbeBitrateEstimator::EraseOldClusters(int64_t timestamp_ms) {
for (auto it = clusters_.begin(); it != clusters_.end();) {
if (it->second.last_receive_ms < timestamp_ms) {
it = clusters_.erase(it);
} else {
++it;
}
}
}
} // namespace webrtc

View File

@ -1,55 +0,0 @@
/*
* 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_
#define MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_
#include <map>
#include <limits>
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
namespace webrtc {
class RtcEventLog;
class ProbeBitrateEstimator {
public:
explicit ProbeBitrateEstimator(RtcEventLog* event_log);
~ProbeBitrateEstimator();
// Should be called for every probe packet we receive feedback about.
// Returns the estimated bitrate if the probe completes a valid cluster.
int HandleProbeAndEstimateBitrate(const PacketFeedback& packet_feedback);
rtc::Optional<int> FetchAndResetLastEstimatedBitrateBps();
private:
struct AggregatedCluster {
int num_probes = 0;
int64_t first_send_ms = std::numeric_limits<int64_t>::max();
int64_t last_send_ms = 0;
int64_t first_receive_ms = std::numeric_limits<int64_t>::max();
int64_t last_receive_ms = 0;
int size_last_send = 0;
int size_first_receive = 0;
int size_total = 0;
};
// Erases old cluster data that was seen before |timestamp_ms|.
void EraseOldClusters(int64_t timestamp_ms);
std::map<int, AggregatedCluster> clusters_;
RtcEventLog* const event_log_;
rtc::Optional<int> estimated_bitrate_bps_;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_

View File

@ -1,221 +0,0 @@
/*
* 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/probe_bitrate_estimator.h"
#include <vector>
#include <utility>
#include "modules/remote_bitrate_estimator/aimd_rate_control.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
constexpr int kInvalidBitrate = -1;
constexpr int kDefaultMinProbes = 5;
constexpr int kDefaultMinBytes = 5000;
constexpr float kTargetUtilizationFraction = 0.95f;
} // anonymous namespace
class LegacyTestProbeBitrateEstimator : public ::testing::Test {
public:
LegacyTestProbeBitrateEstimator() : probe_bitrate_estimator_(nullptr) {}
// TODO(philipel): Use PacedPacketInfo when ProbeBitrateEstimator is rewritten
// to use that information.
void AddPacketFeedback(int probe_cluster_id,
size_t size_bytes,
int64_t send_time_ms,
int64_t arrival_time_ms,
int min_probes = kDefaultMinProbes,
int min_bytes = kDefaultMinBytes) {
PacedPacketInfo pacing_info(probe_cluster_id, min_probes, min_bytes);
PacketFeedback packet_feedback(arrival_time_ms, send_time_ms, 0, size_bytes,
pacing_info);
measured_bps_ =
probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback);
}
protected:
int measured_bps_ = kInvalidBitrate;
ProbeBitrateEstimator probe_bitrate_estimator_;
};
TEST_F(LegacyTestProbeBitrateEstimator, OneCluster) {
AddPacketFeedback(0, 1000, 0, 10);
AddPacketFeedback(0, 1000, 10, 20);
AddPacketFeedback(0, 1000, 20, 30);
AddPacketFeedback(0, 1000, 30, 40);
EXPECT_NEAR(measured_bps_, 800000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, OneClusterTooFewProbes) {
AddPacketFeedback(0, 2000, 0, 10);
AddPacketFeedback(0, 2000, 10, 20);
AddPacketFeedback(0, 2000, 20, 30);
EXPECT_EQ(kInvalidBitrate, measured_bps_);
}
TEST_F(LegacyTestProbeBitrateEstimator, OneClusterTooFewBytes) {
const int kMinBytes = 6000;
AddPacketFeedback(0, 800, 0, 10, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 800, 10, 20, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 800, 20, 30, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 800, 30, 40, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 800, 40, 50, kDefaultMinProbes, kMinBytes);
EXPECT_EQ(kInvalidBitrate, measured_bps_);
}
TEST_F(LegacyTestProbeBitrateEstimator, SmallCluster) {
const int kMinBytes = 1000;
AddPacketFeedback(0, 150, 0, 10, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 150, 10, 20, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 150, 20, 30, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 150, 30, 40, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 150, 40, 50, kDefaultMinProbes, kMinBytes);
AddPacketFeedback(0, 150, 50, 60, kDefaultMinProbes, kMinBytes);
EXPECT_NEAR(measured_bps_, 120000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, LargeCluster) {
const int kMinProbes = 30;
const int kMinBytes = 312500;
int64_t send_time = 0;
int64_t receive_time = 5;
for (int i = 0; i < 25; ++i) {
AddPacketFeedback(0, 12500, send_time, receive_time, kMinProbes, kMinBytes);
++send_time;
++receive_time;
}
EXPECT_NEAR(measured_bps_, 100000000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, FastReceive) {
AddPacketFeedback(0, 1000, 0, 15);
AddPacketFeedback(0, 1000, 10, 30);
AddPacketFeedback(0, 1000, 20, 35);
AddPacketFeedback(0, 1000, 30, 40);
EXPECT_NEAR(measured_bps_, 800000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, TooFastReceive) {
AddPacketFeedback(0, 1000, 0, 19);
AddPacketFeedback(0, 1000, 10, 22);
AddPacketFeedback(0, 1000, 20, 25);
AddPacketFeedback(0, 1000, 40, 27);
EXPECT_EQ(measured_bps_, kInvalidBitrate);
}
TEST_F(LegacyTestProbeBitrateEstimator, SlowReceive) {
AddPacketFeedback(0, 1000, 0, 10);
AddPacketFeedback(0, 1000, 10, 40);
AddPacketFeedback(0, 1000, 20, 70);
AddPacketFeedback(0, 1000, 30, 85);
// Expected send rate = 800 kbps, expected receive rate = 320 kbps.
EXPECT_NEAR(measured_bps_, kTargetUtilizationFraction * 320000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, BurstReceive) {
AddPacketFeedback(0, 1000, 0, 50);
AddPacketFeedback(0, 1000, 10, 50);
AddPacketFeedback(0, 1000, 20, 50);
AddPacketFeedback(0, 1000, 40, 50);
EXPECT_EQ(measured_bps_, kInvalidBitrate);
}
TEST_F(LegacyTestProbeBitrateEstimator, MultipleClusters) {
AddPacketFeedback(0, 1000, 0, 10);
AddPacketFeedback(0, 1000, 10, 20);
AddPacketFeedback(0, 1000, 20, 30);
AddPacketFeedback(0, 1000, 40, 60);
// Expected send rate = 600 kbps, expected receive rate = 480 kbps.
EXPECT_NEAR(measured_bps_, kTargetUtilizationFraction * 480000, 10);
AddPacketFeedback(0, 1000, 50, 60);
// Expected send rate = 640 kbps, expected receive rate = 640 kbps.
EXPECT_NEAR(measured_bps_, 640000, 10);
AddPacketFeedback(1, 1000, 60, 70);
AddPacketFeedback(1, 1000, 65, 77);
AddPacketFeedback(1, 1000, 70, 84);
AddPacketFeedback(1, 1000, 75, 90);
// Expected send rate = 1600 kbps, expected receive rate = 1200 kbps.
EXPECT_NEAR(measured_bps_, kTargetUtilizationFraction * 1200000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, IgnoreOldClusters) {
AddPacketFeedback(0, 1000, 0, 10);
AddPacketFeedback(0, 1000, 10, 20);
AddPacketFeedback(0, 1000, 20, 30);
AddPacketFeedback(1, 1000, 60, 70);
AddPacketFeedback(1, 1000, 65, 77);
AddPacketFeedback(1, 1000, 70, 84);
AddPacketFeedback(1, 1000, 75, 90);
// Expected send rate = 1600 kbps, expected receive rate = 1200 kbps.
EXPECT_NEAR(measured_bps_, kTargetUtilizationFraction * 1200000, 10);
// Coming in 6s later
AddPacketFeedback(0, 1000, 40 + 6000, 60 + 6000);
EXPECT_EQ(measured_bps_, kInvalidBitrate);
}
TEST_F(LegacyTestProbeBitrateEstimator, IgnoreSizeLastSendPacket) {
AddPacketFeedback(0, 1000, 0, 10);
AddPacketFeedback(0, 1000, 10, 20);
AddPacketFeedback(0, 1000, 20, 30);
AddPacketFeedback(0, 1000, 30, 40);
AddPacketFeedback(0, 1500, 40, 50);
// Expected send rate = 800 kbps, expected receive rate = 900 kbps.
EXPECT_NEAR(measured_bps_, 800000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, IgnoreSizeFirstReceivePacket) {
AddPacketFeedback(0, 1500, 0, 10);
AddPacketFeedback(0, 1000, 10, 20);
AddPacketFeedback(0, 1000, 20, 30);
AddPacketFeedback(0, 1000, 30, 40);
// Expected send rate = 933 kbps, expected receive rate = 800 kbps.
EXPECT_NEAR(measured_bps_, kTargetUtilizationFraction * 800000, 10);
}
TEST_F(LegacyTestProbeBitrateEstimator, NoLastEstimatedBitrateBps) {
EXPECT_FALSE(probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps());
}
TEST_F(LegacyTestProbeBitrateEstimator, FetchLastEstimatedBitrateBps) {
AddPacketFeedback(0, 1000, 0, 10);
AddPacketFeedback(0, 1000, 10, 20);
AddPacketFeedback(0, 1000, 20, 30);
AddPacketFeedback(0, 1000, 30, 40);
auto estimated_bitrate_bps =
probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps();
EXPECT_TRUE(estimated_bitrate_bps);
EXPECT_NEAR(*estimated_bitrate_bps, 800000, 10);
EXPECT_FALSE(probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps());
}
} // namespace webrtc

View File

@ -14,7 +14,6 @@
#include "test/gtest.h"
namespace webrtc {
namespace webrtc_cc {
void ComparePacketFeedbackVectors(const std::vector<PacketFeedback>& truth,
const std::vector<PacketFeedback>& input) {
ASSERT_EQ(truth.size(), input.size());
@ -40,5 +39,4 @@ void ComparePacketFeedbackVectors(const std::vector<PacketFeedback>& truth,
EXPECT_EQ(truth[i].pacing_info, input[i].pacing_info);
}
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -16,10 +16,8 @@
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
namespace webrtc {
namespace webrtc_cc {
void ComparePacketFeedbackVectors(const std::vector<PacketFeedback>& truth,
const std::vector<PacketFeedback>& input);
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_RTP_CONGESTION_CONTROLLER_UNITTESTS_HELPER_H_

View File

@ -18,7 +18,6 @@
#include "system_wrappers/include/clock.h"
namespace webrtc {
namespace webrtc_cc {
SendTimeHistory::SendTimeHistory(const Clock* clock,
int64_t packet_age_limit_ms)
@ -103,5 +102,4 @@ size_t SendTimeHistory::GetOutstandingBytes(uint16_t local_net_id,
return outstanding_bytes;
}
} // namespace webrtc_cc
} // namespace webrtc

View File

@ -19,7 +19,6 @@
namespace webrtc {
class Clock;
struct PacketFeedback;
namespace webrtc_cc {
class SendTimeHistory {
public:
@ -54,6 +53,5 @@ class SendTimeHistory {
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SendTimeHistory);
};
} // namespace webrtc_cc
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_RTP_SEND_TIME_HISTORY_H_

View File

@ -17,7 +17,7 @@
#include <vector>
#include "modules/bitrate_controller/include/bitrate_controller.h"
#include "modules/congestion_controller/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/probe_controller.h"
#include "modules/pacing/alr_detector.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"

View File

@ -8,11 +8,11 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/congestion_controller/include/send_side_congestion_controller.h"
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "modules/bitrate_controller/include/bitrate_controller.h"
#include "modules/congestion_controller/congestion_controller_unittests_helper.h"
#include "modules/congestion_controller/include/mock/mock_congestion_observer.h"
#include "modules/congestion_controller/include/send_side_congestion_controller.h"
#include "modules/congestion_controller/rtp/congestion_controller_unittests_helper.h"
#include "modules/pacing/mock/mock_paced_sender.h"
#include "modules/pacing/packet_router.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"

View File

@ -1,92 +0,0 @@
/*
* Copyright (c) 2015 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/send_time_history.h"
#include <algorithm>
#include <utility>
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
SendTimeHistory::SendTimeHistory(const Clock* clock,
int64_t packet_age_limit_ms)
: clock_(clock), packet_age_limit_ms_(packet_age_limit_ms) {}
SendTimeHistory::~SendTimeHistory() {}
void SendTimeHistory::AddAndRemoveOld(const PacketFeedback& packet) {
int64_t now_ms = clock_->TimeInMilliseconds();
// Remove old.
while (!history_.empty() &&
now_ms - history_.begin()->second.creation_time_ms >
packet_age_limit_ms_) {
// TODO(sprang): Warn if erasing (too many) old items?
history_.erase(history_.begin());
}
// Add new.
int64_t unwrapped_seq_num = seq_num_unwrapper_.Unwrap(packet.sequence_number);
history_.insert(std::make_pair(unwrapped_seq_num, packet));
}
bool SendTimeHistory::OnSentPacket(uint16_t sequence_number,
int64_t send_time_ms) {
int64_t unwrapped_seq_num = seq_num_unwrapper_.Unwrap(sequence_number);
auto it = history_.find(unwrapped_seq_num);
if (it == history_.end())
return false;
it->second.send_time_ms = send_time_ms;
return true;
}
bool SendTimeHistory::GetFeedback(PacketFeedback* packet_feedback,
bool remove) {
RTC_DCHECK(packet_feedback);
int64_t unwrapped_seq_num =
seq_num_unwrapper_.Unwrap(packet_feedback->sequence_number);
latest_acked_seq_num_.emplace(
std::max(unwrapped_seq_num, latest_acked_seq_num_.value_or(0)));
RTC_DCHECK_GE(*latest_acked_seq_num_, 0);
auto it = history_.find(unwrapped_seq_num);
if (it == history_.end())
return false;
// Save arrival_time not to overwrite it.
int64_t arrival_time_ms = packet_feedback->arrival_time_ms;
*packet_feedback = it->second;
packet_feedback->arrival_time_ms = arrival_time_ms;
if (remove)
history_.erase(it);
return true;
}
size_t SendTimeHistory::GetOutstandingBytes(uint16_t local_net_id,
uint16_t remote_net_id) const {
size_t outstanding_bytes = 0;
auto unacked_it = history_.begin();
if (latest_acked_seq_num_) {
unacked_it = history_.lower_bound(*latest_acked_seq_num_);
}
for (; unacked_it != history_.end(); ++unacked_it) {
if (unacked_it->second.local_net_id == local_net_id &&
unacked_it->second.remote_net_id == remote_net_id &&
unacked_it->second.send_time_ms >= 0) {
outstanding_bytes += unacked_it->second.payload_size;
}
}
return outstanding_bytes;
}
} // namespace webrtc

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2015 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_SEND_TIME_HISTORY_H_
#define MODULES_CONGESTION_CONTROLLER_SEND_TIME_HISTORY_H_
#include <map>
#include "modules/include/module_common_types.h"
#include "rtc_base/constructormagic.h"
namespace webrtc {
class Clock;
struct PacketFeedback;
class SendTimeHistory {
public:
SendTimeHistory(const Clock* clock, int64_t packet_age_limit_ms);
~SendTimeHistory();
// Cleanup old entries, then add new packet info with provided parameters.
void AddAndRemoveOld(const PacketFeedback& packet);
// Updates packet info identified by |sequence_number| with |send_time_ms|.
// Return false if not found.
bool OnSentPacket(uint16_t sequence_number, int64_t send_time_ms);
// Look up PacketFeedback for a sent packet, based on the sequence number, and
// populate all fields except for arrival_time. The packet parameter must
// thus be non-null and have the sequence_number field set.
bool GetFeedback(PacketFeedback* packet_feedback, bool remove);
size_t GetOutstandingBytes(uint16_t local_net_id,
uint16_t remote_net_id) const;
private:
const Clock* const clock_;
const int64_t packet_age_limit_ms_;
SequenceNumberUnwrapper seq_num_unwrapper_;
std::map<int64_t, PacketFeedback> history_;
rtc::Optional<int64_t> latest_acked_seq_num_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SendTimeHistory);
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_SEND_TIME_HISTORY_H_

View File

@ -1,237 +0,0 @@
/*
* Copyright (c) 2015 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 <algorithm>
#include <limits>
#include <random>
#include <vector>
#include "modules/congestion_controller/send_time_history.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "system_wrappers/include/clock.h"
#include "test/gtest.h"
namespace webrtc {
namespace test {
static const int kDefaultHistoryLengthMs = 1000;
class LegacySendTimeHistoryTest : public ::testing::Test {
protected:
LegacySendTimeHistoryTest()
: clock_(0), history_(&clock_, kDefaultHistoryLengthMs) {}
~LegacySendTimeHistoryTest() {}
virtual void SetUp() {}
virtual void TearDown() {}
void AddPacketWithSendTime(uint16_t sequence_number,
size_t length,
int64_t send_time_ms,
const PacedPacketInfo& pacing_info) {
PacketFeedback packet(clock_.TimeInMilliseconds(), sequence_number, length,
0, 0, pacing_info);
history_.AddAndRemoveOld(packet);
history_.OnSentPacket(sequence_number, send_time_ms);
}
webrtc::SimulatedClock clock_;
SendTimeHistory history_;
};
TEST_F(LegacySendTimeHistoryTest, SaveAndRestoreNetworkId) {
const PacedPacketInfo kPacingInfo(0, 5, 1200);
uint16_t sequence_number = 0;
int64_t now_ms = clock_.TimeInMilliseconds();
for (int i = 1; i < 5; ++i) {
PacketFeedback packet(now_ms, sequence_number, 1000, i, i - 1,
kPacingInfo);
history_.AddAndRemoveOld(packet);
history_.OnSentPacket(sequence_number, now_ms);
PacketFeedback restored(now_ms, sequence_number);
EXPECT_TRUE(history_.GetFeedback(&restored, sequence_number++));
EXPECT_EQ(packet.local_net_id, restored.local_net_id);
EXPECT_EQ(packet.remote_net_id, restored.remote_net_id);
}
}
TEST_F(LegacySendTimeHistoryTest, AddRemoveOne) {
const uint16_t kSeqNo = 10;
// TODO(philipel): Fix PacedPacketInfo constructor?
const PacedPacketInfo kPacingInfo(0, 5, 1200);
const PacketFeedback kSentPacket(0, 1, kSeqNo, 1, kPacingInfo);
AddPacketWithSendTime(kSeqNo, 1, 1, kPacingInfo);
PacketFeedback received_packet(0, 0, kSeqNo, 0, kPacingInfo);
EXPECT_TRUE(history_.GetFeedback(&received_packet, false));
EXPECT_EQ(kSentPacket, received_packet);
PacketFeedback received_packet2(0, 0, kSeqNo, 0, kPacingInfo);
EXPECT_TRUE(history_.GetFeedback(&received_packet2, true));
EXPECT_EQ(kSentPacket, received_packet2);
PacketFeedback received_packet3(0, 0, kSeqNo, 0, kPacingInfo);
EXPECT_FALSE(history_.GetFeedback(&received_packet3, true));
}
TEST_F(LegacySendTimeHistoryTest, PopulatesExpectedFields) {
const uint16_t kSeqNo = 10;
const int64_t kSendTime = 1000;
const int64_t kReceiveTime = 2000;
const size_t kPayloadSize = 42;
const PacedPacketInfo kPacingInfo(3, 10, 1212);
AddPacketWithSendTime(kSeqNo, kPayloadSize, kSendTime, kPacingInfo);
PacketFeedback packet_feedback(kReceiveTime, kSeqNo);
EXPECT_TRUE(history_.GetFeedback(&packet_feedback, true));
EXPECT_EQ(kReceiveTime, packet_feedback.arrival_time_ms);
EXPECT_EQ(kSendTime, packet_feedback.send_time_ms);
EXPECT_EQ(kSeqNo, packet_feedback.sequence_number);
EXPECT_EQ(kPayloadSize, packet_feedback.payload_size);
EXPECT_EQ(kPacingInfo, packet_feedback.pacing_info);
}
TEST_F(LegacySendTimeHistoryTest, AddThenRemoveOutOfOrder) {
std::vector<PacketFeedback> sent_packets;
std::vector<PacketFeedback> received_packets;
const size_t num_items = 100;
const size_t kPacketSize = 400;
const size_t kTransmissionTime = 1234;
const PacedPacketInfo kPacingInfo(1, 2, 200);
for (size_t i = 0; i < num_items; ++i) {
sent_packets.push_back(PacketFeedback(0, static_cast<int64_t>(i),
static_cast<uint16_t>(i), kPacketSize,
kPacingInfo));
received_packets.push_back(PacketFeedback(
static_cast<int64_t>(i) + kTransmissionTime, 0,
static_cast<uint16_t>(i), kPacketSize, PacedPacketInfo()));
}
for (size_t i = 0; i < num_items; ++i) {
PacketFeedback packet = sent_packets[i];
packet.arrival_time_ms = PacketFeedback::kNotReceived;
packet.send_time_ms = PacketFeedback::kNoSendTime;
history_.AddAndRemoveOld(packet);
}
for (size_t i = 0; i < num_items; ++i)
history_.OnSentPacket(sent_packets[i].sequence_number,
sent_packets[i].send_time_ms);
std::shuffle(received_packets.begin(), received_packets.end(),
std::mt19937(std::random_device()()));
for (size_t i = 0; i < num_items; ++i) {
PacketFeedback packet = received_packets[i];
EXPECT_TRUE(history_.GetFeedback(&packet, false));
PacketFeedback sent_packet = sent_packets[packet.sequence_number];
sent_packet.arrival_time_ms = packet.arrival_time_ms;
EXPECT_EQ(sent_packet, packet);
EXPECT_TRUE(history_.GetFeedback(&packet, true));
}
for (PacketFeedback packet : sent_packets)
EXPECT_FALSE(history_.GetFeedback(&packet, false));
}
TEST_F(LegacySendTimeHistoryTest, HistorySize) {
const int kItems = kDefaultHistoryLengthMs / 100;
for (int i = 0; i < kItems; ++i) {
clock_.AdvanceTimeMilliseconds(100);
AddPacketWithSendTime(i, 0, i * 100, PacedPacketInfo());
}
for (int i = 0; i < kItems; ++i) {
PacketFeedback packet(0, 0, static_cast<uint16_t>(i), 0, PacedPacketInfo());
EXPECT_TRUE(history_.GetFeedback(&packet, false));
EXPECT_EQ(i * 100, packet.send_time_ms);
}
clock_.AdvanceTimeMilliseconds(101);
AddPacketWithSendTime(kItems, 0, kItems * 101, PacedPacketInfo());
PacketFeedback packet(0, 0, 0, 0, PacedPacketInfo());
EXPECT_FALSE(history_.GetFeedback(&packet, false));
for (int i = 1; i < (kItems + 1); ++i) {
PacketFeedback packet2(0, 0, static_cast<uint16_t>(i), 0,
PacedPacketInfo());
EXPECT_TRUE(history_.GetFeedback(&packet2, false));
int64_t expected_time_ms = (i == kItems) ? i * 101 : i * 100;
EXPECT_EQ(expected_time_ms, packet2.send_time_ms);
}
}
TEST_F(LegacySendTimeHistoryTest, HistorySizeWithWraparound) {
const uint16_t kMaxSeqNo = std::numeric_limits<uint16_t>::max();
AddPacketWithSendTime(kMaxSeqNo - 2, 0, 0, PacedPacketInfo());
clock_.AdvanceTimeMilliseconds(100);
AddPacketWithSendTime(kMaxSeqNo - 1, 1, 100, PacedPacketInfo());
clock_.AdvanceTimeMilliseconds(100);
AddPacketWithSendTime(kMaxSeqNo, 0, 200, PacedPacketInfo());
clock_.AdvanceTimeMilliseconds(kDefaultHistoryLengthMs - 200 + 1);
AddPacketWithSendTime(0, 0, kDefaultHistoryLengthMs, PacedPacketInfo());
PacketFeedback packet(0, static_cast<uint16_t>(kMaxSeqNo - 2));
EXPECT_FALSE(history_.GetFeedback(&packet, false));
PacketFeedback packet2(0, static_cast<uint16_t>(kMaxSeqNo - 1));
EXPECT_TRUE(history_.GetFeedback(&packet2, false));
PacketFeedback packet3(0, static_cast<uint16_t>(kMaxSeqNo));
EXPECT_TRUE(history_.GetFeedback(&packet3, false));
PacketFeedback packet4(0, 0);
EXPECT_TRUE(history_.GetFeedback(&packet4, false));
// Create a gap (kMaxSeqNo - 1) -> 0.
PacketFeedback packet5(0, kMaxSeqNo);
EXPECT_TRUE(history_.GetFeedback(&packet5, true));
clock_.AdvanceTimeMilliseconds(100);
AddPacketWithSendTime(1, 0, 1100, PacedPacketInfo());
PacketFeedback packet6(0, static_cast<uint16_t>(kMaxSeqNo - 2));
EXPECT_FALSE(history_.GetFeedback(&packet6, false));
PacketFeedback packet7(0, static_cast<uint16_t>(kMaxSeqNo - 1));
EXPECT_FALSE(history_.GetFeedback(&packet7, false));
PacketFeedback packet8(0, kMaxSeqNo);
EXPECT_FALSE(history_.GetFeedback(&packet8, false));
PacketFeedback packet9(0, 0);
EXPECT_TRUE(history_.GetFeedback(&packet9, false));
PacketFeedback packet10(0, 1);
EXPECT_TRUE(history_.GetFeedback(&packet10, false));
}
TEST_F(LegacySendTimeHistoryTest, InterlievedGetAndRemove) {
const uint16_t kSeqNo = 1;
const int64_t kTimestamp = 2;
const PacedPacketInfo kPacingInfo1(1, 1, 100);
const PacedPacketInfo kPacingInfo2(2, 2, 200);
const PacedPacketInfo kPacingInfo3(3, 3, 300);
PacketFeedback packets[3] = {
{0, kTimestamp, kSeqNo, 0, kPacingInfo1},
{0, kTimestamp + 1, kSeqNo + 1, 0, kPacingInfo2},
{0, kTimestamp + 2, kSeqNo + 2, 0, kPacingInfo3}};
AddPacketWithSendTime(packets[0].sequence_number, packets[0].payload_size,
packets[0].send_time_ms, packets[0].pacing_info);
AddPacketWithSendTime(packets[1].sequence_number, packets[1].payload_size,
packets[1].send_time_ms, packets[1].pacing_info);
PacketFeedback packet(0, 0, packets[0].sequence_number, 0, PacedPacketInfo());
EXPECT_TRUE(history_.GetFeedback(&packet, true));
EXPECT_EQ(packets[0], packet);
AddPacketWithSendTime(packets[2].sequence_number, packets[2].payload_size,
packets[2].send_time_ms, packets[2].pacing_info);
PacketFeedback packet2(0, 0, packets[1].sequence_number, 0, kPacingInfo1);
EXPECT_TRUE(history_.GetFeedback(&packet2, true));
EXPECT_EQ(packets[1], packet2);
PacketFeedback packet3(0, 0, packets[2].sequence_number, 0, kPacingInfo2);
EXPECT_TRUE(history_.GetFeedback(&packet3, true));
EXPECT_EQ(packets[2], packet3);
}
} // namespace test
} // namespace webrtc

View File

@ -14,7 +14,7 @@
#include <deque>
#include <vector>
#include "modules/congestion_controller/send_time_history.h"
#include "modules/congestion_controller/rtp/send_time_history.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/thread_annotations.h"
#include "rtc_base/thread_checker.h"

View File

@ -13,7 +13,7 @@
#include <vector>
#include "modules/bitrate_controller/include/mock/mock_bitrate_controller.h"
#include "modules/congestion_controller/congestion_controller_unittests_helper.h"
#include "modules/congestion_controller/rtp/congestion_controller_unittests_helper.h"
#include "modules/congestion_controller/transport_feedback_adapter.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"

View File

@ -1,183 +0,0 @@
/*
* 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/trendline_estimator.h"
#include <math.h>
#include <algorithm>
#include "api/optional.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"
namespace webrtc {
namespace {
rtc::Optional<double> LinearFitSlope(
const std::deque<std::pair<double, double>>& points) {
RTC_DCHECK(points.size() >= 2);
// Compute the "center of mass".
double sum_x = 0;
double sum_y = 0;
for (const auto& point : points) {
sum_x += point.first;
sum_y += point.second;
}
double x_avg = sum_x / points.size();
double y_avg = sum_y / points.size();
// Compute the slope k = \sum (x_i-x_avg)(y_i-y_avg) / \sum (x_i-x_avg)^2
double numerator = 0;
double denominator = 0;
for (const auto& point : points) {
numerator += (point.first - x_avg) * (point.second - y_avg);
denominator += (point.first - x_avg) * (point.first - x_avg);
}
if (denominator == 0)
return rtc::nullopt;
return numerator / denominator;
}
constexpr double kMaxAdaptOffsetMs = 15.0;
constexpr double kOverUsingTimeThreshold = 10;
constexpr int kMinNumDeltas = 60;
} // namespace
enum { kDeltaCounterMax = 1000 };
TrendlineEstimator::TrendlineEstimator(size_t window_size,
double smoothing_coef,
double threshold_gain)
: window_size_(window_size),
smoothing_coef_(smoothing_coef),
threshold_gain_(threshold_gain),
num_of_deltas_(0),
first_arrival_time_ms_(-1),
accumulated_delay_(0),
smoothed_delay_(0),
delay_hist_(),
trendline_(0),
k_up_(0.0087),
k_down_(0.039),
overusing_time_threshold_(kOverUsingTimeThreshold),
threshold_(12.5),
last_update_ms_(-1),
prev_offset_(0.0),
time_over_using_(-1),
overuse_counter_(0),
hypothesis_(BandwidthUsage::kBwNormal) {}
TrendlineEstimator::~TrendlineEstimator() {}
void TrendlineEstimator::Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms) {
const double delta_ms = recv_delta_ms - send_delta_ms;
++num_of_deltas_;
if (num_of_deltas_ > kDeltaCounterMax)
num_of_deltas_ = kDeltaCounterMax;
if (first_arrival_time_ms_ == -1)
first_arrival_time_ms_ = arrival_time_ms;
// Exponential backoff filter.
accumulated_delay_ += delta_ms;
BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
accumulated_delay_);
smoothed_delay_ = smoothing_coef_ * smoothed_delay_ +
(1 - smoothing_coef_) * accumulated_delay_;
BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms,
smoothed_delay_);
// Simple linear regression.
delay_hist_.push_back(std::make_pair(
static_cast<double>(arrival_time_ms - first_arrival_time_ms_),
smoothed_delay_));
if (delay_hist_.size() > window_size_)
delay_hist_.pop_front();
if (delay_hist_.size() == window_size_) {
// Only update trendline_ if it is possible to fit a line to the data.
trendline_ = LinearFitSlope(delay_hist_).value_or(trendline_);
}
BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trendline_);
Detect(trendline_slope(), send_delta_ms, num_of_deltas(), arrival_time_ms);
}
BandwidthUsage TrendlineEstimator::State() const {
return hypothesis_;
}
void TrendlineEstimator::Detect(double offset,
double ts_delta,
int num_of_deltas,
int64_t now_ms) {
if (num_of_deltas < 2) {
hypothesis_ = BandwidthUsage::kBwNormal;
return;
}
const double T = std::min(num_of_deltas, kMinNumDeltas) * offset;
BWE_TEST_LOGGING_PLOT(1, "T", now_ms, T);
BWE_TEST_LOGGING_PLOT(1, "threshold", now_ms, threshold_);
if (T > threshold_) {
if (time_over_using_ == -1) {
// Initialize the timer. Assume that we've been
// over-using half of the time since the previous
// sample.
time_over_using_ = ts_delta / 2;
} else {
// Increment timer
time_over_using_ += ts_delta;
}
overuse_counter_++;
if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) {
if (offset >= prev_offset_) {
time_over_using_ = 0;
overuse_counter_ = 0;
hypothesis_ = BandwidthUsage::kBwOverusing;
}
}
} else if (T < -threshold_) {
time_over_using_ = -1;
overuse_counter_ = 0;
hypothesis_ = BandwidthUsage::kBwUnderusing;
} else {
time_over_using_ = -1;
overuse_counter_ = 0;
hypothesis_ = BandwidthUsage::kBwNormal;
}
prev_offset_ = offset;
UpdateThreshold(T, now_ms);
}
void TrendlineEstimator::UpdateThreshold(double modified_offset,
int64_t now_ms) {
if (last_update_ms_ == -1)
last_update_ms_ = now_ms;
if (fabs(modified_offset) > threshold_ + kMaxAdaptOffsetMs) {
// Avoid adapting the threshold to big latency spikes, caused e.g.,
// by a sudden capacity drop.
last_update_ms_ = now_ms;
return;
}
const double k = fabs(modified_offset) < threshold_ ? k_down_ : k_up_;
const int64_t kMaxTimeDeltaMs = 100;
int64_t time_delta_ms = std::min(now_ms - last_update_ms_, kMaxTimeDeltaMs);
threshold_ += k * (fabs(modified_offset) - threshold_) * time_delta_ms;
threshold_ = rtc::SafeClamp(threshold_, 6.f, 600.f);
last_update_ms_ = now_ms;
}
} // namespace webrtc

View File

@ -1,92 +0,0 @@
/*
* 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.
*/
#ifndef MODULES_CONGESTION_CONTROLLER_TRENDLINE_ESTIMATOR_H_
#define MODULES_CONGESTION_CONTROLLER_TRENDLINE_ESTIMATOR_H_
#include <stddef.h>
#include <stdint.h>
#include <deque>
#include <utility>
#include "modules/congestion_controller/delay_increase_detector_interface.h"
#include "rtc_base/constructormagic.h"
namespace webrtc {
class TrendlineEstimator : public DelayIncreaseDetectorInterface {
public:
// |window_size| is the number of points required to compute a trend line.
// |smoothing_coef| controls how much we smooth out the delay before fitting
// the trend line. |threshold_gain| is used to scale the trendline slope for
// comparison to the old threshold. Once the old estimator has been removed
// (or the thresholds been merged into the estimators), we can just set the
// threshold instead of setting a gain.
TrendlineEstimator(size_t window_size,
double smoothing_coef,
double threshold_gain);
~TrendlineEstimator() override;
// Update the estimator with a new sample. The deltas should represent deltas
// between timestamp groups as defined by the InterArrival class.
void Update(double recv_delta_ms,
double send_delta_ms,
int64_t arrival_time_ms) override;
BandwidthUsage State() const override;
// Returns the estimated trend k multiplied by some gain.
// 0 < k < 1 -> the delay increases, queues are filling up
// k == 0 -> the delay does not change
// k < 0 -> the delay decreases, queues are being emptied
double trendline_slope() const { return trendline_ * threshold_gain_; }
// Returns the number of deltas which the current estimator state is based on.
unsigned int num_of_deltas() const { return num_of_deltas_; }
private:
void Detect(double offset,
double ts_delta,
int num_of_deltas,
int64_t now_ms);
void UpdateThreshold(double modified_offset, int64_t now_ms);
// Parameters.
const size_t window_size_;
const double smoothing_coef_;
const double threshold_gain_;
// Used by the existing threshold.
unsigned int num_of_deltas_;
// Keep the arrival times small by using the change from the first packet.
int64_t first_arrival_time_ms_;
// Exponential backoff filtering.
double accumulated_delay_;
double smoothed_delay_;
// Linear least squares regression.
std::deque<std::pair<double, double>> delay_hist_;
double trendline_;
const double k_up_;
const double k_down_;
double overusing_time_threshold_;
double threshold_;
int64_t last_update_ms_;
double prev_offset_;
double time_over_using_;
int overuse_counter_;
BandwidthUsage hypothesis_;
RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator);
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_TRENDLINE_ESTIMATOR_H_

View File

@ -1,73 +0,0 @@
/*
* 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/trendline_estimator.h"
#include "rtc_base/random.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
constexpr size_t kWindowSize = 20;
constexpr double kSmoothing = 0.0;
constexpr double kGain = 1;
constexpr int64_t kAvgTimeBetweenPackets = 10;
constexpr size_t kPacketCount = 2 * kWindowSize + 1;
void TestEstimator(double slope, double jitter_stddev, double tolerance) {
TrendlineEstimator estimator(kWindowSize, kSmoothing, kGain);
Random random(0x1234567);
int64_t send_times[kPacketCount];
int64_t recv_times[kPacketCount];
int64_t send_start_time = random.Rand(1000000);
int64_t recv_start_time = random.Rand(1000000);
for (size_t i = 0; i < kPacketCount; ++i) {
send_times[i] = send_start_time + i * kAvgTimeBetweenPackets;
double latency = i * kAvgTimeBetweenPackets / (1 - slope);
double jitter = random.Gaussian(0, jitter_stddev);
recv_times[i] = recv_start_time + latency + jitter;
}
for (size_t i = 1; i < kPacketCount; ++i) {
double recv_delta = recv_times[i] - recv_times[i - 1];
double send_delta = send_times[i] - send_times[i - 1];
estimator.Update(recv_delta, send_delta, recv_times[i]);
if (i < kWindowSize)
EXPECT_NEAR(estimator.trendline_slope(), 0, 0.001);
else
EXPECT_NEAR(estimator.trendline_slope(), slope, tolerance);
}
}
} // namespace
TEST(LegacyTrendlineEstimator, PerfectLineSlopeOneHalf) {
TestEstimator(0.5, 0, 0.001);
}
TEST(LegacyTrendlineEstimator, PerfectLineSlopeMinusOne) {
TestEstimator(-1, 0, 0.001);
}
TEST(LegacyTrendlineEstimator, PerfectLineSlopeZero) {
TestEstimator(0, 0, 0.001);
}
TEST(LegacyTrendlineEstimator, JitteryLineSlopeOneHalf) {
TestEstimator(0.5, kAvgTimeBetweenPackets / 3.0, 0.01);
}
TEST(LegacyTrendlineEstimator, JitteryLineSlopeMinusOne) {
TestEstimator(-1, kAvgTimeBetweenPackets / 3.0, 0.075);
}
TEST(LegacyTrendlineEstimator, JitteryLineSlopeZero) {
TestEstimator(0, kAvgTimeBetweenPackets / 3.0, 0.02);
}
} // namespace webrtc

View File

@ -153,8 +153,9 @@ if (rtc_include_tests) {
"../bitrate_controller",
"../congestion_controller",
"../congestion_controller:delay_based_bwe",
"../congestion_controller:estimators",
"../congestion_controller:transport_feedback",
"../congestion_controller/goog_cc:estimators",
"../congestion_controller/rtp:transport_feedback",
"../pacing",
"../rtp_rtcp",
"../rtp_rtcp:rtp_rtcp_format",

View File

@ -15,8 +15,8 @@
#include <vector>
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "modules/congestion_controller/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/send_time_history.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/rtp/send_time_history.h"
#include "modules/remote_bitrate_estimator/test/bwe.h"
namespace webrtc {

View File

@ -243,7 +243,7 @@ if (!build_with_chromium) {
"../api/audio_codecs:audio_codecs_api",
"../modules/congestion_controller",
"../modules/congestion_controller:delay_based_bwe",
"../modules/congestion_controller:estimators",
"../modules/congestion_controller/goog_cc:estimators",
"../modules/pacing",
"../modules/rtp_rtcp",
"../system_wrappers:system_wrappers_default",

View File

@ -31,9 +31,9 @@
#include "modules/audio_coding/neteq/tools/neteq_replacement_input.h"
#include "modules/audio_coding/neteq/tools/neteq_test.h"
#include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
#include "modules/congestion_controller/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/bitrate_estimator.h"
#include "modules/congestion_controller/delay_based_bwe.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/goog_cc/bitrate_estimator.h"
#include "modules/congestion_controller/include/receive_side_congestion_controller.h"
#include "modules/congestion_controller/include/send_side_congestion_controller.h"
#include "modules/include/module_common_types.h"