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

Review URL: https://codereview.webrtc.org/1376423002 .

Cr-Commit-Position: refs/heads/master@{#10809}
This commit is contained in:
Stefan Holmer
2015-11-26 15:35:02 +01:00
parent 0fcaf99b71
commit 06e05a85b9
14 changed files with 264 additions and 422 deletions

View File

@ -747,31 +747,6 @@ struct VideoCodec {
}
};
// 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 {

View File

@ -31,13 +31,10 @@ InterArrival::InterArrival(uint32_t timestamp_group_length_ticks,
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,
int* packet_size_delta) {
int64_t* arrival_time_delta_ms) {
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
@ -62,23 +59,19 @@ bool InterArrival::ComputeDeltas(uint32_t timestamp,
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);
}
// Accumulate the frame size.
current_timestamp_group_.size += packet_size;
current_timestamp_group_.complete_time_ms = arrival_time_ms;
current_timestamp_group_.complete_time_ms =
std::max(current_timestamp_group_.complete_time_ms, arrival_time_ms);
return calculated_deltas;
}

View File

@ -24,7 +24,7 @@ namespace webrtc {
class InterArrival {
public:
// A timestamp group is defined as all packets with a timestamp which are at
// most timestamp_group_length_ticks older than the first timestamp in that
// most timestamp_group_length_ticks newer than the first timestamp in that
// group.
InterArrival(uint32_t timestamp_group_length_ticks,
double timestamp_to_ms_coeff,
@ -34,30 +34,21 @@ class InterArrival {
// 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,
int* packet_size_delta);
int64_t* arrival_time_delta_ms);
private:
struct TimestampGroup {
TimestampGroup()
: size(0),
first_timestamp(0),
timestamp(0),
complete_time_ms(-1) {}
TimestampGroup() : 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;

View File

@ -45,34 +45,30 @@ class InterArrivalTest : public ::testing::Test {
// 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,
size_t packet_size) {
void ExpectFalse(int64_t timestamp_us, int64_t arrival_time_ms) {
InternalExpectFalse(inter_arrival_rtp_.get(),
MakeRtpTimestamp(timestamp_us), arrival_time_ms,
packet_size);
MakeRtpTimestamp(timestamp_us), arrival_time_ms);
InternalExpectFalse(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
arrival_time_ms, packet_size);
arrival_time_ms);
}
// 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,
size_t packet_size, int64_t expected_timestamp_delta_us,
void ExpectTrue(int64_t timestamp_us,
int64_t arrival_time_ms,
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, packet_size,
arrival_time_ms,
MakeRtpTimestamp(expected_timestamp_delta_us),
expected_arrival_time_delta_ms,
expected_packet_size_delta, timestamp_near);
expected_arrival_time_delta_ms, timestamp_near);
InternalExpectTrue(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
arrival_time_ms, packet_size,
arrival_time_ms,
MakeAbsSendTime(expected_timestamp_delta_us),
expected_arrival_time_delta_ms,
expected_packet_size_delta, timestamp_near << 8);
expected_arrival_time_delta_ms, timestamp_near << 8);
}
void WrapTestHelper(int64_t wrap_start_us, uint32_t timestamp_near,
@ -82,29 +78,29 @@ class InterArrivalTest : public ::testing::Test {
// G1
int64_t arrival_time = 17;
ExpectFalse(0, arrival_time, 1);
ExpectFalse(0, arrival_time);
// G2
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(wrap_start_us / 4, arrival_time, 1);
ExpectFalse(wrap_start_us / 4, arrival_time);
// G3
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(wrap_start_us / 2, arrival_time, 1,
wrap_start_us / 4, 6, 0, // Delta G2-G1
ExpectTrue(wrap_start_us / 2, arrival_time, wrap_start_us / 4,
6, // 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, 1,
wrap_start_us / 4, 6, 0, // Delta G3-G2
ExpectTrue(wrap_start_us / 2 + wrap_start_us / 4, arrival_time,
wrap_start_us / 4, 6, // Delta G3-G2
timestamp_near);
// G5
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(wrap_start_us, arrival_time, 2,
wrap_start_us / 4, 6, 0, // Delta G4-G3
ExpectTrue(wrap_start_us, arrival_time, wrap_start_us / 4,
6, // Delta G4-G3
timestamp_near);
for (int i = 0; i < 10; ++i) {
// Slowly step across the wrap point.
@ -113,39 +109,34 @@ class InterArrivalTest : public ::testing::Test {
// 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, 1);
ExpectFalse(wrap_start_us + kMinStep * (9 - i), arrival_time);
} else {
ExpectFalse(wrap_start_us + kMinStep * i, arrival_time, 1);
ExpectFalse(wrap_start_us + kMinStep * i, arrival_time);
}
}
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, 100);
ExpectFalse(wrap_start_us - 100, arrival_time);
// G6
arrival_time += kBurstThresholdMs + 1;
int64_t g6_arrival_time = arrival_time;
ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time, 10,
ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time,
wrap_start_us / 4 + 9 * kMinStep,
g5_arrival_time - g4_arrival_time,
(2 + 10) - 1, // Delta G5-G4
timestamp_near);
g5_arrival_time - g4_arrival_time, timestamp_near);
// This packet is out of order and should be dropped.
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time, 100);
ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time);
// G7
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs,
arrival_time, 100,
ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs, arrival_time,
// Delta G6-G5
kTriggerNewGroupUs - 9 * kMinStep,
g6_arrival_time - g5_arrival_time,
10 - (2 + 10),
timestamp_near);
g6_arrival_time - g5_arrival_time, timestamp_near);
}
private:
@ -160,43 +151,29 @@ class InterArrivalTest : public ::testing::Test {
}
static void InternalExpectFalse(InterArrival* inter_arrival,
uint32_t timestamp, int64_t arrival_time_ms,
size_t packet_size) {
uint32_t timestamp,
int64_t arrival_time_ms) {
uint32_t dummy_timestamp = 101;
int64_t dummy_arrival_time_ms = 303;
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);
bool computed = inter_arrival->ComputeDeltas(
timestamp, arrival_time_ms, &dummy_timestamp, &dummy_arrival_time_ms);
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;
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);
bool computed = inter_arrival->ComputeDeltas(
timestamp, arrival_time_ms, &delta_timestamp, &delta_arrival_time_ms);
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_;
@ -204,131 +181,124 @@ class InterArrivalTest : public ::testing::Test {
};
TEST_F(InterArrivalTest, FirstPacket) {
ExpectFalse(0, 17, 1);
ExpectFalse(0, 17);
}
TEST_F(InterArrivalTest, FirstGroup) {
// G1
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
ExpectFalse(0, arrival_time, 1);
ExpectFalse(0, arrival_time);
// G2
arrival_time += kBurstThresholdMs + 1;
int64_t g2_arrival_time = arrival_time;
ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
ExpectFalse(kTriggerNewGroupUs, arrival_time);
// 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, 1,
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time,
// Delta G2-G1
kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1,
0);
kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 0);
}
TEST_F(InterArrivalTest, SecondGroup) {
// G1
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
ExpectFalse(0, arrival_time, 1);
ExpectFalse(0, arrival_time);
// G2
arrival_time += kBurstThresholdMs + 1;
int64_t g2_arrival_time = arrival_time;
ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
ExpectFalse(kTriggerNewGroupUs, arrival_time);
// G3
arrival_time += kBurstThresholdMs + 1;
int64_t g3_arrival_time = arrival_time;
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time,
// Delta G2-G1
kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1,
0);
kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 0);
// G4
// First packet of 4th group yields deltas between group 2 and 3.
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(3 * kTriggerNewGroupUs, arrival_time, 2,
ExpectTrue(3 * kTriggerNewGroupUs, arrival_time,
// Delta G3-G2
kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, -1,
0);
kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, 0);
}
TEST_F(InterArrivalTest, AccumulatedGroup) {
// G1
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
ExpectFalse(0, arrival_time, 1);
ExpectFalse(0, arrival_time);
// G2
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(kTriggerNewGroupUs, 28, 2);
ExpectFalse(kTriggerNewGroupUs, 28);
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, 1);
ExpectFalse(timestamp, arrival_time);
}
int64_t g2_arrival_time = arrival_time;
int64_t g2_timestamp = timestamp;
// G3
arrival_time = 500;
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 100,
g2_timestamp, g2_arrival_time - g1_arrival_time,
(2 + 10) - 1, // Delta G2-G1
0);
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, g2_timestamp,
g2_arrival_time - g1_arrival_time, 0);
}
TEST_F(InterArrivalTest, OutOfOrderPacket) {
// G1
int64_t arrival_time = 17;
int64_t timestamp = 0;
ExpectFalse(timestamp, arrival_time, 1);
ExpectFalse(timestamp, arrival_time);
int64_t g1_timestamp = timestamp;
int64_t g1_arrival_time = arrival_time;
// G2
arrival_time += 11;
timestamp += kTriggerNewGroupUs;
ExpectFalse(timestamp, 28, 2);
ExpectFalse(timestamp, 28);
for (int i = 0; i < 10; ++i) {
arrival_time += kBurstThresholdMs + 1;
timestamp += kMinStep;
ExpectFalse(timestamp, arrival_time, 1);
ExpectFalse(timestamp, arrival_time);
}
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, 100);
ExpectFalse(g1_timestamp, arrival_time);
// G3
arrival_time = 500;
timestamp = 2 * kTriggerNewGroupUs;
ExpectTrue(timestamp, arrival_time, 100,
ExpectTrue(timestamp, arrival_time,
// Delta G2-G1
g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time,
(2 + 10) - 1,
0);
g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time, 0);
}
TEST_F(InterArrivalTest, OutOfOrderWithinGroup) {
// G1
int64_t arrival_time = 17;
int64_t timestamp = 0;
ExpectFalse(timestamp, arrival_time, 1);
ExpectFalse(timestamp, arrival_time);
int64_t g1_timestamp = timestamp;
int64_t g1_arrival_time = arrival_time;
// G2
timestamp += kTriggerNewGroupUs;
arrival_time += 11;
ExpectFalse(kTriggerNewGroupUs, 28, 2);
ExpectFalse(kTriggerNewGroupUs, 28);
timestamp += 10 * kMinStep;
int64_t g2_timestamp = timestamp;
for (int i = 0; i < 10; ++i) {
@ -336,7 +306,7 @@ TEST_F(InterArrivalTest, OutOfOrderWithinGroup) {
// nevertheless accumulated to group because their timestamps are higher
// than the initial timestamp of the group.
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(timestamp, arrival_time, 1);
ExpectFalse(timestamp, arrival_time);
timestamp -= kMinStep;
}
int64_t g2_arrival_time = arrival_time;
@ -344,21 +314,19 @@ TEST_F(InterArrivalTest, OutOfOrderWithinGroup) {
// However, this packet is deemed out of order and should be dropped.
arrival_time = 281;
timestamp = g1_timestamp;
ExpectFalse(timestamp, arrival_time, 100);
ExpectFalse(timestamp, arrival_time);
// G3
timestamp = 2 * kTriggerNewGroupUs;
arrival_time = 500;
ExpectTrue(timestamp, arrival_time, 100,
g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time,
(2 + 10) - 1,
0);
ExpectTrue(timestamp, arrival_time, g2_timestamp - g1_timestamp,
g2_arrival_time - g1_arrival_time, 0);
}
TEST_F(InterArrivalTest, TwoBursts) {
// G1
int64_t g1_arrival_time = 17;
ExpectFalse(0, g1_arrival_time, 1);
ExpectFalse(0, g1_arrival_time);
// G2
int64_t timestamp = kTriggerNewGroupUs;
@ -367,7 +335,7 @@ TEST_F(InterArrivalTest, TwoBursts) {
// A bunch of packets arriving in one burst (within 5 ms apart).
timestamp += 30000;
arrival_time += kBurstThresholdMs;
ExpectFalse(timestamp, arrival_time, 1);
ExpectFalse(timestamp, arrival_time);
}
int64_t g2_arrival_time = arrival_time;
int64_t g2_timestamp = timestamp;
@ -375,27 +343,23 @@ TEST_F(InterArrivalTest, TwoBursts) {
// G3
timestamp += 30000;
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(timestamp, arrival_time, 100,
g2_timestamp, g2_arrival_time - g1_arrival_time,
10 - 1, // Delta G2-G1
0);
ExpectTrue(timestamp, arrival_time, g2_timestamp,
g2_arrival_time - g1_arrival_time, 0);
}
TEST_F(InterArrivalTest, NoBursts) {
// G1
ExpectFalse(0, 17, 1);
ExpectFalse(0, 17);
// G2
int64_t timestamp = kTriggerNewGroupUs;
int64_t arrival_time = 28;
ExpectFalse(timestamp, arrival_time, 2);
ExpectFalse(timestamp, arrival_time);
// G3
ExpectTrue(kTriggerNewGroupUs + 30000, arrival_time + kBurstThresholdMs + 1,
100, timestamp - 0, arrival_time - 17,
2 - 1, // Delta G2-G1
0);
timestamp - 0, arrival_time - 17, 0);
}
// Yields 0xfffffffe when converted to internal representation in

View File

@ -50,12 +50,11 @@ bool ReadExperimentConstants(double* k_up, double* k_down) {
"%lf,%lf", k_up, k_down) == 2;
}
OveruseDetector::OveruseDetector(const OverUseDetectorOptions& options)
OveruseDetector::OveruseDetector()
: 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),

