summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc')
-rw-r--r--third_party/libwebrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc530
1 files changed, 530 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc b/third_party/libwebrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc
new file mode 100644
index 0000000000..581963e96d
--- /dev/null
+++ b/third_party/libwebrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/remote_bitrate_estimator/inter_arrival.h"
+
+#include <memory>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace testing {
+
+enum {
+ kTimestampGroupLengthUs = 5000,
+ kMinStep = 20,
+ kTriggerNewGroupUs = kTimestampGroupLengthUs + kMinStep,
+ kBurstThresholdMs = 5,
+ kAbsSendTimeFraction = 18,
+ kAbsSendTimeInterArrivalUpshift = 8,
+ kInterArrivalShift = kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift,
+};
+
+const double kRtpTimestampToMs = 1.0 / 90.0;
+const double kAstToMs = 1000.0 / static_cast<double>(1 << kInterArrivalShift);
+
+class InterArrivalTest : public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ inter_arrival_.reset(new InterArrival(kTimestampGroupLengthUs / 1000, 1.0));
+ inter_arrival_rtp_.reset(new InterArrival(
+ MakeRtpTimestamp(kTimestampGroupLengthUs), kRtpTimestampToMs));
+ inter_arrival_ast_.reset(
+ new InterArrival(MakeAbsSendTime(kTimestampGroupLengthUs), kAstToMs));
+ }
+
+ // 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) {
+ InternalExpectFalse(inter_arrival_rtp_.get(),
+ MakeRtpTimestamp(timestamp_us), arrival_time_ms,
+ packet_size);
+ InternalExpectFalse(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
+ 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,
+ 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, packet_size,
+ MakeRtpTimestamp(expected_timestamp_delta_us),
+ expected_arrival_time_delta_ms,
+ expected_packet_size_delta, timestamp_near);
+ InternalExpectTrue(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
+ arrival_time_ms, packet_size,
+ MakeAbsSendTime(expected_timestamp_delta_us),
+ expected_arrival_time_delta_ms,
+ expected_packet_size_delta, timestamp_near << 8);
+ }
+
+ void WrapTestHelper(int64_t wrap_start_us,
+ uint32_t timestamp_near,
+ bool unorderly_within_group) {
+ // Step through the range of a 32 bit int, 1/4 at a time to not cause
+ // packets close to wraparound to be judged as out of order.
+
+ // G1
+ int64_t arrival_time = 17;
+ ExpectFalse(0, arrival_time, 1);
+
+ // G2
+ arrival_time += kBurstThresholdMs + 1;
+ ExpectFalse(wrap_start_us / 4, arrival_time, 1);
+
+ // G3
+ arrival_time += kBurstThresholdMs + 1;
+ 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, 1,
+ wrap_start_us / 4, 6, 0, // 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
+ timestamp_near);
+ for (int i = 0; i < 10; ++i) {
+ // Slowly step across the wrap point.
+ arrival_time += kBurstThresholdMs + 1;
+ if (unorderly_within_group) {
+ // 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);
+ } else {
+ 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, 100);
+
+ // G6
+ arrival_time += kBurstThresholdMs + 1;
+ int64_t g6_arrival_time = arrival_time;
+ ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time, 10,
+ wrap_start_us / 4 + 9 * kMinStep,
+ 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, 100);
+
+ // G7
+ arrival_time += kBurstThresholdMs + 1;
+ ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs, arrival_time, 100,
+ // Delta G6-G5
+ kTriggerNewGroupUs - 9 * kMinStep,
+ g6_arrival_time - g5_arrival_time, 10 - (2 + 10),
+ timestamp_near);
+ }
+
+ std::unique_ptr<InterArrival> inter_arrival_;
+
+ private:
+ static uint32_t MakeRtpTimestamp(int64_t us) {
+ return static_cast<uint32_t>(static_cast<uint64_t>(us * 90 + 500) / 1000);
+ }
+
+ static uint32_t MakeAbsSendTime(int64_t us) {
+ uint32_t absolute_send_time =
+ static_cast<uint32_t>(((static_cast<uint64_t>(us) << 18) + 500000) /
+ 1000000) &
+ 0x00FFFFFFul;
+ return absolute_send_time << 8;
+ }
+
+ static void InternalExpectFalse(InterArrival* inter_arrival,
+ uint32_t timestamp,
+ int64_t arrival_time_ms,
+ size_t packet_size) {
+ 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, 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;
+ int delta_packet_size = 909;
+ bool computed = inter_arrival->ComputeDeltas(
+ timestamp, arrival_time_ms, 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);
+ }
+
+ std::unique_ptr<InterArrival> inter_arrival_rtp_;
+ std::unique_ptr<InterArrival> inter_arrival_ast_;
+};
+
+TEST_F(InterArrivalTest, FirstPacket) {
+ 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, 1);
+
+ // G2
+ arrival_time += kBurstThresholdMs + 1;
+ int64_t g2_arrival_time = 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, 1,
+ // Delta G2-G1
+ 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, 1);
+
+ // G2
+ arrival_time += kBurstThresholdMs + 1;
+ int64_t g2_arrival_time = arrival_time;
+ ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
+
+ // G3
+ arrival_time += kBurstThresholdMs + 1;
+ int64_t g3_arrival_time = arrival_time;
+ ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
+ // Delta G2-G1
+ 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, 2,
+ // Delta G3-G2
+ 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, 1);
+
+ // G2
+ arrival_time += kBurstThresholdMs + 1;
+ 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, 1);
+ }
+ 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);
+}
+
+TEST_F(InterArrivalTest, OutOfOrderPacket) {
+ // G1
+ int64_t arrival_time = 17;
+ int64_t timestamp = 0;
+ 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, 2);
+ for (int i = 0; i < 10; ++i) {
+ arrival_time += kBurstThresholdMs + 1;
+ timestamp += kMinStep;
+ 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, 100);
+
+ // G3
+ arrival_time = 500;
+ timestamp = 2 * kTriggerNewGroupUs;
+ ExpectTrue(timestamp, arrival_time, 100,
+ // Delta G2-G1
+ 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, 1);
+ int64_t g1_timestamp = timestamp;
+ int64_t g1_arrival_time = arrival_time;
+
+ // G2
+ timestamp += kTriggerNewGroupUs;
+ arrival_time += 11;
+ ExpectFalse(kTriggerNewGroupUs, 28, 2);
+ timestamp += 10 * kMinStep;
+ int64_t g2_timestamp = timestamp;
+ for (int i = 0; i < 10; ++i) {
+ // 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.
+ arrival_time += kBurstThresholdMs + 1;
+ ExpectFalse(timestamp, arrival_time, 1);
+ timestamp -= kMinStep;
+ }
+ int64_t g2_arrival_time = arrival_time;
+
+ // However, this packet is deemed out of order and should be dropped.
+ arrival_time = 281;
+ timestamp = g1_timestamp;
+ ExpectFalse(timestamp, arrival_time, 100);
+
+ // 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);
+}
+
+TEST_F(InterArrivalTest, TwoBursts) {
+ // G1
+ int64_t g1_arrival_time = 17;
+ ExpectFalse(0, g1_arrival_time, 1);
+
+ // G2
+ int64_t timestamp = kTriggerNewGroupUs;
+ int64_t arrival_time = 100; // Simulate no packets arriving for 100 ms.
+ for (int i = 0; i < 10; ++i) {
+ // A bunch of packets arriving in one burst (within 5 ms apart).
+ timestamp += 30000;
+ arrival_time += kBurstThresholdMs;
+ ExpectFalse(timestamp, arrival_time, 1);
+ }
+ int64_t g2_arrival_time = arrival_time;
+ int64_t g2_timestamp = timestamp;
+
+ // 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);
+}
+
+TEST_F(InterArrivalTest, NoBursts) {
+ // G1
+ ExpectFalse(0, 17, 1);
+
+ // G2
+ int64_t timestamp = kTriggerNewGroupUs;
+ int64_t arrival_time = 28;
+ ExpectFalse(timestamp, arrival_time, 2);
+
+ // G3
+ ExpectTrue(kTriggerNewGroupUs + 30000, arrival_time + kBurstThresholdMs + 1,
+ 100, timestamp - 0, arrival_time - 17,
+ 2 - 1, // Delta G2-G1
+ 0);
+}
+
+// Yields 0xfffffffe when converted to internal representation in
+// inter_arrival_rtp_ and inter_arrival_ast_ respectively.
+static const int64_t kStartRtpTimestampWrapUs = 47721858827;
+static const int64_t kStartAbsSendTimeWrapUs = 63999995;
+
+TEST_F(InterArrivalTest, RtpTimestampWrap) {
+ WrapTestHelper(kStartRtpTimestampWrapUs, 1, false);
+}
+
+TEST_F(InterArrivalTest, AbsSendTimeWrap) {
+ WrapTestHelper(kStartAbsSendTimeWrapUs, 1, false);
+}
+
+TEST_F(InterArrivalTest, RtpTimestampWrapOutOfOrderWithinGroup) {
+ WrapTestHelper(kStartRtpTimestampWrapUs, 1, true);
+}
+
+TEST_F(InterArrivalTest, AbsSendTimeWrapOutOfOrderWithinGroup) {
+ WrapTestHelper(kStartAbsSendTimeWrapUs, 1, true);
+}
+
+TEST_F(InterArrivalTest, PositiveArrivalTimeJump) {
+ const size_t kPacketSize = 1000;
+ uint32_t send_time_ms = 10000;
+ int64_t arrival_time_ms = 20000;
+ int64_t system_time_ms = 30000;
+
+ uint32_t send_delta;
+ int64_t arrival_delta;
+ int size_delta;
+ EXPECT_FALSE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+
+ const int kTimeDeltaMs = 30;
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ EXPECT_FALSE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs + InterArrival::kArrivalTimeOffsetThresholdMs;
+ system_time_ms += kTimeDeltaMs;
+ EXPECT_TRUE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+ EXPECT_EQ(kTimeDeltaMs, static_cast<int>(send_delta));
+ EXPECT_EQ(kTimeDeltaMs, arrival_delta);
+ EXPECT_EQ(size_delta, 0);
+
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ // The previous arrival time jump should now be detected and cause a reset.
+ EXPECT_FALSE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+
+ // The two next packets will not give a valid delta since we're in the initial
+ // state.
+ for (int i = 0; i < 2; ++i) {
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ EXPECT_FALSE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+ }
+
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ EXPECT_TRUE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+ EXPECT_EQ(kTimeDeltaMs, static_cast<int>(send_delta));
+ EXPECT_EQ(kTimeDeltaMs, arrival_delta);
+ EXPECT_EQ(size_delta, 0);
+}
+
+TEST_F(InterArrivalTest, NegativeArrivalTimeJump) {
+ const size_t kPacketSize = 1000;
+ uint32_t send_time_ms = 10000;
+ int64_t arrival_time_ms = 20000;
+ int64_t system_time_ms = 30000;
+
+ uint32_t send_delta;
+ int64_t arrival_delta;
+ int size_delta;
+ EXPECT_FALSE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+
+ const int kTimeDeltaMs = 30;
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ EXPECT_FALSE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ EXPECT_TRUE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+ EXPECT_EQ(kTimeDeltaMs, static_cast<int>(send_delta));
+ EXPECT_EQ(kTimeDeltaMs, arrival_delta);
+ EXPECT_EQ(size_delta, 0);
+
+ // Three out of order will fail, after that we will be reset and two more will
+ // fail before we get our first valid delta after the reset.
+ arrival_time_ms -= 1000;
+ for (int i = 0; i < InterArrival::kReorderedResetThreshold + 3; ++i) {
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ // The previous arrival time jump should now be detected and cause a reset.
+ EXPECT_FALSE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+ }
+
+ send_time_ms += kTimeDeltaMs;
+ arrival_time_ms += kTimeDeltaMs;
+ system_time_ms += kTimeDeltaMs;
+ EXPECT_TRUE(inter_arrival_->ComputeDeltas(
+ send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
+ &arrival_delta, &size_delta));
+ EXPECT_EQ(kTimeDeltaMs, static_cast<int>(send_delta));
+ EXPECT_EQ(kTimeDeltaMs, arrival_delta);
+ EXPECT_EQ(size_delta, 0);
+}
+} // namespace testing
+} // namespace webrtc