Revert of Make overuse estimator one dimensional. (patchset #5 id:80001 of https://codereview.webrtc.org/1376423002/ )
Reason for revert:
Broke webrtc_perf_tests on bots.
Original issue's description:
> Make overuse estimator one dimensional.
>
> This drops the payload size difference dimension of the Kalman filter,
> which doesn't improve the quality of the estimation when pacing packets
> on the send-side.
>
> R=gaetano.carlucci@gmail.com, mflodman@webrtc.org, terelius@webrtc.org
>
> Committed: https://crrev.com/06e05a85b9e4def75ed5e6b582c4df842616f25f
> Cr-Commit-Position: refs/heads/master@{#10809}
TBR=terelius@webrtc.org,mflodman@webrtc.org,gaetano.carlucci@gmail.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review URL: https://codereview.webrtc.org/1481003002
Cr-Commit-Position: refs/heads/master@{#10816}
diff --git a/webrtc/common_types.h b/webrtc/common_types.h
index a6453c2..048485f 100644
--- a/webrtc/common_types.h
+++ b/webrtc/common_types.h
@@ -747,6 +747,31 @@
}
};
+// Bandwidth over-use detector options. These are used to drive
+// experimentation with bandwidth estimation parameters.
+// See modules/remote_bitrate_estimator/overuse_detector.h
+struct OverUseDetectorOptions {
+ OverUseDetectorOptions()
+ : initial_slope(8.0/512.0),
+ initial_offset(0),
+ initial_e(),
+ initial_process_noise(),
+ initial_avg_noise(0.0),
+ initial_var_noise(50) {
+ initial_e[0][0] = 100;
+ initial_e[1][1] = 1e-1;
+ initial_e[0][1] = initial_e[1][0] = 0;
+ initial_process_noise[0] = 1e-13;
+ initial_process_noise[1] = 1e-2;
+ }
+ double initial_slope;
+ double initial_offset;
+ double initial_e[2][2];
+ double initial_process_noise[2];
+ double initial_avg_noise;
+ double initial_var_noise;
+};
+
// This structure will have the information about when packet is actually
// received by socket.
struct PacketTime {
diff --git a/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc b/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc
index a9d0f88..961d6bf 100644
--- a/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc
+++ b/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc
@@ -31,10 +31,13 @@
bool InterArrival::ComputeDeltas(uint32_t timestamp,
int64_t arrival_time_ms,
+ size_t packet_size,
uint32_t* timestamp_delta,
- int64_t* arrival_time_delta_ms) {
+ int64_t* arrival_time_delta_ms,
+ int* packet_size_delta) {
assert(timestamp_delta != NULL);
assert(arrival_time_delta_ms != NULL);
+ assert(packet_size_delta != NULL);
bool calculated_deltas = false;
if (current_timestamp_group_.IsFirstPacket()) {
// We don't have enough data to update the filter, so we store it until we
@@ -59,19 +62,23 @@
return false;
}
assert(*arrival_time_delta_ms >= 0);
+ *packet_size_delta = static_cast<int>(current_timestamp_group_.size) -
+ static_cast<int>(prev_timestamp_group_.size);
calculated_deltas = true;
}
prev_timestamp_group_ = current_timestamp_group_;
// The new timestamp is now the current frame.
current_timestamp_group_.first_timestamp = timestamp;
current_timestamp_group_.timestamp = timestamp;
+ current_timestamp_group_.size = 0;
}
else {
current_timestamp_group_.timestamp = LatestTimestamp(
current_timestamp_group_.timestamp, timestamp);
}
- current_timestamp_group_.complete_time_ms =
- std::max(current_timestamp_group_.complete_time_ms, arrival_time_ms);
+ // Accumulate the frame size.
+ current_timestamp_group_.size += packet_size;
+ current_timestamp_group_.complete_time_ms = arrival_time_ms;
return calculated_deltas;
}
diff --git a/webrtc/modules/remote_bitrate_estimator/inter_arrival.h b/webrtc/modules/remote_bitrate_estimator/inter_arrival.h
index 64ad1f6..427bafc 100644
--- a/webrtc/modules/remote_bitrate_estimator/inter_arrival.h
+++ b/webrtc/modules/remote_bitrate_estimator/inter_arrival.h
@@ -24,7 +24,7 @@
class InterArrival {
public:
// A timestamp group is defined as all packets with a timestamp which are at
- // most timestamp_group_length_ticks newer than the first timestamp in that
+ // most timestamp_group_length_ticks older than the first timestamp in that
// group.
InterArrival(uint32_t timestamp_group_length_ticks,
double timestamp_to_ms_coeff,
@@ -34,21 +34,30 @@
// group is still incomplete or if only one group has been completed.
// |timestamp| is the timestamp.
// |arrival_time_ms| is the local time at which the packet arrived.
+ // |packet_size| is the size of the packet.
// |timestamp_delta| (output) is the computed timestamp delta.
// |arrival_time_delta_ms| (output) is the computed arrival-time delta.
+ // |packet_size_delta| (output) is the computed size delta.
bool ComputeDeltas(uint32_t timestamp,
int64_t arrival_time_ms,
+ size_t packet_size,
uint32_t* timestamp_delta,
- int64_t* arrival_time_delta_ms);
+ int64_t* arrival_time_delta_ms,
+ int* packet_size_delta);
private:
struct TimestampGroup {
- TimestampGroup() : first_timestamp(0), timestamp(0), complete_time_ms(-1) {}
+ TimestampGroup()
+ : size(0),
+ first_timestamp(0),
+ timestamp(0),
+ complete_time_ms(-1) {}
bool IsFirstPacket() const {
return complete_time_ms == -1;
}
+ size_t size;
uint32_t first_timestamp;
uint32_t timestamp;
int64_t complete_time_ms;
diff --git a/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc b/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc
index dfe324c..64f7cca 100644
--- a/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc
+++ b/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc
@@ -45,30 +45,34 @@
// Test that neither inter_arrival instance complete the timestamp group from
// the given data.
- void ExpectFalse(int64_t timestamp_us, int64_t arrival_time_ms) {
+ void ExpectFalse(int64_t timestamp_us, int64_t arrival_time_ms,
+ size_t packet_size) {
InternalExpectFalse(inter_arrival_rtp_.get(),
- MakeRtpTimestamp(timestamp_us), arrival_time_ms);
+ MakeRtpTimestamp(timestamp_us), arrival_time_ms,
+ packet_size);
InternalExpectFalse(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
- arrival_time_ms);
+ arrival_time_ms, packet_size);
}
// Test that both inter_arrival instances complete the timestamp group from
// the given data and that all returned deltas are as expected (except
// timestamp delta, which is rounded from us to different ranges and must
// match within an interval, given in |timestamp_near].
- void ExpectTrue(int64_t timestamp_us,
- int64_t arrival_time_ms,
- int64_t expected_timestamp_delta_us,
+ void ExpectTrue(int64_t timestamp_us, int64_t arrival_time_ms,
+ size_t packet_size, int64_t expected_timestamp_delta_us,
int64_t expected_arrival_time_delta_ms,
+ int expected_packet_size_delta,
uint32_t timestamp_near) {
InternalExpectTrue(inter_arrival_rtp_.get(), MakeRtpTimestamp(timestamp_us),
- arrival_time_ms,
+ arrival_time_ms, packet_size,
MakeRtpTimestamp(expected_timestamp_delta_us),
- expected_arrival_time_delta_ms, timestamp_near);
+ expected_arrival_time_delta_ms,
+ expected_packet_size_delta, timestamp_near);
InternalExpectTrue(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
- arrival_time_ms,
+ arrival_time_ms, packet_size,
MakeAbsSendTime(expected_timestamp_delta_us),
- expected_arrival_time_delta_ms, timestamp_near << 8);
+ expected_arrival_time_delta_ms,
+ expected_packet_size_delta, timestamp_near << 8);
}
void WrapTestHelper(int64_t wrap_start_us, uint32_t timestamp_near,
@@ -78,29 +82,29 @@
// G1
int64_t arrival_time = 17;
- ExpectFalse(0, arrival_time);
+ ExpectFalse(0, arrival_time, 1);
// G2
arrival_time += kBurstThresholdMs + 1;
- ExpectFalse(wrap_start_us / 4, arrival_time);
+ ExpectFalse(wrap_start_us / 4, arrival_time, 1);
// G3
arrival_time += kBurstThresholdMs + 1;
- ExpectTrue(wrap_start_us / 2, arrival_time, wrap_start_us / 4,
- 6, // Delta G2-G1
+ ExpectTrue(wrap_start_us / 2, arrival_time, 1,
+ wrap_start_us / 4, 6, 0, // Delta G2-G1
0);
// G4
arrival_time += kBurstThresholdMs + 1;
int64_t g4_arrival_time = arrival_time;
- ExpectTrue(wrap_start_us / 2 + wrap_start_us / 4, arrival_time,
- wrap_start_us / 4, 6, // Delta G3-G2
+ ExpectTrue(wrap_start_us / 2 + wrap_start_us / 4, arrival_time, 1,
+ wrap_start_us / 4, 6, 0, // Delta G3-G2
timestamp_near);
// G5
arrival_time += kBurstThresholdMs + 1;
- ExpectTrue(wrap_start_us, arrival_time, wrap_start_us / 4,
- 6, // Delta G4-G3
+ ExpectTrue(wrap_start_us, arrival_time, 2,
+ wrap_start_us / 4, 6, 0, // Delta G4-G3
timestamp_near);
for (int i = 0; i < 10; ++i) {
// Slowly step across the wrap point.
@@ -109,34 +113,39 @@
// These packets arrive with timestamps in decreasing order but are
// nevertheless accumulated to group because their timestamps are higher
// than the initial timestamp of the group.
- ExpectFalse(wrap_start_us + kMinStep * (9 - i), arrival_time);
+ ExpectFalse(wrap_start_us + kMinStep * (9 - i), arrival_time, 1);
} else {
- ExpectFalse(wrap_start_us + kMinStep * i, arrival_time);
+ ExpectFalse(wrap_start_us + kMinStep * i, arrival_time, 1);
}
}
int64_t g5_arrival_time = arrival_time;
// This packet is out of order and should be dropped.
arrival_time += kBurstThresholdMs + 1;
- ExpectFalse(wrap_start_us - 100, arrival_time);
+ ExpectFalse(wrap_start_us - 100, arrival_time, 100);
// G6
arrival_time += kBurstThresholdMs + 1;
int64_t g6_arrival_time = arrival_time;
- ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time,
+ ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time, 10,
wrap_start_us / 4 + 9 * kMinStep,
- g5_arrival_time - g4_arrival_time, timestamp_near);
+ g5_arrival_time - g4_arrival_time,
+ (2 + 10) - 1, // Delta G5-G4
+ timestamp_near);
// This packet is out of order and should be dropped.
arrival_time += kBurstThresholdMs + 1;
- ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time);
+ ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time, 100);
// G7
arrival_time += kBurstThresholdMs + 1;
- ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs, arrival_time,
+ ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs,
+ arrival_time, 100,
// Delta G6-G5
kTriggerNewGroupUs - 9 * kMinStep,
- g6_arrival_time - g5_arrival_time, timestamp_near);
+ g6_arrival_time - g5_arrival_time,
+ 10 - (2 + 10),
+ timestamp_near);
}
private:
@@ -151,29 +160,43 @@
}
static void InternalExpectFalse(InterArrival* inter_arrival,
- uint32_t timestamp,
- int64_t arrival_time_ms) {
+ uint32_t timestamp, int64_t arrival_time_ms,
+ size_t packet_size) {
uint32_t dummy_timestamp = 101;
int64_t dummy_arrival_time_ms = 303;
- bool computed = inter_arrival->ComputeDeltas(
- timestamp, arrival_time_ms, &dummy_timestamp, &dummy_arrival_time_ms);
+ int dummy_packet_size = 909;
+ bool computed = inter_arrival->ComputeDeltas(timestamp,
+ arrival_time_ms,
+ packet_size,
+ &dummy_timestamp,
+ &dummy_arrival_time_ms,
+ &dummy_packet_size);
EXPECT_EQ(computed, false);
EXPECT_EQ(101ul, dummy_timestamp);
EXPECT_EQ(303, dummy_arrival_time_ms);
+ EXPECT_EQ(909, dummy_packet_size);
}
static void InternalExpectTrue(InterArrival* inter_arrival,
uint32_t timestamp, int64_t arrival_time_ms,
+ size_t packet_size,
uint32_t expected_timestamp_delta,
int64_t expected_arrival_time_delta_ms,
+ int expected_packet_size_delta,
uint32_t timestamp_near) {
uint32_t delta_timestamp = 101;
int64_t delta_arrival_time_ms = 303;
- bool computed = inter_arrival->ComputeDeltas(
- timestamp, arrival_time_ms, &delta_timestamp, &delta_arrival_time_ms);
+ int delta_packet_size = 909;
+ bool computed = inter_arrival->ComputeDeltas(timestamp,
+ arrival_time_ms,
+ packet_size,
+ &delta_timestamp,
+ &delta_arrival_time_ms,
+ &delta_packet_size);
EXPECT_EQ(true, computed);
EXPECT_NEAR(expected_timestamp_delta, delta_timestamp, timestamp_near);
EXPECT_EQ(expected_arrival_time_delta_ms, delta_arrival_time_ms);
+ EXPECT_EQ(expected_packet_size_delta, delta_packet_size);
}
rtc::scoped_ptr<InterArrival> inter_arrival_rtp_;
@@ -181,124 +204,131 @@
};
TEST_F(InterArrivalTest, FirstPacket) {
- ExpectFalse(0, 17);
+ ExpectFalse(0, 17, 1);
}
TEST_F(InterArrivalTest, FirstGroup) {
// G1
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
- ExpectFalse(0, arrival_time);
+ ExpectFalse(0, arrival_time, 1);
// G2
arrival_time += kBurstThresholdMs + 1;
int64_t g2_arrival_time = arrival_time;
- ExpectFalse(kTriggerNewGroupUs, arrival_time);
+ ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
// G3
// Only once the first packet of the third group arrives, do we see the deltas
// between the first two.
arrival_time += kBurstThresholdMs + 1;
- ExpectTrue(2 * kTriggerNewGroupUs, arrival_time,
+ ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
// Delta G2-G1
- kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 0);
+ kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1,
+ 0);
}
TEST_F(InterArrivalTest, SecondGroup) {
// G1
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
- ExpectFalse(0, arrival_time);
+ ExpectFalse(0, arrival_time, 1);
// G2
arrival_time += kBurstThresholdMs + 1;
int64_t g2_arrival_time = arrival_time;
- ExpectFalse(kTriggerNewGroupUs, arrival_time);
+ ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
// G3
arrival_time += kBurstThresholdMs + 1;
int64_t g3_arrival_time = arrival_time;
- ExpectTrue(2 * kTriggerNewGroupUs, arrival_time,
+ ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
// Delta G2-G1
- kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 0);
+ kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1,
+ 0);
// G4
// First packet of 4th group yields deltas between group 2 and 3.
arrival_time += kBurstThresholdMs + 1;
- ExpectTrue(3 * kTriggerNewGroupUs, arrival_time,
+ ExpectTrue(3 * kTriggerNewGroupUs, arrival_time, 2,
// Delta G3-G2
- kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, 0);
+ kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, -1,
+ 0);
}
TEST_F(InterArrivalTest, AccumulatedGroup) {
// G1
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
- ExpectFalse(0, arrival_time);
+ ExpectFalse(0, arrival_time, 1);
// G2
arrival_time += kBurstThresholdMs + 1;
- ExpectFalse(kTriggerNewGroupUs, 28);
+ ExpectFalse(kTriggerNewGroupUs, 28, 2);
int64_t timestamp = kTriggerNewGroupUs;
for (int i = 0; i < 10; ++i) {
// A bunch of packets arriving within the same group.
arrival_time += kBurstThresholdMs + 1;
timestamp += kMinStep;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 1);
}
int64_t g2_arrival_time = arrival_time;
int64_t g2_timestamp = timestamp;
// G3
arrival_time = 500;
- ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, g2_timestamp,
- g2_arrival_time - g1_arrival_time, 0);
+ ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 100,
+ g2_timestamp, g2_arrival_time - g1_arrival_time,
+ (2 + 10) - 1, // Delta G2-G1
+ 0);
}
TEST_F(InterArrivalTest, OutOfOrderPacket) {
// G1
int64_t arrival_time = 17;
int64_t timestamp = 0;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 1);
int64_t g1_timestamp = timestamp;
int64_t g1_arrival_time = arrival_time;
// G2
arrival_time += 11;
timestamp += kTriggerNewGroupUs;
- ExpectFalse(timestamp, 28);
+ ExpectFalse(timestamp, 28, 2);
for (int i = 0; i < 10; ++i) {
arrival_time += kBurstThresholdMs + 1;
timestamp += kMinStep;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 1);
}
int64_t g2_timestamp = timestamp;
int64_t g2_arrival_time = arrival_time;
// This packet is out of order and should be dropped.
arrival_time = 281;
- ExpectFalse(g1_timestamp, arrival_time);
+ ExpectFalse(g1_timestamp, arrival_time, 100);
// G3
arrival_time = 500;
timestamp = 2 * kTriggerNewGroupUs;
- ExpectTrue(timestamp, arrival_time,
+ ExpectTrue(timestamp, arrival_time, 100,
// Delta G2-G1
- g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time, 0);
+ g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time,
+ (2 + 10) - 1,
+ 0);
}
TEST_F(InterArrivalTest, OutOfOrderWithinGroup) {
// G1
int64_t arrival_time = 17;
int64_t timestamp = 0;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 1);
int64_t g1_timestamp = timestamp;
int64_t g1_arrival_time = arrival_time;
// G2
timestamp += kTriggerNewGroupUs;
arrival_time += 11;
- ExpectFalse(kTriggerNewGroupUs, 28);
+ ExpectFalse(kTriggerNewGroupUs, 28, 2);
timestamp += 10 * kMinStep;
int64_t g2_timestamp = timestamp;
for (int i = 0; i < 10; ++i) {
@@ -306,7 +336,7 @@
// nevertheless accumulated to group because their timestamps are higher
// than the initial timestamp of the group.
arrival_time += kBurstThresholdMs + 1;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 1);
timestamp -= kMinStep;
}
int64_t g2_arrival_time = arrival_time;
@@ -314,19 +344,21 @@
// However, this packet is deemed out of order and should be dropped.
arrival_time = 281;
timestamp = g1_timestamp;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 100);
// G3
timestamp = 2 * kTriggerNewGroupUs;
arrival_time = 500;
- ExpectTrue(timestamp, arrival_time, g2_timestamp - g1_timestamp,
- g2_arrival_time - g1_arrival_time, 0);
+ ExpectTrue(timestamp, arrival_time, 100,
+ g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time,
+ (2 + 10) - 1,
+ 0);
}
TEST_F(InterArrivalTest, TwoBursts) {
// G1
int64_t g1_arrival_time = 17;
- ExpectFalse(0, g1_arrival_time);
+ ExpectFalse(0, g1_arrival_time, 1);
// G2
int64_t timestamp = kTriggerNewGroupUs;
@@ -335,7 +367,7 @@
// A bunch of packets arriving in one burst (within 5 ms apart).
timestamp += 30000;
arrival_time += kBurstThresholdMs;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 1);
}
int64_t g2_arrival_time = arrival_time;
int64_t g2_timestamp = timestamp;
@@ -343,23 +375,27 @@
// G3
timestamp += 30000;
arrival_time += kBurstThresholdMs + 1;
- ExpectTrue(timestamp, arrival_time, g2_timestamp,
- g2_arrival_time - g1_arrival_time, 0);
+ ExpectTrue(timestamp, arrival_time, 100,
+ g2_timestamp, g2_arrival_time - g1_arrival_time,
+ 10 - 1, // Delta G2-G1
+ 0);
}
TEST_F(InterArrivalTest, NoBursts) {
// G1
- ExpectFalse(0, 17);
+ ExpectFalse(0, 17, 1);
// G2
int64_t timestamp = kTriggerNewGroupUs;
int64_t arrival_time = 28;
- ExpectFalse(timestamp, arrival_time);
+ ExpectFalse(timestamp, arrival_time, 2);
// G3
ExpectTrue(kTriggerNewGroupUs + 30000, arrival_time + kBurstThresholdMs + 1,
- timestamp - 0, arrival_time - 17, 0);
+ 100, timestamp - 0, arrival_time - 17,
+ 2 - 1, // Delta G2-G1
+ 0);
}
// Yields 0xfffffffe when converted to internal representation in
diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc
index 5bb105e..c934089 100644
--- a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc
+++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc
@@ -50,11 +50,12 @@
"%lf,%lf", k_up, k_down) == 2;
}
-OveruseDetector::OveruseDetector()
+OveruseDetector::OveruseDetector(const OverUseDetectorOptions& options)
: in_experiment_(AdaptiveThresholdExperimentIsEnabled()),
k_up_(0.01),
k_down_(0.00018),
overusing_time_threshold_(100),
+ options_(options),
threshold_(12.5),
last_update_ms_(-1),
prev_offset_(0.0),
diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector.h b/webrtc/modules/remote_bitrate_estimator/overuse_detector.h
index d451a3e..56e9c14 100644
--- a/webrtc/modules/remote_bitrate_estimator/overuse_detector.h
+++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector.h
@@ -24,7 +24,7 @@
class OveruseDetector {
public:
- OveruseDetector();
+ explicit OveruseDetector(const OverUseDetectorOptions& options);
virtual ~OveruseDetector();
// Update the detection state based on the estimated inter-arrival time delta
@@ -51,6 +51,7 @@
double overusing_time_threshold_;
// Must be first member variable. Cannot be const because we need to be
// copyable.
+ webrtc::OverUseDetectorOptions options_;
double threshold_;
int64_t last_update_ms_;
double prev_offset_;
diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc b/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc
index d474a4d..dcad04b 100644
--- a/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc
+++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc
@@ -36,21 +36,22 @@
receive_time_ms_(0),
rtp_timestamp_(10 * 90),
overuse_detector_(),
- overuse_estimator_(new OveruseEstimator()),
+ overuse_estimator_(new OveruseEstimator(options_)),
inter_arrival_(new InterArrival(5 * 90, kRtpTimestampToMs, true)),
random_(1234) {}
protected:
- void SetUp() override { overuse_detector_.reset(new OveruseDetector()); }
+ void SetUp() override {
+ overuse_detector_.reset(new OveruseDetector(options_));
+ }
- int Run100000Samples(int packets_per_frame,
- int mean_ms,
+ int Run100000Samples(int packets_per_frame, size_t packet_size, int mean_ms,
int standard_deviation_ms) {
int unique_overuse = 0;
int last_overuse = -1;
for (int i = 0; i < 100000; ++i) {
for (int j = 0; j < packets_per_frame; ++j) {
- UpdateDetector(rtp_timestamp_, receive_time_ms_);
+ UpdateDetector(rtp_timestamp_, receive_time_ms_, packet_size);
}
rtp_timestamp_ += mean_ms * 90;
now_ms_ += mean_ms;
@@ -67,14 +68,12 @@
return unique_overuse;
}
- int RunUntilOveruse(int packets_per_frame,
- int mean_ms,
- int standard_deviation_ms,
- int drift_per_frame_ms) {
+ int RunUntilOveruse(int packets_per_frame, size_t packet_size, int mean_ms,
+ int standard_deviation_ms, int drift_per_frame_ms) {
// Simulate a higher send pace, that is too high.
for (int i = 0; i < 1000; ++i) {
for (int j = 0; j < packets_per_frame; ++j) {
- UpdateDetector(rtp_timestamp_, receive_time_ms_);
+ UpdateDetector(rtp_timestamp_, receive_time_ms_, packet_size);
}
rtp_timestamp_ += mean_ms * 90;
now_ms_ += mean_ms + drift_per_frame_ms;
@@ -88,13 +87,19 @@
return -1;
}
- void UpdateDetector(uint32_t rtp_timestamp, int64_t receive_time_ms) {
+ void UpdateDetector(uint32_t rtp_timestamp, int64_t receive_time_ms,
+ size_t packet_size) {
uint32_t timestamp_delta;
int64_t time_delta;
- if (inter_arrival_->ComputeDeltas(rtp_timestamp, receive_time_ms,
- ×tamp_delta, &time_delta)) {
+ int size_delta;
+ if (inter_arrival_->ComputeDeltas(rtp_timestamp,
+ receive_time_ms,
+ packet_size,
+ ×tamp_delta,
+ &time_delta,
+ &size_delta)) {
double timestamp_delta_ms = timestamp_delta / 90.0;
- overuse_estimator_->Update(time_delta, timestamp_delta_ms,
+ overuse_estimator_->Update(time_delta, timestamp_delta_ms, size_delta,
overuse_detector_->State());
overuse_detector_->Detect(
overuse_estimator_->offset(), timestamp_delta_ms,
@@ -105,6 +110,7 @@
int64_t now_ms_;
int64_t receive_time_ms_;
uint32_t rtp_timestamp_;
+ OverUseDetectorOptions options_;
rtc::scoped_ptr<OveruseDetector> overuse_detector_;
rtc::scoped_ptr<OveruseEstimator> overuse_estimator_;
rtc::scoped_ptr<InterArrival> inter_arrival_;
@@ -125,12 +131,13 @@
}
TEST_F(OveruseDetectorTest, SimpleNonOveruse30fps) {
+ size_t packet_size = 1200;
uint32_t frame_duration_ms = 33;
uint32_t rtp_timestamp = 10 * 90;
// No variance.
for (int i = 0; i < 1000; ++i) {
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
now_ms_ += frame_duration_ms;
rtp_timestamp += frame_duration_ms * 90;
EXPECT_EQ(kBwNormal, overuse_detector_->State());
@@ -141,9 +148,10 @@
TEST_F(OveruseDetectorTest, SimpleNonOveruseWithReceiveVariance) {
uint32_t frame_duration_ms = 10;
uint32_t rtp_timestamp = 10 * 90;
+ size_t packet_size = 1200;
for (int i = 0; i < 1000; ++i) {
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
now_ms_ += frame_duration_ms - 5;
@@ -158,8 +166,10 @@
// Roughly 1 Mbit/s.
uint32_t frame_duration_ms = 10;
uint32_t rtp_timestamp = 10 * 90;
+ size_t packet_size = 1200;
+
for (int i = 0; i < 1000; ++i) {
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
now_ms_ += frame_duration_ms;
if (i % 2) {
rtp_timestamp += (frame_duration_ms - 5) * 90;
@@ -171,30 +181,32 @@
}
TEST_F(OveruseDetectorTest, SimpleOveruse2000Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 6;
int frame_duration_ms = 33;
int drift_per_frame_ms = 1;
int sigma_ms = 0; // No variance.
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(8, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, SimpleOveruse100kbit10fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 100;
int drift_per_frame_ms = 1;
int sigma_ms = 0; // No variance.
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(6, frames_until_overuse);
}
@@ -202,11 +214,12 @@
uint32_t frame_duration_ms = 100;
uint32_t drift_per_frame_ms = 10;
uint32_t rtp_timestamp = frame_duration_ms * 90;
+ size_t packet_size = 1200;
int offset = 10;
// Run 1000 samples to reach steady state.
for (int i = 0; i < 1000; ++i) {
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
offset = rand() % 50;
@@ -220,12 +233,12 @@
// Above noise generate a standard deviation of approximately 28 ms.
// Total build up of 150 ms.
for (int j = 0; j < 15; ++j) {
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
now_ms_ += frame_duration_ms + drift_per_frame_ms;
rtp_timestamp += frame_duration_ms * 90;
EXPECT_EQ(kBwNormal, overuse_detector_->State());
}
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
EXPECT_EQ(kBwOverusing, overuse_detector_->State());
}
@@ -233,11 +246,12 @@
uint32_t frame_duration_ms = 100;
uint32_t drift_per_frame_ms = 1;
uint32_t rtp_timestamp = frame_duration_ms * 90;
+ size_t packet_size = 1200;
int offset = 10;
// Run 1000 samples to reach steady state.
for (int i = 0; i < 1000; ++i) {
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
offset = rand() % 2;
@@ -250,12 +264,12 @@
// Simulate a higher send pace, that is too high.
// Total build up of 6 ms.
for (int j = 0; j < 6; ++j) {
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
now_ms_ += frame_duration_ms + drift_per_frame_ms;
rtp_timestamp += frame_duration_ms * 90;
EXPECT_EQ(kBwNormal, overuse_detector_->State());
}
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
EXPECT_EQ(kBwOverusing, overuse_detector_->State());
}
@@ -263,16 +277,17 @@
uint32_t frame_duration_ms = 33;
uint32_t drift_per_frame_ms = 1;
uint32_t rtp_timestamp = frame_duration_ms * 90;
+ size_t packet_size = 1200;
int offset = 0;
// Run 1000 samples to reach steady state.
for (int i = 0; i < 1000; ++i) {
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
offset = rand() % 2;
@@ -285,285 +300,305 @@
// Simulate a higher send pace, that is too high.
// Total build up of 30 ms.
for (int j = 0; j < 5; ++j) {
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
now_ms_ += frame_duration_ms + drift_per_frame_ms * 6;
rtp_timestamp += frame_duration_ms * 90;
EXPECT_EQ(kBwNormal, overuse_detector_->State());
}
- UpdateDetector(rtp_timestamp, now_ms_);
+ UpdateDetector(rtp_timestamp, now_ms_, packet_size);
EXPECT_EQ(kBwOverusing, overuse_detector_->State());
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(LowGaussianVariance30Kbit3fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 333;
int drift_per_frame_ms = 1;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(13, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(14, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift30Kbit3fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 333;
int drift_per_frame_ms = 100;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(13, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(4, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVariance30Kbit3fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 333;
int drift_per_frame_ms = 1;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
- EXPECT_EQ(50, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
+ EXPECT_EQ(46, unique_overuse);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(42, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift30Kbit3fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 333;
int drift_per_frame_ms = 100;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
- EXPECT_EQ(50, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
+ EXPECT_EQ(46, unique_overuse);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(4, frames_until_overuse);
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(LowGaussianVariance100Kbit5fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 2;
int frame_duration_ms = 200;
int drift_per_frame_ms = 1;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(12, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(12, frames_until_overuse);
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(HighGaussianVariance100Kbit5fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 2;
int frame_duration_ms = 200;
int drift_per_frame_ms = 1;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(16, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(37, frames_until_overuse);
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(LowGaussianVariance100Kbit10fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 100;
int drift_per_frame_ms = 1;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(12, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(12, frames_until_overuse);
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(HighGaussianVariance100Kbit10fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 100;
int drift_per_frame_ms = 1;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(12, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(37, frames_until_overuse);
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(LowGaussianVariance300Kbit30fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 33;
int drift_per_frame_ms = 1;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(14, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift300Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 33;
int drift_per_frame_ms = 10;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(6, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVariance300Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 33;
int drift_per_frame_ms = 1;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(49, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift300Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 1;
int frame_duration_ms = 33;
int drift_per_frame_ms = 10;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(8, frames_until_overuse);
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(LowGaussianVariance1000Kbit30fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 3;
int frame_duration_ms = 33;
int drift_per_frame_ms = 1;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(14, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift1000Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 3;
int frame_duration_ms = 33;
int drift_per_frame_ms = 10;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(6, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVariance1000Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 3;
int frame_duration_ms = 33;
int drift_per_frame_ms = 1;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(49, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift1000Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 3;
int frame_duration_ms = 33;
int drift_per_frame_ms = 10;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(8, frames_until_overuse);
}
TEST_F(OveruseDetectorTest,
DISABLED_ON_ANDROID(LowGaussianVariance2000Kbit30fps)) {
+ size_t packet_size = 1200;
int packets_per_frame = 6;
int frame_duration_ms = 33;
int drift_per_frame_ms = 1;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(14, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift2000Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 6;
int frame_duration_ms = 33;
int drift_per_frame_ms = 10;
int sigma_ms = 3;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(6, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVariance2000Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 6;
int frame_duration_ms = 33;
int drift_per_frame_ms = 1;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(49, frames_until_overuse);
}
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift2000Kbit30fps) {
+ size_t packet_size = 1200;
int packets_per_frame = 6;
int frame_duration_ms = 33;
int drift_per_frame_ms = 10;
int sigma_ms = 10;
- int unique_overuse =
- Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
+ int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
- int frames_until_overuse = RunUntilOveruse(
- packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
+ int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
+ frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(8, frames_until_overuse);
}
@@ -574,7 +609,9 @@
"WebRTC-AdaptiveBweThreshold/Enabled-0.01,0.00018/") {}
protected:
- void SetUp() override { overuse_detector_.reset(new OveruseDetector()); }
+ void SetUp() override {
+ overuse_detector_.reset(new OveruseDetector(options_));
+ }
test::ScopedFieldTrials override_field_trials_;
};
diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc
index a9d3bfe..4be7b74 100644
--- a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc
+++ b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc
@@ -16,7 +16,6 @@
#include <stdlib.h>
#include <string.h>
-#include "webrtc/base/checks.h"
#include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "webrtc/system_wrappers/include/logging.h"
@@ -25,25 +24,33 @@
enum { kMinFramePeriodHistoryLength = 60 };
enum { kDeltaCounterMax = 1000 };
-OveruseEstimator::OveruseEstimator()
- : num_of_deltas_(0),
- offset_(0),
- prev_offset_(offset_),
- e_(0.1),
- process_noise_(1e-2),
- avg_noise_(0),
- var_noise_(50),
- send_delta_history_() {}
-
-OveruseEstimator::~OveruseEstimator() {
- send_delta_history_.clear();
+OveruseEstimator::OveruseEstimator(const OverUseDetectorOptions& options)
+ : options_(options),
+ num_of_deltas_(0),
+ slope_(options_.initial_slope),
+ offset_(options_.initial_offset),
+ prev_offset_(options_.initial_offset),
+ E_(),
+ process_noise_(),
+ avg_noise_(options_.initial_avg_noise),
+ var_noise_(options_.initial_var_noise),
+ ts_delta_hist_() {
+ memcpy(E_, options_.initial_e, sizeof(E_));
+ memcpy(process_noise_, options_.initial_process_noise,
+ sizeof(process_noise_));
}
-void OveruseEstimator::Update(double recv_delta_ms,
- double send_delta_ms,
+OveruseEstimator::~OveruseEstimator() {
+ ts_delta_hist_.clear();
+}
+
+void OveruseEstimator::Update(int64_t t_delta,
+ double ts_delta,
+ int size_delta,
BandwidthUsage current_hypothesis) {
- const double min_frame_period = UpdateMinFramePeriod(send_delta_ms);
- const double delta_ms = recv_delta_ms - send_delta_ms;
+ const double min_frame_period = UpdateMinFramePeriod(ts_delta);
+ const double t_ts_delta = t_delta - ts_delta;
+ double fs_delta = size_delta;
++num_of_deltas_;
if (num_of_deltas_ > kDeltaCounterMax) {
@@ -51,14 +58,19 @@
}
// Update the Kalman filter.
- e_ += process_noise_;
+ E_[0][0] += process_noise_[0];
+ E_[1][1] += process_noise_[1];
if ((current_hypothesis == kBwOverusing && offset_ < prev_offset_) ||
(current_hypothesis == kBwUnderusing && offset_ > prev_offset_)) {
- e_ += 10 * process_noise_;
+ E_[1][1] += 10 * process_noise_[1];
}
- const double residual = delta_ms - offset_;
+ const double h[2] = {fs_delta, 1.0};
+ const double Eh[2] = {E_[0][0]*h[0] + E_[0][1]*h[1],
+ E_[1][0]*h[0] + E_[1][1]*h[1]};
+
+ const double residual = t_ts_delta - slope_*h[0] - offset_;
const bool in_stable_state = (current_hypothesis == kBwNormal);
const double max_residual = 3.0 * sqrt(var_noise_);
@@ -70,47 +82,66 @@
UpdateNoiseEstimate(residual < 0 ? -max_residual : max_residual,
min_frame_period, in_stable_state);
}
- const double k = e_ / (var_noise_ + e_);
+
+ const double denom = var_noise_ + h[0]*Eh[0] + h[1]*Eh[1];
+
+ const double K[2] = {Eh[0] / denom,
+ Eh[1] / denom};
+
+ const double IKh[2][2] = {{1.0 - K[0]*h[0], -K[0]*h[1]},
+ {-K[1]*h[0], 1.0 - K[1]*h[1]}};
+ const double e00 = E_[0][0];
+ const double e01 = E_[0][1];
// Update state.
- e_ = e_ * (1.0 - k);
+ E_[0][0] = e00 * IKh[0][0] + E_[1][0] * IKh[0][1];
+ E_[0][1] = e01 * IKh[0][0] + E_[1][1] * IKh[0][1];
+ E_[1][0] = e00 * IKh[1][0] + E_[1][0] * IKh[1][1];
+ E_[1][1] = e01 * IKh[1][0] + E_[1][1] * IKh[1][1];
- // The covariance matrix must be positive.
- RTC_DCHECK(e_ >= 0.0);
- if (e_ < 0)
- LOG(LS_ERROR) << "The over-use estimator's covariance is negative!";
+ // The covariance matrix must be positive semi-definite.
+ bool positive_semi_definite = E_[0][0] + E_[1][1] >= 0 &&
+ E_[0][0] * E_[1][1] - E_[0][1] * E_[1][0] >= 0 && E_[0][0] >= 0;
+ assert(positive_semi_definite);
+ if (!positive_semi_definite) {
+ LOG(LS_ERROR) << "The over-use estimator's covariance matrix is no longer "
+ "semi-definite.";
+ }
- offset_ = offset_ + k * residual;
+ slope_ = slope_ + K[0] * residual;
+ prev_offset_ = offset_;
+ offset_ = offset_ + K[1] * residual;
}
-double OveruseEstimator::UpdateMinFramePeriod(double send_delta_ms) {
- double min_frame_period = send_delta_ms;
- if (send_delta_history_.size() >= kMinFramePeriodHistoryLength) {
- send_delta_history_.pop_front();
+double OveruseEstimator::UpdateMinFramePeriod(double ts_delta) {
+ double min_frame_period = ts_delta;
+ if (ts_delta_hist_.size() >= kMinFramePeriodHistoryLength) {
+ ts_delta_hist_.pop_front();
}
- for (double delta_ms : send_delta_history_) {
- min_frame_period = std::min(delta_ms, min_frame_period);
+ std::list<double>::iterator it = ts_delta_hist_.begin();
+ for (; it != ts_delta_hist_.end(); it++) {
+ min_frame_period = std::min(*it, min_frame_period);
}
- send_delta_history_.push_back(send_delta_ms);
+ ts_delta_hist_.push_back(ts_delta);
return min_frame_period;
}
void OveruseEstimator::UpdateNoiseEstimate(double residual,
- double send_delta_ms,
+ double ts_delta,
bool stable_state) {
if (!stable_state) {
return;
}
// Faster filter during startup to faster adapt to the jitter level
// of the network. |alpha| is tuned for 30 frames per second, but is scaled
- // according to |send_delta_ms|.
+ // according to |ts_delta|.
double alpha = 0.01;
if (num_of_deltas_ > 10*30) {
alpha = 0.002;
}
// Only update the noise estimate if we're not over-using. |beta| is a
// function of alpha and the time delta since the previous update.
- const double beta = pow(1 - alpha, send_delta_ms * 30.0 / 1000.0);
+ const double beta = pow(1 - alpha, ts_delta * 30.0 / 1000.0);
avg_noise_ = beta * avg_noise_
+ (1 - beta) * residual;
var_noise_ = beta * var_noise_
diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h
index d04e7d9..d671f39 100644
--- a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h
+++ b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h
@@ -20,15 +20,14 @@
class OveruseEstimator {
public:
- OveruseEstimator();
+ explicit OveruseEstimator(const OverUseDetectorOptions& options);
~OveruseEstimator();
// Update the estimator with a new sample. The deltas should represent deltas
// between timestamp groups as defined by the InterArrival class.
// |current_hypothesis| should be the hypothesis of the over-use detector at
// this time.
- void Update(double recv_delta_ms,
- double send_delta_ms,
+ void Update(int64_t t_delta, double ts_delta, int size_delta,
BandwidthUsage current_hypothesis);
// Returns the estimated noise/jitter variance in ms^2.
@@ -48,21 +47,21 @@
}
private:
- double UpdateMinFramePeriod(double send_delta_ms);
- void UpdateNoiseEstimate(double residual,
- double send_delta_ms,
- bool stable_state);
+ double UpdateMinFramePeriod(double ts_delta);
+ void UpdateNoiseEstimate(double residual, double ts_delta, bool stable_state);
// Must be first member variable. Cannot be const because we need to be
// copyable.
+ OverUseDetectorOptions options_;
uint16_t num_of_deltas_;
+ double slope_;
double offset_;
double prev_offset_;
- double e_;
- double process_noise_;
+ double E_[2][2];
+ double process_noise_[2];
double avg_noise_;
double var_noise_;
- std::list<double> send_delta_history_;
+ std::list<double> ts_delta_hist_;
RTC_DISALLOW_COPY_AND_ASSIGN(OveruseEstimator);
};
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
index cd91912..51f7d43 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
@@ -102,6 +102,10 @@
: crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
observer_(observer),
clock_(clock),
+ ssrcs_(),
+ inter_arrival_(),
+ estimator_(OverUseDetectorOptions()),
+ detector_(OverUseDetectorOptions()),
incoming_bitrate_(kBitrateWindowMs, 8000),
last_process_time_(-1),
process_interval_ms_(kProcessIntervalMs),
@@ -267,6 +271,7 @@
uint32_t ts_delta = 0;
int64_t t_delta = 0;
+ int size_delta = 0;
// For now only try to detect probes while we don't have a valid estimate, and
// make sure the packet was paced. We currently assume that only packets
// larger than 200 bytes are paced by the sender.
@@ -296,10 +301,10 @@
new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
kTimestampToMs, true));
}
- if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, &ts_delta,
- &t_delta)) {
+ if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, payload_size,
+ &ts_delta, &t_delta, &size_delta)) {
double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
- estimator_.Update(t_delta, ts_delta_ms, detector_.State());
+ estimator_.Update(t_delta, ts_delta_ms, size_delta, detector_.State());
detector_.Detect(estimator_.offset(), ts_delta_ms,
estimator_.num_of_deltas(), arrival_time_ms);
UpdateStats(static_cast<int>(t_delta - ts_delta_ms), now_ms);
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
index 29115b9..f1a1cb6 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
@@ -28,13 +28,14 @@
static const double kTimestampToMs = 1.0 / 90.0;
struct RemoteBitrateEstimatorSingleStream::Detector {
- explicit Detector(int64_t last_packet_time_ms, bool enable_burst_grouping)
- : last_packet_time_ms(last_packet_time_ms),
- inter_arrival(90 * kTimestampGroupLengthMs,
- kTimestampToMs,
- enable_burst_grouping),
- estimator(),
- detector() {}
+ explicit Detector(int64_t last_packet_time_ms,
+ const OverUseDetectorOptions& options,
+ bool enable_burst_grouping)
+ : last_packet_time_ms(last_packet_time_ms),
+ inter_arrival(90 * kTimestampGroupLengthMs, kTimestampToMs,
+ enable_burst_grouping),
+ estimator(options),
+ detector(options) {}
int64_t last_packet_time_ms;
InterArrival inter_arrival;
OveruseEstimator estimator;
@@ -81,8 +82,8 @@
// automatically cleaned up when we have one RemoteBitrateEstimator per REMB
// group.
std::pair<SsrcOveruseEstimatorMap::iterator, bool> insert_result =
- overuse_detectors_.insert(
- std::make_pair(ssrc, new Detector(now_ms, true)));
+ overuse_detectors_.insert(std::make_pair(
+ ssrc, new Detector(now_ms, OverUseDetectorOptions(), true)));
it = insert_result.first;
}
Detector* estimator = it->second;
@@ -91,10 +92,12 @@
const BandwidthUsage prior_state = estimator->detector.State();
uint32_t timestamp_delta = 0;
int64_t time_delta = 0;
+ int size_delta = 0;
if (estimator->inter_arrival.ComputeDeltas(rtp_timestamp, arrival_time_ms,
- ×tamp_delta, &time_delta)) {
+ payload_size, ×tamp_delta,
+ &time_delta, &size_delta)) {
double timestamp_delta_ms = timestamp_delta * kTimestampToMs;
- estimator->estimator.Update(time_delta, timestamp_delta_ms,
+ estimator->estimator.Update(time_delta, timestamp_delta_ms, size_delta,
estimator->detector.State());
estimator->detector.Detect(estimator->estimator.offset(),
timestamp_delta_ms,
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc
index 70051bb..a6c182a 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc
@@ -52,7 +52,7 @@
}
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThreeStreamsWrap) {
- CapacityDropTestHelper(3, true, 567);
+ CapacityDropTestHelper(3, true, 734);
}
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThirteenStreamsWrap) {
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
index 42d68da..7a7645f 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
@@ -61,7 +61,8 @@
class RtcpFormatRembTest : public ::testing::Test {
protected:
RtcpFormatRembTest()
- : system_clock_(Clock::GetRealTimeClock()),
+ : over_use_detector_options_(),
+ system_clock_(Clock::GetRealTimeClock()),
dummy_rtp_rtcp_impl_(nullptr),
receive_statistics_(ReceiveStatistics::Create(system_clock_)),
rtcp_sender_(nullptr),
@@ -74,6 +75,7 @@
void SetUp() override;
void TearDown() override;
+ OverUseDetectorOptions over_use_detector_options_;
Clock* system_clock_;
ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_;
rtc::scoped_ptr<ReceiveStatistics> receive_statistics_;
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index 7f0121c..5b0e656 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -66,7 +66,8 @@
class RtcpReceiverTest : public ::testing::Test {
protected:
RtcpReceiverTest()
- : system_clock_(1335900000),
+ : over_use_detector_options_(),
+ system_clock_(1335900000),
remote_bitrate_observer_(),
remote_bitrate_estimator_(
new RemoteBitrateEstimatorSingleStream(&remote_bitrate_observer_,
@@ -130,6 +131,7 @@
return 0;
}
+ OverUseDetectorOptions over_use_detector_options_;
SimulatedClock system_clock_;
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
RTCPReceiver* rtcp_receiver_;