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:
parent
8fc7fa798f
commit
bf40b42af5
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user