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 <ivoc@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27202}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 5d02637..c1a7275 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -421,6 +421,7 @@
"../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 6580d1d..64e9c5b 100644
--- a/api/test/neteq_simulator_factory.cc
+++ b/api/test/neteq_simulator_factory.cc
@@ -50,7 +50,30 @@
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<NetEqSimulator> 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<NetEqSimulator>
+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 e37ff55..245162f 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 <memory>
+#include <string>
+#include "absl/strings/string_view.h"
#include "api/test/neteq_simulator.h"
namespace webrtc {
@@ -24,8 +26,20 @@
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<NetEqSimulator> CreateSimulator(int argc, char* argv[]);
+ std::unique_ptr<NetEqSimulator> 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<NetEqSimulator> CreateSimulatorFromString(
+ absl::string_view event_log_file_contents,
+ absl::string_view replacement_audio_file,
+ Config simulation_config);
private:
std::unique_ptr<NetEqTestFactory> 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 9107e5e..60fd897 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 <limits>
+#include <memory>
#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<uint32_t> ssrc_filter)
- : source_(RtcEventLogSource::Create(file_name, ssrc_filter)) {
- LoadNextPacket();
- AdvanceOutputEvent();
+NetEqEventLogInput* NetEqEventLogInput::CreateFromFile(
+ const std::string& file_name,
+ absl::optional<uint32_t> ssrc_filter) {
+ return new NetEqEventLogInput(
+ RtcEventLogSource::CreateFromFile(file_name, ssrc_filter));
+}
+
+NetEqEventLogInput* NetEqEventLogInput::CreateFromString(
+ const std::string& file_contents,
+ absl::optional<uint32_t> ssrc_filter) {
+ return new NetEqEventLogInput(
+ RtcEventLogSource::CreateFromString(file_contents, ssrc_filter));
}
absl::optional<int64_t> NetEqEventLogInput::NextOutputEventTime() const {
@@ -40,5 +48,12 @@
return source_.get();
}
+NetEqEventLogInput::NetEqEventLogInput(
+ std::unique_ptr<RtcEventLogSource> 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 e04df16..238946a 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 @@
// RtcEventLogSource.
class NetEqEventLogInput final : public NetEqPacketSourceInput {
public:
- NetEqEventLogInput(const std::string& file_name,
- absl::optional<uint32_t> ssrc_filter);
+ static NetEqEventLogInput* CreateFromFile(
+ const std::string& file_name,
+ absl::optional<uint32_t> ssrc_filter);
+ static NetEqEventLogInput* CreateFromString(
+ const std::string& file_contents,
+ absl::optional<uint32_t> ssrc_filter);
absl::optional<int64_t> NextOutputEventTime() const override;
void AdvanceOutputEvent() override;
@@ -37,6 +41,7 @@
PacketSource* source() override;
private:
+ NetEqEventLogInput(std::unique_ptr<RtcEventLogSource> source);
std::unique_ptr<RtcEventLogSource> source_;
};
diff --git a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
index 7ebc326..1d313f5 100644
--- a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
+++ b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
@@ -377,8 +377,8 @@
config.ssrc_filter = absl::make_optional(ssrc);
}
- std::unique_ptr<webrtc::test::NetEqTest> test = factory.InitializeTest(
- /*input_filename=*/argv[1], config);
+ std::unique_ptr<webrtc::test::NetEqTest> 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 f352e3a..832d678 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(const Config& other) = default;
NetEqTestFactory::Config::~Config() = default;
-std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
- std::string input_file_name,
+std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTestFromString(
+ const std::string& input_string,
+ const Config& config) {
+ std::unique_ptr<NetEqInput> input(
+ NetEqEventLogInput::CreateFromString(input_string, config.ssrc_filter));
+ RTC_CHECK(input) << "Cannot parse input string";
+ return InitializeTest(std::move(input), config);
+}
+
+std::unique_ptr<NetEqTest> 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 @@
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<NetEqTest> NetEqTestFactory::InitializeTest(
+ std::unique_ptr<NetEqInput> input,
+ const Config& config) {
+ RTC_CHECK(!input->ended()) << "Input is empty";
// Check the sample rate.
absl::optional<int> 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 4da5d55..34b7c77 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 @@
absl::optional<std::string> output_audio_filename;
};
- std::unique_ptr<NetEqTest> InitializeTest(std::string input_filename,
- const Config& config);
+ std::unique_ptr<NetEqTest> InitializeTestFromFile(
+ const std::string& input_filename,
+ const Config& config);
+ std::unique_ptr<NetEqTest> InitializeTestFromString(
+ const std::string& input_string,
+ const Config& config);
private:
+ std::unique_ptr<NetEqTest> InitializeTest(std::unique_ptr<NetEqInput> input,
+ const Config& config);
std::unique_ptr<SsrcSwitchDetector> ssrc_switch_detector_;
std::unique_ptr<NetEqStatsPlotter> 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 591e2b9..fa9f2d9 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 @@
}
} // namespace
-RtcEventLogSource* RtcEventLogSource::Create(
+std::unique_ptr<RtcEventLogSource> RtcEventLogSource::CreateFromFile(
const std::string& file_name,
absl::optional<uint32_t> ssrc_filter) {
- RtcEventLogSource* source = new RtcEventLogSource();
- RTC_CHECK(source->OpenFile(file_name, ssrc_filter));
+ auto source = std::unique_ptr<RtcEventLogSource>(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> RtcEventLogSource::CreateFromString(
+ const std::string& file_contents,
+ absl::optional<uint32_t> ssrc_filter) {
+ auto source = std::unique_ptr<RtcEventLogSource>(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 @@
RtcEventLogSource::RtcEventLogSource() : PacketSource() {}
-bool RtcEventLogSource::OpenFile(const std::string& file_name,
- absl::optional<uint32_t> ssrc_filter) {
- ParsedRtcEventLog parsed_log;
- if (!parsed_log.ParseFile(file_name))
- return false;
-
+bool RtcEventLogSource::Initialize(const ParsedRtcEventLog& parsed_log,
+ absl::optional<uint32_t> ssrc_filter) {
const auto first_log_end_time_us =
parsed_log.stop_log_events().empty()
? std::numeric_limits<int64_t>::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 5238efb..3c91f73 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 @@
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<uint32_t> ssrc_filter);
+ static std::unique_ptr<RtcEventLogSource> CreateFromFile(
+ const std::string& file_name,
+ absl::optional<uint32_t> ssrc_filter);
+ // Same as above, but uses a string with the file contents.
+ static std::unique_ptr<RtcEventLogSource> CreateFromString(
+ const std::string& file_contents,
+ absl::optional<uint32_t> ssrc_filter);
virtual ~RtcEventLogSource();
@@ -48,8 +53,8 @@
private:
RtcEventLogSource();
- bool OpenFile(const std::string& file_name,
- absl::optional<uint32_t> ssrc_filter);
+ bool Initialize(const ParsedRtcEventLog& parsed_log,
+ absl::optional<uint32_t> ssrc_filter);
std::vector<std::unique_ptr<Packet>> rtp_packets_;
size_t rtp_packet_index_ = 0;