blob: 4ef239aa4cac93302fa50131768b1a91d2cb0da7 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/statistics_calculator.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
13#include <assert.h>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000014#include <string.h> // memset
Henrik Lundin1bb8cf82015-08-25 13:08:04 +020015#include <algorithm>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/audio_coding/neteq/delay_manager.h"
18#include "rtc_base/checks.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010019#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "system_wrappers/include/metrics.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000021
22namespace webrtc {
23
henrik.lundin2979f552017-05-05 05:04:16 -070024namespace {
25size_t AddIntToSizeTWithLowerCap(int a, size_t b) {
26 const size_t ret = b + a;
27 // If a + b is negative, resulting in a negative wrap, cap it to zero instead.
28 static_assert(sizeof(size_t) >= sizeof(int),
29 "int must not be wider than size_t for this to work");
30 return (a < 0 && ret > b) ? 0 : ret;
31}
Henrik Lundin2a8bd092019-04-26 09:47:07 +020032
33constexpr int kInterruptionLenMs = 150;
henrik.lundin2979f552017-05-05 05:04:16 -070034} // namespace
35
henrikg91d6ede2015-09-17 00:24:34 -070036// Allocating the static const so that it can be passed by reference to
37// RTC_DCHECK.
Henrik Lundin1bb8cf82015-08-25 13:08:04 +020038const size_t StatisticsCalculator::kLenWaitingTimes;
39
Henrik Lundin1f4ffe02015-08-19 10:46:50 +020040StatisticsCalculator::PeriodicUmaLogger::PeriodicUmaLogger(
41 const std::string& uma_name,
42 int report_interval_ms,
43 int max_value)
44 : uma_name_(uma_name),
45 report_interval_ms_(report_interval_ms),
46 max_value_(max_value),
Yves Gerey665174f2018-06-19 15:03:05 +020047 timer_(0) {}
Henrik Lundin1f4ffe02015-08-19 10:46:50 +020048
49StatisticsCalculator::PeriodicUmaLogger::~PeriodicUmaLogger() = default;
50
51void StatisticsCalculator::PeriodicUmaLogger::AdvanceClock(int step_ms) {
52 timer_ += step_ms;
53 if (timer_ < report_interval_ms_) {
54 return;
55 }
56 LogToUma(Metric());
57 Reset();
58 timer_ -= report_interval_ms_;
henrikg91d6ede2015-09-17 00:24:34 -070059 RTC_DCHECK_GE(timer_, 0);
Henrik Lundin1f4ffe02015-08-19 10:46:50 +020060}
61
62void StatisticsCalculator::PeriodicUmaLogger::LogToUma(int value) const {
asapersson53805322015-12-21 01:46:20 -080063 RTC_HISTOGRAM_COUNTS_SPARSE(uma_name_, value, 1, max_value_, 50);
Henrik Lundin1f4ffe02015-08-19 10:46:50 +020064}
65
66StatisticsCalculator::PeriodicUmaCount::PeriodicUmaCount(
67 const std::string& uma_name,
68 int report_interval_ms,
69 int max_value)
Yves Gerey665174f2018-06-19 15:03:05 +020070 : PeriodicUmaLogger(uma_name, report_interval_ms, max_value) {}
Henrik Lundin1f4ffe02015-08-19 10:46:50 +020071
72StatisticsCalculator::PeriodicUmaCount::~PeriodicUmaCount() {
73 // Log the count for the current (incomplete) interval.
74 LogToUma(Metric());
75}
76
77void StatisticsCalculator::PeriodicUmaCount::RegisterSample() {
78 ++counter_;
79}
80
81int StatisticsCalculator::PeriodicUmaCount::Metric() const {
82 return counter_;
83}
84
85void StatisticsCalculator::PeriodicUmaCount::Reset() {
86 counter_ = 0;
87}
88
89StatisticsCalculator::PeriodicUmaAverage::PeriodicUmaAverage(
90 const std::string& uma_name,
91 int report_interval_ms,
92 int max_value)
Yves Gerey665174f2018-06-19 15:03:05 +020093 : PeriodicUmaLogger(uma_name, report_interval_ms, max_value) {}
Henrik Lundin1f4ffe02015-08-19 10:46:50 +020094
95StatisticsCalculator::PeriodicUmaAverage::~PeriodicUmaAverage() {
96 // Log the average for the current (incomplete) interval.
97 LogToUma(Metric());
98}
99
100void StatisticsCalculator::PeriodicUmaAverage::RegisterSample(int value) {
101 sum_ += value;
102 ++counter_;
103}
104
105int StatisticsCalculator::PeriodicUmaAverage::Metric() const {
henrik.lundine5942132016-02-09 00:35:53 -0800106 return counter_ == 0 ? 0 : static_cast<int>(sum_ / counter_);
Henrik Lundin1f4ffe02015-08-19 10:46:50 +0200107}
108
109void StatisticsCalculator::PeriodicUmaAverage::Reset() {
110 sum_ = 0.0;
111 counter_ = 0;
112}
113
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000114StatisticsCalculator::StatisticsCalculator()
115 : preemptive_samples_(0),
116 accelerate_samples_(0),
117 added_zero_samples_(0),
minyue@webrtc.org7d721ee2015-02-18 10:01:53 +0000118 expanded_speech_samples_(0),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000119 expanded_noise_samples_(0),
120 discarded_packets_(0),
121 lost_timestamps_(0),
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000122 timestamps_since_last_report_(0),
Henrik Lundin1f4ffe02015-08-19 10:46:50 +0200123 secondary_decoded_samples_(0),
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200124 discarded_secondary_packets_(0),
Henrik Lundin1f4ffe02015-08-19 10:46:50 +0200125 delayed_packet_outage_counter_(
126 "WebRTC.Audio.DelayedPacketOutageEventsPerMinute",
127 60000, // 60 seconds report interval.
128 100),
129 excess_buffer_delay_("WebRTC.Audio.AverageExcessBufferDelayMs",
130 60000, // 60 seconds report interval.
Minyue Li34d990f2018-10-16 16:55:52 +0200131 1000),
132 buffer_full_counter_("WebRTC.Audio.JitterBufferFullPerMinute",
133 60000, // 60 seconds report interval.
134 100) {}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000135
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200136StatisticsCalculator::~StatisticsCalculator() = default;
137
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000138void StatisticsCalculator::Reset() {
139 preemptive_samples_ = 0;
140 accelerate_samples_ = 0;
141 added_zero_samples_ = 0;
minyue@webrtc.org7d721ee2015-02-18 10:01:53 +0000142 expanded_speech_samples_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000143 expanded_noise_samples_ = 0;
minyue@webrtc.org2c1bcf22015-02-17 10:17:09 +0000144 secondary_decoded_samples_ = 0;
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200145 discarded_secondary_packets_ = 0;
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200146 waiting_times_.clear();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000147}
148
149void StatisticsCalculator::ResetMcu() {
150 discarded_packets_ = 0;
151 lost_timestamps_ = 0;
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000152 timestamps_since_last_report_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000153}
154
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +0200155void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples,
156 bool is_new_concealment_event) {
minyue@webrtc.org7d721ee2015-02-18 10:01:53 +0000157 expanded_speech_samples_ += num_samples;
Alex Narest7ff6ca52018-02-07 18:46:33 +0100158 ConcealedSamplesCorrection(rtc::dchecked_cast<int>(num_samples), true);
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +0200159 lifetime_stats_.concealment_events += is_new_concealment_event;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000160}
161
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +0200162void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples,
163 bool is_new_concealment_event) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000164 expanded_noise_samples_ += num_samples;
Alex Narest7ff6ca52018-02-07 18:46:33 +0100165 ConcealedSamplesCorrection(rtc::dchecked_cast<int>(num_samples), false);
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +0200166 lifetime_stats_.concealment_events += is_new_concealment_event;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000167}
168
henrik.lundin2979f552017-05-05 05:04:16 -0700169void StatisticsCalculator::ExpandedVoiceSamplesCorrection(int num_samples) {
170 expanded_speech_samples_ =
171 AddIntToSizeTWithLowerCap(num_samples, expanded_speech_samples_);
Alex Narest7ff6ca52018-02-07 18:46:33 +0100172 ConcealedSamplesCorrection(num_samples, true);
henrik.lundin2979f552017-05-05 05:04:16 -0700173}
174
175void StatisticsCalculator::ExpandedNoiseSamplesCorrection(int num_samples) {
176 expanded_noise_samples_ =
177 AddIntToSizeTWithLowerCap(num_samples, expanded_noise_samples_);
Alex Narest7ff6ca52018-02-07 18:46:33 +0100178 ConcealedSamplesCorrection(num_samples, false);
Henrik Lundinac0a5032017-09-25 12:22:46 +0200179}
180
Henrik Lundin2a8bd092019-04-26 09:47:07 +0200181void StatisticsCalculator::DecodedOutputPlayed() {
182 decoded_output_played_ = true;
183}
184
185void StatisticsCalculator::EndExpandEvent(int fs_hz) {
186 RTC_DCHECK_GE(lifetime_stats_.concealed_samples,
187 concealed_samples_at_event_end_);
188 const int event_duration_ms =
189 1000 *
190 (lifetime_stats_.concealed_samples - concealed_samples_at_event_end_) /
191 fs_hz;
192 if (event_duration_ms >= kInterruptionLenMs && decoded_output_played_) {
193 lifetime_stats_.interruption_count++;
194 lifetime_stats_.total_interruption_duration_ms += event_duration_ms;
195 }
196 concealed_samples_at_event_end_ = lifetime_stats_.concealed_samples;
197}
198
Alex Narest7ff6ca52018-02-07 18:46:33 +0100199void StatisticsCalculator::ConcealedSamplesCorrection(int num_samples,
200 bool is_voice) {
Henrik Lundinac0a5032017-09-25 12:22:46 +0200201 if (num_samples < 0) {
202 // Store negative correction to subtract from future positive additions.
203 // See also the function comment in the header file.
204 concealed_samples_correction_ -= num_samples;
Ivo Creusenbf4a2212019-04-24 14:06:24 +0200205 if (!is_voice) {
206 silent_concealed_samples_correction_ -= num_samples;
Alex Narest7ff6ca52018-02-07 18:46:33 +0100207 }
Henrik Lundinac0a5032017-09-25 12:22:46 +0200208 return;
209 }
210
211 const size_t canceled_out =
212 std::min(static_cast<size_t>(num_samples), concealed_samples_correction_);
213 concealed_samples_correction_ -= canceled_out;
214 lifetime_stats_.concealed_samples += num_samples - canceled_out;
Alex Narest7ff6ca52018-02-07 18:46:33 +0100215
Ivo Creusenbf4a2212019-04-24 14:06:24 +0200216 if (!is_voice) {
217 const size_t silent_canceled_out = std::min(
218 static_cast<size_t>(num_samples), silent_concealed_samples_correction_);
219 silent_concealed_samples_correction_ -= silent_canceled_out;
220 lifetime_stats_.silent_concealed_samples +=
221 num_samples - silent_canceled_out;
Alex Narest7ff6ca52018-02-07 18:46:33 +0100222 }
henrik.lundin2979f552017-05-05 05:04:16 -0700223}
224
Peter Kastingdce40cf2015-08-24 14:52:23 -0700225void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000226 preemptive_samples_ += num_samples;
Ivo Creusend1c2f782018-09-13 14:39:55 +0200227 operations_and_state_.preemptive_samples += num_samples;
Ivo Creusenbf4a2212019-04-24 14:06:24 +0200228 lifetime_stats_.inserted_samples_for_deceleration += num_samples;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000229}
230
Peter Kastingdce40cf2015-08-24 14:52:23 -0700231void StatisticsCalculator::AcceleratedSamples(size_t num_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000232 accelerate_samples_ += num_samples;
Ivo Creusend1c2f782018-09-13 14:39:55 +0200233 operations_and_state_.accelerate_samples += num_samples;
Ivo Creusenbf4a2212019-04-24 14:06:24 +0200234 lifetime_stats_.removed_samples_for_acceleration += num_samples;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000235}
236
Peter Kastingdce40cf2015-08-24 14:52:23 -0700237void StatisticsCalculator::AddZeros(size_t num_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000238 added_zero_samples_ += num_samples;
239}
240
Peter Kastingdce40cf2015-08-24 14:52:23 -0700241void StatisticsCalculator::PacketsDiscarded(size_t num_packets) {
Ivo Creusen2db46b02018-12-14 16:49:12 +0100242 operations_and_state_.discarded_primary_packets += num_packets;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000243}
244
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200245void StatisticsCalculator::SecondaryPacketsDiscarded(size_t num_packets) {
246 discarded_secondary_packets_ += num_packets;
Ivo Creusenbf4a2212019-04-24 14:06:24 +0200247 lifetime_stats_.fec_packets_discarded += num_packets;
248}
249
250void StatisticsCalculator::SecondaryPacketsReceived(size_t num_packets) {
251 lifetime_stats_.fec_packets_received += num_packets;
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200252}
253
Peter Kastingdce40cf2015-08-24 14:52:23 -0700254void StatisticsCalculator::LostSamples(size_t num_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000255 lost_timestamps_ += num_samples;
256}
257
Peter Kastingdce40cf2015-08-24 14:52:23 -0700258void StatisticsCalculator::IncreaseCounter(size_t num_samples, int fs_hz) {
259 const int time_step_ms =
260 rtc::CheckedDivExact(static_cast<int>(1000 * num_samples), fs_hz);
Henrik Lundin1f4ffe02015-08-19 10:46:50 +0200261 delayed_packet_outage_counter_.AdvanceClock(time_step_ms);
262 excess_buffer_delay_.AdvanceClock(time_step_ms);
Minyue Li34d990f2018-10-16 16:55:52 +0200263 buffer_full_counter_.AdvanceClock(time_step_ms);
Peter Kastingb7e50542015-06-11 12:55:50 -0700264 timestamps_since_last_report_ += static_cast<uint32_t>(num_samples);
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000265 if (timestamps_since_last_report_ >
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000266 static_cast<uint32_t>(fs_hz * kMaxReportPeriod)) {
267 lost_timestamps_ = 0;
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000268 timestamps_since_last_report_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000269 discarded_packets_ = 0;
270 }
Steve Anton2dbc69f2017-08-24 17:15:13 -0700271 lifetime_stats_.total_samples_received += num_samples;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000272}
273
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200274void StatisticsCalculator::JitterBufferDelay(size_t num_samples,
275 uint64_t waiting_time_ms) {
276 lifetime_stats_.jitter_buffer_delay_ms += waiting_time_ms * num_samples;
Chen Xing0acffb52019-01-15 15:46:29 +0100277 lifetime_stats_.jitter_buffer_emitted_count += num_samples;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200278}
279
minyue@webrtc.org2c1bcf22015-02-17 10:17:09 +0000280void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) {
281 secondary_decoded_samples_ += num_samples;
282}
283
Ivo Creusendc6d5532018-09-27 11:43:42 +0200284void StatisticsCalculator::FlushedPacketBuffer() {
285 operations_and_state_.packet_buffer_flushes++;
Minyue Li34d990f2018-10-16 16:55:52 +0200286 buffer_full_counter_.RegisterSample();
Ivo Creusendc6d5532018-09-27 11:43:42 +0200287}
288
Jakob Ivarsson44507082019-03-05 16:59:03 +0100289void StatisticsCalculator::ReceivedPacket() {
290 ++lifetime_stats_.jitter_buffer_packets_received;
291}
292
293void StatisticsCalculator::RelativePacketArrivalDelay(size_t delay_ms) {
294 lifetime_stats_.relative_packet_arrival_delay_ms += delay_ms;
295}
296
Jakob Ivarsson352ce5c2018-11-27 12:52:16 +0100297void StatisticsCalculator::LogDelayedPacketOutageEvent(int num_samples,
298 int fs_hz) {
299 int outage_duration_ms = num_samples / (fs_hz / 1000);
asaperssona2c58e22016-03-07 01:52:59 -0800300 RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs",
301 outage_duration_ms, 1 /* min */, 2000 /* max */,
302 100 /* bucket count */);
Henrik Lundin1f4ffe02015-08-19 10:46:50 +0200303 delayed_packet_outage_counter_.RegisterSample();
Jakob Ivarsson352ce5c2018-11-27 12:52:16 +0100304 lifetime_stats_.delayed_packet_outage_samples += num_samples;
Henrik Lundinbef77e22015-08-18 14:58:09 +0200305}
306
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000307void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) {
Henrik Lundin1f4ffe02015-08-19 10:46:50 +0200308 excess_buffer_delay_.RegisterSample(waiting_time_ms);
henrikg91d6ede2015-09-17 00:24:34 -0700309 RTC_DCHECK_LE(waiting_times_.size(), kLenWaitingTimes);
henrik.lundin1e346b22015-08-27 13:41:02 -0700310 if (waiting_times_.size() == kLenWaitingTimes) {
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200311 // Erase first value.
312 waiting_times_.pop_front();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000313 }
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200314 waiting_times_.push_back(waiting_time_ms);
Ivo Creusend1c2f782018-09-13 14:39:55 +0200315 operations_and_state_.last_waiting_time_ms = waiting_time_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000316}
317
Yves Gerey665174f2018-06-19 15:03:05 +0200318void StatisticsCalculator::GetNetworkStatistics(int fs_hz,
319 size_t num_samples_in_buffers,
320 size_t samples_per_packet,
321 NetEqNetworkStatistics* stats) {
Henrik Lundindccfc402017-09-25 12:30:58 +0200322 RTC_DCHECK_GT(fs_hz, 0);
323 RTC_DCHECK(stats);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000324
325 stats->added_zero_samples = added_zero_samples_;
Peter Kastingb7e50542015-06-11 12:55:50 -0700326 stats->current_buffer_size_ms =
327 static_cast<uint16_t>(num_samples_in_buffers * 1000 / fs_hz);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000328
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000329 stats->packet_loss_rate =
330 CalculateQ14Ratio(lost_timestamps_, timestamps_since_last_report_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000331
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000332 stats->accelerate_rate =
333 CalculateQ14Ratio(accelerate_samples_, timestamps_since_last_report_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000334
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000335 stats->preemptive_rate =
336 CalculateQ14Ratio(preemptive_samples_, timestamps_since_last_report_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000337
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000338 stats->expand_rate =
minyue@webrtc.org7d721ee2015-02-18 10:01:53 +0000339 CalculateQ14Ratio(expanded_speech_samples_ + expanded_noise_samples_,
henrik.lundin@webrtc.org5e3d7c72014-10-08 12:10:53 +0000340 timestamps_since_last_report_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000341
Yves Gerey665174f2018-06-19 15:03:05 +0200342 stats->speech_expand_rate = CalculateQ14Ratio(expanded_speech_samples_,
343 timestamps_since_last_report_);
minyue@webrtc.org7d721ee2015-02-18 10:01:53 +0000344
Yves Gerey665174f2018-06-19 15:03:05 +0200345 stats->secondary_decoded_rate = CalculateQ14Ratio(
346 secondary_decoded_samples_, timestamps_since_last_report_);
minyue@webrtc.org2c1bcf22015-02-17 10:17:09 +0000347
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200348 const size_t discarded_secondary_samples =
349 discarded_secondary_packets_ * samples_per_packet;
Yves Gerey665174f2018-06-19 15:03:05 +0200350 stats->secondary_discarded_rate =
351 CalculateQ14Ratio(discarded_secondary_samples,
352 static_cast<uint32_t>(discarded_secondary_samples +
353 secondary_decoded_samples_));
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200354
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200355 if (waiting_times_.size() == 0) {
356 stats->mean_waiting_time_ms = -1;
357 stats->median_waiting_time_ms = -1;
358 stats->min_waiting_time_ms = -1;
359 stats->max_waiting_time_ms = -1;
360 } else {
361 std::sort(waiting_times_.begin(), waiting_times_.end());
362 // Find mid-point elements. If the size is odd, the two values
363 // |middle_left| and |middle_right| will both be the one middle element; if
364 // the size is even, they will be the the two neighboring elements at the
365 // middle of the list.
366 const int middle_left = waiting_times_[(waiting_times_.size() - 1) / 2];
367 const int middle_right = waiting_times_[waiting_times_.size() / 2];
368 // Calculate the average of the two. (Works also for odd sizes.)
369 stats->median_waiting_time_ms = (middle_left + middle_right) / 2;
370 stats->min_waiting_time_ms = waiting_times_.front();
371 stats->max_waiting_time_ms = waiting_times_.back();
372 double sum = 0;
373 for (auto time : waiting_times_) {
374 sum += time;
375 }
376 stats->mean_waiting_time_ms = static_cast<int>(sum / waiting_times_.size());
377 }
378
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000379 // Reset counters.
380 ResetMcu();
381 Reset();
382}
383
Henrik Lundindccfc402017-09-25 12:30:58 +0200384void StatisticsCalculator::PopulateDelayManagerStats(
385 int ms_per_packet,
386 const DelayManager& delay_manager,
387 NetEqNetworkStatistics* stats) {
388 RTC_DCHECK(stats);
389 stats->preferred_buffer_size_ms =
390 (delay_manager.TargetLevel() >> 8) * ms_per_packet;
391 stats->jitter_peaks_found = delay_manager.PeakFound();
392 stats->clockdrift_ppm =
393 rtc::saturated_cast<int32_t>(delay_manager.EstimatedClockDriftPpm());
394}
395
Steve Anton2dbc69f2017-08-24 17:15:13 -0700396NetEqLifetimeStatistics StatisticsCalculator::GetLifetimeStatistics() const {
397 return lifetime_stats_;
398}
399
Ivo Creusend1c2f782018-09-13 14:39:55 +0200400NetEqOperationsAndState StatisticsCalculator::GetOperationsAndState() const {
401 return operations_and_state_;
402}
403
Peter Kastingdce40cf2015-08-24 14:52:23 -0700404uint16_t StatisticsCalculator::CalculateQ14Ratio(size_t numerator,
Peter Kastingb7e50542015-06-11 12:55:50 -0700405 uint32_t denominator) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000406 if (numerator == 0) {
407 return 0;
408 } else if (numerator < denominator) {
409 // Ratio must be smaller than 1 in Q14.
410 assert((numerator << 14) / denominator < (1 << 14));
Peter Kastingb7e50542015-06-11 12:55:50 -0700411 return static_cast<uint16_t>((numerator << 14) / denominator);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000412 } else {
413 // Will not produce a ratio larger than 1, since this is probably an error.
414 return 1 << 14;
415 }
416}
417
418} // namespace webrtc