From c9ac93fabb990eb861d9ae9aafe0517a470982c8 Mon Sep 17 00:00:00 2001 From: Minyue Li Date: Tue, 26 Jun 2018 13:01:32 +0200 Subject: [PATCH] Adding NetEq lifetime stats to event log visualizer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:9147 Change-Id: I798f8ac41192182d50df6fe98fbe56c8cb7f294c Reviewed-on: https://webrtc-review.googlesource.com/85340 Commit-Queue: Minyue Li Reviewed-by: Björn Terelius Reviewed-by: Ivo Creusen Cr-Commit-Position: refs/heads/master@{#23738} --- .../neteq/tools/neteq_stats_getter.cc | 4 +- .../neteq/tools/neteq_stats_getter.h | 10 ++++- rtc_tools/event_log_visualizer/analyzer.cc | 43 ++++++++++++++++--- rtc_tools/event_log_visualizer/analyzer.h | 17 +++++++- rtc_tools/event_log_visualizer/main.cc | 14 ++++-- 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc index 58c9ae4acb..1a521760b1 100644 --- a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc +++ b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc @@ -46,15 +46,17 @@ void NetEqStatsGetter::AfterGetAudio(int64_t time_now_ms, NetEq* neteq) { // TODO(minyue): Get stats should better not be called as a call back after // get audio. It is called independently from get audio in practice. + const auto lifetime_stat = neteq->GetLifetimeStatistics(); if (last_stats_query_time_ms_ == 0 || rtc::TimeDiff(time_now_ms, last_stats_query_time_ms_) >= stats_query_interval_ms_) { NetEqNetworkStatistics stats; RTC_CHECK_EQ(neteq->NetworkStatistics(&stats), 0); stats_.push_back(std::make_pair(time_now_ms, stats)); + lifetime_stats_.push_back(std::make_pair(time_now_ms, lifetime_stat)); last_stats_query_time_ms_ = time_now_ms; } - const auto lifetime_stat = neteq->GetLifetimeStatistics(); + if (current_concealment_event_ != lifetime_stat.concealment_events && voice_concealed_samples_until_last_event_ < lifetime_stat.voice_concealed_samples) { diff --git a/modules/audio_coding/neteq/tools/neteq_stats_getter.h b/modules/audio_coding/neteq/tools/neteq_stats_getter.h index 975393c316..b1b12bb1f8 100644 --- a/modules/audio_coding/neteq/tools/neteq_stats_getter.h +++ b/modules/audio_coding/neteq/tools/neteq_stats_getter.h @@ -77,8 +77,13 @@ class NetEqStatsGetter : public NetEqGetAudioCallback { return concealment_events_; } - const std::vector>& stats() const { - return stats_; + const std::vector>* stats() const { + return &stats_; + } + + const std::vector>* + lifetime_stats() const { + return &lifetime_stats_; } Stats AverageStats() const; @@ -88,6 +93,7 @@ class NetEqStatsGetter : public NetEqGetAudioCallback { int64_t stats_query_interval_ms_ = 1000; int64_t last_stats_query_time_ms_ = 0; std::vector> stats_; + std::vector> lifetime_stats_; size_t current_concealment_event_ = 1; uint64_t voice_concealed_samples_until_last_event_ = 0; std::vector concealment_events_; diff --git a/rtc_tools/event_log_visualizer/analyzer.cc b/rtc_tools/event_log_visualizer/analyzer.cc index 99235e087a..d20d401f15 100644 --- a/rtc_tools/event_log_visualizer/analyzer.cc +++ b/rtc_tools/event_log_visualizer/analyzer.cc @@ -1844,20 +1844,23 @@ void EventLogAnalyzer::CreateAudioJitterBufferGraph( plot->SetTitle("NetEq timing for " + GetStreamName(kIncomingPacket, ssrc)); } -void EventLogAnalyzer::CreateNetEqStatsGraph( +template +void EventLogAnalyzer::CreateNetEqStatsGraphInternal( const NetEqStatsGetterMap& neteq_stats, - rtc::FunctionView stats_extractor, + rtc::FunctionView>*( + const test::NetEqStatsGetter*)> data_extractor, + rtc::FunctionView stats_extractor, const std::string& plot_name, Plot* plot) const { std::map time_series; for (const auto& st : neteq_stats) { const uint32_t ssrc = st.first; - const auto& stats = st.second->stats(); - - for (size_t i = 0; i < stats.size(); ++i) { - const float time = ToCallTimeSec(stats[i].first * 1000); // ms to us. - const float value = stats_extractor(stats[i].second); + const std::vector>* data_vector = + data_extractor(st.second.get()); + for (const auto& data : *data_vector) { + const float time = ToCallTimeSec(data.first * 1000); // ms to us. + const float value = stats_extractor(data.second); time_series[ssrc].points.emplace_back(TimeSeriesPoint(time, value)); } } @@ -1874,6 +1877,32 @@ void EventLogAnalyzer::CreateNetEqStatsGraph( plot->SetTitle(plot_name); } +void EventLogAnalyzer::CreateNetEqNetworkStatsGraph( + const NetEqStatsGetterMap& neteq_stats, + rtc::FunctionView stats_extractor, + const std::string& plot_name, + Plot* plot) const { + CreateNetEqStatsGraphInternal( + neteq_stats, + [](const test::NetEqStatsGetter* stats_getter) { + return stats_getter->stats(); + }, + stats_extractor, plot_name, plot); +} + +void EventLogAnalyzer::CreateNetEqLifetimeStatsGraph( + const NetEqStatsGetterMap& neteq_stats, + rtc::FunctionView stats_extractor, + const std::string& plot_name, + Plot* plot) const { + CreateNetEqStatsGraphInternal( + neteq_stats, + [](const test::NetEqStatsGetter* stats_getter) { + return stats_getter->lifetime_stats(); + }, + stats_extractor, plot_name, plot); +} + void EventLogAnalyzer::CreateIceCandidatePairConfigGraph(Plot* plot) { std::map configs_by_cp_id; for (const auto& config : parsed_log_.ice_candidate_pair_configs()) { diff --git a/rtc_tools/event_log_visualizer/analyzer.h b/rtc_tools/event_log_visualizer/analyzer.h index 6c7e056119..22101b6585 100644 --- a/rtc_tools/event_log_visualizer/analyzer.h +++ b/rtc_tools/event_log_visualizer/analyzer.h @@ -76,14 +76,20 @@ class EventLogAnalyzer { std::map>; NetEqStatsGetterMap SimulateNetEq(const std::string& replacement_file_name, int file_sample_rate_hz) const; + void CreateAudioJitterBufferGraph(uint32_t ssrc, const test::NetEqStatsGetter* stats_getter, Plot* plot) const; - void CreateNetEqStatsGraph( + void CreateNetEqNetworkStatsGraph( const NetEqStatsGetterMap& neteq_stats_getters, rtc::FunctionView stats_extractor, const std::string& plot_name, Plot* plot) const; + void CreateNetEqLifetimeStatsGraph( + const NetEqStatsGetterMap& neteq_stats_getters, + rtc::FunctionView stats_extractor, + const std::string& plot_name, + Plot* plot) const; void CreateIceCandidatePairConfigGraph(Plot* plot); void CreateIceConnectivityCheckGraph(Plot* plot); @@ -122,6 +128,15 @@ class EventLogAnalyzer { } } + template + void CreateNetEqStatsGraphInternal( + const NetEqStatsGetterMap& neteq_stats, + rtc::FunctionView>*( + const test::NetEqStatsGetter*)> data_extractor, + rtc::FunctionView stats_extractor, + const std::string& plot_name, + Plot* plot) const; + template void CreateAccumulatedPacketsTimeSeries(Plot* plot, const IterableType& packets, diff --git a/rtc_tools/event_log_visualizer/main.cc b/rtc_tools/event_log_visualizer/main.cc index 8a303b244f..b1fc0d2847 100644 --- a/rtc_tools/event_log_visualizer/main.cc +++ b/rtc_tools/event_log_visualizer/main.cc @@ -341,30 +341,36 @@ int main(int argc, char* argv[]) { analyzer.CreateAudioJitterBufferGraph(it->first, it->second.get(), collection->AppendNewPlot()); } - analyzer.CreateNetEqStatsGraph( + analyzer.CreateNetEqNetworkStatsGraph( neteq_stats, [](const webrtc::NetEqNetworkStatistics& stats) { return stats.expand_rate / 16384.f; }, "Expand rate", collection->AppendNewPlot()); - analyzer.CreateNetEqStatsGraph( + analyzer.CreateNetEqNetworkStatsGraph( neteq_stats, [](const webrtc::NetEqNetworkStatistics& stats) { return stats.speech_expand_rate / 16384.f; }, "Speech expand rate", collection->AppendNewPlot()); - analyzer.CreateNetEqStatsGraph( + analyzer.CreateNetEqNetworkStatsGraph( neteq_stats, [](const webrtc::NetEqNetworkStatistics& stats) { return stats.accelerate_rate / 16384.f; }, "Accelerate rate", collection->AppendNewPlot()); - analyzer.CreateNetEqStatsGraph( + analyzer.CreateNetEqNetworkStatsGraph( neteq_stats, [](const webrtc::NetEqNetworkStatistics& stats) { return stats.packet_loss_rate / 16384.f; }, "Packet loss rate", collection->AppendNewPlot()); + analyzer.CreateNetEqLifetimeStatsGraph( + neteq_stats, + [](const webrtc::NetEqLifetimeStatistics& stats) { + return static_cast(stats.concealment_events); + }, + "Concealment events", collection->AppendNewPlot()); } if (FLAG_plot_ice_candidate_pair_config) {