1 /* 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 11 #include "webrtc/modules/audio_coding/neteq/statistics_calculator.h" 12 13 #include <assert.h> 14 #include <string.h> // memset 15 16 #include "webrtc/modules/audio_coding/neteq/decision_logic.h" 17 #include "webrtc/modules/audio_coding/neteq/delay_manager.h" 18 19 namespace webrtc { 20 21 StatisticsCalculator::StatisticsCalculator() 22 : preemptive_samples_(0), 23 accelerate_samples_(0), 24 added_zero_samples_(0), 25 expanded_voice_samples_(0), 26 expanded_noise_samples_(0), 27 discarded_packets_(0), 28 lost_timestamps_(0), 29 last_report_timestamp_(0), 30 len_waiting_times_(0), 31 next_waiting_time_index_(0) { 32 memset(waiting_times_, 0, kLenWaitingTimes * sizeof(waiting_times_[0])); 33 } 34 35 void StatisticsCalculator::Reset() { 36 preemptive_samples_ = 0; 37 accelerate_samples_ = 0; 38 added_zero_samples_ = 0; 39 expanded_voice_samples_ = 0; 40 expanded_noise_samples_ = 0; 41 } 42 43 void StatisticsCalculator::ResetMcu() { 44 discarded_packets_ = 0; 45 lost_timestamps_ = 0; 46 last_report_timestamp_ = 0; 47 } 48 49 void StatisticsCalculator::ResetWaitingTimeStatistics() { 50 memset(waiting_times_, 0, kLenWaitingTimes * sizeof(waiting_times_[0])); 51 len_waiting_times_ = 0; 52 next_waiting_time_index_ = 0; 53 } 54 55 void StatisticsCalculator::ExpandedVoiceSamples(int num_samples) { 56 expanded_voice_samples_ += num_samples; 57 } 58 59 void StatisticsCalculator::ExpandedNoiseSamples(int num_samples) { 60 expanded_noise_samples_ += num_samples; 61 } 62 63 void StatisticsCalculator::PreemptiveExpandedSamples(int num_samples) { 64 preemptive_samples_ += num_samples; 65 } 66 67 void StatisticsCalculator::AcceleratedSamples(int num_samples) { 68 accelerate_samples_ += num_samples; 69 } 70 71 void StatisticsCalculator::AddZeros(int num_samples) { 72 added_zero_samples_ += num_samples; 73 } 74 75 void StatisticsCalculator::PacketsDiscarded(int num_packets) { 76 discarded_packets_ += num_packets; 77 } 78 79 void StatisticsCalculator::LostSamples(int num_samples) { 80 lost_timestamps_ += num_samples; 81 } 82 83 void StatisticsCalculator::IncreaseCounter(int num_samples, int fs_hz) { 84 last_report_timestamp_ += num_samples; 85 if (last_report_timestamp_ > 86 static_cast<uint32_t>(fs_hz * kMaxReportPeriod)) { 87 lost_timestamps_ = 0; 88 last_report_timestamp_ = 0; 89 discarded_packets_ = 0; 90 } 91 } 92 93 void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) { 94 assert(next_waiting_time_index_ < kLenWaitingTimes); 95 waiting_times_[next_waiting_time_index_] = waiting_time_ms; 96 next_waiting_time_index_++; 97 if (next_waiting_time_index_ >= kLenWaitingTimes) { 98 next_waiting_time_index_ = 0; 99 } 100 if (len_waiting_times_ < kLenWaitingTimes) { 101 len_waiting_times_++; 102 } 103 } 104 105 void StatisticsCalculator::GetNetworkStatistics( 106 int fs_hz, 107 int num_samples_in_buffers, 108 int samples_per_packet, 109 const DelayManager& delay_manager, 110 const DecisionLogic& decision_logic, 111 NetEqNetworkStatistics *stats) { 112 if (fs_hz <= 0 || !stats) { 113 assert(false); 114 return; 115 } 116 117 stats->added_zero_samples = added_zero_samples_; 118 stats->current_buffer_size_ms = num_samples_in_buffers * 1000 / fs_hz; 119 const int ms_per_packet = decision_logic.packet_length_samples() / 120 (fs_hz / 1000); 121 stats->preferred_buffer_size_ms = (delay_manager.TargetLevel() >> 8) * 122 ms_per_packet; 123 stats->jitter_peaks_found = delay_manager.PeakFound(); 124 stats->clockdrift_ppm = delay_manager.AverageIAT(); 125 126 stats->packet_loss_rate = CalculateQ14Ratio(lost_timestamps_, 127 last_report_timestamp_); 128 129 const unsigned discarded_samples = discarded_packets_ * samples_per_packet; 130 stats->packet_discard_rate = CalculateQ14Ratio(discarded_samples, 131 last_report_timestamp_); 132 133 stats->accelerate_rate = CalculateQ14Ratio(accelerate_samples_, 134 last_report_timestamp_); 135 136 stats->preemptive_rate = CalculateQ14Ratio(preemptive_samples_, 137 last_report_timestamp_); 138 139 stats->expand_rate = CalculateQ14Ratio(expanded_voice_samples_ + 140 expanded_noise_samples_, 141 last_report_timestamp_); 142 143 // Reset counters. 144 ResetMcu(); 145 Reset(); 146 } 147 148 void StatisticsCalculator::WaitingTimes(std::vector<int>* waiting_times) { 149 if (!waiting_times) { 150 return; 151 } 152 waiting_times->assign(waiting_times_, waiting_times_ + len_waiting_times_); 153 ResetWaitingTimeStatistics(); 154 } 155 156 int StatisticsCalculator::CalculateQ14Ratio(uint32_t numerator, 157 uint32_t denominator) { 158 if (numerator == 0) { 159 return 0; 160 } else if (numerator < denominator) { 161 // Ratio must be smaller than 1 in Q14. 162 assert((numerator << 14) / denominator < (1 << 14)); 163 return (numerator << 14) / denominator; 164 } else { 165 // Will not produce a ratio larger than 1, since this is probably an error. 166 return 1 << 14; 167 } 168 } 169 170 } // namespace webrtc 171