* 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));
}
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);
}
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) {
int64_t arrival_time = 17;
ExpectFalse(0, arrival_time, 1);
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(wrap_start_us / 4, arrival_time, 1);
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(wrap_start_us / 2, arrival_time, 1, wrap_start_us / 4, 6,
0,
0);
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,
timestamp_near);
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(wrap_start_us, arrival_time, 2, wrap_start_us / 4, 6,
0,
timestamp_near);
for (int i = 0; i < 10; ++i) {
arrival_time += kBurstThresholdMs + 1;
if (unorderly_within_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;
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(wrap_start_us - 100, arrival_time, 100);
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,
timestamp_near);
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time, 100);
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs, arrival_time, 100,
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) {
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
ExpectFalse(0, arrival_time, 1);
arrival_time += kBurstThresholdMs + 1;
int64_t g2_arrival_time = arrival_time;
ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1, 0);
}
TEST_F(InterArrivalTest, SecondGroup) {
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
ExpectFalse(0, arrival_time, 1);
arrival_time += kBurstThresholdMs + 1;
int64_t g2_arrival_time = arrival_time;
ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
arrival_time += kBurstThresholdMs + 1;
int64_t g3_arrival_time = arrival_time;
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1, 0);
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(3 * kTriggerNewGroupUs, arrival_time, 2,
kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, -1, 0);
}
TEST_F(InterArrivalTest, AccumulatedGroup) {
int64_t arrival_time = 17;
int64_t g1_arrival_time = arrival_time;
ExpectFalse(0, arrival_time, 1);
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(kTriggerNewGroupUs, 28, 2);
int64_t timestamp = kTriggerNewGroupUs;
for (int i = 0; i < 10; ++i) {
arrival_time += kBurstThresholdMs + 1;
timestamp += kMinStep;
ExpectFalse(timestamp, arrival_time, 1);
}
int64_t g2_arrival_time = arrival_time;
int64_t g2_timestamp = timestamp;
arrival_time = 500;
ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 100, g2_timestamp,
g2_arrival_time - g1_arrival_time,
(2 + 10) - 1,
0);
}
TEST_F(InterArrivalTest, OutOfOrderPacket) {
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;
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;
arrival_time = 281;
ExpectFalse(g1_timestamp, arrival_time, 100);
arrival_time = 500;
timestamp = 2 * kTriggerNewGroupUs;
ExpectTrue(timestamp, arrival_time, 100,
g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time,
(2 + 10) - 1, 0);
}
TEST_F(InterArrivalTest, OutOfOrderWithinGroup) {
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;
timestamp += kTriggerNewGroupUs;
arrival_time += 11;
ExpectFalse(kTriggerNewGroupUs, 28, 2);
timestamp += 10 * kMinStep;
int64_t g2_timestamp = timestamp;
for (int i = 0; i < 10; ++i) {
arrival_time += kBurstThresholdMs + 1;
ExpectFalse(timestamp, arrival_time, 1);
timestamp -= kMinStep;
}
int64_t g2_arrival_time = arrival_time;
arrival_time = 281;
timestamp = g1_timestamp;
ExpectFalse(timestamp, arrival_time, 100);
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) {
int64_t g1_arrival_time = 17;
ExpectFalse(0, g1_arrival_time, 1);
int64_t timestamp = kTriggerNewGroupUs;
int64_t arrival_time = 100;
for (int i = 0; i < 10; ++i) {
timestamp += 30000;
arrival_time += kBurstThresholdMs;
ExpectFalse(timestamp, arrival_time, 1);
}
int64_t g2_arrival_time = arrival_time;
int64_t g2_timestamp = timestamp;
timestamp += 30000;
arrival_time += kBurstThresholdMs + 1;
ExpectTrue(timestamp, arrival_time, 100, g2_timestamp,
g2_arrival_time - g1_arrival_time,
10 - 1,
0);
}
TEST_F(InterArrivalTest, NoBursts) {
ExpectFalse(0, 17, 1);
int64_t timestamp = kTriggerNewGroupUs;
int64_t arrival_time = 28;
ExpectFalse(timestamp, arrival_time, 2);
ExpectTrue(kTriggerNewGroupUs + 30000, arrival_time + kBurstThresholdMs + 1,
100, timestamp - 0, arrival_time - 17,
2 - 1,
0);
}
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;
EXPECT_FALSE(inter_arrival_->ComputeDeltas(
send_time_ms, arrival_time_ms, system_time_ms, kPacketSize, &send_delta,
&arrival_delta, &size_delta));
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);
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;
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);
}
}
}