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:
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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,
|
||||
×tamp_delta,
|
||||
&time_delta,
|
||||
&size_delta)) {
|
||||
if (inter_arrival_->ComputeDeltas(rtp_timestamp, receive_time_ms,
|
||||
×tamp_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_;
|
||||
};
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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, ×tamp_delta,
|
||||
&time_delta, &size_delta)) {
|
||||
×tamp_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,
|
||||
|
||||
@ -52,7 +52,7 @@ TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropTwoStreamsWrap) {
|
||||
}
|
||||
|
||||
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThreeStreamsWrap) {
|
||||
CapacityDropTestHelper(3, true, 734);
|
||||
CapacityDropTestHelper(3, true, 567);
|
||||
}
|
||||
|
||||
TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThirteenStreamsWrap) {
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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_;
|
||||
|
||||
Reference in New Issue
Block a user