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

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: Created 4 years, 4 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/system_wrappers/include/clock.h" 17 #include "webrtc/system_wrappers/include/clock.h"
16 18
17 namespace webrtc { 19 namespace webrtc {
18 20
19 namespace { 21 namespace {
20 // Periodic time interval for processing samples. 22 // Periodic time interval for processing samples.
21 const int64_t kProcessIntervalMs = 2000; 23 const int64_t kProcessIntervalMs = 2000;
24
25 const uint32_t kSsrc0 = 0;
26
22 } // namespace 27 } // namespace
23 28
24 // Class holding periodically computed metrics. 29 // Class holding periodically computed metrics.
25 class AggregatedCounter { 30 class AggregatedCounter {
26 public: 31 public:
27 AggregatedCounter() : sum_(0) {} 32 AggregatedCounter() : sum_(0) {}
28 ~AggregatedCounter() {} 33 ~AggregatedCounter() {}
29 34
30 void Add(int sample) { 35 void Add(int sample) {
31 sum_ += sample; 36 sum_ += sample;
(...skipping 15 matching lines...) Expand all
47 void Compute() { 52 void Compute() {
48 if (stats_.num_samples == 0) 53 if (stats_.num_samples == 0)
49 return; 54 return;
50 55
51 stats_.average = (sum_ + stats_.num_samples / 2) / stats_.num_samples; 56 stats_.average = (sum_ + stats_.num_samples / 2) / stats_.num_samples;
52 } 57 }
53 int64_t sum_; 58 int64_t sum_;
54 AggregatedStats stats_; 59 AggregatedStats stats_;
55 }; 60 };
56 61
62 // Class holding gathered samples within a process interval.
63 class Samples {
64 public:
65 Samples() {}
66 ~Samples() {}
67
68 void Add(int sample, uint32_t ssrc) { samples_[ssrc].Add(sample); }
69 void Set(int sample, uint32_t ssrc) { samples_[ssrc].Set(sample); }
70
71 int64_t Num() const {
stefan-webrtc 2016/09/08 07:13:34 Should we rename Num and num_ Count() and count_?
åsapersson 2016/09/19 12:45:40 Done.
72 int64_t num = 0;
73 for (const auto& it : samples_)
74 num += it.second.num_;
75 return num;
76 }
77
78 int64_t Sum() const {
79 int64_t sum = 0;
80 for (const auto& it : samples_)
81 sum += it.second.sum_;
82 return sum;
83 }
84
85 int Max() const {
86 int max = std::numeric_limits<int>::min();
87 for (const auto& it : samples_)
88 max = std::max(it.second.max_, max);
89 return max;
90 }
91
92 void Reset() {
93 for (auto& it : samples_)
94 it.second.Reset();
95 }
96
97 int64_t Diff() const {
98 int64_t sum_diff = 0;
99 int num = 0;
100 for (const auto& it : samples_) {
101 if (it.second.num_ > 0) {
102 int64_t diff = it.second.sum_ - it.second.last_sum_;
103 if (diff >= 0) {
104 sum_diff += diff;
105 ++num;
106 }
107 }
108 }
109 return (num > 0) ? sum_diff : -1;
110 }
111
112 private:
113 struct Stats {
114 void Add(int sample) {
115 sum_ += sample;
116 ++num_;
117 max_ = std::max(sample, max_);
118 }
119 void Set(int sample) {
120 sum_ = sample;
121 ++num_;
122 }
123 void Reset() {
124 if (num_ > 0)
125 last_sum_ = sum_;
126 sum_ = 0;
127 num_ = 0;
128 max_ = std::numeric_limits<int>::min();
129 }
130
131 int max_ = std::numeric_limits<int>::min();
132 int64_t num_ = 0;
133 int64_t sum_ = 0;
134 int64_t last_sum_ = 0;
135 };
136
137 std::map<uint32_t, Stats> samples_; // Gathered samples mapped by SSRC.
138 };
139
57 // StatsCounter class. 140 // StatsCounter class.
58 StatsCounter::StatsCounter(Clock* clock, 141 StatsCounter::StatsCounter(Clock* clock,
59 bool include_empty_intervals, 142 bool include_empty_intervals,
60 StatsCounterObserver* observer) 143 StatsCounterObserver* observer)
61 : max_(0), 144 : samples_(new Samples()),
62 sum_(0), 145 include_empty_intervals_(include_empty_intervals),
63 num_samples_(0),
64 last_sum_(0),
65 clock_(clock), 146 clock_(clock),
66 include_empty_intervals_(include_empty_intervals),
67 observer_(observer), 147 observer_(observer),
68 aggregated_counter_(new AggregatedCounter()), 148 aggregated_counter_(new AggregatedCounter()),
69 last_process_time_ms_(-1) {} 149 last_process_time_ms_(-1) {}
70 150
71 StatsCounter::~StatsCounter() {} 151 StatsCounter::~StatsCounter() {}
72 152
73 AggregatedStats StatsCounter::GetStats() { 153 AggregatedStats StatsCounter::GetStats() {
74 return aggregated_counter_->ComputeStats(); 154 return aggregated_counter_->ComputeStats();
75 } 155 }
76 156
(...skipping 14 matching lines...) Expand all
91 if (include_empty_intervals_) { 171 if (include_empty_intervals_) {
92 for (int64_t i = 0; i < num_intervals - 1; ++i) { 172 for (int64_t i = 0; i < num_intervals - 1; ++i) {
93 aggregated_counter_->Add(0); 173 aggregated_counter_->Add(0);
94 if (observer_) 174 if (observer_)
95 observer_->OnMetricUpdated(0); 175 observer_->OnMetricUpdated(0);
96 } 176 }
97 } 177 }
98 return true; 178 return true;
99 } 179 }
100 180
101 void StatsCounter::Set(int sample) { 181 void StatsCounter::Set(int sample, uint32_t ssrc) {
102 TryProcess(); 182 TryProcess();
103 ++num_samples_; 183 samples_->Set(sample, ssrc);
104 sum_ = sample;
105 } 184 }
106 185
107 void StatsCounter::Add(int sample) { 186 void StatsCounter::Add(int sample) {
stefan-webrtc 2016/09/08 07:15:13 Do you think it would be better to just expose the
åsapersson 2016/09/19 12:45:40 It is only one subclass that have use for setting
108 TryProcess(); 187 TryProcess();
109 ++num_samples_; 188 samples_->Add(sample, kSsrc0);
110 sum_ += sample;
111
112 if (num_samples_ == 1)
113 max_ = sample;
114 max_ = std::max(sample, max_);
115 } 189 }
116 190
117 void StatsCounter::TryProcess() { 191 void StatsCounter::TryProcess() {
118 if (!TimeToProcess()) 192 if (!TimeToProcess())
119 return; 193 return;
120 194
121 int metric; 195 int metric;
122 if (GetMetric(&metric)) { 196 if (GetMetric(&metric)) {
123 aggregated_counter_->Add(metric); 197 aggregated_counter_->Add(metric);
124 if (observer_) 198 if (observer_)
125 observer_->OnMetricUpdated(metric); 199 observer_->OnMetricUpdated(metric);
126 } 200 }
127 last_sum_ = sum_; 201
128 sum_ = 0; 202 samples_->Reset();
129 max_ = 0;
130 num_samples_ = 0;
131 } 203 }
132 204
133 // StatsCounter sub-classes. 205 // StatsCounter sub-classes.
134 AvgCounter::AvgCounter(Clock* clock, StatsCounterObserver* observer) 206 AvgCounter::AvgCounter(Clock* clock, StatsCounterObserver* observer)
135 : StatsCounter(clock, 207 : StatsCounter(clock,
136 false, // |include_empty_intervals| 208 false, // |include_empty_intervals|
137 observer) {} 209 observer) {}
138 210
139 void AvgCounter::Add(int sample) { 211 void AvgCounter::Add(int sample) {
140 StatsCounter::Add(sample); 212 StatsCounter::Add(sample);
141 } 213 }
142 214
143 bool AvgCounter::GetMetric(int* metric) const { 215 bool AvgCounter::GetMetric(int* metric) const {
144 if (num_samples_ == 0) 216 int64_t num = samples_->Num();
217 if (num == 0)
145 return false; 218 return false;
stefan-webrtc 2016/09/08 07:13:34 This is a fairly expensive way of checking for no
åsapersson 2016/09/19 12:45:40 The expected size will be one for all sub-classes
146 *metric = (sum_ + num_samples_ / 2) / num_samples_; 219
220 *metric = (samples_->Sum() + num / 2) / num;
147 return true; 221 return true;
148 } 222 }
149 223
150 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer) 224 MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer)
151 : StatsCounter(clock, 225 : StatsCounter(clock,
152 false, // |include_empty_intervals| 226 false, // |include_empty_intervals|
153 observer) {} 227 observer) {}
154 228
155 void MaxCounter::Add(int sample) { 229 void MaxCounter::Add(int sample) {
156 StatsCounter::Add(sample); 230 StatsCounter::Add(sample);
157 } 231 }
158 232
159 bool MaxCounter::GetMetric(int* metric) const { 233 bool MaxCounter::GetMetric(int* metric) const {
160 if (num_samples_ == 0) 234 int64_t num = samples_->Num();
235 if (num == 0)
161 return false; 236 return false;
162 *metric = max_; 237
238 *metric = samples_->Max();
163 return true; 239 return true;
164 } 240 }
165 241
166 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer) 242 PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer)
167 : StatsCounter(clock, 243 : StatsCounter(clock,
168 false, // |include_empty_intervals| 244 false, // |include_empty_intervals|
169 observer) {} 245 observer) {}
170 246
171 void PercentCounter::Add(bool sample) { 247 void PercentCounter::Add(bool sample) {
172 StatsCounter::Add(sample ? 1 : 0); 248 StatsCounter::Add(sample ? 1 : 0);
173 } 249 }
174 250
175 bool PercentCounter::GetMetric(int* metric) const { 251 bool PercentCounter::GetMetric(int* metric) const {
176 if (num_samples_ == 0) 252 int64_t num = samples_->Num();
253 if (num == 0)
177 return false; 254 return false;
178 *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_; 255
256 *metric = (samples_->Sum() * 100 + num / 2) / num;
179 return true; 257 return true;
180 } 258 }
181 259
182 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer) 260 PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer)
183 : StatsCounter(clock, 261 : StatsCounter(clock,
184 false, // |include_empty_intervals| 262 false, // |include_empty_intervals|
185 observer) {} 263 observer) {}
186 264
187 void PermilleCounter::Add(bool sample) { 265 void PermilleCounter::Add(bool sample) {
188 StatsCounter::Add(sample ? 1 : 0); 266 StatsCounter::Add(sample ? 1 : 0);
189 } 267 }
190 268
191 bool PermilleCounter::GetMetric(int* metric) const { 269 bool PermilleCounter::GetMetric(int* metric) const {
192 if (num_samples_ == 0) 270 int64_t num = samples_->Num();
271 if (num == 0)
193 return false; 272 return false;
194 *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_; 273
274 *metric = (samples_->Sum() * 1000 + num / 2) / num;
195 return true; 275 return true;
196 } 276 }
197 277
198 RateCounter::RateCounter(Clock* clock, 278 RateCounter::RateCounter(Clock* clock,
199 StatsCounterObserver* observer, 279 StatsCounterObserver* observer,
200 bool include_empty_intervals) 280 bool include_empty_intervals)
201 : StatsCounter(clock, include_empty_intervals, observer) {} 281 : StatsCounter(clock, include_empty_intervals, observer) {}
202 282
203 void RateCounter::Add(int sample) { 283 void RateCounter::Add(int sample) {
204 StatsCounter::Add(sample); 284 StatsCounter::Add(sample);
205 } 285 }
206 286
207 bool RateCounter::GetMetric(int* metric) const { 287 bool RateCounter::GetMetric(int* metric) const {
208 if (num_samples_ == 0) 288 if (samples_->Num() == 0)
209 return false; 289 return false;
210 *metric = (sum_ * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; 290
291 *metric =
292 (samples_->Sum() * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs;
211 return true; 293 return true;
212 } 294 }
213 295
214 RateAccCounter::RateAccCounter(Clock* clock, 296 RateAccCounter::RateAccCounter(Clock* clock,
215 StatsCounterObserver* observer, 297 StatsCounterObserver* observer,
216 bool include_empty_intervals) 298 bool include_empty_intervals)
217 : StatsCounter(clock, include_empty_intervals, observer) {} 299 : StatsCounter(clock, include_empty_intervals, observer) {}
218 300
219 void RateAccCounter::Set(int sample) { 301 void RateAccCounter::Set(int sample, uint32_t ssrc) {
220 StatsCounter::Set(sample); 302 StatsCounter::Set(sample, ssrc);
221 } 303 }
222 304
223 bool RateAccCounter::GetMetric(int* metric) const { 305 bool RateAccCounter::GetMetric(int* metric) const {
224 if (num_samples_ == 0 || last_sum_ > sum_) 306 if (samples_->Num() == 0)
225 return false; 307 return false;
226 *metric = 308
227 ((sum_ - last_sum_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; 309 int64_t diff = samples_->Diff();
310 if (diff < 0 || (!include_empty_intervals_ && diff == 0))
311 return false;
312
313 *metric = (diff * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs;
228 return true; 314 return true;
229 } 315 }
230 316
231 } // namespace webrtc 317 } // 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