From 5ec61565cb5cd7076c3c003017dfaa2543cf42a0 Mon Sep 17 00:00:00 2001 From: Ivo Creusen Date: Wed, 20 Mar 2019 10:52:18 +0100 Subject: [PATCH] Allow passing an event log as string to NetEqSimulator. Previously only reading from the filesystem was supported, this CL allows parsing an event log from a string. Bug: webrtc:10337 Change-Id: Iadde3319eb8fb4175625f510201fac9c01c80ed9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/127296 Commit-Queue: Ivo Creusen Reviewed-by: Minyue Li Reviewed-by: Karl Wiberg Cr-Commit-Position: refs/heads/master@{#27202} --- api/BUILD.gn | 1 + api/test/neteq_simulator_factory.cc | 25 +++++++++++++++++- api/test/neteq_simulator_factory.h | 14 ++++++++++ .../neteq/tools/neteq_event_log_input.cc | 25 ++++++++++++++---- .../neteq/tools/neteq_event_log_input.h | 9 +++++-- .../audio_coding/neteq/tools/neteq_rtpplay.cc | 4 +-- .../neteq/tools/neteq_test_factory.cc | 24 ++++++++++++++--- .../neteq/tools/neteq_test_factory.h | 10 +++++-- .../neteq/tools/rtc_event_log_source.cc | 26 ++++++++++++------- .../neteq/tools/rtc_event_log_source.h | 13 +++++++--- 10 files changed, 122 insertions(+), 29 deletions(-) diff --git a/api/BUILD.gn b/api/BUILD.gn index 5d02637085..c1a7275a9c 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -421,6 +421,7 @@ if (rtc_include_tests) { "../rtc_base:checks", "../rtc_base:rtc_base_approved", "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", ] } } diff --git a/api/test/neteq_simulator_factory.cc b/api/test/neteq_simulator_factory.cc index 6580d1d576..64e9c5b8cc 100644 --- a/api/test/neteq_simulator_factory.cc +++ b/api/test/neteq_simulator_factory.cc @@ -50,7 +50,30 @@ std::unique_ptr NetEqSimulatorFactory::CreateSimulator( config.replacement_audio_file = FLAG_replacement_audio_file; config.max_nr_packets_in_buffer = FLAG_max_nr_packets_in_buffer; config.output_audio_filename = output_audio_filename; - return factory_->InitializeTest(argv[1], config); + return factory_->InitializeTestFromFile(argv[1], config); +} + +std::unique_ptr NetEqSimulatorFactory::CreateSimulatorFromFile( + absl::string_view event_log_filename, + absl::string_view replacement_audio_filename, + Config simulation_config) { + NetEqTestFactory::Config config; + config.replacement_audio_file = std::string(replacement_audio_filename); + config.max_nr_packets_in_buffer = simulation_config.max_nr_packets_in_buffer; + return factory_->InitializeTestFromFile(std::string(event_log_filename), + config); +} + +std::unique_ptr +NetEqSimulatorFactory::CreateSimulatorFromString( + absl::string_view event_log_file_contents, + absl::string_view replacement_audio_filename, + Config simulation_config) { + NetEqTestFactory::Config config; + config.replacement_audio_file = std::string(replacement_audio_filename); + config.max_nr_packets_in_buffer = simulation_config.max_nr_packets_in_buffer; + return factory_->InitializeTestFromString( + std::string(event_log_file_contents), config); } } // namespace test diff --git a/api/test/neteq_simulator_factory.h b/api/test/neteq_simulator_factory.h index e37ff55dd4..245162fd23 100644 --- a/api/test/neteq_simulator_factory.h +++ b/api/test/neteq_simulator_factory.h @@ -12,7 +12,9 @@ #define API_TEST_NETEQ_SIMULATOR_FACTORY_H_ #include +#include +#include "absl/strings/string_view.h" #include "api/test/neteq_simulator.h" namespace webrtc { @@ -24,8 +26,20 @@ class NetEqSimulatorFactory { public: NetEqSimulatorFactory(); ~NetEqSimulatorFactory(); + struct Config { + int max_nr_packets_in_buffer = 0; + }; // This function takes the same arguments as the neteq_rtpplay utility. std::unique_ptr CreateSimulator(int argc, char* argv[]); + std::unique_ptr CreateSimulatorFromFile( + absl::string_view event_log_filename, + absl::string_view replacement_audio_filename, + Config simulation_config); + // The same as above, but pass the file contents as a string. + std::unique_ptr CreateSimulatorFromString( + absl::string_view event_log_file_contents, + absl::string_view replacement_audio_file, + Config simulation_config); private: std::unique_ptr factory_; diff --git a/modules/audio_coding/neteq/tools/neteq_event_log_input.cc b/modules/audio_coding/neteq/tools/neteq_event_log_input.cc index 9107e5e5ef..60fd897dfb 100644 --- a/modules/audio_coding/neteq/tools/neteq_event_log_input.cc +++ b/modules/audio_coding/neteq/tools/neteq_event_log_input.cc @@ -11,6 +11,7 @@ #include "modules/audio_coding/neteq/tools/neteq_event_log_input.h" #include +#include #include "modules/audio_coding/neteq/tools/rtc_event_log_source.h" #include "rtc_base/checks.h" @@ -18,11 +19,18 @@ namespace webrtc { namespace test { -NetEqEventLogInput::NetEqEventLogInput(const std::string& file_name, - absl::optional ssrc_filter) - : source_(RtcEventLogSource::Create(file_name, ssrc_filter)) { - LoadNextPacket(); - AdvanceOutputEvent(); +NetEqEventLogInput* NetEqEventLogInput::CreateFromFile( + const std::string& file_name, + absl::optional ssrc_filter) { + return new NetEqEventLogInput( + RtcEventLogSource::CreateFromFile(file_name, ssrc_filter)); +} + +NetEqEventLogInput* NetEqEventLogInput::CreateFromString( + const std::string& file_contents, + absl::optional ssrc_filter) { + return new NetEqEventLogInput( + RtcEventLogSource::CreateFromString(file_contents, ssrc_filter)); } absl::optional NetEqEventLogInput::NextOutputEventTime() const { @@ -40,5 +48,12 @@ PacketSource* NetEqEventLogInput::source() { return source_.get(); } +NetEqEventLogInput::NetEqEventLogInput( + std::unique_ptr source) + : source_(std::move(source)) { + LoadNextPacket(); + AdvanceOutputEvent(); +} + } // namespace test } // namespace webrtc diff --git a/modules/audio_coding/neteq/tools/neteq_event_log_input.h b/modules/audio_coding/neteq/tools/neteq_event_log_input.h index e04df1684f..238946a547 100644 --- a/modules/audio_coding/neteq/tools/neteq_event_log_input.h +++ b/modules/audio_coding/neteq/tools/neteq_event_log_input.h @@ -27,8 +27,12 @@ class RtcEventLogSource; // RtcEventLogSource. class NetEqEventLogInput final : public NetEqPacketSourceInput { public: - NetEqEventLogInput(const std::string& file_name, - absl::optional ssrc_filter); + static NetEqEventLogInput* CreateFromFile( + const std::string& file_name, + absl::optional ssrc_filter); + static NetEqEventLogInput* CreateFromString( + const std::string& file_contents, + absl::optional ssrc_filter); absl::optional NextOutputEventTime() const override; void AdvanceOutputEvent() override; @@ -37,6 +41,7 @@ class NetEqEventLogInput final : public NetEqPacketSourceInput { PacketSource* source() override; private: + NetEqEventLogInput(std::unique_ptr source); std::unique_ptr source_; }; diff --git a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc index 7ebc326ee5..1d313f5f36 100644 --- a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc +++ b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc @@ -377,8 +377,8 @@ int main(int argc, char* argv[]) { config.ssrc_filter = absl::make_optional(ssrc); } - std::unique_ptr test = factory.InitializeTest( - /*input_filename=*/argv[1], config); + std::unique_ptr test = + factory.InitializeTestFromFile(/*input_filename=*/argv[1], config); test->Run(); return 0; } diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.cc b/modules/audio_coding/neteq/tools/neteq_test_factory.cc index f352e3aec9..832d678bb5 100644 --- a/modules/audio_coding/neteq/tools/neteq_test_factory.cc +++ b/modules/audio_coding/neteq/tools/neteq_test_factory.cc @@ -108,8 +108,17 @@ NetEqTestFactory::Config::Config() = default; NetEqTestFactory::Config::Config(const Config& other) = default; NetEqTestFactory::Config::~Config() = default; -std::unique_ptr NetEqTestFactory::InitializeTest( - std::string input_file_name, +std::unique_ptr NetEqTestFactory::InitializeTestFromString( + const std::string& input_string, + const Config& config) { + std::unique_ptr input( + NetEqEventLogInput::CreateFromString(input_string, config.ssrc_filter)); + RTC_CHECK(input) << "Cannot parse input string"; + return InitializeTest(std::move(input), config); +} + +std::unique_ptr NetEqTestFactory::InitializeTestFromFile( + const std::string& input_file_name, const Config& config) { // Gather RTP header extensions in a map. NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = { @@ -125,12 +134,19 @@ std::unique_ptr NetEqTestFactory::InitializeTest( input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map, config.ssrc_filter)); } else { - input.reset(new NetEqEventLogInput(input_file_name, config.ssrc_filter)); + input.reset(NetEqEventLogInput::CreateFromFile(input_file_name, + config.ssrc_filter)); } std::cout << "Input file: " << input_file_name << std::endl; RTC_CHECK(input) << "Cannot open input file"; - RTC_CHECK(!input->ended()) << "Input file is empty"; + return InitializeTest(std::move(input), config); +} + +std::unique_ptr NetEqTestFactory::InitializeTest( + std::unique_ptr input, + const Config& config) { + RTC_CHECK(!input->ended()) << "Input is empty"; // Check the sample rate. absl::optional sample_rate_hz; diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.h b/modules/audio_coding/neteq/tools/neteq_test_factory.h index 4da5d5577c..34b7c775d8 100644 --- a/modules/audio_coding/neteq/tools/neteq_test_factory.h +++ b/modules/audio_coding/neteq/tools/neteq_test_factory.h @@ -133,10 +133,16 @@ class NetEqTestFactory { absl::optional output_audio_filename; }; - std::unique_ptr InitializeTest(std::string input_filename, - const Config& config); + std::unique_ptr InitializeTestFromFile( + const std::string& input_filename, + const Config& config); + std::unique_ptr InitializeTestFromString( + const std::string& input_string, + const Config& config); private: + std::unique_ptr InitializeTest(std::unique_ptr input, + const Config& config); std::unique_ptr ssrc_switch_detector_; std::unique_ptr stats_plotter_; }; diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc b/modules/audio_coding/neteq/tools/rtc_event_log_source.cc index 591e2b9e16..fa9f2d955c 100644 --- a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc +++ b/modules/audio_coding/neteq/tools/rtc_event_log_source.cc @@ -36,11 +36,23 @@ bool ShouldSkipStream(ParsedRtcEventLog::MediaType media_type, } } // namespace -RtcEventLogSource* RtcEventLogSource::Create( +std::unique_ptr RtcEventLogSource::CreateFromFile( const std::string& file_name, absl::optional ssrc_filter) { - RtcEventLogSource* source = new RtcEventLogSource(); - RTC_CHECK(source->OpenFile(file_name, ssrc_filter)); + auto source = std::unique_ptr(new RtcEventLogSource()); + ParsedRtcEventLog parsed_log; + RTC_CHECK(parsed_log.ParseFile(file_name)); + RTC_CHECK(source->Initialize(parsed_log, ssrc_filter)); + return source; +} + +std::unique_ptr RtcEventLogSource::CreateFromString( + const std::string& file_contents, + absl::optional ssrc_filter) { + auto source = std::unique_ptr(new RtcEventLogSource()); + ParsedRtcEventLog parsed_log; + RTC_CHECK(parsed_log.ParseString(file_contents)); + RTC_CHECK(source->Initialize(parsed_log, ssrc_filter)); return source; } @@ -64,12 +76,8 @@ int64_t RtcEventLogSource::NextAudioOutputEventMs() { RtcEventLogSource::RtcEventLogSource() : PacketSource() {} -bool RtcEventLogSource::OpenFile(const std::string& file_name, - absl::optional ssrc_filter) { - ParsedRtcEventLog parsed_log; - if (!parsed_log.ParseFile(file_name)) - return false; - +bool RtcEventLogSource::Initialize(const ParsedRtcEventLog& parsed_log, + absl::optional ssrc_filter) { const auto first_log_end_time_us = parsed_log.stop_log_events().empty() ? std::numeric_limits::max() diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.h b/modules/audio_coding/neteq/tools/rtc_event_log_source.h index 5238efb6e4..3c91f73eb8 100644 --- a/modules/audio_coding/neteq/tools/rtc_event_log_source.h +++ b/modules/audio_coding/neteq/tools/rtc_event_log_source.h @@ -33,8 +33,13 @@ class RtcEventLogSource : public PacketSource { public: // Creates an RtcEventLogSource reading from |file_name|. If the file cannot // be opened, or has the wrong format, NULL will be returned. - static RtcEventLogSource* Create(const std::string& file_name, - absl::optional ssrc_filter); + static std::unique_ptr CreateFromFile( + const std::string& file_name, + absl::optional ssrc_filter); + // Same as above, but uses a string with the file contents. + static std::unique_ptr CreateFromString( + const std::string& file_contents, + absl::optional ssrc_filter); virtual ~RtcEventLogSource(); @@ -48,8 +53,8 @@ class RtcEventLogSource : public PacketSource { private: RtcEventLogSource(); - bool OpenFile(const std::string& file_name, - absl::optional ssrc_filter); + bool Initialize(const ParsedRtcEventLog& parsed_log, + absl::optional ssrc_filter); std::vector> rtp_packets_; size_t rtp_packet_index_ = 0;