• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018 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 "modules/audio_coding/neteq/tools/neteq_stats_getter.h"
12 
13 #include <algorithm>
14 #include <numeric>
15 #include <utility>
16 
17 #include "rtc_base/checks.h"
18 #include "rtc_base/strings/string_builder.h"
19 #include "rtc_base/time_utils.h"
20 
21 namespace webrtc {
22 namespace test {
23 
ToString() const24 std::string NetEqStatsGetter::ConcealmentEvent::ToString() const {
25   char ss_buf[256];
26   rtc::SimpleStringBuilder ss(ss_buf);
27   ss << "ConcealmentEvent duration_ms:" << duration_ms
28      << " event_number:" << concealment_event_number
29      << " time_from_previous_event_end_ms:" << time_from_previous_event_end_ms;
30   return ss.str();
31 }
32 
NetEqStatsGetter(std::unique_ptr<NetEqDelayAnalyzer> delay_analyzer)33 NetEqStatsGetter::NetEqStatsGetter(
34     std::unique_ptr<NetEqDelayAnalyzer> delay_analyzer)
35     : delay_analyzer_(std::move(delay_analyzer)) {}
36 
BeforeGetAudio(NetEq * neteq)37 void NetEqStatsGetter::BeforeGetAudio(NetEq* neteq) {
38   if (delay_analyzer_) {
39     delay_analyzer_->BeforeGetAudio(neteq);
40   }
41 }
42 
AfterGetAudio(int64_t time_now_ms,const AudioFrame & audio_frame,bool muted,NetEq * neteq)43 void NetEqStatsGetter::AfterGetAudio(int64_t time_now_ms,
44                                      const AudioFrame& audio_frame,
45                                      bool muted,
46                                      NetEq* neteq) {
47   // TODO(minyue): Get stats should better not be called as a call back after
48   // get audio. It is called independently from get audio in practice.
49   const auto lifetime_stat = neteq->GetLifetimeStatistics();
50   if (last_stats_query_time_ms_ == 0 ||
51       rtc::TimeDiff(time_now_ms, last_stats_query_time_ms_) >=
52           stats_query_interval_ms_) {
53     NetEqNetworkStatistics stats;
54     RTC_CHECK_EQ(neteq->NetworkStatistics(&stats), 0);
55     stats_.push_back(std::make_pair(time_now_ms, stats));
56     lifetime_stats_.push_back(std::make_pair(time_now_ms, lifetime_stat));
57     last_stats_query_time_ms_ = time_now_ms;
58   }
59 
60   const auto voice_concealed_samples =
61       lifetime_stat.concealed_samples - lifetime_stat.silent_concealed_samples;
62   if (current_concealment_event_ != lifetime_stat.concealment_events &&
63       voice_concealed_samples_until_last_event_ < voice_concealed_samples) {
64     if (last_event_end_time_ms_ > 0) {
65       // Do not account for the first event to avoid start of the call
66       // skewing.
67       ConcealmentEvent concealment_event;
68       uint64_t last_event_voice_concealed_samples =
69           voice_concealed_samples - voice_concealed_samples_until_last_event_;
70       RTC_CHECK_GT(last_event_voice_concealed_samples, 0);
71       concealment_event.duration_ms = last_event_voice_concealed_samples /
72                                       (audio_frame.sample_rate_hz_ / 1000);
73       concealment_event.concealment_event_number = current_concealment_event_;
74       concealment_event.time_from_previous_event_end_ms =
75           time_now_ms - last_event_end_time_ms_;
76       concealment_events_.emplace_back(concealment_event);
77       voice_concealed_samples_until_last_event_ = voice_concealed_samples;
78     }
79     last_event_end_time_ms_ = time_now_ms;
80     voice_concealed_samples_until_last_event_ = voice_concealed_samples;
81     current_concealment_event_ = lifetime_stat.concealment_events;
82   }
83 
84   if (delay_analyzer_) {
85     delay_analyzer_->AfterGetAudio(time_now_ms, audio_frame, muted, neteq);
86   }
87 }
88 
AverageSpeechExpandRate() const89 double NetEqStatsGetter::AverageSpeechExpandRate() const {
90   double sum_speech_expand = std::accumulate(
91       stats_.begin(), stats_.end(), double{0.0},
92       [](double a, std::pair<int64_t, NetEqNetworkStatistics> b) {
93         return a + static_cast<double>(b.second.speech_expand_rate);
94       });
95   return sum_speech_expand / 16384.0 / stats_.size();
96 }
97 
AverageStats() const98 NetEqStatsGetter::Stats NetEqStatsGetter::AverageStats() const {
99   Stats sum_stats = std::accumulate(
100       stats_.begin(), stats_.end(), Stats(),
101       [](Stats a, std::pair<int64_t, NetEqNetworkStatistics> bb) {
102         const auto& b = bb.second;
103         a.current_buffer_size_ms += b.current_buffer_size_ms;
104         a.preferred_buffer_size_ms += b.preferred_buffer_size_ms;
105         a.jitter_peaks_found += b.jitter_peaks_found;
106         a.packet_loss_rate += b.packet_loss_rate / 16384.0;
107         a.expand_rate += b.expand_rate / 16384.0;
108         a.speech_expand_rate += b.speech_expand_rate / 16384.0;
109         a.preemptive_rate += b.preemptive_rate / 16384.0;
110         a.accelerate_rate += b.accelerate_rate / 16384.0;
111         a.secondary_decoded_rate += b.secondary_decoded_rate / 16384.0;
112         a.secondary_discarded_rate += b.secondary_discarded_rate / 16384.0;
113         a.added_zero_samples += b.added_zero_samples;
114         a.mean_waiting_time_ms += b.mean_waiting_time_ms;
115         a.median_waiting_time_ms += b.median_waiting_time_ms;
116         a.min_waiting_time_ms = std::min(
117             a.min_waiting_time_ms, static_cast<double>(b.min_waiting_time_ms));
118         a.max_waiting_time_ms = std::max(
119             a.max_waiting_time_ms, static_cast<double>(b.max_waiting_time_ms));
120         return a;
121       });
122 
123   sum_stats.current_buffer_size_ms /= stats_.size();
124   sum_stats.preferred_buffer_size_ms /= stats_.size();
125   sum_stats.jitter_peaks_found /= stats_.size();
126   sum_stats.packet_loss_rate /= stats_.size();
127   sum_stats.expand_rate /= stats_.size();
128   sum_stats.speech_expand_rate /= stats_.size();
129   sum_stats.preemptive_rate /= stats_.size();
130   sum_stats.accelerate_rate /= stats_.size();
131   sum_stats.secondary_decoded_rate /= stats_.size();
132   sum_stats.secondary_discarded_rate /= stats_.size();
133   sum_stats.added_zero_samples /= stats_.size();
134   sum_stats.mean_waiting_time_ms /= stats_.size();
135   sum_stats.median_waiting_time_ms /= stats_.size();
136 
137   return sum_stats;
138 }
139 
140 }  // namespace test
141 }  // namespace webrtc
142