1/*
2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
12
13#include <assert.h>
14
15namespace webrtc {
16
17RateStatistics::RateStatistics(uint32_t window_size_ms, float scale)
18    : num_buckets_(window_size_ms + 1),  // N ms in (N+1) buckets.
19      buckets_(new uint32_t[num_buckets_]()),
20      accumulated_count_(0),
21      oldest_time_(0),
22      oldest_index_(0),
23      scale_(scale / (num_buckets_ - 1)) {
24}
25
26RateStatistics::~RateStatistics() {
27}
28
29void RateStatistics::Reset() {
30  accumulated_count_ = 0;
31  oldest_time_ = 0;
32  oldest_index_ = 0;
33  for (int i = 0; i < num_buckets_; i++) {
34    buckets_[i] = 0;
35  }
36}
37
38void RateStatistics::Update(uint32_t count, int64_t now_ms) {
39  if (now_ms < oldest_time_) {
40    // Too old data is ignored.
41    return;
42  }
43
44  EraseOld(now_ms);
45
46  int now_offset = static_cast<int>(now_ms - oldest_time_);
47  assert(now_offset < num_buckets_);
48  int index = oldest_index_ + now_offset;
49  if (index >= num_buckets_) {
50    index -= num_buckets_;
51  }
52  buckets_[index] += count;
53  accumulated_count_ += count;
54}
55
56uint32_t RateStatistics::Rate(int64_t now_ms) {
57  EraseOld(now_ms);
58  return static_cast<uint32_t>(accumulated_count_ * scale_ + 0.5f);
59}
60
61void RateStatistics::EraseOld(int64_t now_ms) {
62  int64_t new_oldest_time = now_ms - num_buckets_ + 1;
63  if (new_oldest_time <= oldest_time_) {
64    return;
65  }
66
67  while (oldest_time_ < new_oldest_time) {
68    uint32_t count_in_oldest_bucket = buckets_[oldest_index_];
69    assert(accumulated_count_ >= count_in_oldest_bucket);
70    accumulated_count_ -= count_in_oldest_bucket;
71    buckets_[oldest_index_] = 0;
72    if (++oldest_index_ >= num_buckets_) {
73      oldest_index_ = 0;
74    }
75    ++oldest_time_;
76    if (accumulated_count_ == 0) {
77      // This guarantees we go through all the buckets at most once, even if
78      // |new_oldest_time| is far greater than |oldest_time_|.
79      break;
80    }
81  }
82  oldest_time_ = new_oldest_time;
83}
84
85}  // namespace webrtc
86