Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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/modules/audio_coding/neteq/statistics_calculator.h" | 11 #include "webrtc/modules/audio_coding/neteq/statistics_calculator.h" |
| 12 | 12 |
| 13 #include <assert.h> | 13 #include <assert.h> |
| 14 #include <string.h> // memset | 14 #include <string.h> // memset |
| 15 #include <algorithm> | |
| 15 | 16 |
| 16 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 17 #include "webrtc/base/safe_conversions.h" | 18 #include "webrtc/base/safe_conversions.h" |
| 18 #include "webrtc/modules/audio_coding/neteq/decision_logic.h" | 19 #include "webrtc/modules/audio_coding/neteq/decision_logic.h" |
| 19 #include "webrtc/modules/audio_coding/neteq/delay_manager.h" | 20 #include "webrtc/modules/audio_coding/neteq/delay_manager.h" |
| 20 #include "webrtc/system_wrappers/interface/metrics.h" | 21 #include "webrtc/system_wrappers/interface/metrics.h" |
| 21 | 22 |
| 22 namespace webrtc { | 23 namespace webrtc { |
| 23 | 24 |
| 25 // Allocating the static const so that it can be passed by reference to DCHECK. | |
| 26 const size_t StatisticsCalculator::kLenWaitingTimes; | |
| 27 | |
| 24 StatisticsCalculator::PeriodicUmaLogger::PeriodicUmaLogger( | 28 StatisticsCalculator::PeriodicUmaLogger::PeriodicUmaLogger( |
| 25 const std::string& uma_name, | 29 const std::string& uma_name, |
| 26 int report_interval_ms, | 30 int report_interval_ms, |
| 27 int max_value) | 31 int max_value) |
| 28 : uma_name_(uma_name), | 32 : uma_name_(uma_name), |
| 29 report_interval_ms_(report_interval_ms), | 33 report_interval_ms_(report_interval_ms), |
| 30 max_value_(max_value), | 34 max_value_(max_value), |
| 31 timer_(0) { | 35 timer_(0) { |
| 32 } | 36 } |
| 33 | 37 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 | 104 |
| 101 StatisticsCalculator::StatisticsCalculator() | 105 StatisticsCalculator::StatisticsCalculator() |
| 102 : preemptive_samples_(0), | 106 : preemptive_samples_(0), |
| 103 accelerate_samples_(0), | 107 accelerate_samples_(0), |
| 104 added_zero_samples_(0), | 108 added_zero_samples_(0), |
| 105 expanded_speech_samples_(0), | 109 expanded_speech_samples_(0), |
| 106 expanded_noise_samples_(0), | 110 expanded_noise_samples_(0), |
| 107 discarded_packets_(0), | 111 discarded_packets_(0), |
| 108 lost_timestamps_(0), | 112 lost_timestamps_(0), |
| 109 timestamps_since_last_report_(0), | 113 timestamps_since_last_report_(0), |
| 110 len_waiting_times_(0), | |
| 111 next_waiting_time_index_(0), | |
| 112 secondary_decoded_samples_(0), | 114 secondary_decoded_samples_(0), |
| 113 delayed_packet_outage_counter_( | 115 delayed_packet_outage_counter_( |
| 114 "WebRTC.Audio.DelayedPacketOutageEventsPerMinute", | 116 "WebRTC.Audio.DelayedPacketOutageEventsPerMinute", |
| 115 60000, // 60 seconds report interval. | 117 60000, // 60 seconds report interval. |
| 116 100), | 118 100), |
| 117 excess_buffer_delay_("WebRTC.Audio.AverageExcessBufferDelayMs", | 119 excess_buffer_delay_("WebRTC.Audio.AverageExcessBufferDelayMs", |
| 118 60000, // 60 seconds report interval. | 120 60000, // 60 seconds report interval. |
| 119 1000) { | 121 1000) { |
| 120 memset(waiting_times_, 0, kLenWaitingTimes * sizeof(waiting_times_[0])); | |
| 121 } | 122 } |
| 122 | 123 |
| 124 StatisticsCalculator::~StatisticsCalculator() = default; | |
| 125 | |
| 123 void StatisticsCalculator::Reset() { | 126 void StatisticsCalculator::Reset() { |
| 124 preemptive_samples_ = 0; | 127 preemptive_samples_ = 0; |
| 125 accelerate_samples_ = 0; | 128 accelerate_samples_ = 0; |
| 126 added_zero_samples_ = 0; | 129 added_zero_samples_ = 0; |
| 127 expanded_speech_samples_ = 0; | 130 expanded_speech_samples_ = 0; |
| 128 expanded_noise_samples_ = 0; | 131 expanded_noise_samples_ = 0; |
| 129 secondary_decoded_samples_ = 0; | 132 secondary_decoded_samples_ = 0; |
| 133 waiting_times_.clear(); | |
| 130 } | 134 } |
| 131 | 135 |
| 132 void StatisticsCalculator::ResetMcu() { | 136 void StatisticsCalculator::ResetMcu() { |
| 133 discarded_packets_ = 0; | 137 discarded_packets_ = 0; |
| 134 lost_timestamps_ = 0; | 138 lost_timestamps_ = 0; |
| 135 timestamps_since_last_report_ = 0; | 139 timestamps_since_last_report_ = 0; |
| 136 } | 140 } |
| 137 | 141 |
| 138 void StatisticsCalculator::ResetWaitingTimeStatistics() { | |
| 139 memset(waiting_times_, 0, kLenWaitingTimes * sizeof(waiting_times_[0])); | |
| 140 len_waiting_times_ = 0; | |
| 141 next_waiting_time_index_ = 0; | |
| 142 } | |
| 143 | |
| 144 void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples) { | 142 void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples) { |
| 145 expanded_speech_samples_ += num_samples; | 143 expanded_speech_samples_ += num_samples; |
| 146 } | 144 } |
| 147 | 145 |
| 148 void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples) { | 146 void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples) { |
| 149 expanded_noise_samples_ += num_samples; | 147 expanded_noise_samples_ += num_samples; |
| 150 } | 148 } |
| 151 | 149 |
| 152 void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) { | 150 void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) { |
| 153 preemptive_samples_ += num_samples; | 151 preemptive_samples_ += num_samples; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 | 187 |
| 190 void StatisticsCalculator::LogDelayedPacketOutageEvent(int outage_duration_ms) { | 188 void StatisticsCalculator::LogDelayedPacketOutageEvent(int outage_duration_ms) { |
| 191 RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs", | 189 RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs", |
| 192 outage_duration_ms, 1 /* min */, 2000 /* max */, | 190 outage_duration_ms, 1 /* min */, 2000 /* max */, |
| 193 100 /* bucket count */); | 191 100 /* bucket count */); |
| 194 delayed_packet_outage_counter_.RegisterSample(); | 192 delayed_packet_outage_counter_.RegisterSample(); |
| 195 } | 193 } |
| 196 | 194 |
| 197 void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) { | 195 void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) { |
| 198 excess_buffer_delay_.RegisterSample(waiting_time_ms); | 196 excess_buffer_delay_.RegisterSample(waiting_time_ms); |
| 199 assert(next_waiting_time_index_ < kLenWaitingTimes); | 197 DCHECK_LE(waiting_times_.size(), kLenWaitingTimes); |
| 200 waiting_times_[next_waiting_time_index_] = waiting_time_ms; | 198 while (waiting_times_.size() >= kLenWaitingTimes) { |
|
Peter Kasting
2015/08/25 22:00:02
Drive-by nit: This would violate the Chromium styl
hlundin-webrtc
2015/08/27 11:51:54
Fixed in https://codereview.webrtc.org/1319953002/
| |
| 201 next_waiting_time_index_++; | 199 // Erase first value. |
| 202 if (next_waiting_time_index_ >= kLenWaitingTimes) { | 200 waiting_times_.pop_front(); |
| 203 next_waiting_time_index_ = 0; | |
| 204 } | 201 } |
| 205 if (len_waiting_times_ < kLenWaitingTimes) { | 202 waiting_times_.push_back(waiting_time_ms); |
| 206 len_waiting_times_++; | |
| 207 } | |
| 208 } | 203 } |
| 209 | 204 |
| 210 void StatisticsCalculator::GetNetworkStatistics( | 205 void StatisticsCalculator::GetNetworkStatistics( |
| 211 int fs_hz, | 206 int fs_hz, |
| 212 size_t num_samples_in_buffers, | 207 size_t num_samples_in_buffers, |
| 213 size_t samples_per_packet, | 208 size_t samples_per_packet, |
| 214 const DelayManager& delay_manager, | 209 const DelayManager& delay_manager, |
| 215 const DecisionLogic& decision_logic, | 210 const DecisionLogic& decision_logic, |
| 216 NetEqNetworkStatistics *stats) { | 211 NetEqNetworkStatistics *stats) { |
| 217 if (fs_hz <= 0 || !stats) { | 212 if (fs_hz <= 0 || !stats) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 247 timestamps_since_last_report_); | 242 timestamps_since_last_report_); |
| 248 | 243 |
| 249 stats->speech_expand_rate = | 244 stats->speech_expand_rate = |
| 250 CalculateQ14Ratio(expanded_speech_samples_, | 245 CalculateQ14Ratio(expanded_speech_samples_, |
| 251 timestamps_since_last_report_); | 246 timestamps_since_last_report_); |
| 252 | 247 |
| 253 stats->secondary_decoded_rate = | 248 stats->secondary_decoded_rate = |
| 254 CalculateQ14Ratio(secondary_decoded_samples_, | 249 CalculateQ14Ratio(secondary_decoded_samples_, |
| 255 timestamps_since_last_report_); | 250 timestamps_since_last_report_); |
| 256 | 251 |
| 252 if (waiting_times_.size() == 0) { | |
| 253 stats->mean_waiting_time_ms = -1; | |
| 254 stats->median_waiting_time_ms = -1; | |
| 255 stats->min_waiting_time_ms = -1; | |
| 256 stats->max_waiting_time_ms = -1; | |
| 257 } else { | |
| 258 std::sort(waiting_times_.begin(), waiting_times_.end()); | |
| 259 // Find mid-point elements. If the size is odd, the two values | |
| 260 // |middle_left| and |middle_right| will both be the one middle element; if | |
| 261 // the size is even, they will be the the two neighboring elements at the | |
| 262 // middle of the list. | |
| 263 const int middle_left = waiting_times_[(waiting_times_.size() - 1) / 2]; | |
| 264 const int middle_right = waiting_times_[waiting_times_.size() / 2]; | |
| 265 // Calculate the average of the two. (Works also for odd sizes.) | |
| 266 stats->median_waiting_time_ms = (middle_left + middle_right) / 2; | |
| 267 stats->min_waiting_time_ms = waiting_times_.front(); | |
| 268 stats->max_waiting_time_ms = waiting_times_.back(); | |
| 269 double sum = 0; | |
| 270 for (auto time : waiting_times_) { | |
| 271 sum += time; | |
| 272 } | |
| 273 stats->mean_waiting_time_ms = static_cast<int>(sum / waiting_times_.size()); | |
| 274 } | |
| 275 | |
| 257 // Reset counters. | 276 // Reset counters. |
| 258 ResetMcu(); | 277 ResetMcu(); |
| 259 Reset(); | 278 Reset(); |
| 260 } | 279 } |
| 261 | 280 |
| 262 void StatisticsCalculator::WaitingTimes(std::vector<int>* waiting_times) { | |
| 263 if (!waiting_times) { | |
| 264 return; | |
| 265 } | |
| 266 waiting_times->assign(waiting_times_, waiting_times_ + len_waiting_times_); | |
| 267 ResetWaitingTimeStatistics(); | |
| 268 } | |
| 269 | |
| 270 uint16_t StatisticsCalculator::CalculateQ14Ratio(size_t numerator, | 281 uint16_t StatisticsCalculator::CalculateQ14Ratio(size_t numerator, |
| 271 uint32_t denominator) { | 282 uint32_t denominator) { |
| 272 if (numerator == 0) { | 283 if (numerator == 0) { |
| 273 return 0; | 284 return 0; |
| 274 } else if (numerator < denominator) { | 285 } else if (numerator < denominator) { |
| 275 // Ratio must be smaller than 1 in Q14. | 286 // Ratio must be smaller than 1 in Q14. |
| 276 assert((numerator << 14) / denominator < (1 << 14)); | 287 assert((numerator << 14) / denominator < (1 << 14)); |
| 277 return static_cast<uint16_t>((numerator << 14) / denominator); | 288 return static_cast<uint16_t>((numerator << 14) / denominator); |
| 278 } else { | 289 } else { |
| 279 // Will not produce a ratio larger than 1, since this is probably an error. | 290 // Will not produce a ratio larger than 1, since this is probably an error. |
| 280 return 1 << 14; | 291 return 1 << 14; |
| 281 } | 292 } |
| 282 } | 293 } |
| 283 | 294 |
| 284 } // namespace webrtc | 295 } // namespace webrtc |
| OLD | NEW |