OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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/video/stats_counter.h" | 11 #include "webrtc/video/stats_counter.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 | 14 |
15 #include "webrtc/system_wrappers/include/clock.h" | 15 #include "webrtc/system_wrappers/include/clock.h" |
16 | 16 |
17 namespace webrtc { | 17 namespace webrtc { |
18 | 18 |
19 namespace { | 19 namespace { |
20 // Periodic time interval for processing samples. | 20 // Periodic time interval for processing samples. |
21 const int64_t kProcessIntervalMs = 2000; | 21 const int64_t kProcessIntervalMs = 2000; |
22 | |
23 int64_t Num(const std::map<uint32_t, StatsCounter::Samples>& samples) { | |
24 int64_t num = 0; | |
25 for (const auto& it : samples) | |
26 num += it.second.num_; | |
27 return num; | |
28 } | |
29 | |
30 int64_t Sum(const std::map<uint32_t, StatsCounter::Samples>& samples) { | |
31 int64_t sum = 0; | |
32 for (const auto& it : samples) | |
33 sum += it.second.sum_; | |
34 return sum; | |
35 } | |
36 | |
37 int Max(const std::map<uint32_t, StatsCounter::Samples>& samples) { | |
38 int max = std::numeric_limits<int>::min(); | |
39 for (const auto& it : samples) | |
40 max = std::max(it.second.max_, max); | |
41 return max; | |
42 } | |
43 | |
44 void Reset(std::map<uint32_t, StatsCounter::Samples>* samples) { | |
45 for (auto& it : *samples) | |
46 it.second.Reset(); | |
47 } | |
48 | |
49 int64_t Diff(const std::map<uint32_t, StatsCounter::Samples>& samples) { | |
50 int64_t sum_diff = 0; | |
51 int num = 0; | |
52 for (const auto& it : samples) { | |
53 if (it.second.num_ > 0) { | |
54 int64_t diff = it.second.sum_ - it.second.last_sum_; | |
55 if (diff >= 0) { | |
56 sum_diff += diff; | |
57 ++num; | |
58 } | |
59 } | |
60 } | |
61 return (num > 0) ? sum_diff : -1; | |
62 } | |
22 } // namespace | 63 } // namespace |
23 | 64 |
24 // Class holding periodically computed metrics. | 65 // Class holding periodically computed metrics. |
25 class AggregatedCounter { | 66 class AggregatedCounter { |
26 public: | 67 public: |
27 AggregatedCounter() : sum_(0) {} | 68 AggregatedCounter() : sum_(0) {} |
28 ~AggregatedCounter() {} | 69 ~AggregatedCounter() {} |
29 | 70 |
30 void Add(int sample) { | 71 void Add(int sample) { |
31 sum_ += sample; | 72 sum_ += sample; |
(...skipping 15 matching lines...) Expand all Loading... | |
47 void Compute() { | 88 void Compute() { |
48 if (stats_.num_samples == 0) | 89 if (stats_.num_samples == 0) |
49 return; | 90 return; |
50 | 91 |
51 stats_.average = (sum_ + stats_.num_samples / 2) / stats_.num_samples; | 92 stats_.average = (sum_ + stats_.num_samples / 2) / stats_.num_samples; |
52 } | 93 } |
53 int64_t sum_; | 94 int64_t sum_; |
54 AggregatedStats stats_; | 95 AggregatedStats stats_; |
55 }; | 96 }; |
56 | 97 |
98 // Gathered samples within a process interval. | |
99 void StatsCounter::Samples::Add(int sample) { | |
100 sum_ += sample; | |
101 ++num_; | |
102 max_ = std::max(sample, max_); | |
103 } | |
104 | |
105 void StatsCounter::Samples::Set(int sample) { | |
106 sum_ = sample; | |
107 ++num_; | |
108 } | |
109 | |
110 void StatsCounter::Samples::Reset() { | |
111 if (num_ > 0) | |
112 last_sum_ = sum_; | |
113 sum_ = 0; | |
114 num_ = 0; | |
115 max_ = std::numeric_limits<int>::min(); | |
116 } | |
117 | |
57 // StatsCounter class. | 118 // StatsCounter class. |
58 StatsCounter::StatsCounter(Clock* clock, | 119 StatsCounter::StatsCounter(Clock* clock, |
59 bool include_empty_intervals, | 120 bool include_empty_intervals, |
60 StatsCounterObserver* observer) | 121 StatsCounterObserver* observer) |
61 : max_(0), | 122 : include_empty_intervals_(include_empty_intervals), |
62 sum_(0), | |
63 num_samples_(0), | |
64 last_sum_(0), | |
65 clock_(clock), | 123 clock_(clock), |
66 include_empty_intervals_(include_empty_intervals), | |
67 observer_(observer), | 124 observer_(observer), |
68 aggregated_counter_(new AggregatedCounter()), | 125 aggregated_counter_(new AggregatedCounter()), |
69 last_process_time_ms_(-1) {} | 126 last_process_time_ms_(-1) {} |
70 | 127 |
71 StatsCounter::~StatsCounter() {} | 128 StatsCounter::~StatsCounter() {} |
72 | 129 |
73 AggregatedStats StatsCounter::GetStats() { | 130 AggregatedStats StatsCounter::GetStats() { |
74 return aggregated_counter_->ComputeStats(); | 131 return aggregated_counter_->ComputeStats(); |
75 } | 132 } |
76 | 133 |
(...skipping 14 matching lines...) Expand all Loading... | |
91 if (include_empty_intervals_) { | 148 if (include_empty_intervals_) { |
92 for (int64_t i = 0; i < num_intervals - 1; ++i) { | 149 for (int64_t i = 0; i < num_intervals - 1; ++i) { |
93 aggregated_counter_->Add(0); | 150 aggregated_counter_->Add(0); |
94 if (observer_) | 151 if (observer_) |
95 observer_->OnMetricUpdated(0); | 152 observer_->OnMetricUpdated(0); |
96 } | 153 } |
97 } | 154 } |
98 return true; | 155 return true; |
99 } | 156 } |
100 | 157 |
101 void StatsCounter::Set(int sample) { | 158 void StatsCounter::Set(int sample, uint32_t ssrc) { |
102 TryProcess(); | 159 TryProcess(); |
103 ++num_samples_; | 160 samples_[ssrc].Set(sample); |
104 sum_ = sample; | |
105 } | 161 } |
106 | 162 |
107 void StatsCounter::Add(int sample) { | 163 void StatsCounter::Add(int sample) { |
108 TryProcess(); | 164 TryProcess(); |
109 ++num_samples_; | 165 samples_[0].Add(sample); |
stefan-webrtc
2016/08/19 14:36:56
Is zero some default ssrc? I think it's also a val
åsapersson
2016/08/23 09:06:02
The ssrc can only be set for RateAccCounter (and n
stefan-webrtc
2016/09/08 07:13:34
Acknowledged.
| |
110 sum_ += sample; | |
111 | |
112 if (num_samples_ == 1) | |
113 max_ = sample; | |
114 max_ = std::max(sample, max_); | |
115 } | 166 } |
116 | 167 |
117 void StatsCounter::TryProcess() { | 168 void StatsCounter::TryProcess() { |
118 if (!TimeToProcess()) | 169 if (!TimeToProcess()) |
119 return; | 170 return; |
120 | 171 |
121 int metric; | 172 int metric; |
122 if (GetMetric(&metric)) { | 173 if (GetMetric(&metric)) { |
123 aggregated_counter_->Add(metric); | 174 aggregated_counter_->Add(metric); |
124 if (observer_) | 175 if (observer_) |
125 observer_->OnMetricUpdated(metric); | 176 observer_->OnMetricUpdated(metric); |
126 } | 177 } |
127 last_sum_ = sum_; | 178 |
128 sum_ = 0; | 179 Reset(&samples_); |
129 max_ = 0; | |
130 num_samples_ = 0; | |
131 } | 180 } |
132 | 181 |
133 // StatsCounter sub-classes. | 182 // StatsCounter sub-classes. |
134 AvgCounter::AvgCounter(Clock* clock, StatsCounterObserver* observer) | 183 AvgCounter::AvgCounter(Clock* clock, StatsCounterObserver* observer) |
135 : StatsCounter(clock, | 184 : StatsCounter(clock, |
136 false, // |include_empty_intervals| | 185 false, // |include_empty_intervals| |
137 observer) {} | 186 observer) {} |
138 | 187 |
139 void AvgCounter::Add(int sample) { | 188 void AvgCounter::Add(int sample) { |
140 StatsCounter::Add(sample); | 189 StatsCounter::Add(sample); |
141 } | 190 } |
142 | 191 |
143 bool AvgCounter::GetMetric(int* metric) const { | 192 bool AvgCounter::GetMetric(int* metric) const { |
144 if (num_samples_ == 0) | 193 int64_t num = Num(samples_); |
194 if (num == 0) | |
145 return false; | 195 return false; |
146 *metric = (sum_ + num_samples_ / 2) / num_samples_; | 196 |
197 *metric = (Sum(samples_) + num / 2) / num; | |
147 return true; | 198 return true; |
148 } | 199 } |
149 | 200 |
150 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer) | 201 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer) |
151 : StatsCounter(clock, | 202 : StatsCounter(clock, |
152 false, // |include_empty_intervals| | 203 false, // |include_empty_intervals| |
153 observer) {} | 204 observer) {} |
154 | 205 |
155 void MaxCounter::Add(int sample) { | 206 void MaxCounter::Add(int sample) { |
156 StatsCounter::Add(sample); | 207 StatsCounter::Add(sample); |
157 } | 208 } |
158 | 209 |
159 bool MaxCounter::GetMetric(int* metric) const { | 210 bool MaxCounter::GetMetric(int* metric) const { |
160 if (num_samples_ == 0) | 211 int64_t num = Num(samples_); |
212 if (num == 0) | |
161 return false; | 213 return false; |
162 *metric = max_; | 214 |
215 *metric = Max(samples_); | |
163 return true; | 216 return true; |
164 } | 217 } |
165 | 218 |
166 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer) | 219 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer) |
167 : StatsCounter(clock, | 220 : StatsCounter(clock, |
168 false, // |include_empty_intervals| | 221 false, // |include_empty_intervals| |
169 observer) {} | 222 observer) {} |
170 | 223 |
171 void PercentCounter::Add(bool sample) { | 224 void PercentCounter::Add(bool sample) { |
172 StatsCounter::Add(sample ? 1 : 0); | 225 StatsCounter::Add(sample ? 1 : 0); |
173 } | 226 } |
174 | 227 |
175 bool PercentCounter::GetMetric(int* metric) const { | 228 bool PercentCounter::GetMetric(int* metric) const { |
176 if (num_samples_ == 0) | 229 int64_t num = Num(samples_); |
230 if (num == 0) | |
177 return false; | 231 return false; |
178 *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_; | 232 |
233 *metric = (Sum(samples_) * 100 + num / 2) / num; | |
179 return true; | 234 return true; |
180 } | 235 } |
181 | 236 |
182 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer) | 237 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer) |
183 : StatsCounter(clock, | 238 : StatsCounter(clock, |
184 false, // |include_empty_intervals| | 239 false, // |include_empty_intervals| |
185 observer) {} | 240 observer) {} |
186 | 241 |
187 void PermilleCounter::Add(bool sample) { | 242 void PermilleCounter::Add(bool sample) { |
188 StatsCounter::Add(sample ? 1 : 0); | 243 StatsCounter::Add(sample ? 1 : 0); |
189 } | 244 } |
190 | 245 |
191 bool PermilleCounter::GetMetric(int* metric) const { | 246 bool PermilleCounter::GetMetric(int* metric) const { |
192 if (num_samples_ == 0) | 247 int64_t num = Num(samples_); |
248 if (num == 0) | |
193 return false; | 249 return false; |
194 *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_; | 250 |
251 *metric = (Sum(samples_) * 1000 + num / 2) / num; | |
195 return true; | 252 return true; |
196 } | 253 } |
197 | 254 |
198 RateCounter::RateCounter(Clock* clock, | 255 RateCounter::RateCounter(Clock* clock, |
199 StatsCounterObserver* observer, | 256 StatsCounterObserver* observer, |
200 bool include_empty_intervals) | 257 bool include_empty_intervals) |
201 : StatsCounter(clock, include_empty_intervals, observer) {} | 258 : StatsCounter(clock, include_empty_intervals, observer) {} |
202 | 259 |
203 void RateCounter::Add(int sample) { | 260 void RateCounter::Add(int sample) { |
204 StatsCounter::Add(sample); | 261 StatsCounter::Add(sample); |
205 } | 262 } |
206 | 263 |
207 bool RateCounter::GetMetric(int* metric) const { | 264 bool RateCounter::GetMetric(int* metric) const { |
208 if (num_samples_ == 0) | 265 if (Num(samples_) == 0) |
209 return false; | 266 return false; |
210 *metric = (sum_ * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; | 267 |
268 *metric = | |
269 (Sum(samples_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; | |
211 return true; | 270 return true; |
212 } | 271 } |
213 | 272 |
214 RateAccCounter::RateAccCounter(Clock* clock, | 273 RateAccCounter::RateAccCounter(Clock* clock, |
215 StatsCounterObserver* observer, | 274 StatsCounterObserver* observer, |
216 bool include_empty_intervals) | 275 bool include_empty_intervals) |
217 : StatsCounter(clock, include_empty_intervals, observer) {} | 276 : StatsCounter(clock, include_empty_intervals, observer) {} |
218 | 277 |
219 void RateAccCounter::Set(int sample) { | 278 void RateAccCounter::Set(int sample, uint32_t ssrc) { |
220 StatsCounter::Set(sample); | 279 StatsCounter::Set(sample, ssrc); |
221 } | 280 } |
222 | 281 |
223 bool RateAccCounter::GetMetric(int* metric) const { | 282 bool RateAccCounter::GetMetric(int* metric) const { |
224 if (num_samples_ == 0 || last_sum_ > sum_) | 283 if (Num(samples_) == 0) |
225 return false; | 284 return false; |
226 *metric = | 285 |
227 ((sum_ - last_sum_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; | 286 int64_t diff = Diff(samples_); |
287 if (diff < 0 || (!include_empty_intervals_ && diff == 0)) | |
288 return false; | |
289 | |
290 *metric = (diff * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; | |
228 return true; | 291 return true; |
229 } | 292 } |
230 | 293 |
231 } // namespace webrtc | 294 } // namespace webrtc |
OLD | NEW |