OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/base/ratetracker.h" | 11 #include "webrtc/base/ratetracker.h" |
12 | 12 |
13 #include <stddef.h> | 13 #include <stddef.h> |
14 | 14 |
15 #include <algorithm> | 15 #include <algorithm> |
16 | 16 |
17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
18 #include "webrtc/base/timeutils.h" | 18 #include "webrtc/base/timeutils.h" |
19 | 19 |
20 namespace rtc { | 20 namespace rtc { |
21 | 21 |
22 RateTracker::RateTracker( | 22 RateTracker::RateTracker(uint32_t bucket_milliseconds, size_t bucket_count) |
23 uint32 bucket_milliseconds, size_t bucket_count) | |
24 : bucket_milliseconds_(bucket_milliseconds), | 23 : bucket_milliseconds_(bucket_milliseconds), |
25 bucket_count_(bucket_count), | 24 bucket_count_(bucket_count), |
26 sample_buckets_(new size_t[bucket_count + 1]), | 25 sample_buckets_(new size_t[bucket_count + 1]), |
27 total_sample_count_(0u), | 26 total_sample_count_(0u), |
28 bucket_start_time_milliseconds_(~0u) { | 27 bucket_start_time_milliseconds_(~0u) { |
29 RTC_CHECK(bucket_milliseconds > 0u); | 28 RTC_CHECK(bucket_milliseconds > 0u); |
30 RTC_CHECK(bucket_count > 0u); | 29 RTC_CHECK(bucket_count > 0u); |
31 } | 30 } |
32 | 31 |
33 RateTracker::~RateTracker() { | 32 RateTracker::~RateTracker() { |
34 delete[] sample_buckets_; | 33 delete[] sample_buckets_; |
35 } | 34 } |
36 | 35 |
37 double RateTracker::ComputeRateForInterval( | 36 double RateTracker::ComputeRateForInterval( |
38 uint32 interval_milliseconds) const { | 37 uint32_t interval_milliseconds) const { |
39 if (bucket_start_time_milliseconds_ == ~0u) { | 38 if (bucket_start_time_milliseconds_ == ~0u) { |
40 return 0.0; | 39 return 0.0; |
41 } | 40 } |
42 uint32 current_time = Time(); | 41 uint32_t current_time = Time(); |
43 // Calculate which buckets to sum up given the current time. If the time | 42 // Calculate which buckets to sum up given the current time. If the time |
44 // has passed to a new bucket then we have to skip some of the oldest buckets. | 43 // has passed to a new bucket then we have to skip some of the oldest buckets. |
45 uint32 available_interval_milliseconds = std::min<uint32>( | 44 uint32_t available_interval_milliseconds = std::min<uint32_t>( |
46 interval_milliseconds, | 45 interval_milliseconds, |
47 bucket_milliseconds_ * static_cast<uint32>(bucket_count_)); | 46 bucket_milliseconds_ * static_cast<uint32_t>(bucket_count_)); |
48 // number of old buckets (i.e. after the current bucket in the ring buffer) | 47 // number of old buckets (i.e. after the current bucket in the ring buffer) |
49 // that are expired given our current time interval. | 48 // that are expired given our current time interval. |
50 size_t buckets_to_skip; | 49 size_t buckets_to_skip; |
51 // Number of milliseconds of the first bucket that are not a portion of the | 50 // Number of milliseconds of the first bucket that are not a portion of the |
52 // current interval. | 51 // current interval. |
53 uint32 milliseconds_to_skip; | 52 uint32_t milliseconds_to_skip; |
54 if (current_time > | 53 if (current_time > |
55 initialization_time_milliseconds_ + available_interval_milliseconds) { | 54 initialization_time_milliseconds_ + available_interval_milliseconds) { |
56 uint32 time_to_skip = current_time - bucket_start_time_milliseconds_ + | 55 uint32_t time_to_skip = |
57 static_cast<uint32>(bucket_count_) * bucket_milliseconds_ - | 56 current_time - bucket_start_time_milliseconds_ + |
| 57 static_cast<uint32_t>(bucket_count_) * bucket_milliseconds_ - |
58 available_interval_milliseconds; | 58 available_interval_milliseconds; |
59 buckets_to_skip = time_to_skip / bucket_milliseconds_; | 59 buckets_to_skip = time_to_skip / bucket_milliseconds_; |
60 milliseconds_to_skip = time_to_skip % bucket_milliseconds_; | 60 milliseconds_to_skip = time_to_skip % bucket_milliseconds_; |
61 } else { | 61 } else { |
62 buckets_to_skip = bucket_count_ - current_bucket_; | 62 buckets_to_skip = bucket_count_ - current_bucket_; |
63 milliseconds_to_skip = 0u; | 63 milliseconds_to_skip = 0u; |
64 available_interval_milliseconds = | 64 available_interval_milliseconds = |
65 TimeDiff(current_time, initialization_time_milliseconds_); | 65 TimeDiff(current_time, initialization_time_milliseconds_); |
66 } | 66 } |
67 // If we're skipping all buckets that means that there have been no samples | 67 // If we're skipping all buckets that means that there have been no samples |
(...skipping 16 matching lines...) Loading... |
84 } | 84 } |
85 // Convert to samples per second. | 85 // Convert to samples per second. |
86 return static_cast<double>(total_samples * 1000u) / | 86 return static_cast<double>(total_samples * 1000u) / |
87 static_cast<double>(available_interval_milliseconds); | 87 static_cast<double>(available_interval_milliseconds); |
88 } | 88 } |
89 | 89 |
90 double RateTracker::ComputeTotalRate() const { | 90 double RateTracker::ComputeTotalRate() const { |
91 if (bucket_start_time_milliseconds_ == ~0u) { | 91 if (bucket_start_time_milliseconds_ == ~0u) { |
92 return 0.0; | 92 return 0.0; |
93 } | 93 } |
94 uint32 current_time = Time(); | 94 uint32_t current_time = Time(); |
95 if (TimeIsLaterOrEqual(current_time, initialization_time_milliseconds_)) { | 95 if (TimeIsLaterOrEqual(current_time, initialization_time_milliseconds_)) { |
96 return 0.0; | 96 return 0.0; |
97 } | 97 } |
98 return static_cast<double>(total_sample_count_ * 1000u) / | 98 return static_cast<double>(total_sample_count_ * 1000u) / |
99 static_cast<double>( | 99 static_cast<double>( |
100 TimeDiff(current_time, initialization_time_milliseconds_)); | 100 TimeDiff(current_time, initialization_time_milliseconds_)); |
101 } | 101 } |
102 | 102 |
103 size_t RateTracker::TotalSampleCount() const { | 103 size_t RateTracker::TotalSampleCount() const { |
104 return total_sample_count_; | 104 return total_sample_count_; |
105 } | 105 } |
106 | 106 |
107 void RateTracker::AddSamples(size_t sample_count) { | 107 void RateTracker::AddSamples(size_t sample_count) { |
108 EnsureInitialized(); | 108 EnsureInitialized(); |
109 uint32 current_time = Time(); | 109 uint32_t current_time = Time(); |
110 // Advance the current bucket as needed for the current time, and reset | 110 // Advance the current bucket as needed for the current time, and reset |
111 // bucket counts as we advance. | 111 // bucket counts as we advance. |
112 for (size_t i = 0u; i <= bucket_count_ && | 112 for (size_t i = 0u; i <= bucket_count_ && |
113 current_time >= bucket_start_time_milliseconds_ + bucket_milliseconds_; | 113 current_time >= bucket_start_time_milliseconds_ + bucket_milliseconds_; |
114 ++i) { | 114 ++i) { |
115 bucket_start_time_milliseconds_ += bucket_milliseconds_; | 115 bucket_start_time_milliseconds_ += bucket_milliseconds_; |
116 current_bucket_ = NextBucketIndex(current_bucket_); | 116 current_bucket_ = NextBucketIndex(current_bucket_); |
117 sample_buckets_[current_bucket_] = 0u; | 117 sample_buckets_[current_bucket_] = 0u; |
118 } | 118 } |
119 // Ensure that bucket_start_time_milliseconds_ is updated appropriately if | 119 // Ensure that bucket_start_time_milliseconds_ is updated appropriately if |
120 // the entire buffer of samples has been expired. | 120 // the entire buffer of samples has been expired. |
121 bucket_start_time_milliseconds_ += bucket_milliseconds_ * | 121 bucket_start_time_milliseconds_ += bucket_milliseconds_ * |
122 ((current_time - bucket_start_time_milliseconds_) / bucket_milliseconds_); | 122 ((current_time - bucket_start_time_milliseconds_) / bucket_milliseconds_); |
123 // Add all samples in the bucket that includes the current time. | 123 // Add all samples in the bucket that includes the current time. |
124 sample_buckets_[current_bucket_] += sample_count; | 124 sample_buckets_[current_bucket_] += sample_count; |
125 total_sample_count_ += sample_count; | 125 total_sample_count_ += sample_count; |
126 } | 126 } |
127 | 127 |
128 uint32 RateTracker::Time() const { | 128 uint32_t RateTracker::Time() const { |
129 return rtc::Time(); | 129 return rtc::Time(); |
130 } | 130 } |
131 | 131 |
132 void RateTracker::EnsureInitialized() { | 132 void RateTracker::EnsureInitialized() { |
133 if (bucket_start_time_milliseconds_ == ~0u) { | 133 if (bucket_start_time_milliseconds_ == ~0u) { |
134 initialization_time_milliseconds_ = Time(); | 134 initialization_time_milliseconds_ = Time(); |
135 bucket_start_time_milliseconds_ = initialization_time_milliseconds_; | 135 bucket_start_time_milliseconds_ = initialization_time_milliseconds_; |
136 current_bucket_ = 0u; | 136 current_bucket_ = 0u; |
137 // We only need to initialize the first bucket because we reset buckets when | 137 // We only need to initialize the first bucket because we reset buckets when |
138 // current_bucket_ increments. | 138 // current_bucket_ increments. |
139 sample_buckets_[current_bucket_] = 0u; | 139 sample_buckets_[current_bucket_] = 0u; |
140 } | 140 } |
141 } | 141 } |
142 | 142 |
143 size_t RateTracker::NextBucketIndex(size_t bucket_index) const { | 143 size_t RateTracker::NextBucketIndex(size_t bucket_index) const { |
144 return (bucket_index + 1u) % (bucket_count_ + 1u); | 144 return (bucket_index + 1u) % (bucket_count_ + 1u); |
145 } | 145 } |
146 | 146 |
147 } // namespace rtc | 147 } // namespace rtc |
OLD | NEW |