Modified Simulation Framework Jitter Model.

Using a right-sided (absolute value), truncated gaussian distribution originally with zero mean.

Currently truncated at x = 3 * std_dev.

Added expected value computation.

Modified jitter unittests accordingly.

BUG=webrtc:4848
R=stefan@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#9587}
This commit is contained in:
Cesar Magalhaes 2015-07-15 19:47:10 +02:00
parent 8fc7fa798f
commit bf40b42af5
5 changed files with 71 additions and 26 deletions

View File

@ -124,7 +124,7 @@ TEST_P(DefaultBweTest, SteadyJitter) {
JitterFilter jitter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
jitter.SetJitter(20);
jitter.SetMaxJitter(20);
RunFor(2 * 60 * 1000);
}
@ -134,7 +134,7 @@ TEST_P(DefaultBweTest, IncreasingJitter1) {
JitterFilter jitter(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
for (int i = 0; i < 2 * 60 * 2; ++i) {
jitter.SetJitter(i);
jitter.SetMaxJitter(i);
RunFor(10 * 1000);
}
RunFor(10 * 60 * 1000);
@ -147,10 +147,10 @@ TEST_P(DefaultBweTest, IncreasingJitter2) {
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
RunFor(30 * 1000);
for (int i = 1; i < 51; ++i) {
jitter.SetJitter(10.0f * i);
jitter.SetMaxJitter(10.0f * i);
RunFor(10 * 1000);
}
jitter.SetJitter(0.0f);
jitter.SetMaxJitter(0.0f);
RunFor(10 * 60 * 1000);
}
@ -232,7 +232,7 @@ TEST_P(DefaultBweTest, Multi2) {
RateCounterFilter counter(&uplink_, 0, "");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
choke.set_capacity_kbps(2000);
jitter.SetJitter(120);
jitter.SetMaxJitter(120);
RunFor(5 * 60 * 1000);
}

View File

@ -389,7 +389,8 @@ JitterFilter::JitterFilter(PacketProcessorListener* listener, int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
random_(0x89674523),
stddev_jitter_us_(0),
last_send_time_us_(0) {
last_send_time_us_(0),
reordering_(false) {
}
JitterFilter::JitterFilter(PacketProcessorListener* listener,
@ -397,27 +398,62 @@ JitterFilter::JitterFilter(PacketProcessorListener* listener,
: PacketProcessor(listener, flow_ids, kRegular),
random_(0x89674523),
stddev_jitter_us_(0),
last_send_time_us_(0) {
last_send_time_us_(0),
reordering_(false) {
}
void JitterFilter::SetJitter(int64_t stddev_jitter_ms) {
const int kN = 3; // Truncated N sigma gaussian.
void JitterFilter::SetMaxJitter(int64_t max_jitter_ms) {
BWE_TEST_LOGGING_ENABLE(false);
BWE_TEST_LOGGING_LOG1("Jitter", "%d ms",
static_cast<int>(stddev_jitter_ms));
assert(stddev_jitter_ms >= 0);
stddev_jitter_us_ = stddev_jitter_ms * 1000;
BWE_TEST_LOGGING_LOG1("Max Jitter", "%d ms", static_cast<int>(max_jitter_ms));
assert(max_jitter_ms >= 0);
// Truncated gaussian, Max jitter = kN*sigma.
stddev_jitter_us_ = (max_jitter_ms * 1000 + kN / 2) / kN;
}
namespace {
inline int64_t TruncatedNSigmaGaussian(Random* const random,
int64_t mean,
int64_t std_dev) {
int64_t gaussian_random = random->Gaussian(mean, std_dev);
return std::max(std::min(gaussian_random, kN * std_dev), -kN * std_dev);
}
}
void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
for (Packet* packet : *in_out) {
int64_t new_send_time_us = packet->send_time_us();
new_send_time_us += random_.Gaussian(0, stddev_jitter_us_);
last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
packet->set_send_time_us(last_send_time_us_);
int64_t jitter_us =
std::abs(TruncatedNSigmaGaussian(&random_, 0, stddev_jitter_us_));
int64_t new_send_time_us = packet->send_time_us() + jitter_us;
if (!reordering_) {
new_send_time_us = std::max(last_send_time_us_, new_send_time_us);
}
// Receiver timestamp cannot be lower than sender timestamp.
assert(new_send_time_us >= packet->sender_timestamp_us());
packet->set_send_time_us(new_send_time_us);
last_send_time_us_ = new_send_time_us;
}
}
// Computes the expected value for a right sided (abs) truncated gaussian.
// Does not take into account possible reoerdering updates.
int64_t JitterFilter::MeanUs() {
const double kPi = 3.1415926535897932;
double max_jitter_us = static_cast<double>(kN * stddev_jitter_us_);
double right_sided_mean_us =
static_cast<double>(stddev_jitter_us_) / sqrt(kPi / 2.0);
double truncated_mean_us =
right_sided_mean_us *
(1.0 - exp(-pow(static_cast<double>(kN), 2.0) / 2.0)) +
max_jitter_us * erfc(static_cast<double>(kN));
return static_cast<int64_t>(truncated_mean_us + 0.5);
}
ReorderFilter::ReorderFilter(PacketProcessorListener* listener, int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
random_(0x27452389),

View File

@ -314,13 +314,16 @@ class JitterFilter : public PacketProcessor {
JitterFilter(PacketProcessorListener* listener, const FlowIds& flow_ids);
virtual ~JitterFilter() {}
void SetJitter(int64_t stddev_jitter_ms);
void SetMaxJitter(int64_t stddev_jitter_ms);
virtual void RunFor(int64_t time_ms, Packets* in_out);
void set_reorderdering(bool reordering) { reordering_ = reordering; }
int64_t MeanUs();
private:
Random random_;
int64_t stddev_jitter_us_;
int64_t last_send_time_us_;
bool reordering_; // False by default.
DISALLOW_IMPLICIT_CONSTRUCTORS(JitterFilter);
};

View File

@ -457,12 +457,12 @@ TEST_F(BweTestFramework_DelayFilterTest, IncreasingDelay) {
ASSERT_TRUE(IsSequenceNumberSorted(accumulated_packets_));
}
static void TestJitterFilter(int64_t stddev_jitter_ms) {
static void TestJitterFilter(int64_t max_jitter_ms) {
JitterFilter filter(NULL, 0);
filter.SetJitter(stddev_jitter_ms);
filter.SetMaxJitter(max_jitter_ms);
int64_t now_ms = 0;
uint32_t sequence_number = 0;
uint16_t sequence_number = 0;
// Generate packets, add jitter to them, accumulate the altered packets.
Packets original;
@ -473,9 +473,9 @@ static void TestJitterFilter(int64_t stddev_jitter_ms) {
packets.push_back(new MediaPacket(now_ms * 1000, sequence_number));
original.push_back(new MediaPacket(now_ms * 1000, sequence_number));
++sequence_number;
now_ms += 5 * stddev_jitter_ms;
now_ms += 5 * max_jitter_ms;
}
filter.RunFor(stddev_jitter_ms, &packets);
filter.RunFor(max_jitter_ms, &packets);
jittered.splice(jittered.end(), packets);
}
@ -490,17 +490,22 @@ static void TestJitterFilter(int64_t stddev_jitter_ms) {
// difference (jitter) in stats, then check that mean jitter is close to zero
// and standard deviation of jitter is what we set it to.
Stats<double> jitter_us;
int64_t max_jitter_obtained_us = 0;
for (PacketsIt it1 = original.begin(), it2 = jittered.begin();
it1 != original.end() && it2 != jittered.end(); ++it1, ++it2) {
const MediaPacket* packet1 = static_cast<const MediaPacket*>(*it1);
const MediaPacket* packet2 = static_cast<const MediaPacket*>(*it2);
EXPECT_EQ(packet1->header().sequenceNumber,
packet2->header().sequenceNumber);
jitter_us.Push(packet1->send_time_us() - packet2->send_time_us());
max_jitter_obtained_us =
std::max(max_jitter_obtained_us,
packet2->send_time_us() - packet1->send_time_us());
jitter_us.Push(packet2->send_time_us() - packet1->send_time_us());
}
EXPECT_NEAR(0.0, jitter_us.GetMean(), stddev_jitter_ms * 1000.0 * 0.008);
EXPECT_NEAR(stddev_jitter_ms * 1000.0, jitter_us.GetStdDev(),
stddev_jitter_ms * 1000.0 * 0.02);
EXPECT_NEAR(filter.MeanUs(), jitter_us.GetMean(),
max_jitter_ms * 1000.0 * 0.01);
EXPECT_NEAR(max_jitter_ms * 1000.0, max_jitter_obtained_us,
max_jitter_ms * 1000.0 * 0.01);
for (auto* packet : original)
delete packet;
for (auto* packet : jittered)

View File

@ -36,6 +36,7 @@ class Packet {
virtual int flow_id() const { return flow_id_; }
virtual void set_send_time_us(int64_t send_time_us);
virtual int64_t send_time_us() const { return send_time_us_; }
virtual int64_t sender_timestamp_us() const { return sender_timestamp_us_; }
virtual size_t payload_size() const { return payload_size_; }
virtual Packet::Type GetPacketType() const = 0;
virtual void set_sender_timestamp_us(int64_t sender_timestamp_us) {