Adding NetEq lifetime stats to event log visualizer.
Bug: webrtc:9147 Change-Id: I798f8ac41192182d50df6fe98fbe56c8cb7f294c Reviewed-on: https://webrtc-review.googlesource.com/85340 Commit-Queue: Minyue Li <minyue@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Reviewed-by: Ivo Creusen <ivoc@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23738}
This commit is contained in:
@ -46,15 +46,17 @@ void NetEqStatsGetter::AfterGetAudio(int64_t time_now_ms,
|
|||||||
NetEq* neteq) {
|
NetEq* neteq) {
|
||||||
// TODO(minyue): Get stats should better not be called as a call back after
|
// 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.
|
// get audio. It is called independently from get audio in practice.
|
||||||
|
const auto lifetime_stat = neteq->GetLifetimeStatistics();
|
||||||
if (last_stats_query_time_ms_ == 0 ||
|
if (last_stats_query_time_ms_ == 0 ||
|
||||||
rtc::TimeDiff(time_now_ms, last_stats_query_time_ms_) >=
|
rtc::TimeDiff(time_now_ms, last_stats_query_time_ms_) >=
|
||||||
stats_query_interval_ms_) {
|
stats_query_interval_ms_) {
|
||||||
NetEqNetworkStatistics stats;
|
NetEqNetworkStatistics stats;
|
||||||
RTC_CHECK_EQ(neteq->NetworkStatistics(&stats), 0);
|
RTC_CHECK_EQ(neteq->NetworkStatistics(&stats), 0);
|
||||||
stats_.push_back(std::make_pair(time_now_ms, stats));
|
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;
|
last_stats_query_time_ms_ = time_now_ms;
|
||||||
}
|
}
|
||||||
const auto lifetime_stat = neteq->GetLifetimeStatistics();
|
|
||||||
if (current_concealment_event_ != lifetime_stat.concealment_events &&
|
if (current_concealment_event_ != lifetime_stat.concealment_events &&
|
||||||
voice_concealed_samples_until_last_event_ <
|
voice_concealed_samples_until_last_event_ <
|
||||||
lifetime_stat.voice_concealed_samples) {
|
lifetime_stat.voice_concealed_samples) {
|
||||||
|
@ -77,8 +77,13 @@ class NetEqStatsGetter : public NetEqGetAudioCallback {
|
|||||||
return concealment_events_;
|
return concealment_events_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::pair<int64_t, NetEqNetworkStatistics>>& stats() const {
|
const std::vector<std::pair<int64_t, NetEqNetworkStatistics>>* stats() const {
|
||||||
return stats_;
|
return &stats_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::pair<int64_t, NetEqLifetimeStatistics>>*
|
||||||
|
lifetime_stats() const {
|
||||||
|
return &lifetime_stats_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stats AverageStats() const;
|
Stats AverageStats() const;
|
||||||
@ -88,6 +93,7 @@ class NetEqStatsGetter : public NetEqGetAudioCallback {
|
|||||||
int64_t stats_query_interval_ms_ = 1000;
|
int64_t stats_query_interval_ms_ = 1000;
|
||||||
int64_t last_stats_query_time_ms_ = 0;
|
int64_t last_stats_query_time_ms_ = 0;
|
||||||
std::vector<std::pair<int64_t, NetEqNetworkStatistics>> stats_;
|
std::vector<std::pair<int64_t, NetEqNetworkStatistics>> stats_;
|
||||||
|
std::vector<std::pair<int64_t, NetEqLifetimeStatistics>> lifetime_stats_;
|
||||||
size_t current_concealment_event_ = 1;
|
size_t current_concealment_event_ = 1;
|
||||||
uint64_t voice_concealed_samples_until_last_event_ = 0;
|
uint64_t voice_concealed_samples_until_last_event_ = 0;
|
||||||
std::vector<ConcealmentEvent> concealment_events_;
|
std::vector<ConcealmentEvent> concealment_events_;
|
||||||
|
@ -1844,20 +1844,23 @@ void EventLogAnalyzer::CreateAudioJitterBufferGraph(
|
|||||||
plot->SetTitle("NetEq timing for " + GetStreamName(kIncomingPacket, ssrc));
|
plot->SetTitle("NetEq timing for " + GetStreamName(kIncomingPacket, ssrc));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventLogAnalyzer::CreateNetEqStatsGraph(
|
template <typename NetEqStatsType>
|
||||||
|
void EventLogAnalyzer::CreateNetEqStatsGraphInternal(
|
||||||
const NetEqStatsGetterMap& neteq_stats,
|
const NetEqStatsGetterMap& neteq_stats,
|
||||||
rtc::FunctionView<float(const NetEqNetworkStatistics&)> stats_extractor,
|
rtc::FunctionView<const std::vector<std::pair<int64_t, NetEqStatsType>>*(
|
||||||
|
const test::NetEqStatsGetter*)> data_extractor,
|
||||||
|
rtc::FunctionView<float(const NetEqStatsType&)> stats_extractor,
|
||||||
const std::string& plot_name,
|
const std::string& plot_name,
|
||||||
Plot* plot) const {
|
Plot* plot) const {
|
||||||
std::map<uint32_t, TimeSeries> time_series;
|
std::map<uint32_t, TimeSeries> time_series;
|
||||||
|
|
||||||
for (const auto& st : neteq_stats) {
|
for (const auto& st : neteq_stats) {
|
||||||
const uint32_t ssrc = st.first;
|
const uint32_t ssrc = st.first;
|
||||||
const auto& stats = st.second->stats();
|
const std::vector<std::pair<int64_t, NetEqStatsType>>* data_vector =
|
||||||
|
data_extractor(st.second.get());
|
||||||
for (size_t i = 0; i < stats.size(); ++i) {
|
for (const auto& data : *data_vector) {
|
||||||
const float time = ToCallTimeSec(stats[i].first * 1000); // ms to us.
|
const float time = ToCallTimeSec(data.first * 1000); // ms to us.
|
||||||
const float value = stats_extractor(stats[i].second);
|
const float value = stats_extractor(data.second);
|
||||||
time_series[ssrc].points.emplace_back(TimeSeriesPoint(time, value));
|
time_series[ssrc].points.emplace_back(TimeSeriesPoint(time, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1874,6 +1877,32 @@ void EventLogAnalyzer::CreateNetEqStatsGraph(
|
|||||||
plot->SetTitle(plot_name);
|
plot->SetTitle(plot_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventLogAnalyzer::CreateNetEqNetworkStatsGraph(
|
||||||
|
const NetEqStatsGetterMap& neteq_stats,
|
||||||
|
rtc::FunctionView<float(const NetEqNetworkStatistics&)> stats_extractor,
|
||||||
|
const std::string& plot_name,
|
||||||
|
Plot* plot) const {
|
||||||
|
CreateNetEqStatsGraphInternal<NetEqNetworkStatistics>(
|
||||||
|
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<float(const NetEqLifetimeStatistics&)> stats_extractor,
|
||||||
|
const std::string& plot_name,
|
||||||
|
Plot* plot) const {
|
||||||
|
CreateNetEqStatsGraphInternal<NetEqLifetimeStatistics>(
|
||||||
|
neteq_stats,
|
||||||
|
[](const test::NetEqStatsGetter* stats_getter) {
|
||||||
|
return stats_getter->lifetime_stats();
|
||||||
|
},
|
||||||
|
stats_extractor, plot_name, plot);
|
||||||
|
}
|
||||||
|
|
||||||
void EventLogAnalyzer::CreateIceCandidatePairConfigGraph(Plot* plot) {
|
void EventLogAnalyzer::CreateIceCandidatePairConfigGraph(Plot* plot) {
|
||||||
std::map<uint32_t, TimeSeries> configs_by_cp_id;
|
std::map<uint32_t, TimeSeries> configs_by_cp_id;
|
||||||
for (const auto& config : parsed_log_.ice_candidate_pair_configs()) {
|
for (const auto& config : parsed_log_.ice_candidate_pair_configs()) {
|
||||||
|
@ -76,14 +76,20 @@ class EventLogAnalyzer {
|
|||||||
std::map<uint32_t, std::unique_ptr<test::NetEqStatsGetter>>;
|
std::map<uint32_t, std::unique_ptr<test::NetEqStatsGetter>>;
|
||||||
NetEqStatsGetterMap SimulateNetEq(const std::string& replacement_file_name,
|
NetEqStatsGetterMap SimulateNetEq(const std::string& replacement_file_name,
|
||||||
int file_sample_rate_hz) const;
|
int file_sample_rate_hz) const;
|
||||||
|
|
||||||
void CreateAudioJitterBufferGraph(uint32_t ssrc,
|
void CreateAudioJitterBufferGraph(uint32_t ssrc,
|
||||||
const test::NetEqStatsGetter* stats_getter,
|
const test::NetEqStatsGetter* stats_getter,
|
||||||
Plot* plot) const;
|
Plot* plot) const;
|
||||||
void CreateNetEqStatsGraph(
|
void CreateNetEqNetworkStatsGraph(
|
||||||
const NetEqStatsGetterMap& neteq_stats_getters,
|
const NetEqStatsGetterMap& neteq_stats_getters,
|
||||||
rtc::FunctionView<float(const NetEqNetworkStatistics&)> stats_extractor,
|
rtc::FunctionView<float(const NetEqNetworkStatistics&)> stats_extractor,
|
||||||
const std::string& plot_name,
|
const std::string& plot_name,
|
||||||
Plot* plot) const;
|
Plot* plot) const;
|
||||||
|
void CreateNetEqLifetimeStatsGraph(
|
||||||
|
const NetEqStatsGetterMap& neteq_stats_getters,
|
||||||
|
rtc::FunctionView<float(const NetEqLifetimeStatistics&)> stats_extractor,
|
||||||
|
const std::string& plot_name,
|
||||||
|
Plot* plot) const;
|
||||||
|
|
||||||
void CreateIceCandidatePairConfigGraph(Plot* plot);
|
void CreateIceCandidatePairConfigGraph(Plot* plot);
|
||||||
void CreateIceConnectivityCheckGraph(Plot* plot);
|
void CreateIceConnectivityCheckGraph(Plot* plot);
|
||||||
@ -122,6 +128,15 @@ class EventLogAnalyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename NetEqStatsType>
|
||||||
|
void CreateNetEqStatsGraphInternal(
|
||||||
|
const NetEqStatsGetterMap& neteq_stats,
|
||||||
|
rtc::FunctionView<const std::vector<std::pair<int64_t, NetEqStatsType>>*(
|
||||||
|
const test::NetEqStatsGetter*)> data_extractor,
|
||||||
|
rtc::FunctionView<float(const NetEqStatsType&)> stats_extractor,
|
||||||
|
const std::string& plot_name,
|
||||||
|
Plot* plot) const;
|
||||||
|
|
||||||
template <typename IterableType>
|
template <typename IterableType>
|
||||||
void CreateAccumulatedPacketsTimeSeries(Plot* plot,
|
void CreateAccumulatedPacketsTimeSeries(Plot* plot,
|
||||||
const IterableType& packets,
|
const IterableType& packets,
|
||||||
|
@ -341,30 +341,36 @@ int main(int argc, char* argv[]) {
|
|||||||
analyzer.CreateAudioJitterBufferGraph(it->first, it->second.get(),
|
analyzer.CreateAudioJitterBufferGraph(it->first, it->second.get(),
|
||||||
collection->AppendNewPlot());
|
collection->AppendNewPlot());
|
||||||
}
|
}
|
||||||
analyzer.CreateNetEqStatsGraph(
|
analyzer.CreateNetEqNetworkStatsGraph(
|
||||||
neteq_stats,
|
neteq_stats,
|
||||||
[](const webrtc::NetEqNetworkStatistics& stats) {
|
[](const webrtc::NetEqNetworkStatistics& stats) {
|
||||||
return stats.expand_rate / 16384.f;
|
return stats.expand_rate / 16384.f;
|
||||||
},
|
},
|
||||||
"Expand rate", collection->AppendNewPlot());
|
"Expand rate", collection->AppendNewPlot());
|
||||||
analyzer.CreateNetEqStatsGraph(
|
analyzer.CreateNetEqNetworkStatsGraph(
|
||||||
neteq_stats,
|
neteq_stats,
|
||||||
[](const webrtc::NetEqNetworkStatistics& stats) {
|
[](const webrtc::NetEqNetworkStatistics& stats) {
|
||||||
return stats.speech_expand_rate / 16384.f;
|
return stats.speech_expand_rate / 16384.f;
|
||||||
},
|
},
|
||||||
"Speech expand rate", collection->AppendNewPlot());
|
"Speech expand rate", collection->AppendNewPlot());
|
||||||
analyzer.CreateNetEqStatsGraph(
|
analyzer.CreateNetEqNetworkStatsGraph(
|
||||||
neteq_stats,
|
neteq_stats,
|
||||||
[](const webrtc::NetEqNetworkStatistics& stats) {
|
[](const webrtc::NetEqNetworkStatistics& stats) {
|
||||||
return stats.accelerate_rate / 16384.f;
|
return stats.accelerate_rate / 16384.f;
|
||||||
},
|
},
|
||||||
"Accelerate rate", collection->AppendNewPlot());
|
"Accelerate rate", collection->AppendNewPlot());
|
||||||
analyzer.CreateNetEqStatsGraph(
|
analyzer.CreateNetEqNetworkStatsGraph(
|
||||||
neteq_stats,
|
neteq_stats,
|
||||||
[](const webrtc::NetEqNetworkStatistics& stats) {
|
[](const webrtc::NetEqNetworkStatistics& stats) {
|
||||||
return stats.packet_loss_rate / 16384.f;
|
return stats.packet_loss_rate / 16384.f;
|
||||||
},
|
},
|
||||||
"Packet loss rate", collection->AppendNewPlot());
|
"Packet loss rate", collection->AppendNewPlot());
|
||||||
|
analyzer.CreateNetEqLifetimeStatsGraph(
|
||||||
|
neteq_stats,
|
||||||
|
[](const webrtc::NetEqLifetimeStatistics& stats) {
|
||||||
|
return static_cast<float>(stats.concealment_events);
|
||||||
|
},
|
||||||
|
"Concealment events", collection->AppendNewPlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_plot_ice_candidate_pair_config) {
|
if (FLAG_plot_ice_candidate_pair_config) {
|
||||||
|
Reference in New Issue
Block a user