From d1d8dfb5c332158443c86f0ac9c2d95a03365bc4 Mon Sep 17 00:00:00 2001 From: Ivo Creusen Date: Wed, 6 Dec 2017 10:48:10 +0100 Subject: [PATCH] Add code to generate python visualization to neteq_rtpplay This adds a command line flag to generate a python visualization script from neteq_rtpplay. Bug: webrtc:8614 Change-Id: Ia6f10d7ff0abac6fdbe9302e7f97a8a12a5bb65b Reviewed-on: https://webrtc-review.googlesource.com/29940 Commit-Queue: Ivo Creusen Reviewed-by: Alessio Bazzica Reviewed-by: Henrik Lundin Cr-Commit-Position: refs/heads/master@{#21116} --- .../neteq/tools/neteq_delay_analyzer.cc | 80 +++++++++++++++++++ .../neteq/tools/neteq_delay_analyzer.h | 5 ++ .../audio_coding/neteq/tools/neteq_rtpplay.cc | 13 ++- 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/modules/audio_coding/neteq/tools/neteq_delay_analyzer.cc b/modules/audio_coding/neteq/tools/neteq_delay_analyzer.cc index 34e7a84200..882f82321c 100644 --- a/modules/audio_coding/neteq/tools/neteq_delay_analyzer.cc +++ b/modules/audio_coding/neteq/tools/neteq_delay_analyzer.cc @@ -252,5 +252,85 @@ void NetEqDelayAnalyzer::CreateMatlabScript( } } +void NetEqDelayAnalyzer::CreatePythonScript( + const std::string& script_name) const { + std::vector send_time_s; + std::vector arrival_delay_ms; + std::vector corrected_arrival_delay_ms; + std::vector> playout_delay_ms; + std::vector> target_delay_ms; + CreateGraphs(&send_time_s, &arrival_delay_ms, &corrected_arrival_delay_ms, + &playout_delay_ms, &target_delay_ms); + + // Create an output file stream to the python script file. + std::ofstream output(script_name); + // The iterator is used to batch-output comma-separated values from vectors. + std::ostream_iterator output_iterator(output, ","); + + // Necessary includes + output << "import numpy as np" << std::endl; + output << "import matplotlib.pyplot as plt" << std::endl; + + output << "send_time_s = ["; + std::copy(send_time_s.begin(), send_time_s.end(), output_iterator); + output << "]" << std::endl; + + output << "arrival_delay_ms = ["; + std::copy(arrival_delay_ms.begin(), arrival_delay_ms.end(), output_iterator); + output << "]" << std::endl; + + output << "corrected_arrival_delay_ms = ["; + std::copy(corrected_arrival_delay_ms.begin(), + corrected_arrival_delay_ms.end(), output_iterator); + output << "]" << std::endl; + + output << "playout_delay_ms = ["; + for (const auto& v : playout_delay_ms) { + if (!v) { + output << "float('nan'), "; + } else { + output << *v << ", "; + } + } + output << "]" << std::endl; + + output << "target_delay_ms = ["; + for (const auto& v : target_delay_ms) { + if (!v) { + output << "float('nan'), "; + } else { + output << *v << ", "; + } + } + output << "]" << std::endl; + + output << "if __name__ == '__main__':" << std::endl; + output << " h=plt.plot(send_time_s, arrival_delay_ms, " + << "send_time_s, target_delay_ms, 'g.', " + << "send_time_s, playout_delay_ms)" << std::endl; + output << " plt.setp(h[0],'color',[.75, .75, .75])" << std::endl; + output << " plt.setp(h[1],'markersize',6)" << std::endl; + output << " plt.setp(h[2],'linewidth',1.5)" << std::endl; + output << " plt.axis('tight')" << std::endl; + output << " plt.xlabel('send time [s]')" << std::endl; + output << " plt.ylabel('relative delay [ms]')" << std::endl; + if (!ssrcs_.empty()) { + auto ssrc_it = ssrcs_.cbegin(); + output << " plt.title('SSRC: 0x" << std::hex + << static_cast(*ssrc_it++); + while (ssrc_it != ssrcs_.end()) { + output << ", 0x" << std::hex << static_cast(*ssrc_it++); + } + output << std::dec; + auto pt_it = payload_types_.cbegin(); + output << "; Payload Types: " << *pt_it++; + while (pt_it != payload_types_.end()) { + output << ", " << *pt_it++; + } + output << "')" << std::endl; + } + output << " plt.show()" << std::endl; +} + } // namespace test } // namespace webrtc diff --git a/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h b/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h index 62bea4ea8d..e6d6913f13 100644 --- a/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h +++ b/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h @@ -48,6 +48,11 @@ class NetEqDelayAnalyzer : public test::NetEqPostInsertPacket, // as provided by CreateGraphs. void CreateMatlabScript(const std::string& script_name) const; + // Creates a python script with file name |script_name|. When executed in + // Python, the script will generate graphs with the same timing information + // as provided by CreateGraphs. + void CreatePythonScript(const std::string& script_name) const; + private: struct TimingData { explicit TimingData(double at) : arrival_time_ms(at) {} diff --git a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc index 2657bfaeb5..e2d0907dee 100644 --- a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc +++ b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc @@ -125,6 +125,9 @@ DEFINE_int(transport_seq_no, 5, "Extension ID for transport sequence number"); DEFINE_bool(matlabplot, false, "Generates a matlab script for plotting the delay profile"); +DEFINE_bool(pythonplot, + false, + "Generates a python script for plotting the delay profile"); DEFINE_bool(help, false, "Prints this message"); // Maps a codec type to a printable name string. @@ -614,7 +617,7 @@ int RunTest(int argc, char* argv[]) { NetEqTest::Callbacks callbacks; std::unique_ptr delay_analyzer; - if (FLAG_matlabplot) { + if (FLAG_matlabplot || FLAG_pythonplot) { delay_analyzer.reset(new NetEqDelayAnalyzer); } @@ -637,6 +640,14 @@ int RunTest(int argc, char* argv[]) { << std::endl; delay_analyzer->CreateMatlabScript(matlab_script_name + ".m"); } + if (FLAG_pythonplot) { + auto python_script_name = output_file_name; + std::replace(python_script_name.begin(), python_script_name.end(), '.', + '_'); + std::cout << "Creating Python plot script " << python_script_name + ".py" + << std::endl; + delay_analyzer->CreatePythonScript(python_script_name + ".py"); + } printf("Simulation statistics:\n"); printf(" output duration: %" PRId64 " ms\n", test_duration_ms);