blob: 2fbd83aec0e218a7d77eb45ebe69246fe2176c1a [file] [log] [blame]
terelius54ce6802016-07-13 06:44:41 -07001/*
2 * Copyright (c) 2016 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
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <stdio.h>
12#include <string.h>
Jonas Olsson5b2eda42019-06-11 14:29:40 +020013
terelius54ce6802016-07-13 06:44:41 -070014#include <iostream>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <map>
16#include <memory>
17#include <string>
18#include <utility>
terelius54ce6802016-07-13 06:44:41 -070019
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +020020#include "absl/algorithm/container.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "logging/rtc_event_log/rtc_event_log.h"
Sebastian Janssonb290a6d2019-01-03 14:46:23 +010022#include "logging/rtc_event_log/rtc_event_log_parser.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "modules/audio_coding/neteq/include/neteq.h"
24#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
25#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/flags.h"
27#include "rtc_tools/event_log_visualizer/analyzer.h"
28#include "rtc_tools/event_log_visualizer/plot_base.h"
Bjorn Tereliusef73f592018-09-10 20:11:49 +020029#include "rtc_tools/event_log_visualizer/plot_protobuf.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_tools/event_log_visualizer/plot_python.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020031#include "system_wrappers/include/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "test/field_trial.h"
Steve Anton10542f22019-01-11 09:11:00 -080033#include "test/testsupport/file_utils.h"
terelius54ce6802016-07-13 06:44:41 -070034
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020035WEBRTC_DEFINE_string(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +020036 plot,
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020037 "default",
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +020038 "A comma separated list of plot names. See below for valid options.");
Bjorn Terelius1edfff92017-10-11 13:15:19 +020039
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020040WEBRTC_DEFINE_string(
stefan985d2802016-11-15 06:54:09 -080041 force_fieldtrials,
42 "",
43 "Field trials control experimental feature code which can be forced. "
44 "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enabled/"
45 " will assign the group Enabled to field trial WebRTC-FooFeature. Multiple "
46 "trials are separated by \"/\"");
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020047WEBRTC_DEFINE_string(wav_filename,
48 "",
49 "Path to wav file used for simulation of jitter buffer");
50WEBRTC_DEFINE_bool(help, false, "prints this message");
terelius54ce6802016-07-13 06:44:41 -070051
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020052WEBRTC_DEFINE_bool(
53 show_detector_state,
54 false,
55 "Show the state of the delay based BWE detector on the total "
56 "bitrate graph");
terelius2ee076d2017-08-15 02:04:02 -070057
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020058WEBRTC_DEFINE_bool(show_alr_state,
59 false,
60 "Show the state ALR state on the total bitrate graph");
Ilya Nikolaevskiya4259f62017-12-05 13:19:45 +010061
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020062WEBRTC_DEFINE_bool(
63 parse_unconfigured_header_extensions,
64 true,
65 "Attempt to parse unconfigured header extensions using the default "
66 "WebRTC mapping. This can give very misleading results if the "
67 "application negotiates a different mapping.");
Bjorn Tereliusc4ca1d32018-04-27 14:33:34 +020068
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020069WEBRTC_DEFINE_bool(print_triage_alerts,
70 false,
71 "Print triage alerts, i.e. a list of potential problems.");
Bjorn Terelius2eb31882017-11-30 15:15:25 +010072
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020073WEBRTC_DEFINE_bool(
74 normalize_time,
75 true,
76 "Normalize the log timestamps so that the call starts at time 0.");
Stefan Holmer1d4a2272018-05-24 13:48:09 +020077
Bjorn Tereliusff8cce32019-04-11 18:34:01 +020078WEBRTC_DEFINE_bool(shared_xaxis,
79 false,
80 "Share x-axis between all plots so that zooming in one plot "
81 "updates all the others too. A downside is that certain "
82 "operations like panning become much slower.");
83
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020084WEBRTC_DEFINE_bool(protobuf_output,
85 false,
86 "Output charts as protobuf instead of python code.");
Bjorn Tereliusef73f592018-09-10 20:11:49 +020087
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +020088using webrtc::Plot;
89
90namespace {
91std::vector<std::string> StrSplit(const std::string& s,
92 const std::string& delimiter) {
93 std::vector<std::string> v;
94 size_t pos = 0;
95 while (pos < s.length()) {
96 const std::string token = s.substr(pos, s.find(delimiter, pos) - pos);
97 pos += token.length() + delimiter.length();
98 v.push_back(token);
99 }
100 return v;
101}
102
103struct PlotDeclaration {
104 PlotDeclaration(const std::string& label, std::function<void(Plot*)> f)
105 : label(label), enabled(false), plot_func(f) {}
106 const std::string label;
107 bool enabled;
108 // TODO(terelius): Add a help text/explanation.
109 const std::function<void(Plot*)> plot_func;
110};
111
112class PlotMap {
113 public:
114 void RegisterPlot(const std::string& label, std::function<void(Plot*)> f) {
115 for (const auto& plot : plots_) {
116 RTC_DCHECK(plot.label != label)
117 << "Can't use the same label for multiple plots";
118 }
119 plots_.push_back({label, f});
120 }
121
122 bool EnablePlotsByFlags(
123 const std::vector<std::string>& flags,
124 const std::map<std::string, std::vector<std::string>>& flag_aliases) {
125 bool status = true;
126 for (const std::string& flag : flags) {
127 auto alias_it = flag_aliases.find(flag);
128 if (alias_it != flag_aliases.end()) {
129 const auto& replacements = alias_it->second;
130 for (const auto& replacement : replacements) {
131 status &= EnablePlotByFlag(replacement);
132 }
133 } else {
134 status &= EnablePlotByFlag(flag);
135 }
136 }
137 return status;
138 }
139
140 void EnableAllPlots() {
141 for (auto& plot : plots_) {
142 plot.enabled = true;
143 }
144 }
145
146 std::vector<PlotDeclaration>::iterator begin() { return plots_.begin(); }
147 std::vector<PlotDeclaration>::iterator end() { return plots_.end(); }
148
149 private:
150 bool EnablePlotByFlag(const std::string& flag) {
151 for (auto& plot : plots_) {
152 if (plot.label == flag) {
153 plot.enabled = true;
154 return true;
155 }
156 }
157 if (flag == "simulated_neteq_jitter_buffer_delay") {
158 // This flag is handled separately.
159 return true;
160 }
161 std::cerr << "Unrecognized plot name \'" << flag << "\'. Aborting."
162 << std::endl;
163 return false;
164 }
165
166 std::vector<PlotDeclaration> plots_;
167};
168} // namespace
terelius2ee076d2017-08-15 02:04:02 -0700169
terelius54ce6802016-07-13 06:44:41 -0700170int main(int argc, char* argv[]) {
171 std::string program_name = argv[0];
172 std::string usage =
173 "A tool for visualizing WebRTC event logs.\n"
174 "Example usage:\n" +
175 program_name + " <logfile> | python\n" + "Run " + program_name +
176 " --help for a list of command line options\n";
terelius2ee076d2017-08-15 02:04:02 -0700177
kjellander4fa5be42017-05-16 00:01:23 -0700178 rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
terelius2ee076d2017-08-15 02:04:02 -0700179
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200180 // Flag replacements
181 std::map<std::string, std::vector<std::string>> flag_aliases = {
182 {"default",
183 {"incoming_delay", "incoming_loss_rate", "incoming_bitrate",
184 "outgoing_bitrate,"
185 "incoming_stream_bitrate",
186 "outgoing_stream_bitrate", "network_delay_feedback",
187 "fraction_loss_feedback"}},
188 {"sendside_bwe",
189 {"outgoing_packet_sizes", "outgoing_bitrate", "outgoing_stream_bitrate",
190 "simulated_sendside_bwe", "network_delay_feedback",
191 "fraction_loss_feedback"}},
192 {"receiveside_bwe",
193 {"incoming_packet_sizes", "incoming_delay", "incoming_loss_rate",
194 "incoming_"
195 "bitrate",
196 "incoming_stream_bitrate", "simulated_receiveside_bwe"}},
197 {"rtcp_details",
198 {"incoming_rtcp_fraction_lost", "outgoing_rtcp_fraction_lost",
199 "incoming_rtcp_"
200 "cumulative_lost",
201 "outgoing_rtcp_cumulative_lost",
202 "incoming_rtcp_highest_"
203 "seq_number",
204 "outgoing_rtcp_highest_seq_number",
205 "incoming_rtcp_delay_since_"
206 "last_sr",
207 "outgoing_rtcp_delay_since_last_sr"}},
208 {"simulated_neteq_stats",
209 {"simulated_neteq_jitter_buffer_delay",
210 "simulated_neteq_preferred_buffer_"
211 "size",
212 "simulated_neteq_"
213 "concealment_events",
214 "simulated_neteq_packet_loss_rate",
215 "simulated_neteq_"
216 "preemptive_rate",
217 "simulated_neteq_"
218 "accelerate_rate",
219 "simulated_neteq_speech_expand_rate",
220 "simulated_neteq_"
221 "expand_rate"}}};
222
223 std::vector<std::string> plot_flags = StrSplit(FLAG_plot, ",");
kjellander4fa5be42017-05-16 00:01:23 -0700224
Bjorn Tereliusedab3012018-01-31 17:23:40 +0100225 // InitFieldTrialsFromString stores the char*, so the char array must outlive
226 // the application.
227 webrtc::field_trial::InitFieldTrialsFromString(FLAG_force_fieldtrials);
stefan985d2802016-11-15 06:54:09 -0800228
Sebastian Janssonb290a6d2019-01-03 14:46:23 +0100229 webrtc::ParsedRtcEventLog::UnconfiguredHeaderExtensions header_extensions =
230 webrtc::ParsedRtcEventLog::UnconfiguredHeaderExtensions::kDontParse;
Bjorn Tereliusc4ca1d32018-04-27 14:33:34 +0200231 if (FLAG_parse_unconfigured_header_extensions) {
Sebastian Janssonb290a6d2019-01-03 14:46:23 +0100232 header_extensions = webrtc::ParsedRtcEventLog::
Bjorn Tereliusc4ca1d32018-04-27 14:33:34 +0200233 UnconfiguredHeaderExtensions::kAttemptWebrtcDefaultConfig;
234 }
Sebastian Janssonb290a6d2019-01-03 14:46:23 +0100235 webrtc::ParsedRtcEventLog parsed_log(header_extensions);
terelius54ce6802016-07-13 06:44:41 -0700236
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200237 if (argc == 2) {
238 std::string filename = argv[1];
239 if (!parsed_log.ParseFile(filename)) {
240 std::cerr << "Could not parse the entire log file." << std::endl;
241 std::cerr << "Only the parsable events will be analyzed." << std::endl;
242 }
terelius54ce6802016-07-13 06:44:41 -0700243 }
244
Stefan Holmer1d4a2272018-05-24 13:48:09 +0200245 webrtc::EventLogAnalyzer analyzer(parsed_log, FLAG_normalize_time);
Bjorn Tereliusef73f592018-09-10 20:11:49 +0200246 std::unique_ptr<webrtc::PlotCollection> collection;
247 if (FLAG_protobuf_output) {
248 collection.reset(new webrtc::ProtobufPlotCollection());
249 } else {
Bjorn Tereliusff8cce32019-04-11 18:34:01 +0200250 collection.reset(new webrtc::PythonPlotCollection(FLAG_shared_xaxis));
Bjorn Tereliusef73f592018-09-10 20:11:49 +0200251 }
terelius54ce6802016-07-13 06:44:41 -0700252
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200253 PlotMap plots;
254 plots.RegisterPlot("incoming_packet_sizes", [&](Plot* plot) {
255 analyzer.CreatePacketGraph(webrtc::kIncomingPacket, plot);
256 });
257
258 plots.RegisterPlot("outgoing_packet_sizes", [&](Plot* plot) {
259 analyzer.CreatePacketGraph(webrtc::kOutgoingPacket, plot);
260 });
261 plots.RegisterPlot("incoming_rtcp_types", [&](Plot* plot) {
262 analyzer.CreateRtcpTypeGraph(webrtc::kIncomingPacket, plot);
263 });
264 plots.RegisterPlot("outgoing_rtcp_types", [&](Plot* plot) {
265 analyzer.CreateRtcpTypeGraph(webrtc::kOutgoingPacket, plot);
266 });
267 plots.RegisterPlot("incoming_packet_count", [&](Plot* plot) {
268 analyzer.CreateAccumulatedPacketsGraph(webrtc::kIncomingPacket, plot);
269 });
270 plots.RegisterPlot("outgoing_packet_count", [&](Plot* plot) {
271 analyzer.CreateAccumulatedPacketsGraph(webrtc::kOutgoingPacket, plot);
272 });
273 plots.RegisterPlot("audio_playout",
274 [&](Plot* plot) { analyzer.CreatePlayoutGraph(plot); });
275 plots.RegisterPlot("incoming_audio_level", [&](Plot* plot) {
276 analyzer.CreateAudioLevelGraph(webrtc::kIncomingPacket, plot);
277 });
278 plots.RegisterPlot("outgoing_audio_level", [&](Plot* plot) {
279 analyzer.CreateAudioLevelGraph(webrtc::kOutgoingPacket, plot);
280 });
281 plots.RegisterPlot("incoming_sequence_number_delta", [&](Plot* plot) {
282 analyzer.CreateSequenceNumberGraph(plot);
283 });
284 plots.RegisterPlot("incoming_delay", [&](Plot* plot) {
285 analyzer.CreateIncomingDelayGraph(plot);
286 });
287 plots.RegisterPlot("incoming_loss_rate", [&](Plot* plot) {
288 analyzer.CreateIncomingPacketLossGraph(plot);
289 });
290 plots.RegisterPlot("incoming_bitrate", [&](Plot* plot) {
291 analyzer.CreateTotalIncomingBitrateGraph(plot);
292 });
293 plots.RegisterPlot("outgoing_bitrate", [&](Plot* plot) {
294 analyzer.CreateTotalOutgoingBitrateGraph(plot, FLAG_show_detector_state,
Bjorn Tereliusc4ca1d32018-04-27 14:33:34 +0200295 FLAG_show_alr_state);
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200296 });
297 plots.RegisterPlot("incoming_stream_bitrate", [&](Plot* plot) {
298 analyzer.CreateStreamBitrateGraph(webrtc::kIncomingPacket, plot);
299 });
300 plots.RegisterPlot("outgoing_stream_bitrate", [&](Plot* plot) {
301 analyzer.CreateStreamBitrateGraph(webrtc::kOutgoingPacket, plot);
302 });
303 plots.RegisterPlot("incoming_layer_bitrate_allocation", [&](Plot* plot) {
304 analyzer.CreateBitrateAllocationGraph(webrtc::kIncomingPacket, plot);
305 });
306 plots.RegisterPlot("outgoing_layer_bitrate_allocation", [&](Plot* plot) {
307 analyzer.CreateBitrateAllocationGraph(webrtc::kOutgoingPacket, plot);
308 });
309 plots.RegisterPlot("simulated_receiveside_bwe", [&](Plot* plot) {
310 analyzer.CreateReceiveSideBweSimulationGraph(plot);
311 });
312 plots.RegisterPlot("simulated_sendside_bwe", [&](Plot* plot) {
313 analyzer.CreateSendSideBweSimulationGraph(plot);
314 });
315 plots.RegisterPlot("simulated_goog_cc", [&](Plot* plot) {
316 analyzer.CreateGoogCcSimulationGraph(plot);
317 });
318 plots.RegisterPlot("network_delay_feedback", [&](Plot* plot) {
319 analyzer.CreateNetworkDelayFeedbackGraph(plot);
320 });
321 plots.RegisterPlot("fraction_loss_feedback", [&](Plot* plot) {
322 analyzer.CreateFractionLossGraph(plot);
323 });
324 plots.RegisterPlot("incoming_timestamps", [&](Plot* plot) {
325 analyzer.CreateTimestampGraph(webrtc::kIncomingPacket, plot);
326 });
327 plots.RegisterPlot("outgoing_timestamps", [&](Plot* plot) {
328 analyzer.CreateTimestampGraph(webrtc::kOutgoingPacket, plot);
329 });
330
331 auto GetFractionLost = [](const webrtc::rtcp::ReportBlock& block) -> float {
332 return static_cast<double>(block.fraction_lost()) / 256 * 100;
333 };
334 plots.RegisterPlot("incoming_rtcp_fraction_lost", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200335 analyzer.CreateSenderAndReceiverReportPlot(
336 webrtc::kIncomingPacket, GetFractionLost,
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200337 "Fraction lost (incoming RTCP)", "Loss rate (percent)", plot);
338 });
339 plots.RegisterPlot("outgoing_rtcp_fraction_lost", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200340 analyzer.CreateSenderAndReceiverReportPlot(
341 webrtc::kOutgoingPacket, GetFractionLost,
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200342 "Fraction lost (outgoing RTCP)", "Loss rate (percent)", plot);
343 });
344 auto GetCumulativeLost = [](const webrtc::rtcp::ReportBlock& block) -> float {
345 return block.cumulative_lost_signed();
346 };
347 plots.RegisterPlot("incoming_rtcp_cumulative_lost", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200348 analyzer.CreateSenderAndReceiverReportPlot(
349 webrtc::kIncomingPacket, GetCumulativeLost,
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200350 "Cumulative lost packets (incoming RTCP)", "Packets", plot);
351 });
352 plots.RegisterPlot("outgoing_rtcp_cumulative_lost", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200353 analyzer.CreateSenderAndReceiverReportPlot(
354 webrtc::kOutgoingPacket, GetCumulativeLost,
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200355 "Cumulative lost packets (outgoing RTCP)", "Packets", plot);
356 });
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200357
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200358 auto GetHighestSeqNumber =
359 [](const webrtc::rtcp::ReportBlock& block) -> float {
360 return block.extended_high_seq_num();
361 };
362 plots.RegisterPlot("incoming_rtcp_highest_seq_number", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200363 analyzer.CreateSenderAndReceiverReportPlot(
364 webrtc::kIncomingPacket, GetHighestSeqNumber,
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200365 "Highest sequence number (incoming RTCP)", "Sequence number", plot);
366 });
367 plots.RegisterPlot("outgoing_rtcp_highest_seq_number", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200368 analyzer.CreateSenderAndReceiverReportPlot(
369 webrtc::kOutgoingPacket, GetHighestSeqNumber,
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200370 "Highest sequence number (outgoing RTCP)", "Sequence number", plot);
371 });
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200372
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200373 auto DelaySinceLastSr = [](const webrtc::rtcp::ReportBlock& block) -> float {
374 return static_cast<double>(block.delay_since_last_sr()) / 65536;
375 };
376 plots.RegisterPlot("incoming_rtcp_delay_since_last_sr", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200377 analyzer.CreateSenderAndReceiverReportPlot(
378 webrtc::kIncomingPacket, DelaySinceLastSr,
379 "Delay since last received sender report (incoming RTCP)", "Time (s)",
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200380 plot);
381 });
382 plots.RegisterPlot("outgoing_rtcp_delay_since_last_sr", [&](Plot* plot) {
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200383 analyzer.CreateSenderAndReceiverReportPlot(
384 webrtc::kOutgoingPacket, DelaySinceLastSr,
385 "Delay since last received sender report (outgoing RTCP)", "Time (s)",
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200386 plot);
387 });
Bjorn Tereliusb1222c22018-07-24 13:45:31 +0200388
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200389 plots.RegisterPlot("pacer_delay",
390 [&](Plot* plot) { analyzer.CreatePacerDelayGraph(plot); });
391 plots.RegisterPlot("audio_encoder_bitrate", [&](Plot* plot) {
392 analyzer.CreateAudioEncoderTargetBitrateGraph(plot);
393 });
394 plots.RegisterPlot("audio_encoder_frame_length", [&](Plot* plot) {
395 analyzer.CreateAudioEncoderFrameLengthGraph(plot);
396 });
397 plots.RegisterPlot("audio_encoder_packet_loss", [&](Plot* plot) {
398 analyzer.CreateAudioEncoderPacketLossGraph(plot);
399 });
400 plots.RegisterPlot("audio_encoder_fec", [&](Plot* plot) {
401 analyzer.CreateAudioEncoderEnableFecGraph(plot);
402 });
403 plots.RegisterPlot("audio_encoder_dtx", [&](Plot* plot) {
404 analyzer.CreateAudioEncoderEnableDtxGraph(plot);
405 });
406 plots.RegisterPlot("audio_encoder_num_channels", [&](Plot* plot) {
407 analyzer.CreateAudioEncoderNumChannelsGraph(plot);
408 });
409
410 plots.RegisterPlot("ice_candidate_pair_config", [&](Plot* plot) {
411 analyzer.CreateIceCandidatePairConfigGraph(plot);
412 });
413 plots.RegisterPlot("ice_connectivity_check", [&](Plot* plot) {
414 analyzer.CreateIceConnectivityCheckGraph(plot);
415 });
416 plots.RegisterPlot("dtls_transport_state", [&](Plot* plot) {
417 analyzer.CreateDtlsTransportStateGraph(plot);
418 });
419 plots.RegisterPlot("dtls_writable_state", [&](Plot* plot) {
420 analyzer.CreateDtlsWritableStateGraph(plot);
421 });
422
423 std::string wav_path;
424 if (FLAG_wav_filename[0] != '\0') {
425 wav_path = FLAG_wav_filename;
426 } else {
427 wav_path = webrtc::test::ResourcePath(
428 "audio_processing/conversational_speech/EN_script2_F_sp2_B1", "wav");
Bjorn Terelius0295a962017-10-25 17:42:41 +0200429 }
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200430 absl::optional<webrtc::EventLogAnalyzer::NetEqStatsGetterMap> neteq_stats;
431
432 plots.RegisterPlot("simulated_neteq_expand_rate", [&](Plot* plot) {
433 if (!neteq_stats) {
434 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
Minyue Li45fc6df2018-06-21 11:47:14 +0200435 }
Minyue Lic9ac93f2018-06-26 13:01:32 +0200436 analyzer.CreateNetEqNetworkStatsGraph(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200437 *neteq_stats,
Minyue Li27e2b7d2018-05-07 15:20:24 +0200438 [](const webrtc::NetEqNetworkStatistics& stats) {
439 return stats.expand_rate / 16384.f;
440 },
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200441 "Expand rate", plot);
442 });
443
444 plots.RegisterPlot("simulated_neteq_speech_expand_rate", [&](Plot* plot) {
445 if (!neteq_stats) {
446 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
447 }
Minyue Lic9ac93f2018-06-26 13:01:32 +0200448 analyzer.CreateNetEqNetworkStatsGraph(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200449 *neteq_stats,
Minyue Li27e2b7d2018-05-07 15:20:24 +0200450 [](const webrtc::NetEqNetworkStatistics& stats) {
451 return stats.speech_expand_rate / 16384.f;
452 },
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200453 "Speech expand rate", plot);
454 });
455
456 plots.RegisterPlot("simulated_neteq_accelerate_rate", [&](Plot* plot) {
457 if (!neteq_stats) {
458 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
459 }
Minyue Lic9ac93f2018-06-26 13:01:32 +0200460 analyzer.CreateNetEqNetworkStatsGraph(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200461 *neteq_stats,
Minyue Li27e2b7d2018-05-07 15:20:24 +0200462 [](const webrtc::NetEqNetworkStatistics& stats) {
463 return stats.accelerate_rate / 16384.f;
464 },
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200465 "Accelerate rate", plot);
466 });
467
468 plots.RegisterPlot("simulated_neteq_preemptive_rate", [&](Plot* plot) {
469 if (!neteq_stats) {
470 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
471 }
Minyue Lic9ac93f2018-06-26 13:01:32 +0200472 analyzer.CreateNetEqNetworkStatsGraph(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200473 *neteq_stats,
Minyue Li27e2b7d2018-05-07 15:20:24 +0200474 [](const webrtc::NetEqNetworkStatistics& stats) {
Jakob Ivarsson21f6fd72019-04-04 10:15:02 +0200475 return stats.preemptive_rate / 16384.f;
476 },
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200477 "Preemptive rate", plot);
478 });
479
480 plots.RegisterPlot("simulated_neteq_packet_loss_rate", [&](Plot* plot) {
481 if (!neteq_stats) {
482 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
483 }
Jakob Ivarsson21f6fd72019-04-04 10:15:02 +0200484 analyzer.CreateNetEqNetworkStatsGraph(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200485 *neteq_stats,
Jakob Ivarsson21f6fd72019-04-04 10:15:02 +0200486 [](const webrtc::NetEqNetworkStatistics& stats) {
Minyue Li27e2b7d2018-05-07 15:20:24 +0200487 return stats.packet_loss_rate / 16384.f;
488 },
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200489 "Packet loss rate", plot);
490 });
491
492 plots.RegisterPlot("simulated_neteq_concealment_events", [&](Plot* plot) {
493 if (!neteq_stats) {
494 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
495 }
Minyue Lic9ac93f2018-06-26 13:01:32 +0200496 analyzer.CreateNetEqLifetimeStatsGraph(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200497 *neteq_stats,
Minyue Lic9ac93f2018-06-26 13:01:32 +0200498 [](const webrtc::NetEqLifetimeStatistics& stats) {
499 return static_cast<float>(stats.concealment_events);
500 },
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200501 "Concealment events", plot);
502 });
503
504 plots.RegisterPlot("simulated_neteq_preferred_buffer_size", [&](Plot* plot) {
505 if (!neteq_stats) {
506 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
507 }
Jakob Ivarsson21f6fd72019-04-04 10:15:02 +0200508 analyzer.CreateNetEqNetworkStatsGraph(
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200509 *neteq_stats,
Jakob Ivarsson21f6fd72019-04-04 10:15:02 +0200510 [](const webrtc::NetEqNetworkStatistics& stats) {
511 return stats.preferred_buffer_size_ms;
512 },
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200513 "Preferred buffer size (ms)", plot);
514 });
515
516 if (absl::c_find(plot_flags, "all") != plot_flags.end()) {
517 plots.EnableAllPlots();
518 // Treated separately since it isn't registered like the other plots.
519 plot_flags.push_back("simulated_neteq_jitter_buffer_delay");
520 } else {
521 bool success = plots.EnablePlotsByFlags(plot_flags, flag_aliases);
522 if (!success) {
523 return 1;
524 }
henrik.lundin3c938fc2017-06-14 06:09:58 -0700525 }
526
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200527 if (argc != 2 || FLAG_help) {
528 // Print usage information.
529 std::cerr << usage;
530 if (FLAG_help) {
531 rtc::FlagList::Print(nullptr, false);
532 std::cerr << "List of registered plots (for use with the --plot flag):"
533 << std::endl;
534 for (const auto& plot : plots) {
535 // TODO(terelius): Also print a help text.
536 std::cerr << " " << plot.label << std::endl;
537 }
538 // The following flag doesn't fit the model used for the other plots.
539 std::cerr << "simulated_neteq_jitter_buffer_delay" << std::endl;
540 std::cerr << "List of plot aliases (for use with the --plot flag):"
541 << std::endl;
542 for (const auto& alias : flag_aliases) {
543 std::cerr << " " << alias.first << " = ";
544 for (const auto& replacement : alias.second) {
545 std::cerr << replacement << ",";
546 }
547 std::cerr << std::endl;
548 }
549 }
550 return 0;
Qingsi Wang8eca1ff2018-02-02 11:49:44 -0800551 }
552
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200553 for (const auto& plot : plots) {
554 if (plot.enabled) {
555 Plot* output = collection->AppendNewPlot();
556 plot.plot_func(output);
557 output->SetId(plot.label);
558 }
Zach Stein10a58012018-12-07 12:26:28 -0800559 }
Bjorn Terelius1aa9ee92019-06-11 17:39:38 +0200560
561 // The model we use for registering plots assumes that the each plot label
562 // can be mapped to a lambda that will produce exactly one plot. The
563 // simulated_neteq_jitter_buffer_delay plot doesn't fit this model since it
564 // creates multiple plots, and would need some state kept between the lambda
565 // calls.
566 if (absl::c_find(plot_flags, "simulated_neteq_jitter_buffer_delay") !=
567 plot_flags.end()) {
568 if (!neteq_stats) {
569 neteq_stats = analyzer.SimulateNetEq(wav_path, 48000);
570 }
571 for (webrtc::EventLogAnalyzer::NetEqStatsGetterMap::const_iterator it =
572 neteq_stats->cbegin();
573 it != neteq_stats->cend(); ++it) {
574 analyzer.CreateAudioJitterBufferGraph(it->first, it->second.get(),
575 collection->AppendNewPlot());
576 }
Zach Stein10a58012018-12-07 12:26:28 -0800577 }
578
tereliusdc35dcd2016-08-01 12:03:27 -0700579 collection->Draw();
terelius54ce6802016-07-13 06:44:41 -0700580
Bjorn Tereliusc4ca1d32018-04-27 14:33:34 +0200581 if (FLAG_print_triage_alerts) {
Bjorn Terelius2eb31882017-11-30 15:15:25 +0100582 analyzer.CreateTriageNotifications();
583 analyzer.PrintNotifications(stderr);
584 }
585
terelius54ce6802016-07-13 06:44:41 -0700586 return 0;
587}
terelius2ee076d2017-08-15 02:04:02 -0700588