Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(515)

Side by Side Diff: webrtc/video/stats_counter.cc

Issue 2235223002: Add ability to handle data from multiple streams in RateAccCounter. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: int -> uint32_t Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/video/stats_counter.h ('k') | webrtc/video/stats_counter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include <limits>
15 #include <map>
14 16
15 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
16 #include "webrtc/system_wrappers/include/clock.h" 18 #include "webrtc/system_wrappers/include/clock.h"
17 19
18 namespace webrtc { 20 namespace webrtc {
19 21
20 namespace { 22 namespace {
21 // Default periodic time interval for processing samples. 23 // Default periodic time interval for processing samples.
22 const int64_t kDefaultProcessIntervalMs = 2000; 24 const int64_t kDefaultProcessIntervalMs = 2000;
25 const uint32_t kStreamId0 = 0;
23 } // namespace 26 } // namespace
24 27
25 // Class holding periodically computed metrics. 28 // Class holding periodically computed metrics.
26 class AggregatedCounter { 29 class AggregatedCounter {
27 public: 30 public:
28 AggregatedCounter() : last_sample_(0), sum_samples_(0) {} 31 AggregatedCounter() : last_sample_(0), sum_samples_(0) {}
29 ~AggregatedCounter() {} 32 ~AggregatedCounter() {}
30 33
31 void Add(int sample) { 34 void Add(int sample) {
32 last_sample_ = sample; 35 last_sample_ = sample;
(...skipping 22 matching lines...) Expand all
55 return; 58 return;
56 59
57 stats_.average = 60 stats_.average =
58 (sum_samples_ + stats_.num_samples / 2) / stats_.num_samples; 61 (sum_samples_ + stats_.num_samples / 2) / stats_.num_samples;
59 } 62 }
60 int last_sample_; 63 int last_sample_;
61 int64_t sum_samples_; 64 int64_t sum_samples_;
62 AggregatedStats stats_; 65 AggregatedStats stats_;
63 }; 66 };
64 67
68 // Class holding gathered samples within a process interval.
69 class Samples {
70 public:
71 Samples() : total_count_(0) {}
72 ~Samples() {}
73
74 void Add(int sample, uint32_t stream_id) {
75 samples_[stream_id].Add(sample);
76 ++total_count_;
77 }
78 void Set(int sample, uint32_t stream_id) {
79 samples_[stream_id].Set(sample);
80 ++total_count_;
81 }
82
83 int64_t Count() const { return total_count_; }
84 bool Empty() const { return total_count_ == 0; }
85
86 int64_t Sum() const {
87 int64_t sum = 0;
88 for (const auto& it : samples_)
89 sum += it.second.sum_;
90 return sum;
91 }
92
93 int Max() const {
94 int max = std::numeric_limits<int>::min();
95 for (const auto& it : samples_)
96 max = std::max(it.second.max_, max);
97 return max;
98 }
99
100 void Reset() {
101 for (auto& it : samples_)
102 it.second.Reset();
103 total_count_ = 0;
104 }
105
106 int64_t Diff() const {
107 int64_t sum_diff = 0;
108 int count = 0;
109 for (const auto& it : samples_) {
110 if (it.second.count_ > 0) {
111 int64_t diff = it.second.sum_ - it.second.last_sum_;
112 if (diff >= 0) {
113 sum_diff += diff;
114 ++count;
115 }
116 }
117 }
118 return (count > 0) ? sum_diff : -1;
119 }
120
121 private:
122 struct Stats {
123 void Add(int sample) {
124 sum_ += sample;
125 ++count_;
126 max_ = std::max(sample, max_);
127 }
128 void Set(int sample) {
129 sum_ = sample;
130 ++count_;
131 }
132 void Reset() {
133 if (count_ > 0)
134 last_sum_ = sum_;
135 sum_ = 0;
136 count_ = 0;
137 max_ = std::numeric_limits<int>::min();
138 }
139
140 int max_ = std::numeric_limits<int>::min();
141 int64_t count_ = 0;
142 int64_t sum_ = 0;
143 int64_t last_sum_ = 0;
144 };
145
146 int64_t total_count_;
147 std::map<uint32_t, Stats> samples_; // Gathered samples mapped by stream id.
148 };
149
65 // StatsCounter class. 150 // StatsCounter class.
66 StatsCounter::StatsCounter(Clock* clock, 151 StatsCounter::StatsCounter(Clock* clock,
67 int64_t process_intervals_ms, 152 int64_t process_intervals_ms,
68 bool include_empty_intervals, 153 bool include_empty_intervals,
69 StatsCounterObserver* observer) 154 StatsCounterObserver* observer)
70 : max_(0), 155 : include_empty_intervals_(include_empty_intervals),
71 sum_(0), 156 process_intervals_ms_(process_intervals_ms),
72 num_samples_(0),
73 last_sum_(0),
74 aggregated_counter_(new AggregatedCounter()), 157 aggregated_counter_(new AggregatedCounter()),
75 process_intervals_ms_(process_intervals_ms), 158 samples_(new Samples()),
76 clock_(clock), 159 clock_(clock),
77 include_empty_intervals_(include_empty_intervals),
78 observer_(observer), 160 observer_(observer),
79 last_process_time_ms_(-1), 161 last_process_time_ms_(-1),
80 paused_(false) { 162 paused_(false) {
81 RTC_DCHECK_GT(process_intervals_ms_, 0); 163 RTC_DCHECK_GT(process_intervals_ms_, 0);
82 } 164 }
83 165
84 StatsCounter::~StatsCounter() {} 166 StatsCounter::~StatsCounter() {}
85 167
86 AggregatedStats StatsCounter::GetStats() { 168 AggregatedStats StatsCounter::GetStats() {
87 return aggregated_counter_->ComputeStats(); 169 return aggregated_counter_->ComputeStats();
(...skipping 25 matching lines...) Expand all
113 return false; 195 return false;
114 196
115 // Advance number of complete |process_intervals_ms_| that have passed. 197 // Advance number of complete |process_intervals_ms_| that have passed.
116 int64_t num_intervals = diff_ms / process_intervals_ms_; 198 int64_t num_intervals = diff_ms / process_intervals_ms_;
117 last_process_time_ms_ += num_intervals * process_intervals_ms_; 199 last_process_time_ms_ += num_intervals * process_intervals_ms_;
118 200
119 *elapsed_intervals = num_intervals; 201 *elapsed_intervals = num_intervals;
120 return true; 202 return true;
121 } 203 }
122 204
123 void StatsCounter::Set(int sample) { 205 void StatsCounter::Set(int sample, uint32_t stream_id) {
124 TryProcess(); 206 TryProcess();
125 ++num_samples_; 207 samples_->Set(sample, stream_id);
126 sum_ = sample;
127 paused_ = false; 208 paused_ = false;
128 } 209 }
129 210
130 void StatsCounter::Add(int sample) { 211 void StatsCounter::Add(int sample) {
131 TryProcess(); 212 TryProcess();
132 ++num_samples_; 213 samples_->Add(sample, kStreamId0);
133 sum_ += sample;
134
135 if (num_samples_ == 1)
136 max_ = sample;
137 max_ = std::max(sample, max_);
138 paused_ = false; 214 paused_ = false;
139 } 215 }
140 216
141 // Reports periodically computed metric. 217 // Reports periodically computed metric.
142 void StatsCounter::ReportMetricToAggregatedCounter( 218 void StatsCounter::ReportMetricToAggregatedCounter(
143 int value, 219 int value,
144 int num_values_to_add) const { 220 int num_values_to_add) const {
145 for (int i = 0; i < num_values_to_add; ++i) { 221 for (int i = 0; i < num_values_to_add; ++i) {
146 aggregated_counter_->Add(value); 222 aggregated_counter_->Add(value);
147 if (observer_) 223 if (observer_)
148 observer_->OnMetricUpdated(value); 224 observer_->OnMetricUpdated(value);
149 } 225 }
150 } 226 }
151 227
152 void StatsCounter::TryProcess() { 228 void StatsCounter::TryProcess() {
153 int elapsed_intervals; 229 int elapsed_intervals;
154 if (!TimeToProcess(&elapsed_intervals)) 230 if (!TimeToProcess(&elapsed_intervals))
155 return; 231 return;
156 232
157 // Get and report periodically computed metric. 233 // Get and report periodically computed metric.
158 int metric; 234 int metric;
159 if (GetMetric(&metric)) 235 if (GetMetric(&metric))
160 ReportMetricToAggregatedCounter(metric, 1); 236 ReportMetricToAggregatedCounter(metric, 1);
161 237
162 // Report value for elapsed intervals without samples. 238 // Report value for elapsed intervals without samples.
163 if (IncludeEmptyIntervals()) { 239 if (IncludeEmptyIntervals()) {
164 // If there are no samples, all elapsed intervals are empty (otherwise one 240 // If there are no samples, all elapsed intervals are empty (otherwise one
165 // interval contains sample(s), discard this interval). 241 // interval contains sample(s), discard this interval).
166 int empty_intervals = 242 int empty_intervals =
167 (num_samples_ == 0) ? elapsed_intervals : (elapsed_intervals - 1); 243 samples_->Empty() ? elapsed_intervals : (elapsed_intervals - 1);
168 ReportMetricToAggregatedCounter(GetValueForEmptyInterval(), 244 ReportMetricToAggregatedCounter(GetValueForEmptyInterval(),
169 empty_intervals); 245 empty_intervals);
170 } 246 }
171 247
172 // Reset samples for elapsed interval. 248 // Reset samples for elapsed interval.
173 if (num_samples_ > 0) 249 samples_->Reset();
174 last_sum_ = sum_;
175 sum_ = 0;
176 max_ = 0;
177 num_samples_ = 0;
178 } 250 }
179 251
180 bool StatsCounter::IncludeEmptyIntervals() const { 252 bool StatsCounter::IncludeEmptyIntervals() const {
181 return include_empty_intervals_ && !paused_ && !aggregated_counter_->Empty(); 253 return include_empty_intervals_ && !paused_ && !aggregated_counter_->Empty();
182 } 254 }
183 255
184 // StatsCounter sub-classes. 256 // StatsCounter sub-classes.
185 AvgCounter::AvgCounter(Clock* clock, 257 AvgCounter::AvgCounter(Clock* clock,
186 StatsCounterObserver* observer, 258 StatsCounterObserver* observer,
187 bool include_empty_intervals) 259 bool include_empty_intervals)
188 : StatsCounter(clock, 260 : StatsCounter(clock,
189 kDefaultProcessIntervalMs, 261 kDefaultProcessIntervalMs,
190 include_empty_intervals, 262 include_empty_intervals,
191 observer) {} 263 observer) {}
192 264
193 void AvgCounter::Add(int sample) { 265 void AvgCounter::Add(int sample) {
194 StatsCounter::Add(sample); 266 StatsCounter::Add(sample);
195 } 267 }
196 268
197 bool AvgCounter::GetMetric(int* metric) const { 269 bool AvgCounter::GetMetric(int* metric) const {
198 if (num_samples_ == 0) 270 int64_t count = samples_->Count();
271 if (count == 0)
199 return false; 272 return false;
200 *metric = (sum_ + num_samples_ / 2) / num_samples_; 273
274 *metric = (samples_->Sum() + count / 2) / count;
201 return true; 275 return true;
202 } 276 }
203 277
204 int AvgCounter::GetValueForEmptyInterval() const { 278 int AvgCounter::GetValueForEmptyInterval() const {
205 return aggregated_counter_->last_sample(); 279 return aggregated_counter_->last_sample();
206 } 280 }
207 281
208 MaxCounter::MaxCounter(Clock* clock, 282 MaxCounter::MaxCounter(Clock* clock,
209 StatsCounterObserver* observer, 283 StatsCounterObserver* observer,
210 int64_t process_intervals_ms) 284 int64_t process_intervals_ms)
211 : StatsCounter(clock, 285 : StatsCounter(clock,
212 process_intervals_ms, 286 process_intervals_ms,
213 false, // |include_empty_intervals| 287 false, // |include_empty_intervals|
214 observer) {} 288 observer) {}
215 289
216 void MaxCounter::Add(int sample) { 290 void MaxCounter::Add(int sample) {
217 StatsCounter::Add(sample); 291 StatsCounter::Add(sample);
218 } 292 }
219 293
220 bool MaxCounter::GetMetric(int* metric) const { 294 bool MaxCounter::GetMetric(int* metric) const {
221 if (num_samples_ == 0) 295 if (samples_->Empty())
222 return false; 296 return false;
223 *metric = max_; 297
298 *metric = samples_->Max();
224 return true; 299 return true;
225 } 300 }
226 301
227 int MaxCounter::GetValueForEmptyInterval() const { 302 int MaxCounter::GetValueForEmptyInterval() const {
228 RTC_NOTREACHED(); 303 RTC_NOTREACHED();
229 return 0; 304 return 0;
230 } 305 }
231 306
232 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer) 307 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer)
233 : StatsCounter(clock, 308 : StatsCounter(clock,
234 kDefaultProcessIntervalMs, 309 kDefaultProcessIntervalMs,
235 false, // |include_empty_intervals| 310 false, // |include_empty_intervals|
236 observer) {} 311 observer) {}
237 312
238 void PercentCounter::Add(bool sample) { 313 void PercentCounter::Add(bool sample) {
239 StatsCounter::Add(sample ? 1 : 0); 314 StatsCounter::Add(sample ? 1 : 0);
240 } 315 }
241 316
242 bool PercentCounter::GetMetric(int* metric) const { 317 bool PercentCounter::GetMetric(int* metric) const {
243 if (num_samples_ == 0) 318 int64_t count = samples_->Count();
319 if (count == 0)
244 return false; 320 return false;
245 *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_; 321
322 *metric = (samples_->Sum() * 100 + count / 2) / count;
246 return true; 323 return true;
247 } 324 }
248 325
249 int PercentCounter::GetValueForEmptyInterval() const { 326 int PercentCounter::GetValueForEmptyInterval() const {
250 RTC_NOTREACHED(); 327 RTC_NOTREACHED();
251 return 0; 328 return 0;
252 } 329 }
253 330
254 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer) 331 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer)
255 : StatsCounter(clock, 332 : StatsCounter(clock,
256 kDefaultProcessIntervalMs, 333 kDefaultProcessIntervalMs,
257 false, // |include_empty_intervals| 334 false, // |include_empty_intervals|
258 observer) {} 335 observer) {}
259 336
260 void PermilleCounter::Add(bool sample) { 337 void PermilleCounter::Add(bool sample) {
261 StatsCounter::Add(sample ? 1 : 0); 338 StatsCounter::Add(sample ? 1 : 0);
262 } 339 }
263 340
264 bool PermilleCounter::GetMetric(int* metric) const { 341 bool PermilleCounter::GetMetric(int* metric) const {
265 if (num_samples_ == 0) 342 int64_t count = samples_->Count();
343 if (count == 0)
266 return false; 344 return false;
267 *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_; 345
346 *metric = (samples_->Sum() * 1000 + count / 2) / count;
268 return true; 347 return true;
269 } 348 }
270 349
271 int PermilleCounter::GetValueForEmptyInterval() const { 350 int PermilleCounter::GetValueForEmptyInterval() const {
272 RTC_NOTREACHED(); 351 RTC_NOTREACHED();
273 return 0; 352 return 0;
274 } 353 }
275 354
276 RateCounter::RateCounter(Clock* clock, 355 RateCounter::RateCounter(Clock* clock,
277 StatsCounterObserver* observer, 356 StatsCounterObserver* observer,
278 bool include_empty_intervals) 357 bool include_empty_intervals)
279 : StatsCounter(clock, 358 : StatsCounter(clock,
280 kDefaultProcessIntervalMs, 359 kDefaultProcessIntervalMs,
281 include_empty_intervals, 360 include_empty_intervals,
282 observer) {} 361 observer) {}
283 362
284 void RateCounter::Add(int sample) { 363 void RateCounter::Add(int sample) {
285 StatsCounter::Add(sample); 364 StatsCounter::Add(sample);
286 } 365 }
287 366
288 bool RateCounter::GetMetric(int* metric) const { 367 bool RateCounter::GetMetric(int* metric) const {
289 if (num_samples_ == 0) 368 if (samples_->Empty())
290 return false; 369 return false;
291 *metric = (sum_ * 1000 + process_intervals_ms_ / 2) / process_intervals_ms_; 370
371 *metric = (samples_->Sum() * 1000 + process_intervals_ms_ / 2) /
372 process_intervals_ms_;
292 return true; 373 return true;
293 } 374 }
294 375
295 int RateCounter::GetValueForEmptyInterval() const { 376 int RateCounter::GetValueForEmptyInterval() const {
296 return 0; 377 return 0;
297 } 378 }
298 379
299 RateAccCounter::RateAccCounter(Clock* clock, 380 RateAccCounter::RateAccCounter(Clock* clock,
300 StatsCounterObserver* observer, 381 StatsCounterObserver* observer,
301 bool include_empty_intervals) 382 bool include_empty_intervals)
302 : StatsCounter(clock, 383 : StatsCounter(clock,
303 kDefaultProcessIntervalMs, 384 kDefaultProcessIntervalMs,
304 include_empty_intervals, 385 include_empty_intervals,
305 observer) {} 386 observer) {}
306 387
307 void RateAccCounter::Set(int sample) { 388 void RateAccCounter::Set(int sample, uint32_t stream_id) {
308 StatsCounter::Set(sample); 389 StatsCounter::Set(sample, stream_id);
309 } 390 }
310 391
311 bool RateAccCounter::GetMetric(int* metric) const { 392 bool RateAccCounter::GetMetric(int* metric) const {
312 if (num_samples_ == 0 || last_sum_ > sum_) 393 int64_t diff = samples_->Diff();
394 if (diff < 0 || (!include_empty_intervals_ && diff == 0))
313 return false; 395 return false;
314 *metric = ((sum_ - last_sum_) * 1000 + process_intervals_ms_ / 2) / 396
315 process_intervals_ms_; 397 *metric = (diff * 1000 + process_intervals_ms_ / 2) / process_intervals_ms_;
316 return true; 398 return true;
317 } 399 }
318 400
319 int RateAccCounter::GetValueForEmptyInterval() const { 401 int RateAccCounter::GetValueForEmptyInterval() const {
320 return 0; 402 return 0;
321 } 403 }
322 404
323 } // namespace webrtc 405 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/stats_counter.h ('k') | webrtc/video/stats_counter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698