Rewrote the PRNG using an xorshift* algorithm and moved the files from test/ to base/.
Created a simple unit test for the new random number generator. (It mostly tests that the generated numbers are consistent with the intended distribution, e.g. uniform. It is not a comprehensive test of the quality of the random numbers.) Several assertions in OveruseDetectorTest seem to depend on the exact sequence of random numbers. I updated those numbers to work with the new PRNG. Compute the standard deviation of the expected result in TestReorderFilter instead of passing an uncertainty parameter. BUG=webrtc:5177 Review URL: https://codereview.webrtc.org/1457023002 Cr-Commit-Position: refs/heads/master@{#10965}
This commit is contained in:
parent
0b3d7eec07
commit
84e78f9102
@ -134,6 +134,8 @@ static_library("rtc_base_approved") {
|
||||
"platform_thread.cc",
|
||||
"platform_thread.h",
|
||||
"platform_thread_types.h",
|
||||
"random.cc",
|
||||
"random.h",
|
||||
"safe_conversions.h",
|
||||
"safe_conversions_impl.h",
|
||||
"scoped_ptr.h",
|
||||
|
||||
@ -88,6 +88,8 @@
|
||||
'platform_thread.cc',
|
||||
'platform_thread.h',
|
||||
'platform_thread_types.h',
|
||||
'random.cc',
|
||||
'random.h',
|
||||
'ratetracker.cc',
|
||||
'ratetracker.h',
|
||||
'safe_conversions.h',
|
||||
|
||||
@ -84,6 +84,7 @@
|
||||
'profiler_unittest.cc',
|
||||
'proxy_unittest.cc',
|
||||
'proxydetect_unittest.cc',
|
||||
'random_unittest.cc',
|
||||
'ratelimiter_unittest.cc',
|
||||
'ratetracker_unittest.cc',
|
||||
'referencecountedsingletonfactory_unittest.cc',
|
||||
|
||||
86
webrtc/base/random.cc
Normal file
86
webrtc/base/random.cc
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 "webrtc/base/random.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
Random::Random(uint64_t seed) {
|
||||
RTC_DCHECK(seed != 0x0ull);
|
||||
state_ = seed;
|
||||
}
|
||||
|
||||
uint32_t Random::Rand(uint32_t t) {
|
||||
// Casting the output to 32 bits will give an almost uniform number.
|
||||
// Pr[x=0] = (2^32-1) / (2^64-1)
|
||||
// Pr[x=k] = 2^32 / (2^64-1) for k!=0
|
||||
// Uniform would be Pr[x=k] = 2^32 / 2^64 for all 32-bit integers k.
|
||||
uint32_t x = NextOutput();
|
||||
// If x / 2^32 is uniform on [0,1), then x / 2^32 * (t+1) is uniform on
|
||||
// the interval [0,t+1), so the integer part is uniform on [0,t].
|
||||
uint64_t result = x * (static_cast<uint64_t>(t) + 1);
|
||||
result >>= 32;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t Random::Rand(uint32_t low, uint32_t high) {
|
||||
RTC_DCHECK(low <= high);
|
||||
return Rand(high - low) + low;
|
||||
}
|
||||
|
||||
int32_t Random::Rand(int32_t low, int32_t high) {
|
||||
RTC_DCHECK(low <= high);
|
||||
// We rely on subtraction (and addition) to be the same for signed and
|
||||
// unsigned numbers in two-complement representation. Thus, although
|
||||
// high - low might be negative as an int, it is the correct difference
|
||||
// when interpreted as an unsigned.
|
||||
return Rand(high - low) + low;
|
||||
}
|
||||
|
||||
template <>
|
||||
float Random::Rand<float>() {
|
||||
double result = NextOutput() - 1;
|
||||
result = result / 0xFFFFFFFFFFFFFFFEull;
|
||||
return static_cast<float>(result);
|
||||
}
|
||||
|
||||
template <>
|
||||
double Random::Rand<double>() {
|
||||
double result = NextOutput() - 1;
|
||||
result = result / 0xFFFFFFFFFFFFFFFEull;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Random::Rand<bool>() {
|
||||
return Rand(0, 1) == 1;
|
||||
}
|
||||
|
||||
double Random::Gaussian(double mean, double standard_deviation) {
|
||||
// Creating a Normal distribution variable from two independent uniform
|
||||
// variables based on the Box-Muller transform, which is defined on the
|
||||
// interval (0, 1]. Note that we rely on NextOutput to generate integers
|
||||
// in the range [1, 2^64-1]. Normally this behavior is a bit frustrating,
|
||||
// but here it is exactly what we need.
|
||||
const double kPi = 3.14159265358979323846;
|
||||
double u1 = static_cast<double>(NextOutput()) / 0xFFFFFFFFFFFFFFFFull;
|
||||
double u2 = static_cast<double>(NextOutput()) / 0xFFFFFFFFFFFFFFFFull;
|
||||
return mean + standard_deviation * sqrt(-2 * log(u1)) * cos(2 * kPi * u2);
|
||||
}
|
||||
|
||||
double Random::Exponential(double lambda) {
|
||||
double uniform = Rand<double>();
|
||||
return -log(uniform) / lambda;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -8,23 +8,23 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_RANDOM_H_
|
||||
#define WEBRTC_TEST_RANDOM_H_
|
||||
#ifndef WEBRTC_BASE_RANDOM_H_
|
||||
#define WEBRTC_BASE_RANDOM_H_
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace test {
|
||||
|
||||
class Random {
|
||||
public:
|
||||
explicit Random(uint32_t seed);
|
||||
explicit Random(uint64_t seed);
|
||||
|
||||
// Return pseudo-random integer of the specified type.
|
||||
// We need to limit the size to 32 bits to keep the output close to uniform.
|
||||
template <typename T>
|
||||
T Rand() {
|
||||
static_assert(std::numeric_limits<T>::is_integer &&
|
||||
@ -32,7 +32,7 @@ class Random {
|
||||
std::numeric_limits<T>::digits <= 32,
|
||||
"Rand is only supported for built-in integer types that are "
|
||||
"32 bits or smaller.");
|
||||
return static_cast<T>(Rand(std::numeric_limits<uint32_t>::max()));
|
||||
return static_cast<T>(NextOutput());
|
||||
}
|
||||
|
||||
// Uniformly distributed pseudo-random number in the interval [0, t].
|
||||
@ -41,18 +41,26 @@ class Random {
|
||||
// Uniformly distributed pseudo-random number in the interval [low, high].
|
||||
uint32_t Rand(uint32_t low, uint32_t high);
|
||||
|
||||
// Uniformly distributed pseudo-random number in the interval [low, high].
|
||||
int32_t Rand(int32_t low, int32_t high);
|
||||
|
||||
// Normal Distribution.
|
||||
int Gaussian(int mean, int standard_deviation);
|
||||
double Gaussian(double mean, double standard_deviation);
|
||||
|
||||
// Exponential Distribution.
|
||||
int Exponential(float lambda);
|
||||
|
||||
// TODO(solenberg): Random from histogram.
|
||||
// template<typename T> int Distribution(const std::vector<T> histogram) {
|
||||
double Exponential(double lambda);
|
||||
|
||||
private:
|
||||
uint32_t a_;
|
||||
uint32_t b_;
|
||||
// Outputs a nonzero 64-bit random number.
|
||||
uint64_t NextOutput() {
|
||||
state_ ^= state_ >> 12;
|
||||
state_ ^= state_ << 25;
|
||||
state_ ^= state_ >> 27;
|
||||
RTC_DCHECK(state_ != 0x0ULL);
|
||||
return state_ * 2685821657736338717ull;
|
||||
}
|
||||
|
||||
uint64_t state_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Random);
|
||||
};
|
||||
@ -61,11 +69,14 @@ class Random {
|
||||
template <>
|
||||
float Random::Rand<float>();
|
||||
|
||||
// Return pseudo-random number in the interval [0.0, 1.0).
|
||||
template <>
|
||||
double Random::Rand<double>();
|
||||
|
||||
// Return pseudo-random boolean value.
|
||||
template <>
|
||||
bool Random::Rand<bool>();
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_RANDOM_H_
|
||||
#endif // WEBRTC_BASE_RANDOM_H_
|
||||
302
webrtc/base/random_unittest.cc
Normal file
302
webrtc/base/random_unittest.cc
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 <math.h>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/base/random.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
// Computes the positive remainder of x/n.
|
||||
template <typename T>
|
||||
T fdiv_remainder(T x, T n) {
|
||||
RTC_CHECK_GE(n, static_cast<T>(0));
|
||||
T remainder = x % n;
|
||||
if (remainder < 0)
|
||||
remainder += n;
|
||||
return remainder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Sample a number of random integers of type T. Divide them into buckets
|
||||
// based on the remainder when dividing by bucket_count and check that each
|
||||
// bucket gets roughly the expected number of elements.
|
||||
template <typename T>
|
||||
void UniformBucketTest(T bucket_count, int samples, Random* prng) {
|
||||
std::vector<int> buckets(bucket_count, 0);
|
||||
|
||||
uint64_t total_values = 1ull << (std::numeric_limits<T>::digits +
|
||||
std::numeric_limits<T>::is_signed);
|
||||
T upper_limit =
|
||||
std::numeric_limits<T>::max() -
|
||||
static_cast<T>(total_values % static_cast<uint64_t>(bucket_count));
|
||||
ASSERT_GT(upper_limit, std::numeric_limits<T>::max() / 2);
|
||||
|
||||
for (int i = 0; i < samples; i++) {
|
||||
T sample;
|
||||
do {
|
||||
// We exclude a few numbers from the range so that it is divisible by
|
||||
// the number of buckets. If we are unlucky and hit one of the excluded
|
||||
// numbers we just resample. Note that if the number of buckets is a
|
||||
// power of 2, then we don't have to exclude anything.
|
||||
sample = prng->Rand<T>();
|
||||
} while (sample > upper_limit);
|
||||
buckets[fdiv_remainder(sample, bucket_count)]++;
|
||||
}
|
||||
|
||||
for (T i = 0; i < bucket_count; i++) {
|
||||
// Expect the result to be within 3 standard deviations of the mean.
|
||||
EXPECT_NEAR(buckets[i], samples / bucket_count,
|
||||
3 * sqrt(samples / bucket_count));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, BucketTestSignedChar) {
|
||||
Random prng(7297352569824ull);
|
||||
UniformBucketTest<signed char>(64, 640000, &prng);
|
||||
UniformBucketTest<signed char>(11, 440000, &prng);
|
||||
UniformBucketTest<signed char>(3, 270000, &prng);
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, BucketTestUnsignedChar) {
|
||||
Random prng(7297352569824ull);
|
||||
UniformBucketTest<unsigned char>(64, 640000, &prng);
|
||||
UniformBucketTest<unsigned char>(11, 440000, &prng);
|
||||
UniformBucketTest<unsigned char>(3, 270000, &prng);
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, BucketTestSignedShort) {
|
||||
Random prng(7297352569824ull);
|
||||
UniformBucketTest<int16_t>(64, 640000, &prng);
|
||||
UniformBucketTest<int16_t>(11, 440000, &prng);
|
||||
UniformBucketTest<int16_t>(3, 270000, &prng);
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, BucketTestUnsignedShort) {
|
||||
Random prng(7297352569824ull);
|
||||
UniformBucketTest<uint16_t>(64, 640000, &prng);
|
||||
UniformBucketTest<uint16_t>(11, 440000, &prng);
|
||||
UniformBucketTest<uint16_t>(3, 270000, &prng);
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, BucketTestSignedInt) {
|
||||
Random prng(7297352569824ull);
|
||||
UniformBucketTest<signed int>(64, 640000, &prng);
|
||||
UniformBucketTest<signed int>(11, 440000, &prng);
|
||||
UniformBucketTest<signed int>(3, 270000, &prng);
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, BucketTestUnsignedInt) {
|
||||
Random prng(7297352569824ull);
|
||||
UniformBucketTest<unsigned int>(64, 640000, &prng);
|
||||
UniformBucketTest<unsigned int>(11, 440000, &prng);
|
||||
UniformBucketTest<unsigned int>(3, 270000, &prng);
|
||||
}
|
||||
|
||||
// The range of the random numbers is divided into bucket_count intervals
|
||||
// of consecutive numbers. Check that approximately equally many numbers
|
||||
// from each inteval are generated.
|
||||
void BucketTestSignedInterval(unsigned int bucket_count,
|
||||
unsigned int samples,
|
||||
int32_t low,
|
||||
int32_t high,
|
||||
int sigma_level,
|
||||
Random* prng) {
|
||||
std::vector<unsigned int> buckets(bucket_count, 0);
|
||||
|
||||
ASSERT_GE(high, low);
|
||||
ASSERT_GE(bucket_count, 2u);
|
||||
uint32_t interval = static_cast<uint32_t>(high - low + 1);
|
||||
uint32_t numbers_per_bucket;
|
||||
if (interval == 0) {
|
||||
// The computation high - low + 1 should be 2^32 but overflowed
|
||||
// Hence, bucket_count must be a power of 2
|
||||
ASSERT_EQ(bucket_count & (bucket_count - 1), 0u);
|
||||
numbers_per_bucket = (0x80000000u / bucket_count) * 2;
|
||||
} else {
|
||||
ASSERT_EQ(interval % bucket_count, 0u);
|
||||
numbers_per_bucket = interval / bucket_count;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < samples; i++) {
|
||||
int32_t sample = prng->Rand(low, high);
|
||||
EXPECT_LE(low, sample);
|
||||
EXPECT_GE(high, sample);
|
||||
buckets[static_cast<uint32_t>(sample - low) / numbers_per_bucket]++;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bucket_count; i++) {
|
||||
// Expect the result to be within 3 standard deviations of the mean,
|
||||
// or more generally, within sigma_level standard deviations of the mean.
|
||||
double mean = static_cast<double>(samples) / bucket_count;
|
||||
EXPECT_NEAR(buckets[i], mean, sigma_level * sqrt(mean));
|
||||
}
|
||||
}
|
||||
|
||||
// The range of the random numbers is divided into bucket_count intervals
|
||||
// of consecutive numbers. Check that approximately equally many numbers
|
||||
// from each inteval are generated.
|
||||
void BucketTestUnsignedInterval(unsigned int bucket_count,
|
||||
unsigned int samples,
|
||||
uint32_t low,
|
||||
uint32_t high,
|
||||
int sigma_level,
|
||||
Random* prng) {
|
||||
std::vector<unsigned int> buckets(bucket_count, 0);
|
||||
|
||||
ASSERT_GE(high, low);
|
||||
ASSERT_GE(bucket_count, 2u);
|
||||
uint32_t interval = static_cast<uint32_t>(high - low + 1);
|
||||
uint32_t numbers_per_bucket;
|
||||
if (interval == 0) {
|
||||
// The computation high - low + 1 should be 2^32 but overflowed
|
||||
// Hence, bucket_count must be a power of 2
|
||||
ASSERT_EQ(bucket_count & (bucket_count - 1), 0u);
|
||||
numbers_per_bucket = (0x80000000u / bucket_count) * 2;
|
||||
} else {
|
||||
ASSERT_EQ(interval % bucket_count, 0u);
|
||||
numbers_per_bucket = interval / bucket_count;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < samples; i++) {
|
||||
uint32_t sample = prng->Rand(low, high);
|
||||
EXPECT_LE(low, sample);
|
||||
EXPECT_GE(high, sample);
|
||||
buckets[static_cast<uint32_t>(sample - low) / numbers_per_bucket]++;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bucket_count; i++) {
|
||||
// Expect the result to be within 3 standard deviations of the mean,
|
||||
// or more generally, within sigma_level standard deviations of the mean.
|
||||
double mean = static_cast<double>(samples) / bucket_count;
|
||||
EXPECT_NEAR(buckets[i], mean, sigma_level * sqrt(mean));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, UniformUnsignedInterval) {
|
||||
Random prng(299792458ull);
|
||||
BucketTestUnsignedInterval(2, 100000, 0, 1, 3, &prng);
|
||||
BucketTestUnsignedInterval(7, 100000, 1, 14, 3, &prng);
|
||||
BucketTestUnsignedInterval(11, 100000, 1000, 1010, 3, &prng);
|
||||
BucketTestUnsignedInterval(100, 100000, 0, 99, 3, &prng);
|
||||
BucketTestUnsignedInterval(2, 100000, 0, 4294967295, 3, &prng);
|
||||
BucketTestUnsignedInterval(17, 100000, 455, 2147484110, 3, &prng);
|
||||
// 99.7% of all samples will be within 3 standard deviations of the mean,
|
||||
// but since we test 1000 buckets we allow an interval of 4 sigma.
|
||||
BucketTestUnsignedInterval(1000, 1000000, 0, 2147483999, 4, &prng);
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, UniformSignedInterval) {
|
||||
Random prng(66260695729ull);
|
||||
BucketTestSignedInterval(2, 100000, 0, 1, 3, &prng);
|
||||
BucketTestSignedInterval(7, 100000, -2, 4, 3, &prng);
|
||||
BucketTestSignedInterval(11, 100000, 1000, 1010, 3, &prng);
|
||||
BucketTestSignedInterval(100, 100000, 0, 99, 3, &prng);
|
||||
BucketTestSignedInterval(2, 100000, std::numeric_limits<int32_t>::min(),
|
||||
std::numeric_limits<int32_t>::max(), 3, &prng);
|
||||
BucketTestSignedInterval(17, 100000, -1073741826, 1073741829, 3, &prng);
|
||||
// 99.7% of all samples will be within 3 standard deviations of the mean,
|
||||
// but since we test 1000 buckets we allow an interval of 4 sigma.
|
||||
BucketTestSignedInterval(1000, 1000000, -352, 2147483647, 4, &prng);
|
||||
}
|
||||
|
||||
// The range of the random numbers is divided into bucket_count intervals
|
||||
// of consecutive numbers. Check that approximately equally many numbers
|
||||
// from each inteval are generated.
|
||||
void BucketTestFloat(unsigned int bucket_count,
|
||||
unsigned int samples,
|
||||
int sigma_level,
|
||||
Random* prng) {
|
||||
ASSERT_GE(bucket_count, 2u);
|
||||
std::vector<unsigned int> buckets(bucket_count, 0);
|
||||
|
||||
for (unsigned int i = 0; i < samples; i++) {
|
||||
uint32_t sample = bucket_count * prng->Rand<float>();
|
||||
EXPECT_LE(0u, sample);
|
||||
EXPECT_GE(bucket_count - 1, sample);
|
||||
buckets[sample]++;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bucket_count; i++) {
|
||||
// Expect the result to be within 3 standard deviations of the mean,
|
||||
// or more generally, within sigma_level standard deviations of the mean.
|
||||
double mean = static_cast<double>(samples) / bucket_count;
|
||||
EXPECT_NEAR(buckets[i], mean, sigma_level * sqrt(mean));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, UniformFloatInterval) {
|
||||
Random prng(1380648813ull);
|
||||
BucketTestFloat(100, 100000, 3, &prng);
|
||||
// 99.7% of all samples will be within 3 standard deviations of the mean,
|
||||
// but since we test 1000 buckets we allow an interval of 4 sigma.
|
||||
// BucketTestSignedInterval(1000, 1000000, -352, 2147483647, 4, &prng);
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, SignedHasSameBitPattern) {
|
||||
Random prng_signed(66738480ull), prng_unsigned(66738480ull);
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
signed int s = prng_signed.Rand<signed int>();
|
||||
unsigned int u = prng_unsigned.Rand<unsigned int>();
|
||||
EXPECT_EQ(u, static_cast<unsigned int>(s));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
int16_t s = prng_signed.Rand<int16_t>();
|
||||
uint16_t u = prng_unsigned.Rand<uint16_t>();
|
||||
EXPECT_EQ(u, static_cast<uint16_t>(s));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
signed char s = prng_signed.Rand<signed char>();
|
||||
unsigned char u = prng_unsigned.Rand<unsigned char>();
|
||||
EXPECT_EQ(u, static_cast<unsigned char>(s));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RandomNumberGeneratorTest, Gaussian) {
|
||||
const int kN = 100000;
|
||||
const int kBuckets = 100;
|
||||
const double kMean = 49;
|
||||
const double kStddev = 10;
|
||||
|
||||
Random prng(1256637061);
|
||||
|
||||
std::vector<unsigned int> buckets(kBuckets, 0);
|
||||
for (int i = 0; i < kN; i++) {
|
||||
int index = prng.Gaussian(kMean, kStddev) + 0.5;
|
||||
if (index >= 0 && index < kBuckets) {
|
||||
buckets[index]++;
|
||||
}
|
||||
}
|
||||
|
||||
const double kPi = 3.14159265358979323846;
|
||||
const double kScale = 1 / (kStddev * sqrt(2.0 * kPi));
|
||||
const double kDiv = -2.0 * kStddev * kStddev;
|
||||
for (int n = 0; n < kBuckets; ++n) {
|
||||
// Use Simpsons rule to estimate the probability that a random gaussian
|
||||
// sample is in the interval [n-0.5, n+0.5].
|
||||
double f_left = kScale * exp((n - kMean - 0.5) * (n - kMean - 0.5) / kDiv);
|
||||
double f_mid = kScale * exp((n - kMean) * (n - kMean) / kDiv);
|
||||
double f_right = kScale * exp((n - kMean + 0.5) * (n - kMean + 0.5) / kDiv);
|
||||
double normal_dist = (f_left + 4 * f_mid + f_right) / 6;
|
||||
// Expect the number of samples to be within 3 standard deviations
|
||||
// (rounded up) of the expected number of samples in the bucket.
|
||||
EXPECT_NEAR(buckets[n], kN * normal_dist, 3 * sqrt(kN * normal_dist) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -17,6 +17,7 @@
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/base/buffer.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/random.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
#include "webrtc/call.h"
|
||||
@ -24,7 +25,6 @@
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
#include "webrtc/test/random.h"
|
||||
#include "webrtc/test/test_suite.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
#include "webrtc/test/testsupport/gtest_disable.h"
|
||||
@ -301,7 +301,7 @@ size_t GenerateRtpPacket(uint32_t extensions_bitvector,
|
||||
uint32_t csrcs_count,
|
||||
uint8_t* packet,
|
||||
size_t packet_size,
|
||||
test::Random* prng) {
|
||||
Random* prng) {
|
||||
RTC_CHECK_GE(packet_size, 16 + 4 * csrcs_count + 4 * kNumExtensions);
|
||||
Clock* clock = Clock::GetRealTimeClock();
|
||||
|
||||
@ -349,7 +349,7 @@ size_t GenerateRtpPacket(uint32_t extensions_bitvector,
|
||||
return header_size;
|
||||
}
|
||||
|
||||
rtc::scoped_ptr<rtcp::RawPacket> GenerateRtcpPacket(test::Random* prng) {
|
||||
rtc::scoped_ptr<rtcp::RawPacket> GenerateRtcpPacket(Random* prng) {
|
||||
rtcp::ReportBlock report_block;
|
||||
report_block.To(prng->Rand<uint32_t>()); // Remote SSRC.
|
||||
report_block.WithFractionLost(prng->Rand(50));
|
||||
@ -366,7 +366,7 @@ rtc::scoped_ptr<rtcp::RawPacket> GenerateRtcpPacket(test::Random* prng) {
|
||||
|
||||
void GenerateVideoReceiveConfig(uint32_t extensions_bitvector,
|
||||
VideoReceiveStream::Config* config,
|
||||
test::Random* prng) {
|
||||
Random* prng) {
|
||||
// Create a map from a payload type to an encoder name.
|
||||
VideoReceiveStream::Decoder decoder;
|
||||
decoder.payload_type = prng->Rand(0, 127);
|
||||
@ -395,7 +395,7 @@ void GenerateVideoReceiveConfig(uint32_t extensions_bitvector,
|
||||
|
||||
void GenerateVideoSendConfig(uint32_t extensions_bitvector,
|
||||
VideoSendStream::Config* config,
|
||||
test::Random* prng) {
|
||||
Random* prng) {
|
||||
// Create a map from a payload type to an encoder name.
|
||||
config->encoder_settings.payload_type = prng->Rand(0, 127);
|
||||
config->encoder_settings.payload_name = (prng->Rand<bool>() ? "VP8" : "H264");
|
||||
@ -434,7 +434,7 @@ void LogSessionAndReadBack(size_t rtp_count,
|
||||
VideoReceiveStream::Config receiver_config(nullptr);
|
||||
VideoSendStream::Config sender_config(nullptr);
|
||||
|
||||
test::Random prng(random_seed);
|
||||
Random prng(random_seed);
|
||||
|
||||
// Create rtp_count RTP packets containing random data.
|
||||
for (size_t i = 0; i < rtp_count; i++) {
|
||||
@ -591,7 +591,7 @@ TEST(RtcEventLogTest, LogSessionAndReadBack) {
|
||||
1 + csrcs_count, // Number of BWE loss events.
|
||||
extensions, // Bit vector choosing extensions.
|
||||
csrcs_count, // Number of contributing sources.
|
||||
extensions + csrcs_count); // Random seed.
|
||||
extensions * 3 + csrcs_count + 1); // Random seed.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -609,7 +609,7 @@ void DropOldEvents(uint32_t extensions_bitvector,
|
||||
VideoReceiveStream::Config receiver_config(nullptr);
|
||||
VideoSendStream::Config sender_config(nullptr);
|
||||
|
||||
test::Random prng(random_seed);
|
||||
Random prng(random_seed);
|
||||
|
||||
// Create two RTP packets containing random data.
|
||||
size_t packet_size = prng.Rand(1000, 1100);
|
||||
|
||||
@ -18,11 +18,11 @@
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/event.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
#include "webrtc/base/random.h"
|
||||
#include "webrtc/config.h"
|
||||
#include "webrtc/modules/audio_processing/test/test_utils.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/system_wrappers/include/sleep.h"
|
||||
#include "webrtc/test/random.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -84,7 +84,7 @@ class RandomGenerator {
|
||||
|
||||
private:
|
||||
rtc::CriticalSection crit_;
|
||||
test::Random rand_gen_ GUARDED_BY(crit_);
|
||||
Random rand_gen_ GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
// Variables related to the audio data and formats.
|
||||
|
||||
@ -36,7 +36,7 @@ class BweSimulation : public BweTest,
|
||||
VerboseLogging(true);
|
||||
}
|
||||
|
||||
test::Random random_;
|
||||
Random random_;
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(BweSimulation);
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "webrtc/base/random.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/inter_arrival.h"
|
||||
@ -21,7 +22,6 @@
|
||||
#include "webrtc/modules/remote_bitrate_estimator/overuse_estimator.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
|
||||
#include "webrtc/test/field_trial.h"
|
||||
#include "webrtc/test/random.h"
|
||||
#include "webrtc/test/testsupport/gtest_disable.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -38,7 +38,7 @@ class OveruseDetectorTest : public ::testing::Test {
|
||||
overuse_detector_(),
|
||||
overuse_estimator_(new OveruseEstimator(options_)),
|
||||
inter_arrival_(new InterArrival(5 * 90, kRtpTimestampToMs, true)),
|
||||
random_(1234) {}
|
||||
random_(123456789) {}
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
@ -55,9 +55,10 @@ class OveruseDetectorTest : public ::testing::Test {
|
||||
}
|
||||
rtp_timestamp_ += mean_ms * 90;
|
||||
now_ms_ += mean_ms;
|
||||
receive_time_ms_ =
|
||||
std::max(receive_time_ms_,
|
||||
now_ms_ + random_.Gaussian(0, standard_deviation_ms));
|
||||
receive_time_ms_ = std::max<int64_t>(
|
||||
receive_time_ms_,
|
||||
now_ms_ + static_cast<int64_t>(
|
||||
random_.Gaussian(0, standard_deviation_ms) + 0.5));
|
||||
if (kBwOverusing == overuse_detector_->State()) {
|
||||
if (last_overuse + 1 != i) {
|
||||
unique_overuse++;
|
||||
@ -77,9 +78,10 @@ class OveruseDetectorTest : public ::testing::Test {
|
||||
}
|
||||
rtp_timestamp_ += mean_ms * 90;
|
||||
now_ms_ += mean_ms + drift_per_frame_ms;
|
||||
receive_time_ms_ =
|
||||
std::max(receive_time_ms_,
|
||||
now_ms_ + random_.Gaussian(0, standard_deviation_ms));
|
||||
receive_time_ms_ = std::max<int64_t>(
|
||||
receive_time_ms_,
|
||||
now_ms_ + static_cast<int64_t>(
|
||||
random_.Gaussian(0, standard_deviation_ms) + 0.5));
|
||||
if (kBwOverusing == overuse_detector_->State()) {
|
||||
return i + 1;
|
||||
}
|
||||
@ -114,7 +116,7 @@ class OveruseDetectorTest : public ::testing::Test {
|
||||
rtc::scoped_ptr<OveruseDetector> overuse_detector_;
|
||||
rtc::scoped_ptr<OveruseEstimator> overuse_estimator_;
|
||||
rtc::scoped_ptr<InterArrival> inter_arrival_;
|
||||
test::Random random_;
|
||||
Random random_;
|
||||
};
|
||||
|
||||
TEST_F(OveruseDetectorTest, GaussianRandom) {
|
||||
@ -222,7 +224,7 @@ TEST_F(OveruseDetectorTest, DISABLED_OveruseWithHighVariance100Kbit10fps) {
|
||||
UpdateDetector(rtp_timestamp, now_ms_, packet_size);
|
||||
rtp_timestamp += frame_duration_ms * 90;
|
||||
if (i % 2) {
|
||||
offset = rand() % 50;
|
||||
offset = random_.Rand(0, 49);
|
||||
now_ms_ += frame_duration_ms - offset;
|
||||
} else {
|
||||
now_ms_ += frame_duration_ms + offset;
|
||||
@ -254,7 +256,7 @@ TEST_F(OveruseDetectorTest, DISABLED_OveruseWithLowVariance100Kbit10fps) {
|
||||
UpdateDetector(rtp_timestamp, now_ms_, packet_size);
|
||||
rtp_timestamp += frame_duration_ms * 90;
|
||||
if (i % 2) {
|
||||
offset = rand() % 2;
|
||||
offset = random_.Rand(0, 1);
|
||||
now_ms_ += frame_duration_ms - offset;
|
||||
} else {
|
||||
now_ms_ += frame_duration_ms + offset;
|
||||
@ -290,7 +292,7 @@ TEST_F(OveruseDetectorTest, OveruseWithLowVariance2000Kbit30fps) {
|
||||
UpdateDetector(rtp_timestamp, now_ms_, packet_size);
|
||||
rtp_timestamp += frame_duration_ms * 90;
|
||||
if (i % 2) {
|
||||
offset = rand() % 2;
|
||||
offset = random_.Rand(0, 1);
|
||||
now_ms_ += frame_duration_ms - offset;
|
||||
} else {
|
||||
now_ms_ += frame_duration_ms + offset;
|
||||
@ -323,10 +325,10 @@ TEST_F(OveruseDetectorTest,
|
||||
int sigma_ms = 3;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(13, unique_overuse);
|
||||
EXPECT_EQ(1, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(13, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift30Kbit3fps) {
|
||||
@ -337,7 +339,7 @@ TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift30Kbit3fps) {
|
||||
int sigma_ms = 3;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(13, unique_overuse);
|
||||
EXPECT_EQ(1, 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);
|
||||
@ -351,10 +353,10 @@ TEST_F(OveruseDetectorTest, HighGaussianVariance30Kbit3fps) {
|
||||
int sigma_ms = 10;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(46, unique_overuse);
|
||||
EXPECT_EQ(1, 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);
|
||||
EXPECT_EQ(32, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift30Kbit3fps) {
|
||||
@ -365,7 +367,7 @@ TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift30Kbit3fps) {
|
||||
int sigma_ms = 10;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(46, unique_overuse);
|
||||
EXPECT_EQ(1, 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);
|
||||
@ -380,10 +382,10 @@ TEST_F(OveruseDetectorTest,
|
||||
int sigma_ms = 3;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(12, unique_overuse);
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(13, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest,
|
||||
@ -395,10 +397,10 @@ TEST_F(OveruseDetectorTest,
|
||||
int sigma_ms = 10;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(16, unique_overuse);
|
||||
EXPECT_EQ(1, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(32, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest,
|
||||
@ -410,10 +412,10 @@ TEST_F(OveruseDetectorTest,
|
||||
int sigma_ms = 3;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(12, unique_overuse);
|
||||
EXPECT_EQ(1, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(13, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest,
|
||||
@ -425,10 +427,10 @@ TEST_F(OveruseDetectorTest,
|
||||
int sigma_ms = 10;
|
||||
int unique_overuse = Run100000Samples(packets_per_frame, packet_size,
|
||||
frame_duration_ms, sigma_ms);
|
||||
EXPECT_EQ(12, unique_overuse);
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(32, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest,
|
||||
@ -443,7 +445,7 @@ TEST_F(OveruseDetectorTest,
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(15, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift300Kbit30fps) {
|
||||
@ -471,7 +473,7 @@ TEST_F(OveruseDetectorTest, HighGaussianVariance300Kbit30fps) {
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(41, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift300Kbit30fps) {
|
||||
@ -485,7 +487,7 @@ TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift300Kbit30fps) {
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(10, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest,
|
||||
@ -500,7 +502,7 @@ TEST_F(OveruseDetectorTest,
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(15, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift1000Kbit30fps) {
|
||||
@ -528,7 +530,7 @@ TEST_F(OveruseDetectorTest, HighGaussianVariance1000Kbit30fps) {
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(41, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift1000Kbit30fps) {
|
||||
@ -542,7 +544,7 @@ TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift1000Kbit30fps) {
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(10, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest,
|
||||
@ -557,7 +559,7 @@ TEST_F(OveruseDetectorTest,
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(15, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, LowGaussianVarianceFastDrift2000Kbit30fps) {
|
||||
@ -585,7 +587,7 @@ TEST_F(OveruseDetectorTest, HighGaussianVariance2000Kbit30fps) {
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(41, frames_until_overuse);
|
||||
}
|
||||
|
||||
TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift2000Kbit30fps) {
|
||||
@ -599,7 +601,7 @@ TEST_F(OveruseDetectorTest, HighGaussianVarianceFastDrift2000Kbit30fps) {
|
||||
EXPECT_EQ(0, unique_overuse);
|
||||
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);
|
||||
EXPECT_EQ(10, frames_until_overuse);
|
||||
}
|
||||
|
||||
class OveruseDetectorExperimentTest : public OveruseDetectorTest {
|
||||
|
||||
@ -948,7 +948,7 @@ std::vector<int> BweTest::GetFileSizesBytes(int num_files) {
|
||||
const int kMinKbytes = 100;
|
||||
const int kMaxKbytes = 1000;
|
||||
|
||||
test::Random random(0x12345678);
|
||||
Random random(0x12345678);
|
||||
std::vector<int> tcp_file_sizes_bytes;
|
||||
|
||||
while (num_files-- > 0) {
|
||||
@ -961,7 +961,7 @@ std::vector<int> BweTest::GetFileSizesBytes(int num_files) {
|
||||
std::vector<int64_t> BweTest::GetStartingTimesMs(int num_files) {
|
||||
// OFF state behaves as an exp. distribution with mean = 10 seconds.
|
||||
const float kMeanMs = 10000.0f;
|
||||
test::Random random(0x12345678);
|
||||
Random random(0x12345678);
|
||||
|
||||
std::vector<int64_t> tcp_starting_times_ms;
|
||||
|
||||
|
||||
@ -391,7 +391,7 @@ void JitterFilter::SetMaxJitter(int64_t max_jitter_ms) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
inline int64_t TruncatedNSigmaGaussian(test::Random* const random,
|
||||
inline int64_t TruncatedNSigmaGaussian(Random* const random,
|
||||
int64_t mean,
|
||||
int64_t std_dev) {
|
||||
int64_t gaussian_random = random->Gaussian(mean, std_dev);
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/common.h"
|
||||
#include "webrtc/base/random.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
@ -31,7 +32,6 @@
|
||||
#include "webrtc/modules/remote_bitrate_estimator/test/packet.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
#include "webrtc/test/random.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -265,7 +265,7 @@ class LossFilter : public PacketProcessor {
|
||||
virtual void RunFor(int64_t time_ms, Packets* in_out);
|
||||
|
||||
private:
|
||||
test::Random random_;
|
||||
Random random_;
|
||||
float loss_fraction_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(LossFilter);
|
||||
@ -299,7 +299,7 @@ class JitterFilter : public PacketProcessor {
|
||||
int64_t MeanUs();
|
||||
|
||||
private:
|
||||
test::Random random_;
|
||||
Random random_;
|
||||
int64_t stddev_jitter_us_;
|
||||
int64_t last_send_time_us_;
|
||||
bool reordering_; // False by default.
|
||||
@ -318,7 +318,7 @@ class ReorderFilter : public PacketProcessor {
|
||||
virtual void RunFor(int64_t time_ms, Packets* in_out);
|
||||
|
||||
private:
|
||||
test::Random random_;
|
||||
Random random_;
|
||||
float reorder_fraction_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ReorderFilter);
|
||||
|
||||
@ -22,39 +22,6 @@ namespace webrtc {
|
||||
namespace testing {
|
||||
namespace bwe {
|
||||
|
||||
TEST(BweTestFramework_RandomTest, Gaussian) {
|
||||
enum {
|
||||
kN = 100000,
|
||||
kBuckets = 100,
|
||||
kMean = 49,
|
||||
kStddev = 10
|
||||
};
|
||||
|
||||
test::Random random(0x12345678);
|
||||
|
||||
int buckets[kBuckets] = {0};
|
||||
for (int i = 0; i < kN; ++i) {
|
||||
int index = random.Gaussian(kMean, kStddev);
|
||||
if (index >= 0 && index < kBuckets) {
|
||||
buckets[index]++;
|
||||
}
|
||||
}
|
||||
|
||||
const double kPi = 3.14159265358979323846;
|
||||
const double kScale = kN / (kStddev * sqrt(2.0 * kPi));
|
||||
const double kDiv = -2.0 * kStddev * kStddev;
|
||||
double self_corr = 0.0;
|
||||
double bucket_corr = 0.0;
|
||||
for (int n = 0; n < kBuckets; ++n) {
|
||||
double normal_dist = kScale * exp((n - kMean) * (n - kMean) / kDiv);
|
||||
self_corr += normal_dist * normal_dist;
|
||||
bucket_corr += normal_dist * buckets[n];
|
||||
}
|
||||
printf("Correlation: %f (random sample), %f (self), %f (quotient)\n",
|
||||
bucket_corr, self_corr, bucket_corr / self_corr);
|
||||
EXPECT_NEAR(1.0, bucket_corr / self_corr, 0.0004);
|
||||
}
|
||||
|
||||
static bool IsSequenceNumberSorted(const Packets& packets) {
|
||||
PacketsConstIt last_it = packets.begin();
|
||||
for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
|
||||
@ -533,7 +500,7 @@ TEST(BweTestFramework_JitterFilterTest, Jitter1031) {
|
||||
TestJitterFilter(1031);
|
||||
}
|
||||
|
||||
static void TestReorderFilter(uint16_t reorder_percent, uint16_t near_value) {
|
||||
static void TestReorderFilter(uint16_t reorder_percent) {
|
||||
const uint16_t kPacketCount = 10000;
|
||||
|
||||
// Generate packets with 10 ms interval.
|
||||
@ -559,16 +526,23 @@ static void TestReorderFilter(uint16_t reorder_percent, uint16_t near_value) {
|
||||
for (auto* packet : packets) {
|
||||
const MediaPacket* media_packet = static_cast<const MediaPacket*>(packet);
|
||||
uint16_t sequence_number = media_packet->header().sequenceNumber;
|
||||
// The expected position for sequence number s is in position s-1.
|
||||
if (sequence_number < last_sequence_number) {
|
||||
distance += last_sequence_number - sequence_number;
|
||||
}
|
||||
last_sequence_number = sequence_number;
|
||||
}
|
||||
|
||||
// Because reordering is random, we allow a threshold when comparing. The
|
||||
// maximum distance a packet can be moved is PacketCount - 1.
|
||||
EXPECT_NEAR(
|
||||
((kPacketCount - 1) * reorder_percent) / 100, distance, near_value);
|
||||
// The probability that two elements are swapped is p = reorder_percent / 100.
|
||||
double p = static_cast<double>(reorder_percent) / 100;
|
||||
// The expected number of swaps we perform is p * (PacketCount - 1),
|
||||
// and each swap increases the distance by one.
|
||||
double mean = p * (kPacketCount - 1);
|
||||
// If pair i is chosen to be swapped with probability p, the variance for that
|
||||
// pair is p * (1 - p). Since there are (kPacketCount - 1) independent pairs,
|
||||
// the variance for the number of swaps is (kPacketCount - 1) * p * (1 - p).
|
||||
double std_deviation = sqrt((kPacketCount - 1) * p * (1 - p));
|
||||
EXPECT_NEAR(mean, distance, 3 * std_deviation);
|
||||
|
||||
for (auto* packet : packets)
|
||||
delete packet;
|
||||
@ -576,23 +550,23 @@ static void TestReorderFilter(uint16_t reorder_percent, uint16_t near_value) {
|
||||
|
||||
TEST(BweTestFramework_ReorderFilterTest, Reorder0) {
|
||||
// For 0% reordering, no packets should have been moved, so result is exact.
|
||||
TestReorderFilter(0, 0);
|
||||
TestReorderFilter(0);
|
||||
}
|
||||
|
||||
TEST(BweTestFramework_ReorderFilterTest, Reorder10) {
|
||||
TestReorderFilter(10, 30);
|
||||
TestReorderFilter(10);
|
||||
}
|
||||
|
||||
TEST(BweTestFramework_ReorderFilterTest, Reorder20) {
|
||||
TestReorderFilter(20, 20);
|
||||
TestReorderFilter(20);
|
||||
}
|
||||
|
||||
TEST(BweTestFramework_ReorderFilterTest, Reorder50) {
|
||||
TestReorderFilter(50, 20);
|
||||
TestReorderFilter(50);
|
||||
}
|
||||
|
||||
TEST(BweTestFramework_ReorderFilterTest, Reorder70) {
|
||||
TestReorderFilter(70, 20);
|
||||
TestReorderFilter(70);
|
||||
}
|
||||
|
||||
TEST(BweTestFramework_ReorderFilterTest, Reorder100) {
|
||||
@ -600,7 +574,7 @@ TEST(BweTestFramework_ReorderFilterTest, Reorder100) {
|
||||
// adjacent packets, when the likelihood of a swap is 1.0, a swap will always
|
||||
// occur, so the stream will be in order except for the first packet, which
|
||||
// has been moved to the end. Therefore we expect the result to be exact here.
|
||||
TestReorderFilter(100.0, 0);
|
||||
TestReorderFilter(100.0);
|
||||
}
|
||||
|
||||
class BweTestFramework_ChokeFilterTest : public ::testing::Test {
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
#include <limits>
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/test/random.h"
|
||||
#include "webrtc/base/random.h"
|
||||
|
||||
using webrtc::rtcp::ReportBlock;
|
||||
|
||||
@ -42,7 +42,7 @@ TEST(RtcpPacketReportBlockTest, ParseChecksLength) {
|
||||
TEST(RtcpPacketReportBlockTest, ParseAnyData) {
|
||||
uint8_t buffer[kBufferLength];
|
||||
// Fill buffer with semi-random data.
|
||||
test::Random generator(testing::FLAGS_gtest_random_seed);
|
||||
Random generator(0x256F8A285EC829ull);
|
||||
for (size_t i = 0; i < kBufferLength; ++i)
|
||||
buffer[i] = static_cast<uint8_t>(generator.Rand(0, 0xff));
|
||||
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 "webrtc/test/random.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace test {
|
||||
|
||||
Random::Random(uint32_t seed) : a_(0x531FDB97 ^ seed), b_(0x6420ECA8 + seed) {
|
||||
}
|
||||
|
||||
uint32_t Random::Rand(uint32_t t) {
|
||||
// If b / 2^32 is uniform on [0,1), then b / 2^32 * (t+1) is uniform on
|
||||
// the interval [0,t+1), so the integer part is uniform on [0,t].
|
||||
uint64_t result = b_ * (static_cast<uint64_t>(t) + 1);
|
||||
result >>= 32;
|
||||
a_ ^= b_;
|
||||
b_ += a_;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t Random::Rand(uint32_t low, uint32_t high) {
|
||||
RTC_DCHECK(low <= high);
|
||||
return Rand(high - low) + low;
|
||||
}
|
||||
|
||||
template <>
|
||||
float Random::Rand<float>() {
|
||||
const double kScale = 1.0f / (static_cast<uint64_t>(1) << 32);
|
||||
double result = kScale * b_;
|
||||
a_ ^= b_;
|
||||
b_ += a_;
|
||||
return static_cast<float>(result);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Random::Rand<bool>() {
|
||||
return Rand(0, 1) == 1;
|
||||
}
|
||||
|
||||
int Random::Gaussian(int mean, int standard_deviation) {
|
||||
// Creating a Normal distribution variable from two independent uniform
|
||||
// variables based on the Box-Muller transform, which is defined on the
|
||||
// interval (0, 1], hence the mask+add below.
|
||||
const double kPi = 3.14159265358979323846;
|
||||
const double kScale = 1.0 / 0x80000000ul;
|
||||
double u1 = kScale * ((a_ & 0x7ffffffful) + 1);
|
||||
double u2 = kScale * ((b_ & 0x7ffffffful) + 1);
|
||||
a_ ^= b_;
|
||||
b_ += a_;
|
||||
return static_cast<int>(
|
||||
mean + standard_deviation * sqrt(-2 * log(u1)) * cos(2 * kPi * u2));
|
||||
}
|
||||
|
||||
int Random::Exponential(float lambda) {
|
||||
float uniform = Rand<float>();
|
||||
return static_cast<int>(-log(uniform) / lambda);
|
||||
}
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
@ -41,8 +41,6 @@
|
||||
'mock_voice_engine.h',
|
||||
'null_transport.cc',
|
||||
'null_transport.h',
|
||||
'random.cc',
|
||||
'random.h',
|
||||
'rtp_rtcp_observer.h',
|
||||
'run_loop.cc',
|
||||
'run_loop.h',
|
||||
|
||||
@ -9,11 +9,11 @@
|
||||
*/
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/base/random.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/timeutils.h"
|
||||
#include "webrtc/system_wrappers/include/sleep.h"
|
||||
#include "webrtc/test/channel_transport/channel_transport.h"
|
||||
#include "webrtc/test/random.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h"
|
||||
|
||||
@ -27,7 +27,7 @@ const webrtc::CodecInst kCodecInst = {120, "opus", 48000, 960, 2, 64000};
|
||||
|
||||
namespace voetest {
|
||||
|
||||
using webrtc::test::Random;
|
||||
using webrtc::Random;
|
||||
using webrtc::test::VoiceChannelTransport;
|
||||
|
||||
// This test allows a check on the output signal in an end-to-end call.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user