Home | History | Annotate | Download | only in neteq
      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