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/webrtc@5202 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/modules/modules.gyp b/modules/modules.gyp
index 65c4827..5c2f77f 100644
--- a/modules/modules.gyp
+++ b/modules/modules.gyp
@@ -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',
diff --git a/modules/remote_bitrate_estimator/bitrate_estimator.cc b/modules/remote_bitrate_estimator/bitrate_estimator.cc
deleted file mode 100644
index 8934d43..0000000
--- a/modules/remote_bitrate_estimator/bitrate_estimator.cc
+++ /dev/null
@@ -1,84 +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.
- */
-
-#include "webrtc/modules/remote_bitrate_estimator/bitrate_estimator.h"
-
-namespace webrtc {
-
-const int kBitrateAverageWindowMs = 500;
-
-BitRateStats::BitRateStats()
- : num_buckets_(kBitrateAverageWindowMs + 1), // N ms in (N+1) buckets.
- buckets_(new uint32_t[num_buckets_]()),
- accumulated_bytes_(0),
- oldest_time_(0),
- oldest_index_(0),
- bps_coefficient_(8.f * 1000.f / (num_buckets_ - 1)) {
-}
-
-BitRateStats::~BitRateStats() {
-}
-
-void BitRateStats::Init() {
- accumulated_bytes_ = 0;
- oldest_time_ = 0;
- oldest_index_ = 0;
- for (int i = 0; i < num_buckets_; i++) {
- buckets_[i] = 0;
- }
-}
-
-void BitRateStats::Update(uint32_t packet_size_bytes, int64_t now_ms) {
- if (now_ms < oldest_time_) {
- // Too old data is ignored.
- return;
- }
-
- EraseOld(now_ms);
-
- int now_offset = static_cast<int>(now_ms - oldest_time_);
- assert(now_offset < num_buckets_);
- int index = oldest_index_ + now_offset;
- if (index >= num_buckets_) {
- index -= num_buckets_;
- }
- buckets_[index] += packet_size_bytes;
- accumulated_bytes_ += packet_size_bytes;
-}
-
-uint32_t BitRateStats::BitRate(int64_t now_ms) {
- EraseOld(now_ms);
- return static_cast<uint32_t>(accumulated_bytes_ * bps_coefficient_ + 0.5f);
-}
-
-void BitRateStats::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;
- buckets_[oldest_index_] = 0;
- if (++oldest_index_ >= num_buckets_) {
- oldest_index_ = 0;
- }
- ++oldest_time_;
- if (accumulated_bytes_ == 0) {
- // This guarantees we go through all the buckets at most once, even if
- // |new_oldest_time| is far greater than |oldest_time_|.
- break;
- }
- }
- oldest_time_ = new_oldest_time;
-}
-} // namespace webrtc
diff --git a/modules/remote_bitrate_estimator/bitrate_estimator.h b/modules/remote_bitrate_estimator/bitrate_estimator.h
deleted file mode 100644
index 9ee31eb..0000000
--- a/modules/remote_bitrate_estimator/bitrate_estimator.h
+++ /dev/null
@@ -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_
diff --git a/modules/remote_bitrate_estimator/rate_statistics.cc b/modules/remote_bitrate_estimator/rate_statistics.cc
new file mode 100644
index 0000000..4a9b448
--- /dev/null
+++ b/modules/remote_bitrate_estimator/rate_statistics.cc
@@ -0,0 +1,83 @@
+/*
+ * 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 "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
+
+namespace webrtc {
+
+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_count_(0),
+ oldest_time_(0),
+ oldest_index_(0),
+ scale_(scale / (num_buckets_ - 1)) {
+}
+
+RateStatistics::~RateStatistics() {
+}
+
+void RateStatistics::Reset() {
+ accumulated_count_ = 0;
+ oldest_time_ = 0;
+ oldest_index_ = 0;
+ for (int i = 0; i < num_buckets_; i++) {
+ buckets_[i] = 0;
+ }
+}
+
+void RateStatistics::Update(uint32_t count, int64_t now_ms) {
+ if (now_ms < oldest_time_) {
+ // Too old data is ignored.
+ return;
+ }
+
+ EraseOld(now_ms);
+
+ int now_offset = static_cast<int>(now_ms - oldest_time_);
+ assert(now_offset < num_buckets_);
+ int index = oldest_index_ + now_offset;
+ if (index >= num_buckets_) {
+ index -= num_buckets_;
+ }
+ buckets_[index] += count;
+ accumulated_count_ += count;
+}
+
+uint32_t RateStatistics::Rate(int64_t now_ms) {
+ EraseOld(now_ms);
+ return static_cast<uint32_t>(accumulated_count_ * scale_ + 0.5f);
+}
+
+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 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_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;
+ }
+ }
+ oldest_time_ = new_oldest_time;
+}
+
+} // namespace webrtc
diff --git a/modules/remote_bitrate_estimator/rate_statistics.h b/modules/remote_bitrate_estimator/rate_statistics.h
new file mode 100644
index 0000000..4296690
--- /dev/null
+++ b/modules/remote_bitrate_estimator/rate_statistics.h
@@ -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_
diff --git a/modules/remote_bitrate_estimator/bitrate_estimator_unittest.cc b/modules/remote_bitrate_estimator/rate_statistics_unittest.cc
similarity index 74%
rename from modules/remote_bitrate_estimator/bitrate_estimator_unittest.cc
rename to modules/remote_bitrate_estimator/rate_statistics_unittest.cc
index 3d49ca4..0cbab30 100644
--- a/modules/remote_bitrate_estimator/bitrate_estimator_unittest.cc
+++ b/modules/remote_bitrate_estimator/rate_statistics_unittest.cc
@@ -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 @@
// 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 @@
// 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 @@
// 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
diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
index f8f7e43..bbd353f 100644
--- a/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
+++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
@@ -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
},
diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
index 8eec342..69ebab4 100644
--- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
+++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
@@ -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 @@
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 @@
RemoteBitrateObserver* observer,
Clock* clock)
: clock_(clock),
+ incoming_bitrate_(500, 8000),
observer_(observer),
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
last_process_time_(-1) {
@@ -106,7 +107,7 @@
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 @@
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);