Change BitrateStats to more generalized RateStatistics
BUG=2656 R=holmer@google.com, mflodman@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/4559004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5202 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b613b5ab2b
commit
37968a9be7
@ -173,7 +173,7 @@
|
||||
'module_common_types_unittest.cc',
|
||||
'pacing/paced_sender_unittest.cc',
|
||||
'remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h',
|
||||
'remote_bitrate_estimator/bitrate_estimator_unittest.cc',
|
||||
'remote_bitrate_estimator/rate_statistics_unittest.cc',
|
||||
'remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc',
|
||||
'remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.cc',
|
||||
'remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h',
|
||||
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_BITRATE_ESTIMATOR_H_
|
||||
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_BITRATE_ESTIMATOR_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class BitRateStats {
|
||||
public:
|
||||
BitRateStats();
|
||||
~BitRateStats();
|
||||
|
||||
void Init();
|
||||
void Update(uint32_t packet_size_bytes, int64_t now_ms);
|
||||
uint32_t BitRate(int64_t now_ms);
|
||||
|
||||
private:
|
||||
void EraseOld(int64_t now_ms);
|
||||
|
||||
// Numbers of bytes are kept in buckets (circular buffer), with one bucket
|
||||
// per millisecond.
|
||||
const int num_buckets_;
|
||||
scoped_array<uint32_t> buckets_;
|
||||
|
||||
// Total number of bytes recorded in buckets.
|
||||
uint32_t accumulated_bytes_;
|
||||
|
||||
// Oldest time recorded in buckets.
|
||||
int64_t oldest_time_;
|
||||
|
||||
// Bucket index of oldest bytes recorded in buckets.
|
||||
int oldest_index_;
|
||||
|
||||
// To convert number of bytes in bits/second.
|
||||
const float bps_coefficient_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_BITRATE_ESTIMATOR_H_
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
* 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
|
||||
@ -8,26 +8,24 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/remote_bitrate_estimator/bitrate_estimator.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const int kBitrateAverageWindowMs = 500;
|
||||
|
||||
BitRateStats::BitRateStats()
|
||||
: num_buckets_(kBitrateAverageWindowMs + 1), // N ms in (N+1) buckets.
|
||||
RateStatistics::RateStatistics(uint32_t window_size_ms, float scale)
|
||||
: num_buckets_(window_size_ms + 1), // N ms in (N+1) buckets.
|
||||
buckets_(new uint32_t[num_buckets_]()),
|
||||
accumulated_bytes_(0),
|
||||
accumulated_count_(0),
|
||||
oldest_time_(0),
|
||||
oldest_index_(0),
|
||||
bps_coefficient_(8.f * 1000.f / (num_buckets_ - 1)) {
|
||||
scale_(scale / (num_buckets_ - 1)) {
|
||||
}
|
||||
|
||||
BitRateStats::~BitRateStats() {
|
||||
RateStatistics::~RateStatistics() {
|
||||
}
|
||||
|
||||
void BitRateStats::Init() {
|
||||
accumulated_bytes_ = 0;
|
||||
void RateStatistics::Reset() {
|
||||
accumulated_count_ = 0;
|
||||
oldest_time_ = 0;
|
||||
oldest_index_ = 0;
|
||||
for (int i = 0; i < num_buckets_; i++) {
|
||||
@ -35,7 +33,7 @@ void BitRateStats::Init() {
|
||||
}
|
||||
}
|
||||
|
||||
void BitRateStats::Update(uint32_t packet_size_bytes, int64_t now_ms) {
|
||||
void RateStatistics::Update(uint32_t count, int64_t now_ms) {
|
||||
if (now_ms < oldest_time_) {
|
||||
// Too old data is ignored.
|
||||
return;
|
||||
@ -49,31 +47,31 @@ void BitRateStats::Update(uint32_t packet_size_bytes, int64_t now_ms) {
|
||||
if (index >= num_buckets_) {
|
||||
index -= num_buckets_;
|
||||
}
|
||||
buckets_[index] += packet_size_bytes;
|
||||
accumulated_bytes_ += packet_size_bytes;
|
||||
buckets_[index] += count;
|
||||
accumulated_count_ += count;
|
||||
}
|
||||
|
||||
uint32_t BitRateStats::BitRate(int64_t now_ms) {
|
||||
uint32_t RateStatistics::Rate(int64_t now_ms) {
|
||||
EraseOld(now_ms);
|
||||
return static_cast<uint32_t>(accumulated_bytes_ * bps_coefficient_ + 0.5f);
|
||||
return static_cast<uint32_t>(accumulated_count_ * scale_ + 0.5f);
|
||||
}
|
||||
|
||||
void BitRateStats::EraseOld(int64_t now_ms) {
|
||||
void RateStatistics::EraseOld(int64_t now_ms) {
|
||||
int64_t new_oldest_time = now_ms - num_buckets_ + 1;
|
||||
if (new_oldest_time <= oldest_time_) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (oldest_time_ < new_oldest_time) {
|
||||
uint32_t num_bytes_in_oldest_bucket = buckets_[oldest_index_];
|
||||
assert(accumulated_bytes_ >= num_bytes_in_oldest_bucket);
|
||||
accumulated_bytes_ -= num_bytes_in_oldest_bucket;
|
||||
uint32_t count_in_oldest_bucket = buckets_[oldest_index_];
|
||||
assert(accumulated_count_ >= count_in_oldest_bucket);
|
||||
accumulated_count_ -= count_in_oldest_bucket;
|
||||
buckets_[oldest_index_] = 0;
|
||||
if (++oldest_index_ >= num_buckets_) {
|
||||
oldest_index_ = 0;
|
||||
}
|
||||
++oldest_time_;
|
||||
if (accumulated_bytes_ == 0) {
|
||||
if (accumulated_count_ == 0) {
|
||||
// This guarantees we go through all the buckets at most once, even if
|
||||
// |new_oldest_time| is far greater than |oldest_time_|.
|
||||
break;
|
||||
@ -81,4 +79,5 @@ void BitRateStats::EraseOld(int64_t now_ms) {
|
||||
}
|
||||
oldest_time_ = new_oldest_time;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
53
webrtc/modules/remote_bitrate_estimator/rate_statistics.h
Normal file
53
webrtc/modules/remote_bitrate_estimator/rate_statistics.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_RATE_STATISTICS_H_
|
||||
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_RATE_STATISTICS_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RateStatistics {
|
||||
public:
|
||||
// window_size = window size in ms for the rate estimation
|
||||
// scale = coefficient to convert counts/ms to desired units,
|
||||
// ex: if counts represents bytes, use 8*1000 to go to bits/s
|
||||
RateStatistics(uint32_t window_size_ms, float scale);
|
||||
~RateStatistics();
|
||||
|
||||
void Reset();
|
||||
void Update(uint32_t count, int64_t now_ms);
|
||||
uint32_t Rate(int64_t now_ms);
|
||||
|
||||
private:
|
||||
void EraseOld(int64_t now_ms);
|
||||
|
||||
// Counters are kept in buckets (circular buffer), with one bucket
|
||||
// per millisecond.
|
||||
const int num_buckets_;
|
||||
scoped_array<uint32_t> buckets_;
|
||||
|
||||
// Total count recorded in buckets.
|
||||
uint32_t accumulated_count_;
|
||||
|
||||
// Oldest time recorded in buckets.
|
||||
int64_t oldest_time_;
|
||||
|
||||
// Bucket index of oldest counter recorded in buckets.
|
||||
int oldest_index_;
|
||||
|
||||
// To convert counts/ms to desired units
|
||||
const float scale_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_RATE_STATISTICS_H_
|
@ -9,28 +9,28 @@
|
||||
*/
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/bitrate_estimator.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using webrtc::BitRateStats;
|
||||
using webrtc::RateStatistics;
|
||||
|
||||
class BitRateStatsTest : public ::testing::Test {
|
||||
class RateStatisticsTest : public ::testing::Test {
|
||||
protected:
|
||||
BitRateStatsTest() {}
|
||||
BitRateStats stats_;
|
||||
RateStatisticsTest() : stats_(500, 8000) {}
|
||||
RateStatistics stats_;
|
||||
};
|
||||
|
||||
TEST_F(BitRateStatsTest, TestStrictMode) {
|
||||
TEST_F(RateStatisticsTest, TestStrictMode) {
|
||||
int64_t now_ms = 0;
|
||||
// Should be initialized to 0.
|
||||
EXPECT_EQ(0u, stats_.BitRate(now_ms));
|
||||
EXPECT_EQ(0u, stats_.Rate(now_ms));
|
||||
stats_.Update(1500, now_ms);
|
||||
// Expecting 24 kbps given a 500 ms window with one 1500 bytes packet.
|
||||
EXPECT_EQ(24000u, stats_.BitRate(now_ms));
|
||||
stats_.Init();
|
||||
EXPECT_EQ(24000u, stats_.Rate(now_ms));
|
||||
stats_.Reset();
|
||||
// Expecting 0 after init.
|
||||
EXPECT_EQ(0u, stats_.BitRate(now_ms));
|
||||
EXPECT_EQ(0u, stats_.Rate(now_ms));
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
if (now_ms % 10 == 0) {
|
||||
stats_.Update(1500, now_ms);
|
||||
@ -38,26 +38,26 @@ TEST_F(BitRateStatsTest, TestStrictMode) {
|
||||
// Approximately 1200 kbps expected. Not exact since when packets
|
||||
// are removed we will jump 10 ms to the next packet.
|
||||
if (now_ms > 0 && now_ms % 500 == 0) {
|
||||
EXPECT_NEAR(1200000u, stats_.BitRate(now_ms), 24000u);
|
||||
EXPECT_NEAR(1200000u, stats_.Rate(now_ms), 24000u);
|
||||
}
|
||||
now_ms += 1;
|
||||
}
|
||||
now_ms += 500;
|
||||
// The window is 2 seconds. If nothing has been received for that time
|
||||
// the estimate should be 0.
|
||||
EXPECT_EQ(0u, stats_.BitRate(now_ms));
|
||||
EXPECT_EQ(0u, stats_.Rate(now_ms));
|
||||
}
|
||||
|
||||
TEST_F(BitRateStatsTest, IncreasingThenDecreasingBitrate) {
|
||||
TEST_F(RateStatisticsTest, IncreasingThenDecreasingBitrate) {
|
||||
int64_t now_ms = 0;
|
||||
stats_.Init();
|
||||
stats_.Reset();
|
||||
// Expecting 0 after init.
|
||||
uint32_t bitrate = stats_.BitRate(now_ms);
|
||||
uint32_t bitrate = stats_.Rate(now_ms);
|
||||
EXPECT_EQ(0u, bitrate);
|
||||
// 1000 bytes per millisecond until plateau is reached.
|
||||
while (++now_ms < 10000) {
|
||||
stats_.Update(1000, now_ms);
|
||||
uint32_t new_bitrate = stats_.BitRate(now_ms);
|
||||
uint32_t new_bitrate = stats_.Rate(now_ms);
|
||||
if (new_bitrate != bitrate) {
|
||||
// New bitrate must be higher than previous one.
|
||||
EXPECT_GT(new_bitrate, bitrate);
|
||||
@ -71,13 +71,13 @@ TEST_F(BitRateStatsTest, IncreasingThenDecreasingBitrate) {
|
||||
// 1000 bytes per millisecond until 10-second mark, 8000 kbps expected.
|
||||
while (++now_ms < 10000) {
|
||||
stats_.Update(1000, now_ms);
|
||||
bitrate = stats_.BitRate(now_ms);
|
||||
bitrate = stats_.Rate(now_ms);
|
||||
EXPECT_NEAR(8000000u, bitrate, 80000u);
|
||||
}
|
||||
// Zero bytes per millisecond until 0 is reached.
|
||||
while (++now_ms < 20000) {
|
||||
stats_.Update(0, now_ms);
|
||||
uint32_t new_bitrate = stats_.BitRate(now_ms);
|
||||
uint32_t new_bitrate = stats_.Rate(now_ms);
|
||||
if (new_bitrate != bitrate) {
|
||||
// New bitrate must be lower than previous one.
|
||||
EXPECT_LT(new_bitrate, bitrate);
|
||||
@ -91,7 +91,7 @@ TEST_F(BitRateStatsTest, IncreasingThenDecreasingBitrate) {
|
||||
// Zero bytes per millisecond until 20-second mark, 0 kbps expected.
|
||||
while (++now_ms < 20000) {
|
||||
stats_.Update(0, now_ms);
|
||||
EXPECT_EQ(0u, stats_.BitRate(now_ms));
|
||||
EXPECT_EQ(0u, stats_.Rate(now_ms));
|
||||
}
|
||||
}
|
||||
} // namespace
|
@ -22,8 +22,8 @@
|
||||
'include/bwe_defines.h',
|
||||
'include/remote_bitrate_estimator.h',
|
||||
'include/rtp_to_ntp.h',
|
||||
'bitrate_estimator.cc',
|
||||
'bitrate_estimator.h',
|
||||
'rate_statistics.cc',
|
||||
'rate_statistics.h',
|
||||
'rtp_to_ntp.cc',
|
||||
], # source
|
||||
},
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "webrtc/modules/remote_bitrate_estimator/bitrate_estimator.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/overuse_detector.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/remote_rate_control.h"
|
||||
@ -63,7 +63,7 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
|
||||
|
||||
Clock* clock_;
|
||||
SsrcOveruseDetectorMap overuse_detectors_;
|
||||
BitRateStats incoming_bitrate_;
|
||||
RateStatistics incoming_bitrate_;
|
||||
RemoteRateControl remote_rate_;
|
||||
RemoteBitrateObserver* observer_;
|
||||
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
||||
@ -74,6 +74,7 @@ RemoteBitrateEstimatorSingleStream::RemoteBitrateEstimatorSingleStream(
|
||||
RemoteBitrateObserver* observer,
|
||||
Clock* clock)
|
||||
: clock_(clock),
|
||||
incoming_bitrate_(500, 8000),
|
||||
observer_(observer),
|
||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
last_process_time_(-1) {
|
||||
@ -106,7 +107,7 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket(
|
||||
const BandwidthUsage prior_state = overuse_detector->State();
|
||||
overuse_detector->Update(payload_size, -1, rtp_timestamp, arrival_time_ms);
|
||||
if (overuse_detector->State() == kBwOverusing) {
|
||||
unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time_ms);
|
||||
unsigned int incoming_bitrate = incoming_bitrate_.Rate(arrival_time_ms);
|
||||
if (prior_state != kBwOverusing ||
|
||||
remote_rate_.TimeToReduceFurther(arrival_time_ms, incoming_bitrate)) {
|
||||
// The first overuse should immediately trigger a new estimate.
|
||||
@ -164,7 +165,7 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t time_now) {
|
||||
double mean_noise_var = sum_noise_var /
|
||||
static_cast<double>(overuse_detectors_.size());
|
||||
const RateControlInput input(bw_state,
|
||||
incoming_bitrate_.BitRate(time_now),
|
||||
incoming_bitrate_.Rate(time_now),
|
||||
mean_noise_var);
|
||||
const RateControlRegion region = remote_rate_.Update(&input, time_now);
|
||||
unsigned int target_bitrate = remote_rate_.UpdateBandwidthEstimate(time_now);
|
||||
|
Loading…
Reference in New Issue
Block a user