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