LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_coding/neteq - statistics_calculator.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 162 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include <algorithm>
      16             : 
      17             : #include "webrtc/base/checks.h"
      18             : #include "webrtc/base/safe_conversions.h"
      19             : #include "webrtc/modules/audio_coding/neteq/decision_logic.h"
      20             : #include "webrtc/modules/audio_coding/neteq/delay_manager.h"
      21             : #include "webrtc/system_wrappers/include/metrics.h"
      22             : 
      23             : namespace webrtc {
      24             : 
      25             : // Allocating the static const so that it can be passed by reference to
      26             : // RTC_DCHECK.
      27             : const size_t StatisticsCalculator::kLenWaitingTimes;
      28             : 
      29           0 : StatisticsCalculator::PeriodicUmaLogger::PeriodicUmaLogger(
      30             :     const std::string& uma_name,
      31             :     int report_interval_ms,
      32           0 :     int max_value)
      33             :     : uma_name_(uma_name),
      34             :       report_interval_ms_(report_interval_ms),
      35             :       max_value_(max_value),
      36           0 :       timer_(0) {
      37           0 : }
      38             : 
      39             : StatisticsCalculator::PeriodicUmaLogger::~PeriodicUmaLogger() = default;
      40             : 
      41           0 : void StatisticsCalculator::PeriodicUmaLogger::AdvanceClock(int step_ms) {
      42           0 :   timer_ += step_ms;
      43           0 :   if (timer_ < report_interval_ms_) {
      44           0 :     return;
      45             :   }
      46           0 :   LogToUma(Metric());
      47           0 :   Reset();
      48           0 :   timer_ -= report_interval_ms_;
      49           0 :   RTC_DCHECK_GE(timer_, 0);
      50             : }
      51             : 
      52           0 : void StatisticsCalculator::PeriodicUmaLogger::LogToUma(int value) const {
      53           0 :   RTC_HISTOGRAM_COUNTS_SPARSE(uma_name_, value, 1, max_value_, 50);
      54           0 : }
      55             : 
      56           0 : StatisticsCalculator::PeriodicUmaCount::PeriodicUmaCount(
      57             :     const std::string& uma_name,
      58             :     int report_interval_ms,
      59           0 :     int max_value)
      60           0 :     : PeriodicUmaLogger(uma_name, report_interval_ms, max_value) {
      61           0 : }
      62             : 
      63           0 : StatisticsCalculator::PeriodicUmaCount::~PeriodicUmaCount() {
      64             :   // Log the count for the current (incomplete) interval.
      65           0 :   LogToUma(Metric());
      66           0 : }
      67             : 
      68           0 : void StatisticsCalculator::PeriodicUmaCount::RegisterSample() {
      69           0 :   ++counter_;
      70           0 : }
      71             : 
      72           0 : int StatisticsCalculator::PeriodicUmaCount::Metric() const {
      73           0 :   return counter_;
      74             : }
      75             : 
      76           0 : void StatisticsCalculator::PeriodicUmaCount::Reset() {
      77           0 :   counter_ = 0;
      78           0 : }
      79             : 
      80           0 : StatisticsCalculator::PeriodicUmaAverage::PeriodicUmaAverage(
      81             :     const std::string& uma_name,
      82             :     int report_interval_ms,
      83           0 :     int max_value)
      84           0 :     : PeriodicUmaLogger(uma_name, report_interval_ms, max_value) {
      85           0 : }
      86             : 
      87           0 : StatisticsCalculator::PeriodicUmaAverage::~PeriodicUmaAverage() {
      88             :   // Log the average for the current (incomplete) interval.
      89           0 :   LogToUma(Metric());
      90           0 : }
      91             : 
      92           0 : void StatisticsCalculator::PeriodicUmaAverage::RegisterSample(int value) {
      93           0 :   sum_ += value;
      94           0 :   ++counter_;
      95           0 : }
      96             : 
      97           0 : int StatisticsCalculator::PeriodicUmaAverage::Metric() const {
      98           0 :   return counter_ == 0 ? 0 : static_cast<int>(sum_ / counter_);
      99             : }
     100             : 
     101           0 : void StatisticsCalculator::PeriodicUmaAverage::Reset() {
     102           0 :   sum_ = 0.0;
     103           0 :   counter_ = 0;
     104           0 : }
     105             : 
     106           0 : StatisticsCalculator::StatisticsCalculator()
     107             :     : preemptive_samples_(0),
     108             :       accelerate_samples_(0),
     109             :       added_zero_samples_(0),
     110             :       expanded_speech_samples_(0),
     111             :       expanded_noise_samples_(0),
     112             :       discarded_packets_(0),
     113             :       lost_timestamps_(0),
     114             :       timestamps_since_last_report_(0),
     115             :       secondary_decoded_samples_(0),
     116             :       delayed_packet_outage_counter_(
     117             :           "WebRTC.Audio.DelayedPacketOutageEventsPerMinute",
     118             :           60000,  // 60 seconds report interval.
     119             :           100),
     120             :       excess_buffer_delay_("WebRTC.Audio.AverageExcessBufferDelayMs",
     121             :                            60000,  // 60 seconds report interval.
     122           0 :                            1000) {
     123           0 : }
     124             : 
     125             : StatisticsCalculator::~StatisticsCalculator() = default;
     126             : 
     127           0 : void StatisticsCalculator::Reset() {
     128           0 :   preemptive_samples_ = 0;
     129           0 :   accelerate_samples_ = 0;
     130           0 :   added_zero_samples_ = 0;
     131           0 :   expanded_speech_samples_ = 0;
     132           0 :   expanded_noise_samples_ = 0;
     133           0 :   secondary_decoded_samples_ = 0;
     134           0 :   waiting_times_.clear();
     135           0 : }
     136             : 
     137           0 : void StatisticsCalculator::ResetMcu() {
     138           0 :   discarded_packets_ = 0;
     139           0 :   lost_timestamps_ = 0;
     140           0 :   timestamps_since_last_report_ = 0;
     141           0 : }
     142             : 
     143           0 : void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples) {
     144           0 :   expanded_speech_samples_ += num_samples;
     145           0 : }
     146             : 
     147           0 : void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples) {
     148           0 :   expanded_noise_samples_ += num_samples;
     149           0 : }
     150             : 
     151           0 : void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) {
     152           0 :   preemptive_samples_ += num_samples;
     153           0 : }
     154             : 
     155           0 : void StatisticsCalculator::AcceleratedSamples(size_t num_samples) {
     156           0 :   accelerate_samples_ += num_samples;
     157           0 : }
     158             : 
     159           0 : void StatisticsCalculator::AddZeros(size_t num_samples) {
     160           0 :   added_zero_samples_ += num_samples;
     161           0 : }
     162             : 
     163           0 : void StatisticsCalculator::PacketsDiscarded(size_t num_packets) {
     164           0 :   discarded_packets_ += num_packets;
     165           0 : }
     166             : 
     167           0 : void StatisticsCalculator::LostSamples(size_t num_samples) {
     168           0 :   lost_timestamps_ += num_samples;
     169           0 : }
     170             : 
     171           0 : void StatisticsCalculator::IncreaseCounter(size_t num_samples, int fs_hz) {
     172             :   const int time_step_ms =
     173           0 :       rtc::CheckedDivExact(static_cast<int>(1000 * num_samples), fs_hz);
     174           0 :   delayed_packet_outage_counter_.AdvanceClock(time_step_ms);
     175           0 :   excess_buffer_delay_.AdvanceClock(time_step_ms);
     176           0 :   timestamps_since_last_report_ += static_cast<uint32_t>(num_samples);
     177           0 :   if (timestamps_since_last_report_ >
     178           0 :       static_cast<uint32_t>(fs_hz * kMaxReportPeriod)) {
     179           0 :     lost_timestamps_ = 0;
     180           0 :     timestamps_since_last_report_ = 0;
     181           0 :     discarded_packets_ = 0;
     182             :   }
     183           0 : }
     184             : 
     185           0 : void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) {
     186           0 :   secondary_decoded_samples_ += num_samples;
     187           0 : }
     188             : 
     189           0 : void StatisticsCalculator::LogDelayedPacketOutageEvent(int outage_duration_ms) {
     190           0 :   RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs",
     191             :                        outage_duration_ms, 1 /* min */, 2000 /* max */,
     192             :                        100 /* bucket count */);
     193           0 :   delayed_packet_outage_counter_.RegisterSample();
     194           0 : }
     195             : 
     196           0 : void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) {
     197           0 :   excess_buffer_delay_.RegisterSample(waiting_time_ms);
     198           0 :   RTC_DCHECK_LE(waiting_times_.size(), kLenWaitingTimes);
     199           0 :   if (waiting_times_.size() == kLenWaitingTimes) {
     200             :     // Erase first value.
     201           0 :     waiting_times_.pop_front();
     202             :   }
     203           0 :   waiting_times_.push_back(waiting_time_ms);
     204           0 : }
     205             : 
     206           0 : void StatisticsCalculator::GetNetworkStatistics(
     207             :     int fs_hz,
     208             :     size_t num_samples_in_buffers,
     209             :     size_t samples_per_packet,
     210             :     const DelayManager& delay_manager,
     211             :     const DecisionLogic& decision_logic,
     212             :     NetEqNetworkStatistics *stats) {
     213           0 :   if (fs_hz <= 0 || !stats) {
     214           0 :     assert(false);
     215             :     return;
     216             :   }
     217             : 
     218           0 :   stats->added_zero_samples = added_zero_samples_;
     219           0 :   stats->current_buffer_size_ms =
     220           0 :       static_cast<uint16_t>(num_samples_in_buffers * 1000 / fs_hz);
     221           0 :   const int ms_per_packet = rtc::checked_cast<int>(
     222           0 :       decision_logic.packet_length_samples() / (fs_hz / 1000));
     223           0 :   stats->preferred_buffer_size_ms = (delay_manager.TargetLevel() >> 8) *
     224           0 :       ms_per_packet;
     225           0 :   stats->jitter_peaks_found = delay_manager.PeakFound();
     226           0 :   stats->clockdrift_ppm =
     227           0 :       rtc::saturated_cast<int32_t>(delay_manager.EstimatedClockDriftPpm());
     228             : 
     229           0 :   stats->packet_loss_rate =
     230           0 :       CalculateQ14Ratio(lost_timestamps_, timestamps_since_last_report_);
     231             : 
     232           0 :   const size_t discarded_samples = discarded_packets_ * samples_per_packet;
     233           0 :   stats->packet_discard_rate =
     234           0 :       CalculateQ14Ratio(discarded_samples, timestamps_since_last_report_);
     235             : 
     236           0 :   stats->accelerate_rate =
     237           0 :       CalculateQ14Ratio(accelerate_samples_, timestamps_since_last_report_);
     238             : 
     239           0 :   stats->preemptive_rate =
     240           0 :       CalculateQ14Ratio(preemptive_samples_, timestamps_since_last_report_);
     241             : 
     242           0 :   stats->expand_rate =
     243           0 :       CalculateQ14Ratio(expanded_speech_samples_ + expanded_noise_samples_,
     244             :                         timestamps_since_last_report_);
     245             : 
     246           0 :   stats->speech_expand_rate =
     247           0 :       CalculateQ14Ratio(expanded_speech_samples_,
     248             :                         timestamps_since_last_report_);
     249             : 
     250           0 :   stats->secondary_decoded_rate =
     251           0 :       CalculateQ14Ratio(secondary_decoded_samples_,
     252             :                         timestamps_since_last_report_);
     253             : 
     254           0 :   if (waiting_times_.size() == 0) {
     255           0 :     stats->mean_waiting_time_ms = -1;
     256           0 :     stats->median_waiting_time_ms = -1;
     257           0 :     stats->min_waiting_time_ms = -1;
     258           0 :     stats->max_waiting_time_ms = -1;
     259             :   } else {
     260           0 :     std::sort(waiting_times_.begin(), waiting_times_.end());
     261             :     // Find mid-point elements. If the size is odd, the two values
     262             :     // |middle_left| and |middle_right| will both be the one middle element; if
     263             :     // the size is even, they will be the the two neighboring elements at the
     264             :     // middle of the list.
     265           0 :     const int middle_left = waiting_times_[(waiting_times_.size() - 1) / 2];
     266           0 :     const int middle_right = waiting_times_[waiting_times_.size() / 2];
     267             :     // Calculate the average of the two. (Works also for odd sizes.)
     268           0 :     stats->median_waiting_time_ms = (middle_left + middle_right) / 2;
     269           0 :     stats->min_waiting_time_ms = waiting_times_.front();
     270           0 :     stats->max_waiting_time_ms = waiting_times_.back();
     271           0 :     double sum = 0;
     272           0 :     for (auto time : waiting_times_) {
     273           0 :       sum += time;
     274             :     }
     275           0 :     stats->mean_waiting_time_ms = static_cast<int>(sum / waiting_times_.size());
     276             :   }
     277             : 
     278             :   // Reset counters.
     279           0 :   ResetMcu();
     280           0 :   Reset();
     281             : }
     282             : 
     283           0 : uint16_t StatisticsCalculator::CalculateQ14Ratio(size_t numerator,
     284             :                                                  uint32_t denominator) {
     285           0 :   if (numerator == 0) {
     286           0 :     return 0;
     287           0 :   } else if (numerator < denominator) {
     288             :     // Ratio must be smaller than 1 in Q14.
     289           0 :     assert((numerator << 14) / denominator < (1 << 14));
     290           0 :     return static_cast<uint16_t>((numerator << 14) / denominator);
     291             :   } else {
     292             :     // Will not produce a ratio larger than 1, since this is probably an error.
     293           0 :     return 1 << 14;
     294             :   }
     295             : }
     296             : 
     297             : }  // namespace webrtc

Generated by: LCOV version 1.13