diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index fc07126462..4e95f04a94 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -850,14 +850,6 @@ rtc_library("neteq_test_tools") { "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", ] - - if (rtc_enable_protobuf) { - sources += [ - "neteq/tools/neteq_event_log_input.cc", - "neteq/tools/neteq_event_log_input.h", - ] - deps += [ ":rtc_event_log_source" ] - } } rtc_library("neteq_tools") { @@ -893,6 +885,16 @@ rtc_library("neteq_tools") { "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", ] + + if (rtc_enable_protobuf) { + sources += [ + "neteq/tools/neteq_event_log_input.cc", + "neteq/tools/neteq_event_log_input.h", + ] + deps += [ "../../logging:rtc_event_log_parser" ] + public_deps = # no-presubmit-check TODO(webrtc:8603) + [ "../../logging:rtc_event_log_proto" ] + } } rtc_library("neteq_input_audio_tools") { @@ -912,29 +914,6 @@ rtc_library("neteq_input_audio_tools") { } if (rtc_enable_protobuf) { - rtc_library("rtc_event_log_source") { - testonly = true - - sources = [ - "neteq/tools/rtc_event_log_source.cc", - "neteq/tools/rtc_event_log_source.h", - ] - - deps = [ - ":neteq_tools_minimal", - "../../logging:rtc_event_log_parser", - "../../rtc_base:checks", - "../rtp_rtcp", - "../rtp_rtcp:rtp_rtcp_format", - ] - absl_deps = [ - "//third_party/abseil-cpp/absl/strings", - "//third_party/abseil-cpp/absl/types:optional", - ] - public_deps = # no-presubmit-check TODO(webrtc:8603) - [ "../../logging:rtc_event_log_proto" ] - } - # Only used for test purpose. Since we want to use it from chromium # (see audio_coding_modules_tests_shared below), we cannot guard it # under rtc_include_tests. 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 26255b7771..0ca855b626 100644 --- a/modules/audio_coding/neteq/tools/neteq_event_log_input.cc +++ b/modules/audio_coding/neteq/tools/neteq_event_log_input.cc @@ -14,64 +14,153 @@ #include #include "absl/strings/string_view.h" -#include "modules/audio_coding/neteq/tools/rtc_event_log_source.h" #include "rtc_base/checks.h" namespace webrtc { namespace test { +namespace { -NetEqEventLogInput* NetEqEventLogInput::CreateFromFile( - absl::string_view file_name, - absl::optional ssrc_filter) { - auto event_log_src = - RtcEventLogSource::CreateFromFile(file_name, ssrc_filter); - if (!event_log_src) { +class NetEqEventLogInput : public NetEqInput { + public: + NetEqEventLogInput(const std::vector& packet_stream, + const std::vector& output_events, + const std::vector& + neteq_set_minimum_delay_events, + absl::optional end_time_ms) + : packet_stream_(packet_stream), + packet_stream_it_(packet_stream_.begin()), + output_events_(output_events), + output_events_it_(output_events_.begin()), + neteq_set_minimum_delay_events_(neteq_set_minimum_delay_events), + neteq_set_minimum_delay_events_it_( + neteq_set_minimum_delay_events_.begin()), + end_time_ms_(end_time_ms) { + // Ignore all output events before the first packet. + while (output_events_it_ != output_events_.end() && + output_events_it_->log_time_ms() < + packet_stream_it_->log_time_ms()) { + ++output_events_it_; + } + } + + absl::optional NextPacketTime() const override { + if (packet_stream_it_ == packet_stream_.end()) { + return absl::nullopt; + } + if (end_time_ms_ && packet_stream_it_->rtp.log_time_ms() > *end_time_ms_) { + return absl::nullopt; + } + return packet_stream_it_->rtp.log_time_ms(); + } + + absl::optional NextOutputEventTime() const override { + if (output_events_it_ == output_events_.end()) { + return absl::nullopt; + } + if (end_time_ms_ && output_events_it_->log_time_ms() > *end_time_ms_) { + return absl::nullopt; + } + return output_events_it_->log_time_ms(); + } + + absl::optional NextSetMinimumDelayInfo() const override { + if (neteq_set_minimum_delay_events_it_ == + neteq_set_minimum_delay_events_.end()) { + return absl::nullopt; + } + if (end_time_ms_ && + neteq_set_minimum_delay_events_it_->log_time_ms() > *end_time_ms_) { + return absl::nullopt; + } + return SetMinimumDelayInfo( + neteq_set_minimum_delay_events_it_->log_time_ms(), + neteq_set_minimum_delay_events_it_->minimum_delay_ms); + } + + std::unique_ptr PopPacket() override { + if (packet_stream_it_ == packet_stream_.end()) { + return nullptr; + } + auto packet_data = std::make_unique(); + packet_data->header = packet_stream_it_->rtp.header; + packet_data->time_ms = packet_stream_it_->rtp.log_time_ms(); + + // This is a header-only "dummy" packet. Set the payload to all zeros, with + // length according to the virtual length. + packet_data->payload.SetSize(packet_stream_it_->rtp.total_length - + packet_stream_it_->rtp.header_length); + std::fill_n(packet_data->payload.data(), packet_data->payload.size(), 0); + + ++packet_stream_it_; + return packet_data; + } + + void AdvanceOutputEvent() override { + if (output_events_it_ != output_events_.end()) { + ++output_events_it_; + } + } + + void AdvanceSetMinimumDelay() override { + if (neteq_set_minimum_delay_events_it_ != + neteq_set_minimum_delay_events_.end()) { + ++neteq_set_minimum_delay_events_it_; + } + } + + bool ended() const override { return !NextEventTime(); } + + absl::optional NextHeader() const override { + if (packet_stream_it_ == packet_stream_.end()) { + return absl::nullopt; + } + return packet_stream_it_->rtp.header; + } + + private: + const std::vector packet_stream_; + std::vector::const_iterator packet_stream_it_; + const std::vector output_events_; + std::vector::const_iterator output_events_it_; + const std::vector + neteq_set_minimum_delay_events_; + std::vector::const_iterator + neteq_set_minimum_delay_events_it_; + const absl::optional end_time_ms_; +}; + +} // namespace + +std::unique_ptr CreateNetEqEventLogInput( + const ParsedRtcEventLog& parsed_log, + absl::optional ssrc) { + if (parsed_log.incoming_audio_ssrcs().empty()) { return nullptr; } - return new NetEqEventLogInput(std::move(event_log_src)); -} - -NetEqEventLogInput* NetEqEventLogInput::CreateFromString( - absl::string_view file_contents, - absl::optional ssrc_filter) { - auto event_log_src = - RtcEventLogSource::CreateFromString(file_contents, ssrc_filter); - if (!event_log_src) { + // Pick the first SSRC if none was provided. + ssrc = ssrc.value_or(*parsed_log.incoming_audio_ssrcs().begin()); + auto streams = parsed_log.incoming_rtp_packets_by_ssrc(); + auto stream = + std::find_if(streams.begin(), streams.end(), + [ssrc](auto stream) { return stream.ssrc == ssrc; }); + if (stream == streams.end()) { return nullptr; } - return new NetEqEventLogInput(std::move(event_log_src)); -} - -absl::optional NetEqEventLogInput::NextOutputEventTime() const { - return next_output_event_ms_; -} - -absl::optional -NetEqEventLogInput::NextSetMinimumDelayInfo() const { - return next_minimum_delay_event_info_; -} - -void NetEqEventLogInput::AdvanceOutputEvent() { - next_output_event_ms_ = source_->NextAudioOutputEventMs(); - if (*next_output_event_ms_ == std::numeric_limits::max()) { - next_output_event_ms_ = absl::nullopt; + auto output_events_it = parsed_log.audio_playout_events().find(*ssrc); + if (output_events_it == parsed_log.audio_playout_events().end()) { + return nullptr; } -} - -void NetEqEventLogInput::AdvanceSetMinimumDelay() { - next_minimum_delay_event_info_ = source_->NextSetMinimumDelayEvent(); -} - -PacketSource* NetEqEventLogInput::source() { - return source_.get(); -} - -NetEqEventLogInput::NetEqEventLogInput( - std::unique_ptr source) - : source_(std::move(source)) { - LoadNextPacket(); - AdvanceOutputEvent(); - AdvanceSetMinimumDelay(); + std::vector neteq_set_minimum_delay_events; + auto neteq_set_minimum_delay_events_it = + parsed_log.neteq_set_minimum_delay_events().find(*ssrc); + if (neteq_set_minimum_delay_events_it != + parsed_log.neteq_set_minimum_delay_events().end()) { + neteq_set_minimum_delay_events = neteq_set_minimum_delay_events_it->second; + } + int64_t end_time_ms = parsed_log.first_log_segment().stop_time_ms(); + return std::make_unique( + stream->incoming_packets, output_events_it->second, + neteq_set_minimum_delay_events, end_time_ms); } } // namespace test 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 1e64cc59a4..a84de8469c 100644 --- a/modules/audio_coding/neteq/tools/neteq_event_log_input.h +++ b/modules/audio_coding/neteq/tools/neteq_event_log_input.h @@ -11,43 +11,17 @@ #ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EVENT_LOG_INPUT_H_ #define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EVENT_LOG_INPUT_H_ -#include -#include -#include - #include "absl/strings/string_view.h" -#include "modules/audio_coding/neteq/tools/neteq_packet_source_input.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "absl/types/optional.h" +#include "logging/rtc_event_log/rtc_event_log_parser.h" +#include "modules/audio_coding/neteq/tools/neteq_input.h" namespace webrtc { namespace test { -class RtcEventLogSource; - -// Implementation of NetEqPacketSourceInput to be used with an -// RtcEventLogSource. -class NetEqEventLogInput final : public NetEqPacketSourceInput { - public: - static NetEqEventLogInput* CreateFromFile( - absl::string_view file_name, - absl::optional ssrc_filter); - static NetEqEventLogInput* CreateFromString( - absl::string_view file_contents, - absl::optional ssrc_filter); - - absl::optional NextOutputEventTime() const override; - absl::optional NextSetMinimumDelayInfo() const override; - void AdvanceOutputEvent() override; - void AdvanceSetMinimumDelay() override; - - protected: - PacketSource* source() override; - - private: - NetEqEventLogInput(std::unique_ptr source); - std::unique_ptr source_; - absl::optional next_minimum_delay_event_info_; -}; +std::unique_ptr CreateNetEqEventLogInput( + const ParsedRtcEventLog& parsed_log, + absl::optional ssrc); } // namespace test } // namespace webrtc diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.cc b/modules/audio_coding/neteq/tools/neteq_test_factory.cc index 6cd371406c..5f595d8b4e 100644 --- a/modules/audio_coding/neteq/tools/neteq_test_factory.cc +++ b/modules/audio_coding/neteq/tools/neteq_test_factory.cc @@ -112,8 +112,14 @@ std::unique_ptr NetEqTestFactory::InitializeTestFromString( absl::string_view input_string, NetEqFactory* factory, const Config& config) { - std::unique_ptr input( - NetEqEventLogInput::CreateFromString(input_string, config.ssrc_filter)); + ParsedRtcEventLog parsed_log; + auto status = parsed_log.ParseString(input_string); + if (!status.ok()) { + std::cerr << "Failed to parse event log: " << status.message() << std::endl; + return nullptr; + } + std::unique_ptr input = + CreateNetEqEventLogInput(parsed_log, config.ssrc_filter); if (!input) { std::cerr << "Error: Cannot parse input string" << std::endl; return nullptr; @@ -139,8 +145,14 @@ std::unique_ptr NetEqTestFactory::InitializeTestFromFile( input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map, config.ssrc_filter)); } else { - input.reset(NetEqEventLogInput::CreateFromFile(input_file_name, - config.ssrc_filter)); + ParsedRtcEventLog parsed_log; + auto status = parsed_log.ParseFile(input_file_name); + if (!status.ok()) { + std::cerr << "Failed to parse event log: " << status.message() + << std::endl; + return nullptr; + } + input = CreateNetEqEventLogInput(parsed_log, config.ssrc_filter); } std::cout << "Input file: " << input_file_name << std::endl; diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc b/modules/audio_coding/neteq/tools/rtc_event_log_source.cc deleted file mode 100644 index 68acfb7f62..0000000000 --- a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_coding/neteq/tools/rtc_event_log_source.h" - -#include - -#include -#include -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "logging/rtc_event_log/rtc_event_processor.h" -#include "modules/audio_coding/neteq/tools/neteq_input.h" -#include "modules/audio_coding/neteq/tools/packet.h" -#include "rtc_base/checks.h" - -namespace webrtc { -namespace test { - -namespace { -bool ShouldSkipStream(ParsedRtcEventLog::MediaType media_type, - uint32_t ssrc, - absl::optional ssrc_filter) { - if (media_type != ParsedRtcEventLog::MediaType::AUDIO) - return true; - if (ssrc_filter.has_value() && ssrc != *ssrc_filter) - return true; - return false; -} -} // namespace - -std::unique_ptr RtcEventLogSource::CreateFromFile( - absl::string_view file_name, - absl::optional ssrc_filter) { - auto source = std::unique_ptr(new RtcEventLogSource()); - ParsedRtcEventLog parsed_log; - auto status = parsed_log.ParseFile(file_name); - if (!status.ok()) { - std::cerr << "Failed to parse event log: " << status.message() << std::endl; - std::cerr << "Skipping log." << std::endl; - return nullptr; - } - if (!source->Initialize(parsed_log, ssrc_filter)) { - std::cerr << "Failed to initialize source from event log, skipping." - << std::endl; - return nullptr; - } - return source; -} - -std::unique_ptr RtcEventLogSource::CreateFromString( - absl::string_view file_contents, - absl::optional ssrc_filter) { - auto source = std::unique_ptr(new RtcEventLogSource()); - ParsedRtcEventLog parsed_log; - auto status = parsed_log.ParseString(file_contents); - if (!status.ok()) { - std::cerr << "Failed to parse event log: " << status.message() << std::endl; - std::cerr << "Skipping log." << std::endl; - return nullptr; - } - if (!source->Initialize(parsed_log, ssrc_filter)) { - std::cerr << "Failed to initialize source from event log, skipping." - << std::endl; - return nullptr; - } - return source; -} - -RtcEventLogSource::~RtcEventLogSource() {} - -std::unique_ptr RtcEventLogSource::NextPacket() { - if (rtp_packet_index_ >= rtp_packets_.size()) - return nullptr; - - std::unique_ptr packet = std::move(rtp_packets_[rtp_packet_index_++]); - return packet; -} - -int64_t RtcEventLogSource::NextAudioOutputEventMs() { - if (audio_output_index_ >= audio_outputs_.size()) - return std::numeric_limits::max(); - - int64_t output_time_ms = audio_outputs_[audio_output_index_++]; - return output_time_ms; -} - -absl::optional -RtcEventLogSource::NextSetMinimumDelayEvent() { - if (minimum_delay_index_ >= minimum_delay_.size()) { - return absl::nullopt; - } - return minimum_delay_[minimum_delay_index_++]; -} - -RtcEventLogSource::RtcEventLogSource() : PacketSource() {} - -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() - : parsed_log.stop_log_events().front().log_time_us(); - - std::set packet_ssrcs; - auto handle_rtp_packet = - [this, first_log_end_time_us, - &packet_ssrcs](const webrtc::LoggedRtpPacketIncoming& incoming) { - if (!filter_.test(incoming.rtp.header.payloadType) && - incoming.log_time_us() < first_log_end_time_us) { - rtp_packets_.emplace_back(std::make_unique( - incoming.rtp.header, incoming.rtp.total_length, - incoming.rtp.total_length - incoming.rtp.header_length, - static_cast(incoming.log_time_ms()))); - packet_ssrcs.insert(rtp_packets_.back()->header().ssrc); - } - }; - - std::set ignored_ssrcs; - auto handle_audio_playout = - [this, first_log_end_time_us, &packet_ssrcs, - &ignored_ssrcs](const webrtc::LoggedAudioPlayoutEvent& audio_playout) { - if (audio_playout.log_time_us() < first_log_end_time_us) { - if (packet_ssrcs.count(audio_playout.ssrc) > 0) { - audio_outputs_.emplace_back(audio_playout.log_time_ms()); - } else { - ignored_ssrcs.insert(audio_playout.ssrc); - } - } - }; - - auto handle_neteq_set_minimum_delay = - [this, first_log_end_time_us, &packet_ssrcs]( - const webrtc::LoggedNetEqSetMinimumDelayEvent minimum_delay_event) { - if (minimum_delay_event.log_time_us() < first_log_end_time_us) { - if (packet_ssrcs.count(minimum_delay_event.remote_ssrc) > 0) { - minimum_delay_.emplace_back(minimum_delay_event.log_time_ms(), - minimum_delay_event.minimum_delay_ms); - } - } - }; - - // This wouldn't be needed if we knew that there was at most one audio stream. - webrtc::RtcEventProcessor event_processor; - for (const auto& rtp_packets : parsed_log.incoming_rtp_packets_by_ssrc()) { - ParsedRtcEventLog::MediaType media_type = - parsed_log.GetMediaType(rtp_packets.ssrc, webrtc::kIncomingPacket); - if (ShouldSkipStream(media_type, rtp_packets.ssrc, ssrc_filter)) { - continue; - } - event_processor.AddEvents(rtp_packets.incoming_packets, handle_rtp_packet); - // If no SSRC filter has been set, use the first SSRC only. The simulator - // does not work properly with interleaved packets from multiple SSRCs. - if (!ssrc_filter.has_value()) { - ssrc_filter = rtp_packets.ssrc; - } - } - - for (const auto& audio_playouts : parsed_log.audio_playout_events()) { - if (ssrc_filter.has_value() && audio_playouts.first != *ssrc_filter) - continue; - event_processor.AddEvents(audio_playouts.second, handle_audio_playout); - } - - for (const auto& neteq_set_minimum_delay_event : - parsed_log.neteq_set_minimum_delay_events()) { - if (ssrc_filter.has_value() && - neteq_set_minimum_delay_event.first != *ssrc_filter) { - continue; - } - event_processor.AddEvents(neteq_set_minimum_delay_event.second, - handle_neteq_set_minimum_delay); - } - - // Fills in rtp_packets_ and audio_outputs_. - event_processor.ProcessEventsInOrder(); - - for (const auto& ssrc : ignored_ssrcs) { - std::cout << "Ignoring GetAudio events from SSRC 0x" << std::hex << ssrc - << " because no packets were found with a matching SSRC." - << std::endl; - } - - return true; -} - -} // namespace test -} // namespace webrtc diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.h b/modules/audio_coding/neteq/tools/rtc_event_log_source.h deleted file mode 100644 index 1445314247..0000000000 --- a/modules/audio_coding/neteq/tools/rtc_event_log_source.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_RTC_EVENT_LOG_SOURCE_H_ -#define MODULES_AUDIO_CODING_NETEQ_TOOLS_RTC_EVENT_LOG_SOURCE_H_ - -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" -#include "logging/rtc_event_log/rtc_event_log_parser.h" -#include "modules/audio_coding/neteq/tools/neteq_input.h" -#include "modules/audio_coding/neteq/tools/packet_source.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" - -namespace webrtc { - -class RtpHeaderParser; - -namespace test { - -class Packet; - -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 std::unique_ptr CreateFromFile( - absl::string_view file_name, - absl::optional ssrc_filter); - // Same as above, but uses a string with the file contents. - static std::unique_ptr CreateFromString( - absl::string_view file_contents, - absl::optional ssrc_filter); - - virtual ~RtcEventLogSource(); - - RtcEventLogSource(const RtcEventLogSource&) = delete; - RtcEventLogSource& operator=(const RtcEventLogSource&) = delete; - - std::unique_ptr NextPacket() override; - - // Returns the timestamp of the next audio output event, in milliseconds. The - // maximum value of int64_t is returned if there are no more audio output - // events available. - int64_t NextAudioOutputEventMs(); - - // Returns the next NetEq set minimum delay event if available. - absl::optional NextSetMinimumDelayEvent(); - - private: - RtcEventLogSource(); - - bool Initialize(const ParsedRtcEventLog& parsed_log, - absl::optional ssrc_filter); - - std::vector> rtp_packets_; - size_t rtp_packet_index_ = 0; - std::vector audio_outputs_; - size_t audio_output_index_ = 0; - std::vector minimum_delay_; - size_t minimum_delay_index_ = 0; -}; - -} // namespace test -} // namespace webrtc - -#endif // MODULES_AUDIO_CODING_NETEQ_TOOLS_RTC_EVENT_LOG_SOURCE_H_ diff --git a/rtc_tools/rtc_event_log_visualizer/analyze_audio.cc b/rtc_tools/rtc_event_log_visualizer/analyze_audio.cc index e2b4ecfe8d..6a9ef9e5ec 100644 --- a/rtc_tools/rtc_event_log_visualizer/analyze_audio.cc +++ b/rtc_tools/rtc_event_log_visualizer/analyze_audio.cc @@ -18,6 +18,7 @@ #include "modules/audio_coding/neteq/tools/audio_sink.h" #include "modules/audio_coding/neteq/tools/fake_decode_from_file.h" #include "modules/audio_coding/neteq/tools/neteq_delay_analyzer.h" +#include "modules/audio_coding/neteq/tools/neteq_event_log_input.h" #include "modules/audio_coding/neteq/tools/neteq_replacement_input.h" #include "modules/audio_coding/neteq/tools/neteq_test.h" #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h" @@ -176,114 +177,6 @@ void CreateAudioEncoderNumChannelsGraph(const ParsedRtcEventLog& parsed_log, plot->SetTitle("Reported audio encoder number of channels"); } -class NetEqStreamInput : public test::NetEqInput { - public: - // Does not take any ownership, and all pointers must refer to valid objects - // that outlive the one constructed. - NetEqStreamInput(const std::vector* packet_stream, - const std::vector* output_events, - const std::vector* - neteq_set_minimum_delay_events, - absl::optional end_time_ms) - : packet_stream_(*packet_stream), - packet_stream_it_(packet_stream_.begin()), - output_events_it_(output_events->begin()), - output_events_end_(output_events->end()), - neteq_set_minimum_delay_events_it_( - neteq_set_minimum_delay_events->begin()), - neteq_set_minimum_delay_events_end_( - neteq_set_minimum_delay_events->end()), - end_time_ms_(end_time_ms) { - RTC_DCHECK(packet_stream); - RTC_DCHECK(output_events); - } - - absl::optional NextPacketTime() const override { - if (packet_stream_it_ == packet_stream_.end()) { - return absl::nullopt; - } - if (end_time_ms_ && packet_stream_it_->rtp.log_time_ms() > *end_time_ms_) { - return absl::nullopt; - } - return packet_stream_it_->rtp.log_time_ms(); - } - - absl::optional NextOutputEventTime() const override { - if (output_events_it_ == output_events_end_) { - return absl::nullopt; - } - if (end_time_ms_ && output_events_it_->log_time_ms() > *end_time_ms_) { - return absl::nullopt; - } - return output_events_it_->log_time_ms(); - } - - absl::optional NextSetMinimumDelayInfo() const override { - if (neteq_set_minimum_delay_events_it_ == - neteq_set_minimum_delay_events_end_) { - return absl::nullopt; - } - if (end_time_ms_ && - neteq_set_minimum_delay_events_it_->log_time_ms() > *end_time_ms_) { - return absl::nullopt; - } - return SetMinimumDelayInfo( - neteq_set_minimum_delay_events_it_->log_time_ms(), - neteq_set_minimum_delay_events_it_->minimum_delay_ms); - } - - std::unique_ptr PopPacket() override { - if (packet_stream_it_ == packet_stream_.end()) { - return std::unique_ptr(); - } - std::unique_ptr packet_data(new PacketData()); - packet_data->header = packet_stream_it_->rtp.header; - packet_data->time_ms = packet_stream_it_->rtp.log_time_ms(); - - // This is a header-only "dummy" packet. Set the payload to all zeros, with - // length according to the virtual length. - packet_data->payload.SetSize(packet_stream_it_->rtp.total_length - - packet_stream_it_->rtp.header_length); - std::fill_n(packet_data->payload.data(), packet_data->payload.size(), 0); - - ++packet_stream_it_; - return packet_data; - } - - void AdvanceOutputEvent() override { - if (output_events_it_ != output_events_end_) { - ++output_events_it_; - } - } - - void AdvanceSetMinimumDelay() override { - if (neteq_set_minimum_delay_events_it_ != - neteq_set_minimum_delay_events_end_) { - ++neteq_set_minimum_delay_events_it_; - } - } - - bool ended() const override { return !NextEventTime(); } - - absl::optional NextHeader() const override { - if (packet_stream_it_ == packet_stream_.end()) { - return absl::nullopt; - } - return packet_stream_it_->rtp.header; - } - - private: - const std::vector& packet_stream_; - std::vector::const_iterator packet_stream_it_; - std::vector::const_iterator output_events_it_; - const std::vector::const_iterator output_events_end_; - std::vector::const_iterator - neteq_set_minimum_delay_events_it_; - const std::vector::const_iterator - neteq_set_minimum_delay_events_end_; - const absl::optional end_time_ms_; -}; - namespace { // Factory to create a "replacement decoder" that produces the decoded audio @@ -323,16 +216,12 @@ class ReplacementAudioDecoderFactory : public AudioDecoderFactory { // the test and returns the NetEqDelayAnalyzer object that was used to // instrument the test. std::unique_ptr CreateNetEqTestAndRun( - const std::vector* packet_stream, - const std::vector* output_events, - const std::vector* - neteq_set_minimum_delay_events, - absl::optional end_time_ms, + ParsedRtcEventLog parsed_log, + uint32_t ssrc, const std::string& replacement_file_name, int file_sample_rate_hz) { - std::unique_ptr input( - new NetEqStreamInput(packet_stream, output_events, - neteq_set_minimum_delay_events, end_time_ms)); + std::unique_ptr input = + test::CreateNetEqEventLogInput(parsed_log, ssrc); constexpr int kReplacementPt = 127; std::set cn_types; @@ -373,47 +262,10 @@ NetEqStatsGetterMap SimulateNetEq(const ParsedRtcEventLog& parsed_log, const std::string& replacement_file_name, int file_sample_rate_hz) { NetEqStatsGetterMap neteq_stats; - - for (const auto& stream : parsed_log.incoming_rtp_packets_by_ssrc()) { - const uint32_t ssrc = stream.ssrc; - if (!IsAudioSsrc(parsed_log, kIncomingPacket, ssrc)) - continue; - const std::vector* audio_packets = - &stream.incoming_packets; - if (audio_packets == nullptr) { - // No incoming audio stream found. - continue; - } - - RTC_DCHECK(neteq_stats.find(ssrc) == neteq_stats.end()); - - std::map>::const_iterator - output_events_it = parsed_log.audio_playout_events().find(ssrc); - if (output_events_it == parsed_log.audio_playout_events().end()) { - // Could not find output events with SSRC matching the input audio stream. - // Using the first available stream of output events. - output_events_it = parsed_log.audio_playout_events().cbegin(); - } - - const auto neteq_set_minimum_delay_events_it = - parsed_log.neteq_set_minimum_delay_events().find(ssrc); - std::vector - empty_neteq_set_minimum_delay_event; - const std::vector& - neteq_set_minimum_delay_events = - neteq_set_minimum_delay_events_it == - parsed_log.neteq_set_minimum_delay_events().cend() - ? empty_neteq_set_minimum_delay_event - : neteq_set_minimum_delay_events_it->second; - - int64_t end_time_ms = parsed_log.first_log_segment().stop_time_ms(); - - neteq_stats[ssrc] = - CreateNetEqTestAndRun(audio_packets, &output_events_it->second, - &neteq_set_minimum_delay_events, end_time_ms, - replacement_file_name, file_sample_rate_hz); + for (uint32_t ssrc : parsed_log.incoming_audio_ssrcs()) { + neteq_stats[ssrc] = CreateNetEqTestAndRun( + parsed_log, ssrc, replacement_file_name, file_sample_rate_hz); } - return neteq_stats; }