19a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org/* 29a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 39a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * 49a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * Use of this source code is governed by a BSD-style license 59a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * that can be found in the LICENSE file in the root of the source 69a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * tree. An additional intellectual property rights grant can be found 79a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * in the file PATENTS. All contributing project authors may 89a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * be found in the AUTHORS file in the root of the source tree. 99a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org */ 109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 11e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/statistics_calculator.h" 129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include <assert.h> 143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <string.h> // memset 159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 16e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/decision_logic.h" 17e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/delay_manager.h" 189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgnamespace webrtc { 209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgStatisticsCalculator::StatisticsCalculator() 229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org : preemptive_samples_(0), 239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org accelerate_samples_(0), 249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org added_zero_samples_(0), 259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expanded_voice_samples_(0), 269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expanded_noise_samples_(0), 279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org discarded_packets_(0), 289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lost_timestamps_(0), 299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_(0), 309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org len_waiting_times_(0), 319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org next_waiting_time_index_(0) { 329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memset(waiting_times_, 0, kLenWaitingTimes * sizeof(waiting_times_[0])); 339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::Reset() { 369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org preemptive_samples_ = 0; 379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org accelerate_samples_ = 0; 389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org added_zero_samples_ = 0; 399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expanded_voice_samples_ = 0; 409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expanded_noise_samples_ = 0; 419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::ResetMcu() { 449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org discarded_packets_ = 0; 459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lost_timestamps_ = 0; 469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_ = 0; 479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::ResetWaitingTimeStatistics() { 509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memset(waiting_times_, 0, kLenWaitingTimes * sizeof(waiting_times_[0])); 519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org len_waiting_times_ = 0; 529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org next_waiting_time_index_ = 0; 539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::ExpandedVoiceSamples(int num_samples) { 569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expanded_voice_samples_ += num_samples; 579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::ExpandedNoiseSamples(int num_samples) { 609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expanded_noise_samples_ += num_samples; 619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::PreemptiveExpandedSamples(int num_samples) { 649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org preemptive_samples_ += num_samples; 659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::AcceleratedSamples(int num_samples) { 689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org accelerate_samples_ += num_samples; 699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::AddZeros(int num_samples) { 729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org added_zero_samples_ += num_samples; 739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::PacketsDiscarded(int num_packets) { 769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org discarded_packets_ += num_packets; 779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::LostSamples(int num_samples) { 809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lost_timestamps_ += num_samples; 819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::IncreaseCounter(int num_samples, int fs_hz) { 849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_ += num_samples; 859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (last_report_timestamp_ > 869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static_cast<uint32_t>(fs_hz * kMaxReportPeriod)) { 879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lost_timestamps_ = 0; 889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_ = 0; 899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org discarded_packets_ = 0; 909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) { 949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(next_waiting_time_index_ < kLenWaitingTimes); 959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org waiting_times_[next_waiting_time_index_] = waiting_time_ms; 969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org next_waiting_time_index_++; 979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (next_waiting_time_index_ >= kLenWaitingTimes) { 989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org next_waiting_time_index_ = 0; 999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (len_waiting_times_ < kLenWaitingTimes) { 1019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org len_waiting_times_++; 1029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1039a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 1049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::GetNetworkStatistics( 1069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_hz, 1079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int num_samples_in_buffers, 1089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int samples_per_packet, 1099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const DelayManager& delay_manager, 1109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const DecisionLogic& decision_logic, 1119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org NetEqNetworkStatistics *stats) { 1129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (fs_hz <= 0 || !stats) { 1139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(false); 1149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org return; 1159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->added_zero_samples = added_zero_samples_; 1189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->current_buffer_size_ms = num_samples_in_buffers * 1000 / fs_hz; 1199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const int ms_per_packet = decision_logic.packet_length_samples() / 1209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org (fs_hz / 1000); 1219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->preferred_buffer_size_ms = (delay_manager.TargetLevel() >> 8) * 1229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ms_per_packet; 1239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->jitter_peaks_found = delay_manager.PeakFound(); 1249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->clockdrift_ppm = delay_manager.AverageIAT(); 1259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->packet_loss_rate = CalculateQ14Ratio(lost_timestamps_, 1279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_); 1289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const unsigned discarded_samples = discarded_packets_ * samples_per_packet; 1309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->packet_discard_rate = CalculateQ14Ratio(discarded_samples, 1319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_); 1329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->accelerate_rate = CalculateQ14Ratio(accelerate_samples_, 1349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_); 1359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->preemptive_rate = CalculateQ14Ratio(preemptive_samples_, 1379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_); 1389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->expand_rate = CalculateQ14Ratio(expanded_voice_samples_ + 1409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expanded_noise_samples_, 1419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org last_report_timestamp_); 1429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Reset counters. 1449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ResetMcu(); 1459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org Reset(); 1469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 1479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid StatisticsCalculator::WaitingTimes(std::vector<int>* waiting_times) { 1499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (!waiting_times) { 1509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org return; 1519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org waiting_times->assign(waiting_times_, waiting_times_ + len_waiting_times_); 1539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ResetWaitingTimeStatistics(); 1549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 1559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgint StatisticsCalculator::CalculateQ14Ratio(uint32_t numerator, 1579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org uint32_t denominator) { 1589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (numerator == 0) { 1599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org return 0; 1609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (numerator < denominator) { 1619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Ratio must be smaller than 1 in Q14. 1629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert((numerator << 14) / denominator < (1 << 14)); 1639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org return (numerator << 14) / denominator; 1649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 1659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Will not produce a ratio larger than 1, since this is probably an error. 1669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org return 1 << 14; 1679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 1699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} // namespace webrtc 171