diff --git a/webrtc/common_types.h b/webrtc/common_types.h index a6453c2f30..048485fa2f 100644 --- a/webrtc/common_types.h +++ b/webrtc/common_types.h @@ -747,6 +747,31 @@ 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 { diff --git a/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc b/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc index a9d0f8860d..961d6bfb8e 100644 --- a/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc +++ b/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc @@ -31,10 +31,13 @@ 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) { + int64_t* arrival_time_delta_ms, + int* packet_size_delta) { assert(timestamp_delta != NULL); assert(arrival_time_delta_ms != NULL); + assert(packet_size_delta != NULL); bool calculated_deltas = false; if (current_timestamp_group_.IsFirstPacket()) { // We don't have enough data to update the filter, so we store it until we @@ -59,19 +62,23 @@ bool InterArrival::ComputeDeltas(uint32_t timestamp, return false; } assert(*arrival_time_delta_ms >= 0); + *packet_size_delta = static_cast(current_timestamp_group_.size) - + static_cast(prev_timestamp_group_.size); calculated_deltas = true; } prev_timestamp_group_ = current_timestamp_group_; // The new timestamp is now the current frame. current_timestamp_group_.first_timestamp = timestamp; current_timestamp_group_.timestamp = timestamp; + current_timestamp_group_.size = 0; } else { current_timestamp_group_.timestamp = LatestTimestamp( current_timestamp_group_.timestamp, timestamp); } - current_timestamp_group_.complete_time_ms = - std::max(current_timestamp_group_.complete_time_ms, arrival_time_ms); + // Accumulate the frame size. + current_timestamp_group_.size += packet_size; + current_timestamp_group_.complete_time_ms = arrival_time_ms; return calculated_deltas; } diff --git a/webrtc/modules/remote_bitrate_estimator/inter_arrival.h b/webrtc/modules/remote_bitrate_estimator/inter_arrival.h index 64ad1f68d3..427bafcf96 100644 --- a/webrtc/modules/remote_bitrate_estimator/inter_arrival.h +++ b/webrtc/modules/remote_bitrate_estimator/inter_arrival.h @@ -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 newer than the first timestamp in that + // most timestamp_group_length_ticks older than the first timestamp in that // group. InterArrival(uint32_t timestamp_group_length_ticks, double timestamp_to_ms_coeff, @@ -34,21 +34,30 @@ 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); + int64_t* arrival_time_delta_ms, + int* packet_size_delta); private: struct TimestampGroup { - TimestampGroup() : first_timestamp(0), timestamp(0), complete_time_ms(-1) {} + TimestampGroup() + : size(0), + first_timestamp(0), + timestamp(0), + complete_time_ms(-1) {} bool IsFirstPacket() const { return complete_time_ms == -1; } + size_t size; uint32_t first_timestamp; uint32_t timestamp; int64_t complete_time_ms; diff --git a/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc b/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc index dfe324cdce..64f7ccae6b 100644 --- a/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc +++ b/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc @@ -45,30 +45,34 @@ 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) { + void ExpectFalse(int64_t timestamp_us, int64_t arrival_time_ms, + size_t packet_size) { InternalExpectFalse(inter_arrival_rtp_.get(), - MakeRtpTimestamp(timestamp_us), arrival_time_ms); + MakeRtpTimestamp(timestamp_us), arrival_time_ms, + packet_size); InternalExpectFalse(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us), - arrival_time_ms); + arrival_time_ms, packet_size); } // Test that both inter_arrival instances complete the timestamp group from // the given data and that all returned deltas are as expected (except // timestamp delta, which is rounded from us to different ranges and must // match within an interval, given in |timestamp_near]. - void ExpectTrue(int64_t timestamp_us, - int64_t arrival_time_ms, - int64_t expected_timestamp_delta_us, + void ExpectTrue(int64_t timestamp_us, int64_t arrival_time_ms, + size_t packet_size, int64_t expected_timestamp_delta_us, int64_t expected_arrival_time_delta_ms, + int expected_packet_size_delta, uint32_t timestamp_near) { InternalExpectTrue(inter_arrival_rtp_.get(), MakeRtpTimestamp(timestamp_us), - arrival_time_ms, + arrival_time_ms, packet_size, MakeRtpTimestamp(expected_timestamp_delta_us), - expected_arrival_time_delta_ms, timestamp_near); + expected_arrival_time_delta_ms, + expected_packet_size_delta, timestamp_near); InternalExpectTrue(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us), - arrival_time_ms, + arrival_time_ms, packet_size, MakeAbsSendTime(expected_timestamp_delta_us), - expected_arrival_time_delta_ms, timestamp_near << 8); + expected_arrival_time_delta_ms, + expected_packet_size_delta, timestamp_near << 8); } void WrapTestHelper(int64_t wrap_start_us, uint32_t timestamp_near, @@ -78,29 +82,29 @@ class InterArrivalTest : public ::testing::Test { // G1 int64_t arrival_time = 17; - ExpectFalse(0, arrival_time); + ExpectFalse(0, arrival_time, 1); // G2 arrival_time += kBurstThresholdMs + 1; - ExpectFalse(wrap_start_us / 4, arrival_time); + ExpectFalse(wrap_start_us / 4, arrival_time, 1); // G3 arrival_time += kBurstThresholdMs + 1; - ExpectTrue(wrap_start_us / 2, arrival_time, wrap_start_us / 4, - 6, // Delta G2-G1 + ExpectTrue(wrap_start_us / 2, arrival_time, 1, + wrap_start_us / 4, 6, 0, // Delta G2-G1 0); // G4 arrival_time += kBurstThresholdMs + 1; int64_t g4_arrival_time = arrival_time; - ExpectTrue(wrap_start_us / 2 + wrap_start_us / 4, arrival_time, - wrap_start_us / 4, 6, // Delta G3-G2 + ExpectTrue(wrap_start_us / 2 + wrap_start_us / 4, arrival_time, 1, + wrap_start_us / 4, 6, 0, // Delta G3-G2 timestamp_near); // G5 arrival_time += kBurstThresholdMs + 1; - ExpectTrue(wrap_start_us, arrival_time, wrap_start_us / 4, - 6, // Delta G4-G3 + ExpectTrue(wrap_start_us, arrival_time, 2, + wrap_start_us / 4, 6, 0, // Delta G4-G3 timestamp_near); for (int i = 0; i < 10; ++i) { // Slowly step across the wrap point. @@ -109,34 +113,39 @@ 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); + ExpectFalse(wrap_start_us + kMinStep * (9 - i), arrival_time, 1); } else { - ExpectFalse(wrap_start_us + kMinStep * i, arrival_time); + ExpectFalse(wrap_start_us + kMinStep * i, arrival_time, 1); } } int64_t g5_arrival_time = arrival_time; // This packet is out of order and should be dropped. arrival_time += kBurstThresholdMs + 1; - ExpectFalse(wrap_start_us - 100, arrival_time); + ExpectFalse(wrap_start_us - 100, arrival_time, 100); // G6 arrival_time += kBurstThresholdMs + 1; int64_t g6_arrival_time = arrival_time; - ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time, + ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time, 10, wrap_start_us / 4 + 9 * kMinStep, - g5_arrival_time - g4_arrival_time, timestamp_near); + g5_arrival_time - g4_arrival_time, + (2 + 10) - 1, // Delta G5-G4 + timestamp_near); // This packet is out of order and should be dropped. arrival_time += kBurstThresholdMs + 1; - ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time); + ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time, 100); // G7 arrival_time += kBurstThresholdMs + 1; - ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs, arrival_time, + ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs, + arrival_time, 100, // Delta G6-G5 kTriggerNewGroupUs - 9 * kMinStep, - g6_arrival_time - g5_arrival_time, timestamp_near); + g6_arrival_time - g5_arrival_time, + 10 - (2 + 10), + timestamp_near); } private: @@ -151,29 +160,43 @@ class InterArrivalTest : public ::testing::Test { } static void InternalExpectFalse(InterArrival* inter_arrival, - uint32_t timestamp, - int64_t arrival_time_ms) { + uint32_t timestamp, int64_t arrival_time_ms, + size_t packet_size) { uint32_t dummy_timestamp = 101; int64_t dummy_arrival_time_ms = 303; - bool computed = inter_arrival->ComputeDeltas( - timestamp, arrival_time_ms, &dummy_timestamp, &dummy_arrival_time_ms); + int dummy_packet_size = 909; + bool computed = inter_arrival->ComputeDeltas(timestamp, + arrival_time_ms, + packet_size, + &dummy_timestamp, + &dummy_arrival_time_ms, + &dummy_packet_size); EXPECT_EQ(computed, false); EXPECT_EQ(101ul, dummy_timestamp); EXPECT_EQ(303, dummy_arrival_time_ms); + EXPECT_EQ(909, dummy_packet_size); } static void InternalExpectTrue(InterArrival* inter_arrival, uint32_t timestamp, int64_t arrival_time_ms, + size_t packet_size, uint32_t expected_timestamp_delta, int64_t expected_arrival_time_delta_ms, + int expected_packet_size_delta, uint32_t timestamp_near) { uint32_t delta_timestamp = 101; int64_t delta_arrival_time_ms = 303; - bool computed = inter_arrival->ComputeDeltas( - timestamp, arrival_time_ms, &delta_timestamp, &delta_arrival_time_ms); + int delta_packet_size = 909; + bool computed = inter_arrival->ComputeDeltas(timestamp, + arrival_time_ms, + packet_size, + &delta_timestamp, + &delta_arrival_time_ms, + &delta_packet_size); EXPECT_EQ(true, computed); EXPECT_NEAR(expected_timestamp_delta, delta_timestamp, timestamp_near); EXPECT_EQ(expected_arrival_time_delta_ms, delta_arrival_time_ms); + EXPECT_EQ(expected_packet_size_delta, delta_packet_size); } rtc::scoped_ptr inter_arrival_rtp_; @@ -181,124 +204,131 @@ class InterArrivalTest : public ::testing::Test { }; TEST_F(InterArrivalTest, FirstPacket) { - ExpectFalse(0, 17); + ExpectFalse(0, 17, 1); } TEST_F(InterArrivalTest, FirstGroup) { // G1 int64_t arrival_time = 17; int64_t g1_arrival_time = arrival_time; - ExpectFalse(0, arrival_time); + ExpectFalse(0, arrival_time, 1); // G2 arrival_time += kBurstThresholdMs + 1; int64_t g2_arrival_time = arrival_time; - ExpectFalse(kTriggerNewGroupUs, arrival_time); + ExpectFalse(kTriggerNewGroupUs, arrival_time, 2); // G3 // Only once the first packet of the third group arrives, do we see the deltas // between the first two. arrival_time += kBurstThresholdMs + 1; - ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, + ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1, // Delta G2-G1 - kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 0); + kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1, + 0); } TEST_F(InterArrivalTest, SecondGroup) { // G1 int64_t arrival_time = 17; int64_t g1_arrival_time = arrival_time; - ExpectFalse(0, arrival_time); + ExpectFalse(0, arrival_time, 1); // G2 arrival_time += kBurstThresholdMs + 1; int64_t g2_arrival_time = arrival_time; - ExpectFalse(kTriggerNewGroupUs, arrival_time); + ExpectFalse(kTriggerNewGroupUs, arrival_time, 2); // G3 arrival_time += kBurstThresholdMs + 1; int64_t g3_arrival_time = arrival_time; - ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, + ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1, // Delta G2-G1 - kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 0); + kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1, + 0); // G4 // First packet of 4th group yields deltas between group 2 and 3. arrival_time += kBurstThresholdMs + 1; - ExpectTrue(3 * kTriggerNewGroupUs, arrival_time, + ExpectTrue(3 * kTriggerNewGroupUs, arrival_time, 2, // Delta G3-G2 - kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, 0); + kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, -1, + 0); } TEST_F(InterArrivalTest, AccumulatedGroup) { // G1 int64_t arrival_time = 17; int64_t g1_arrival_time = arrival_time; - ExpectFalse(0, arrival_time); + ExpectFalse(0, arrival_time, 1); // G2 arrival_time += kBurstThresholdMs + 1; - ExpectFalse(kTriggerNewGroupUs, 28); + ExpectFalse(kTriggerNewGroupUs, 28, 2); int64_t timestamp = kTriggerNewGroupUs; for (int i = 0; i < 10; ++i) { // A bunch of packets arriving within the same group. arrival_time += kBurstThresholdMs + 1; timestamp += kMinStep; - ExpectFalse(timestamp, arrival_time); + ExpectFalse(timestamp, arrival_time, 1); } int64_t g2_arrival_time = arrival_time; int64_t g2_timestamp = timestamp; // G3 arrival_time = 500; - ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, g2_timestamp, - g2_arrival_time - g1_arrival_time, 0); + ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 100, + g2_timestamp, g2_arrival_time - g1_arrival_time, + (2 + 10) - 1, // Delta G2-G1 + 0); } TEST_F(InterArrivalTest, OutOfOrderPacket) { // G1 int64_t arrival_time = 17; int64_t timestamp = 0; - ExpectFalse(timestamp, arrival_time); + ExpectFalse(timestamp, arrival_time, 1); int64_t g1_timestamp = timestamp; int64_t g1_arrival_time = arrival_time; // G2 arrival_time += 11; timestamp += kTriggerNewGroupUs; - ExpectFalse(timestamp, 28); + ExpectFalse(timestamp, 28, 2); for (int i = 0; i < 10; ++i) { arrival_time += kBurstThresholdMs + 1; timestamp += kMinStep; - ExpectFalse(timestamp, arrival_time); + ExpectFalse(timestamp, arrival_time, 1); } int64_t g2_timestamp = timestamp; int64_t g2_arrival_time = arrival_time; // This packet is out of order and should be dropped. arrival_time = 281; - ExpectFalse(g1_timestamp, arrival_time); + ExpectFalse(g1_timestamp, arrival_time, 100); // G3 arrival_time = 500; timestamp = 2 * kTriggerNewGroupUs; - ExpectTrue(timestamp, arrival_time, + ExpectTrue(timestamp, arrival_time, 100, // Delta G2-G1 - g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time, 0); + g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time, + (2 + 10) - 1, + 0); } TEST_F(InterArrivalTest, OutOfOrderWithinGroup) { // G1 int64_t arrival_time = 17; int64_t timestamp = 0; - ExpectFalse(timestamp, arrival_time); + ExpectFalse(timestamp, arrival_time, 1); int64_t g1_timestamp = timestamp; int64_t g1_arrival_time = arrival_time; // G2 timestamp += kTriggerNewGroupUs; arrival_time += 11; - ExpectFalse(kTriggerNewGroupUs, 28); + ExpectFalse(kTriggerNewGroupUs, 28, 2); timestamp += 10 * kMinStep; int64_t g2_timestamp = timestamp; for (int i = 0; i < 10; ++i) { @@ -306,7 +336,7 @@ 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); + ExpectFalse(timestamp, arrival_time, 1); timestamp -= kMinStep; } int64_t g2_arrival_time = arrival_time; @@ -314,19 +344,21 @@ 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); + ExpectFalse(timestamp, arrival_time, 100); // G3 timestamp = 2 * kTriggerNewGroupUs; arrival_time = 500; - ExpectTrue(timestamp, arrival_time, g2_timestamp - g1_timestamp, - g2_arrival_time - g1_arrival_time, 0); + ExpectTrue(timestamp, arrival_time, 100, + g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time, + (2 + 10) - 1, + 0); } TEST_F(InterArrivalTest, TwoBursts) { // G1 int64_t g1_arrival_time = 17; - ExpectFalse(0, g1_arrival_time); + ExpectFalse(0, g1_arrival_time, 1); // G2 int64_t timestamp = kTriggerNewGroupUs; @@ -335,7 +367,7 @@ 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); + ExpectFalse(timestamp, arrival_time, 1); } int64_t g2_arrival_time = arrival_time; int64_t g2_timestamp = timestamp; @@ -343,23 +375,27 @@ TEST_F(InterArrivalTest, TwoBursts) { // G3 timestamp += 30000; arrival_time += kBurstThresholdMs + 1; - ExpectTrue(timestamp, arrival_time, g2_timestamp, - g2_arrival_time - g1_arrival_time, 0); + ExpectTrue(timestamp, arrival_time, 100, + g2_timestamp, g2_arrival_time - g1_arrival_time, + 10 - 1, // Delta G2-G1 + 0); } TEST_F(InterArrivalTest, NoBursts) { // G1 - ExpectFalse(0, 17); + ExpectFalse(0, 17, 1); // G2 int64_t timestamp = kTriggerNewGroupUs; int64_t arrival_time = 28; - ExpectFalse(timestamp, arrival_time); + ExpectFalse(timestamp, arrival_time, 2); // G3 ExpectTrue(kTriggerNewGroupUs + 30000, arrival_time + kBurstThresholdMs + 1, - timestamp - 0, arrival_time - 17, 0); + 100, timestamp - 0, arrival_time - 17, + 2 - 1, // Delta G2-G1 + 0); } // Yields 0xfffffffe when converted to internal representation in diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc index 5bb105e2d9..c9340892f2 100644 --- a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc +++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc @@ -50,11 +50,12 @@ bool ReadExperimentConstants(double* k_up, double* k_down) { "%lf,%lf", k_up, k_down) == 2; } -OveruseDetector::OveruseDetector() +OveruseDetector::OveruseDetector(const OverUseDetectorOptions& options) : in_experiment_(AdaptiveThresholdExperimentIsEnabled()), k_up_(0.01), k_down_(0.00018), overusing_time_threshold_(100), + options_(options), threshold_(12.5), last_update_ms_(-1), prev_offset_(0.0), diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector.h b/webrtc/modules/remote_bitrate_estimator/overuse_detector.h index d451a3ed45..56e9c14206 100644 --- a/webrtc/modules/remote_bitrate_estimator/overuse_detector.h +++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector.h @@ -24,7 +24,7 @@ bool AdaptiveThresholdExperimentIsEnabled(); class OveruseDetector { public: - OveruseDetector(); + explicit OveruseDetector(const OverUseDetectorOptions& options); virtual ~OveruseDetector(); // Update the detection state based on the estimated inter-arrival time delta @@ -51,6 +51,7 @@ 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_; diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc b/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc index d474a4d340..dcad04b5f6 100644 --- a/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc +++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc @@ -36,21 +36,22 @@ class OveruseDetectorTest : public ::testing::Test { receive_time_ms_(0), rtp_timestamp_(10 * 90), overuse_detector_(), - overuse_estimator_(new OveruseEstimator()), + overuse_estimator_(new OveruseEstimator(options_)), inter_arrival_(new InterArrival(5 * 90, kRtpTimestampToMs, true)), random_(1234) {} protected: - void SetUp() override { overuse_detector_.reset(new OveruseDetector()); } + void SetUp() override { + overuse_detector_.reset(new OveruseDetector(options_)); + } - int Run100000Samples(int packets_per_frame, - int mean_ms, + int Run100000Samples(int packets_per_frame, size_t packet_size, int mean_ms, int standard_deviation_ms) { int unique_overuse = 0; int last_overuse = -1; for (int i = 0; i < 100000; ++i) { for (int j = 0; j < packets_per_frame; ++j) { - UpdateDetector(rtp_timestamp_, receive_time_ms_); + UpdateDetector(rtp_timestamp_, receive_time_ms_, packet_size); } rtp_timestamp_ += mean_ms * 90; now_ms_ += mean_ms; @@ -67,14 +68,12 @@ class OveruseDetectorTest : public ::testing::Test { return unique_overuse; } - int RunUntilOveruse(int packets_per_frame, - int mean_ms, - int standard_deviation_ms, - int drift_per_frame_ms) { + int RunUntilOveruse(int packets_per_frame, size_t packet_size, int mean_ms, + int standard_deviation_ms, int drift_per_frame_ms) { // Simulate a higher send pace, that is too high. for (int i = 0; i < 1000; ++i) { for (int j = 0; j < packets_per_frame; ++j) { - UpdateDetector(rtp_timestamp_, receive_time_ms_); + UpdateDetector(rtp_timestamp_, receive_time_ms_, packet_size); } rtp_timestamp_ += mean_ms * 90; now_ms_ += mean_ms + drift_per_frame_ms; @@ -88,13 +87,19 @@ class OveruseDetectorTest : public ::testing::Test { return -1; } - void UpdateDetector(uint32_t rtp_timestamp, int64_t receive_time_ms) { + void UpdateDetector(uint32_t rtp_timestamp, int64_t receive_time_ms, + size_t packet_size) { uint32_t timestamp_delta; int64_t time_delta; - if (inter_arrival_->ComputeDeltas(rtp_timestamp, receive_time_ms, - ×tamp_delta, &time_delta)) { + int size_delta; + if (inter_arrival_->ComputeDeltas(rtp_timestamp, + receive_time_ms, + packet_size, + ×tamp_delta, + &time_delta, + &size_delta)) { double timestamp_delta_ms = timestamp_delta / 90.0; - overuse_estimator_->Update(time_delta, timestamp_delta_ms, + overuse_estimator_->Update(time_delta, timestamp_delta_ms, size_delta, overuse_detector_->State()); overuse_detector_->Detect( overuse_estimator_->offset(), timestamp_delta_ms, @@ -105,6 +110,7 @@ class OveruseDetectorTest : public ::testing::Test { int64_t now_ms_; int64_t receive_time_ms_; uint32_t rtp_timestamp_; + OverUseDetectorOptions options_; rtc::scoped_ptr overuse_detector_; rtc::scoped_ptr overuse_estimator_; rtc::scoped_ptr inter_arrival_; @@ -125,12 +131,13 @@ 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_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); now_ms_ += frame_duration_ms; rtp_timestamp += frame_duration_ms * 90; EXPECT_EQ(kBwNormal, overuse_detector_->State()); @@ -141,9 +148,10 @@ TEST_F(OveruseDetectorTest, 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_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); rtp_timestamp += frame_duration_ms * 90; if (i % 2) { now_ms_ += frame_duration_ms - 5; @@ -158,8 +166,10 @@ 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_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); now_ms_ += frame_duration_ms; if (i % 2) { rtp_timestamp += (frame_duration_ms - 5) * 90; @@ -171,30 +181,32 @@ TEST_F(OveruseDetectorTest, 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, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(8, frames_until_overuse); } TEST_F(OveruseDetectorTest, SimpleOveruse100kbit10fps) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 100; int drift_per_frame_ms = 1; int sigma_ms = 0; // No variance. - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(6, frames_until_overuse); } @@ -202,11 +214,12 @@ 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_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); rtp_timestamp += frame_duration_ms * 90; if (i % 2) { offset = rand() % 50; @@ -220,12 +233,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_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); now_ms_ += frame_duration_ms + drift_per_frame_ms; rtp_timestamp += frame_duration_ms * 90; EXPECT_EQ(kBwNormal, overuse_detector_->State()); } - UpdateDetector(rtp_timestamp, now_ms_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); EXPECT_EQ(kBwOverusing, overuse_detector_->State()); } @@ -233,11 +246,12 @@ 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_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); rtp_timestamp += frame_duration_ms * 90; if (i % 2) { offset = rand() % 2; @@ -250,12 +264,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_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); now_ms_ += frame_duration_ms + drift_per_frame_ms; rtp_timestamp += frame_duration_ms * 90; EXPECT_EQ(kBwNormal, overuse_detector_->State()); } - UpdateDetector(rtp_timestamp, now_ms_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); EXPECT_EQ(kBwOverusing, overuse_detector_->State()); } @@ -263,16 +277,17 @@ 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_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); rtp_timestamp += frame_duration_ms * 90; if (i % 2) { offset = rand() % 2; @@ -285,285 +300,305 @@ 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_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); - UpdateDetector(rtp_timestamp, now_ms_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); now_ms_ += frame_duration_ms + drift_per_frame_ms * 6; rtp_timestamp += frame_duration_ms * 90; EXPECT_EQ(kBwNormal, overuse_detector_->State()); } - UpdateDetector(rtp_timestamp, now_ms_); + UpdateDetector(rtp_timestamp, now_ms_, packet_size); EXPECT_EQ(kBwOverusing, overuse_detector_->State()); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(LowGaussianVariance30Kbit3fps)) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 333; int drift_per_frame_ms = 1; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(13, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(14, frames_until_overuse); } TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift30Kbit3fps) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 333; int drift_per_frame_ms = 100; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(13, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(4, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVariance30Kbit3fps) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 333; int drift_per_frame_ms = 1; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); - EXPECT_EQ(50, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); + EXPECT_EQ(46, unique_overuse); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(42, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift30Kbit3fps) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 333; int drift_per_frame_ms = 100; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); - EXPECT_EQ(50, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); + EXPECT_EQ(46, unique_overuse); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(4, frames_until_overuse); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(LowGaussianVariance100Kbit5fps)) { + size_t packet_size = 1200; int packets_per_frame = 2; int frame_duration_ms = 200; int drift_per_frame_ms = 1; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(12, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(12, frames_until_overuse); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(HighGaussianVariance100Kbit5fps)) { + size_t packet_size = 1200; int packets_per_frame = 2; int frame_duration_ms = 200; int drift_per_frame_ms = 1; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(16, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(37, frames_until_overuse); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(LowGaussianVariance100Kbit10fps)) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 100; int drift_per_frame_ms = 1; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(12, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(12, frames_until_overuse); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(HighGaussianVariance100Kbit10fps)) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 100; int drift_per_frame_ms = 1; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(12, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(37, frames_until_overuse); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(LowGaussianVariance300Kbit30fps)) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 33; int drift_per_frame_ms = 1; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(14, frames_until_overuse); } TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift300Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 33; int drift_per_frame_ms = 10; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(6, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVariance300Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 33; int drift_per_frame_ms = 1; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(49, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift300Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 1; int frame_duration_ms = 33; int drift_per_frame_ms = 10; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(8, frames_until_overuse); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(LowGaussianVariance1000Kbit30fps)) { + size_t packet_size = 1200; int packets_per_frame = 3; int frame_duration_ms = 33; int drift_per_frame_ms = 1; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(14, frames_until_overuse); } TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift1000Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 3; int frame_duration_ms = 33; int drift_per_frame_ms = 10; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(6, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVariance1000Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 3; int frame_duration_ms = 33; int drift_per_frame_ms = 1; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(49, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift1000Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 3; int frame_duration_ms = 33; int drift_per_frame_ms = 10; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(8, frames_until_overuse); } TEST_F(OveruseDetectorTest, DISABLED_ON_ANDROID(LowGaussianVariance2000Kbit30fps)) { + size_t packet_size = 1200; int packets_per_frame = 6; int frame_duration_ms = 33; int drift_per_frame_ms = 1; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(14, frames_until_overuse); } TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift2000Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 6; int frame_duration_ms = 33; int drift_per_frame_ms = 10; int sigma_ms = 3; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(6, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVariance2000Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 6; int frame_duration_ms = 33; int drift_per_frame_ms = 1; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(49, frames_until_overuse); } TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift2000Kbit30fps) { + size_t packet_size = 1200; int packets_per_frame = 6; int frame_duration_ms = 33; int drift_per_frame_ms = 10; int sigma_ms = 10; - int unique_overuse = - Run100000Samples(packets_per_frame, frame_duration_ms, sigma_ms); + int unique_overuse = Run100000Samples(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms); EXPECT_EQ(0, unique_overuse); - int frames_until_overuse = RunUntilOveruse( - packets_per_frame, frame_duration_ms, sigma_ms, drift_per_frame_ms); + int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, + frame_duration_ms, sigma_ms, drift_per_frame_ms); EXPECT_EQ(8, frames_until_overuse); } @@ -574,7 +609,9 @@ class OveruseDetectorExperimentTest : public OveruseDetectorTest { "WebRTC-AdaptiveBweThreshold/Enabled-0.01,0.00018/") {} protected: - void SetUp() override { overuse_detector_.reset(new OveruseDetector()); } + void SetUp() override { + overuse_detector_.reset(new OveruseDetector(options_)); + } test::ScopedFieldTrials override_field_trials_; }; diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc index a9d3bfe609..4be7b7493b 100644 --- a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc +++ b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc @@ -16,7 +16,6 @@ #include #include -#include "webrtc/base/checks.h" #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" #include "webrtc/system_wrappers/include/logging.h" @@ -25,25 +24,33 @@ namespace webrtc { enum { kMinFramePeriodHistoryLength = 60 }; enum { kDeltaCounterMax = 1000 }; -OveruseEstimator::OveruseEstimator() - : num_of_deltas_(0), - offset_(0), - prev_offset_(offset_), - e_(0.1), - process_noise_(1e-2), - avg_noise_(0), - var_noise_(50), - send_delta_history_() {} - -OveruseEstimator::~OveruseEstimator() { - send_delta_history_.clear(); +OveruseEstimator::OveruseEstimator(const OverUseDetectorOptions& options) + : options_(options), + num_of_deltas_(0), + slope_(options_.initial_slope), + offset_(options_.initial_offset), + prev_offset_(options_.initial_offset), + E_(), + process_noise_(), + avg_noise_(options_.initial_avg_noise), + var_noise_(options_.initial_var_noise), + ts_delta_hist_() { + memcpy(E_, options_.initial_e, sizeof(E_)); + memcpy(process_noise_, options_.initial_process_noise, + sizeof(process_noise_)); } -void OveruseEstimator::Update(double recv_delta_ms, - double send_delta_ms, +OveruseEstimator::~OveruseEstimator() { + ts_delta_hist_.clear(); +} + +void OveruseEstimator::Update(int64_t t_delta, + double ts_delta, + int size_delta, BandwidthUsage current_hypothesis) { - const double min_frame_period = UpdateMinFramePeriod(send_delta_ms); - const double delta_ms = recv_delta_ms - send_delta_ms; + const double min_frame_period = UpdateMinFramePeriod(ts_delta); + const double t_ts_delta = t_delta - ts_delta; + double fs_delta = size_delta; ++num_of_deltas_; if (num_of_deltas_ > kDeltaCounterMax) { @@ -51,14 +58,19 @@ void OveruseEstimator::Update(double recv_delta_ms, } // Update the Kalman filter. - e_ += process_noise_; + E_[0][0] += process_noise_[0]; + E_[1][1] += process_noise_[1]; if ((current_hypothesis == kBwOverusing && offset_ < prev_offset_) || (current_hypothesis == kBwUnderusing && offset_ > prev_offset_)) { - e_ += 10 * process_noise_; + E_[1][1] += 10 * process_noise_[1]; } - const double residual = delta_ms - offset_; + const double h[2] = {fs_delta, 1.0}; + const double Eh[2] = {E_[0][0]*h[0] + E_[0][1]*h[1], + E_[1][0]*h[0] + E_[1][1]*h[1]}; + + const double residual = t_ts_delta - slope_*h[0] - offset_; const bool in_stable_state = (current_hypothesis == kBwNormal); const double max_residual = 3.0 * sqrt(var_noise_); @@ -70,47 +82,66 @@ void OveruseEstimator::Update(double recv_delta_ms, UpdateNoiseEstimate(residual < 0 ? -max_residual : max_residual, min_frame_period, in_stable_state); } - const double k = e_ / (var_noise_ + e_); + + const double denom = var_noise_ + h[0]*Eh[0] + h[1]*Eh[1]; + + const double K[2] = {Eh[0] / denom, + Eh[1] / denom}; + + const double IKh[2][2] = {{1.0 - K[0]*h[0], -K[0]*h[1]}, + {-K[1]*h[0], 1.0 - K[1]*h[1]}}; + const double e00 = E_[0][0]; + const double e01 = E_[0][1]; // Update state. - e_ = e_ * (1.0 - k); + E_[0][0] = e00 * IKh[0][0] + E_[1][0] * IKh[0][1]; + E_[0][1] = e01 * IKh[0][0] + E_[1][1] * IKh[0][1]; + E_[1][0] = e00 * IKh[1][0] + E_[1][0] * IKh[1][1]; + E_[1][1] = e01 * IKh[1][0] + E_[1][1] * IKh[1][1]; - // The covariance matrix must be positive. - RTC_DCHECK(e_ >= 0.0); - if (e_ < 0) - LOG(LS_ERROR) << "The over-use estimator's covariance is negative!"; + // The covariance matrix must be positive semi-definite. + bool positive_semi_definite = E_[0][0] + E_[1][1] >= 0 && + E_[0][0] * E_[1][1] - E_[0][1] * E_[1][0] >= 0 && E_[0][0] >= 0; + assert(positive_semi_definite); + if (!positive_semi_definite) { + LOG(LS_ERROR) << "The over-use estimator's covariance matrix is no longer " + "semi-definite."; + } - offset_ = offset_ + k * residual; + slope_ = slope_ + K[0] * residual; + prev_offset_ = offset_; + offset_ = offset_ + K[1] * residual; } -double OveruseEstimator::UpdateMinFramePeriod(double send_delta_ms) { - double min_frame_period = send_delta_ms; - if (send_delta_history_.size() >= kMinFramePeriodHistoryLength) { - send_delta_history_.pop_front(); +double OveruseEstimator::UpdateMinFramePeriod(double ts_delta) { + double min_frame_period = ts_delta; + if (ts_delta_hist_.size() >= kMinFramePeriodHistoryLength) { + ts_delta_hist_.pop_front(); } - for (double delta_ms : send_delta_history_) { - min_frame_period = std::min(delta_ms, min_frame_period); + std::list::iterator it = ts_delta_hist_.begin(); + for (; it != ts_delta_hist_.end(); it++) { + min_frame_period = std::min(*it, min_frame_period); } - send_delta_history_.push_back(send_delta_ms); + ts_delta_hist_.push_back(ts_delta); return min_frame_period; } void OveruseEstimator::UpdateNoiseEstimate(double residual, - double send_delta_ms, + double ts_delta, bool stable_state) { if (!stable_state) { return; } // Faster filter during startup to faster adapt to the jitter level // of the network. |alpha| is tuned for 30 frames per second, but is scaled - // according to |send_delta_ms|. + // according to |ts_delta|. double alpha = 0.01; if (num_of_deltas_ > 10*30) { alpha = 0.002; } // Only update the noise estimate if we're not over-using. |beta| is a // function of alpha and the time delta since the previous update. - const double beta = pow(1 - alpha, send_delta_ms * 30.0 / 1000.0); + const double beta = pow(1 - alpha, ts_delta * 30.0 / 1000.0); avg_noise_ = beta * avg_noise_ + (1 - beta) * residual; var_noise_ = beta * var_noise_ diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h index d04e7d9f98..d671f39166 100644 --- a/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h +++ b/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h @@ -20,15 +20,14 @@ namespace webrtc { class OveruseEstimator { public: - OveruseEstimator(); + explicit OveruseEstimator(const OverUseDetectorOptions& options); ~OveruseEstimator(); // Update the estimator with a new sample. The deltas should represent deltas // between timestamp groups as defined by the InterArrival class. // |current_hypothesis| should be the hypothesis of the over-use detector at // this time. - void Update(double recv_delta_ms, - double send_delta_ms, + void Update(int64_t t_delta, double ts_delta, int size_delta, BandwidthUsage current_hypothesis); // Returns the estimated noise/jitter variance in ms^2. @@ -48,21 +47,21 @@ class OveruseEstimator { } private: - double UpdateMinFramePeriod(double send_delta_ms); - void UpdateNoiseEstimate(double residual, - double send_delta_ms, - bool stable_state); + double UpdateMinFramePeriod(double ts_delta); + void UpdateNoiseEstimate(double residual, double ts_delta, bool stable_state); // Must be first member variable. Cannot be const because we need to be // copyable. + OverUseDetectorOptions options_; uint16_t num_of_deltas_; + double slope_; double offset_; double prev_offset_; - double e_; - double process_noise_; + double E_[2][2]; + double process_noise_[2]; double avg_noise_; double var_noise_; - std::list send_delta_history_; + std::list ts_delta_hist_; RTC_DISALLOW_COPY_AND_ASSIGN(OveruseEstimator); }; diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc index cd919124fb..51f7d4320a 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc @@ -102,6 +102,10 @@ 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), @@ -267,6 +271,7 @@ 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. @@ -296,10 +301,10 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo( new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, kTimestampToMs, true)); } - if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, &ts_delta, - &t_delta)) { + if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, payload_size, + &ts_delta, &t_delta, &size_delta)) { double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift); - estimator_.Update(t_delta, ts_delta_ms, detector_.State()); + estimator_.Update(t_delta, ts_delta_ms, size_delta, detector_.State()); detector_.Detect(estimator_.offset(), ts_delta_ms, estimator_.num_of_deltas(), arrival_time_ms); UpdateStats(static_cast(t_delta - ts_delta_ms), now_ms); diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc index 29115b94bb..f1a1cb6602 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc @@ -28,13 +28,14 @@ enum { kTimestampGroupLengthMs = 5 }; static const double kTimestampToMs = 1.0 / 90.0; struct RemoteBitrateEstimatorSingleStream::Detector { - explicit Detector(int64_t last_packet_time_ms, bool enable_burst_grouping) - : last_packet_time_ms(last_packet_time_ms), - inter_arrival(90 * kTimestampGroupLengthMs, - kTimestampToMs, - enable_burst_grouping), - estimator(), - detector() {} + explicit Detector(int64_t last_packet_time_ms, + const OverUseDetectorOptions& options, + bool enable_burst_grouping) + : last_packet_time_ms(last_packet_time_ms), + inter_arrival(90 * kTimestampGroupLengthMs, kTimestampToMs, + enable_burst_grouping), + estimator(options), + detector(options) {} int64_t last_packet_time_ms; InterArrival inter_arrival; OveruseEstimator estimator; @@ -81,8 +82,8 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket(int64_t arrival_time_ms, // automatically cleaned up when we have one RemoteBitrateEstimator per REMB // group. std::pair insert_result = - overuse_detectors_.insert( - std::make_pair(ssrc, new Detector(now_ms, true))); + overuse_detectors_.insert(std::make_pair( + ssrc, new Detector(now_ms, OverUseDetectorOptions(), true))); it = insert_result.first; } Detector* estimator = it->second; @@ -91,10 +92,12 @@ 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, - ×tamp_delta, &time_delta)) { + payload_size, ×tamp_delta, + &time_delta, &size_delta)) { double timestamp_delta_ms = timestamp_delta * kTimestampToMs; - estimator->estimator.Update(time_delta, timestamp_delta_ms, + estimator->estimator.Update(time_delta, timestamp_delta_ms, size_delta, estimator->detector.State()); estimator->detector.Detect(estimator->estimator.offset(), timestamp_delta_ms, diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc index 70051bb5fa..a6c182a7bc 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc @@ -52,7 +52,7 @@ TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropTwoStreamsWrap) { } TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThreeStreamsWrap) { - CapacityDropTestHelper(3, true, 567); + CapacityDropTestHelper(3, true, 734); } TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThirteenStreamsWrap) { diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc index 42d68dacfc..7a7645fd1b 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc @@ -61,7 +61,8 @@ class TestTransport : public Transport { class RtcpFormatRembTest : public ::testing::Test { protected: RtcpFormatRembTest() - : system_clock_(Clock::GetRealTimeClock()), + : over_use_detector_options_(), + system_clock_(Clock::GetRealTimeClock()), dummy_rtp_rtcp_impl_(nullptr), receive_statistics_(ReceiveStatistics::Create(system_clock_)), rtcp_sender_(nullptr), @@ -74,6 +75,7 @@ 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 receive_statistics_; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc index 7f0121cff7..5b0e656e32 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc @@ -66,7 +66,8 @@ class TestTransport : public Transport, class RtcpReceiverTest : public ::testing::Test { protected: RtcpReceiverTest() - : system_clock_(1335900000), + : over_use_detector_options_(), + system_clock_(1335900000), remote_bitrate_observer_(), remote_bitrate_estimator_( new RemoteBitrateEstimatorSingleStream(&remote_bitrate_observer_, @@ -130,6 +131,7 @@ class RtcpReceiverTest : public ::testing::Test { return 0; } + OverUseDetectorOptions over_use_detector_options_; SimulatedClock system_clock_; ModuleRtpRtcpImpl* rtp_rtcp_impl_; RTCPReceiver* rtcp_receiver_;