View File

@ -24,7 +24,7 @@ bool AdaptiveThresholdExperimentIsEnabled();
class OveruseDetector {
public:
explicit OveruseDetector(const OverUseDetectorOptions& options);
OveruseDetector();
virtual ~OveruseDetector();
// Update the detection state based on the estimated inter-arrival time delta
@ -51,7 +51,6 @@ class OveruseDetector {
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_;

View File

@ -36,22 +36,21 @@ class OveruseDetectorTest : public ::testing::Test {
receive_time_ms_(0),
rtp_timestamp_(10 * 90),
overuse_detector_(),
overuse_estimator_(new OveruseEstimator(options_)),
overuse_estimator_(new OveruseEstimator()),
inter_arrival_(new InterArrival(5 * 90, kRtpTimestampToMs, true)),
random_(1234) {}
protected:
void SetUp() override {
overuse_detector_.reset(new OveruseDetector(options_));
}
void SetUp() override { overuse_detector_.reset(new OveruseDetector()); }
int Run100000Samples(int packets_per_frame, size_t packet_size, int mean_ms,
int Run100000Samples(int packets_per_frame,
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_, packet_size);
UpdateDetector(rtp_timestamp_, receive_time_ms_);
}
rtp_timestamp_ += mean_ms * 90;
now_ms_ += mean_ms;
@ -68,12 +67,14 @@ class OveruseDetectorTest : public ::testing::Test {
return unique_overuse;
}
int RunUntilOveruse(int packets_per_frame, size_t packet_size, int mean_ms,
int standard_deviation_ms, int drift_per_frame_ms) {
int RunUntilOveruse(int packets_per_frame,
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_, packet_size);
UpdateDetector(rtp_timestamp_, receive_time_ms_);
}
rtp_timestamp_ += mean_ms * 90;
now_ms_ += mean_ms + drift_per_frame_ms;
@ -87,19 +88,13 @@ class OveruseDetectorTest : public ::testing::Test {
return -1;
}
void UpdateDetector(uint32_t rtp_timestamp, int64_t receive_time_ms,
size_t packet_size) {
void UpdateDetector(uint32_t rtp_timestamp, int64_t receive_time_ms) {
uint32_t timestamp_delta;
int64_t time_delta;
int size_delta;
if (inter_arrival_->ComputeDeltas(rtp_timestamp,
receive_time_ms,
packet_size,
&timestamp_delta,
&time_delta,
&size_delta)) {
if (inter_arrival_->ComputeDeltas(rtp_timestamp, receive_time_ms,
&timestamp_delta, &time_delta)) {
double timestamp_delta_ms = timestamp_delta / 90.0;
overuse_estimator_->Update(time_delta, timestamp_delta_ms, size_delta,
overuse_estimator_->Update(time_delta, timestamp_delta_ms,
overuse_detector_->State());
overuse_detector_->Detect(
overuse_estimator_->offset(), timestamp_delta_ms,
@ -110,7 +105,6 @@ class OveruseDetectorTest : public ::testing::Test {
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_;
@ -131,13 +125,12 @@ TEST_F(OveruseDetectorTest, GaussianRandom) {
}
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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
now_ms_ += frame_duration_ms;
rtp_timestamp += frame_duration_ms * 90;
EXPECT_EQ(kBwNormal, overuse_detector_->State());
@ -148,10 +141,9 @@ TEST_F(OveruseDetectorTest, SimpleNonOveruse30fps) {
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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
now_ms_ += frame_duration_ms - 5;
@ -166,10 +158,8 @@ TEST_F(OveruseDetectorTest, SimpleNonOveruseWithRtpTimestampVariance) {
// 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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
now_ms_ += frame_duration_ms;
if (i % 2) {
rtp_timestamp += (frame_duration_ms - 5) * 90;
@ -181,32 +171,30 @@ TEST_F(OveruseDetectorTest, SimpleNonOveruseWithRtpTimestampVariance) {
}
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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(6, frames_until_overuse);
}
@ -214,12 +202,11 @@ TEST_F(OveruseDetectorTest, DISABLED_OveruseWithHighVariance100Kbit10fps) {
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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
offset = rand() % 50;
@ -233,12 +220,12 @@ TEST_F(OveruseDetectorTest, DISABLED_OveruseWithHighVariance100Kbit10fps) {
// 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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
EXPECT_EQ(kBwOverusing, overuse_detector_->State());
}
@ -246,12 +233,11 @@ TEST_F(OveruseDetectorTest, DISABLED_OveruseWithLowVariance100Kbit10fps) {
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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
offset = rand() % 2;
@ -264,12 +250,12 @@ TEST_F(OveruseDetectorTest, DISABLED_OveruseWithLowVariance100Kbit10fps) {
// 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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
EXPECT_EQ(kBwOverusing, overuse_detector_->State());
}
@ -277,17 +263,16 @@ TEST_F(OveruseDetectorTest, OveruseWithLowVariance2000Kbit30fps) {
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_, 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);
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_);
rtp_timestamp += frame_duration_ms * 90;
if (i % 2) {
offset = rand() % 2;
@ -300,305 +285,285 @@ TEST_F(OveruseDetectorTest, OveruseWithLowVariance2000Kbit30fps) {
// 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_, 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);
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_);
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_, packet_size);
UpdateDetector(rtp_timestamp, now_ms_);
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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(13, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(13, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, 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);
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);
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, 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);
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);
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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(12, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(16, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(12, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(12, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, 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, packet_size,
frame_duration_ms, sigma_ms);
int unique_overuse =
Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms);
EXPECT_EQ(0, unique_overuse);
int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size,
frame_duration_ms, sigma_ms, drift_per_frame_ms);
int frames_until_overuse = RunUntilOveruse(
packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms);
EXPECT_EQ(8, frames_until_overuse);
}
@ -609,9 +574,7 @@ class OveruseDetectorExperimentTest : public OveruseDetectorTest {
"WebRTC-AdaptiveBweThreshold/Enabled-0.01,0.00018/") {}
protected:
void SetUp() override {
overuse_detector_.reset(new OveruseDetector(options_));
}
void SetUp() override { overuse_detector_.reset(new OveruseDetector()); }
test::ScopedFieldTrials override_field_trials_;
};

View File

@ -16,6 +16,7 @@
#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"
@ -24,33 +25,25 @@ namespace webrtc {
enum { kMinFramePeriodHistoryLength = 60 };
enum { kDeltaCounterMax = 1000 };
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_));
}
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() {
ts_delta_hist_.clear();
send_delta_history_.clear();
}
void OveruseEstimator::Update(int64_t t_delta,
double ts_delta,
int size_delta,
void OveruseEstimator::Update(double recv_delta_ms,
double send_delta_ms,
BandwidthUsage current_hypothesis) {
const double min_frame_period = UpdateMinFramePeriod(ts_delta);
const double t_ts_delta = t_delta - ts_delta;
double fs_delta = size_delta;
const double min_frame_period = UpdateMinFramePeriod(send_delta_ms);
const double delta_ms = recv_delta_ms - send_delta_ms;
++num_of_deltas_;
if (num_of_deltas_ > kDeltaCounterMax) {
@ -58,19 +51,14 @@ void OveruseEstimator::Update(int64_t t_delta,
}
// Update the Kalman filter.
E_[0][0] += process_noise_[0];
E_[1][1] += process_noise_[1];
e_ += process_noise_;
if ((current_hypothesis == kBwOverusing && offset_ < prev_offset_) ||
(current_hypothesis == kBwUnderusing && offset_ > prev_offset_)) {
E_[1][1] += 10 * process_noise_[1];
e_ += 10 * process_noise_;
}
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 double residual = delta_ms - offset_;
const bool in_stable_state = (current_hypothesis == kBwNormal);
const double max_residual = 3.0 * sqrt(var_noise_);
@ -82,66 +70,47 @@ void OveruseEstimator::Update(int64_t t_delta,
UpdateNoiseEstimate(residual < 0 ? -max_residual : max_residual,
min_frame_period, in_stable_state);
}
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];
const double k = e_ / (var_noise_ + e_);
// Update state.
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];
e_ = e_ * (1.0 - k);
// 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.";
}
// 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!";
slope_ = slope_ + K[0] * residual;
prev_offset_ = offset_;
offset_ = offset_ + K[1] * residual;
offset_ = offset_ + k * residual;
}
double OveruseEstimator::UpdateMinFramePeriod(double ts_delta) {
double min_frame_period = ts_delta;
if (ts_delta_hist_.size() >= kMinFramePeriodHistoryLength) {
ts_delta_hist_.pop_front();
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();
}
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);
for (double delta_ms : send_delta_history_) {
min_frame_period = std::min(delta_ms, min_frame_period);
}
ts_delta_hist_.push_back(ts_delta);
send_delta_history_.push_back(send_delta_ms);
return min_frame_period;
}
void OveruseEstimator::UpdateNoiseEstimate(double residual,
double ts_delta,
double send_delta_ms,
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 |ts_delta|.
// according to |send_delta_ms|.
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, ts_delta * 30.0 / 1000.0);
const double beta = pow(1 - alpha, send_delta_ms * 30.0 / 1000.0);
avg_noise_ = beta * avg_noise_
+ (1 - beta) * residual;
var_noise_ = beta * var_noise_

View File

@ -20,14 +20,15 @@ namespace webrtc {
class OveruseEstimator {
public:
explicit OveruseEstimator(const OverUseDetectorOptions& options);
OveruseEstimator();
~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(int64_t t_delta, double ts_delta, int size_delta,
void Update(double recv_delta_ms,
double send_delta_ms,
BandwidthUsage current_hypothesis);
// Returns the estimated noise/jitter variance in ms^2.
@ -47,21 +48,21 @@ class OveruseEstimator {
}
private:
double UpdateMinFramePeriod(double ts_delta);
void UpdateNoiseEstimate(double residual, double ts_delta, bool stable_state);
double UpdateMinFramePeriod(double send_delta_ms);
void UpdateNoiseEstimate(double residual,
double send_delta_ms,
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_[2][2];
double process_noise_[2];
double e_;
double process_noise_;
double avg_noise_;
double var_noise_;
std::list<double> ts_delta_hist_;
std::list<double> send_delta_history_;
RTC_DISALLOW_COPY_AND_ASSIGN(OveruseEstimator);
};

View File

@ -102,10 +102,6 @@ bool RemoteBitrateEstimatorAbsSendTime::IsWithinClusterBounds(
: 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),
@ -271,7 +267,6 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
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.
@ -301,10 +296,10 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
kTimestampToMs, true));
}
if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, payload_size,
&ts_delta, &t_delta, &size_delta)) {
if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, &ts_delta,
&t_delta)) {
double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
estimator_.Update(t_delta, ts_delta_ms, size_delta, detector_.State());
estimator_.Update(t_delta, ts_delta_ms, 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);

View File

@ -28,14 +28,13 @@ enum { kTimestampGroupLengthMs = 5 };
static const double kTimestampToMs = 1.0 / 90.0;
struct RemoteBitrateEstimatorSingleStream::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) {}
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() {}
int64_t last_packet_time_ms;
InterArrival inter_arrival;
OveruseEstimator estimator;
@ -82,8 +81,8 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket(int64_t arrival_time_ms,
// 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, OverUseDetectorOptions(), true)));
overuse_detectors_.insert(
std::make_pair(ssrc, new Detector(now_ms, true)));
it = insert_result.first;
}
Detector* estimator = it->second;
@ -92,12 +91,10 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket(int64_t arrival_time_ms,
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,
payload_size, &timestamp_delta,
&time_delta, &size_delta)) {
&timestamp_delta, &time_delta)) {
double timestamp_delta_ms = timestamp_delta * kTimestampToMs;
estimator->estimator.Update(time_delta, timestamp_delta_ms, size_delta,
estimator->estimator.Update(time_delta, timestamp_delta_ms,
estimator->detector.State());
estimator->detector.Detect(estimator->estimator.offset(),
timestamp_delta_ms,

View File

@ -52,7 +52,7 @@ TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropTwoStreamsWrap) {
}
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThreeStreamsWrap) {
CapacityDropTestHelper(3, true, 734);
CapacityDropTestHelper(3, true, 567);
}
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThirteenStreamsWrap) {

View File

@ -61,8 +61,7 @@ class TestTransport : public Transport {
class RtcpFormatRembTest : public ::testing::Test {
protected:
RtcpFormatRembTest()
: over_use_detector_options_(),
system_clock_(Clock::GetRealTimeClock()),
: system_clock_(Clock::GetRealTimeClock()),
dummy_rtp_rtcp_impl_(nullptr),
receive_statistics_(ReceiveStatistics::Create(system_clock_)),
rtcp_sender_(nullptr),
@ -75,7 +74,6 @@ class RtcpFormatRembTest : public ::testing::Test {
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_;

View File

@ -66,8 +66,7 @@ class TestTransport : public Transport,
class RtcpReceiverTest : public ::testing::Test {
protected:
RtcpReceiverTest()
: over_use_detector_options_(),
system_clock_(1335900000),
: system_clock_(1335900000),
remote_bitrate_observer_(),
remote_bitrate_estimator_(
new RemoteBitrateEstimatorSingleStream(&remote_bitrate_observer_,
@ -131,7 +130,6 @@ class RtcpReceiverTest : public ::testing::Test {
return 0;
}
OverUseDetectorOptions over_use_detector_options_;
SimulatedClock system_clock_;
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
RTCPReceiver* rtcp_receiver_;