diff --git a/test/DEPS b/test/DEPS index c4634f864c..9bf5867bc5 100644 --- a/test/DEPS +++ b/test/DEPS @@ -54,6 +54,10 @@ specific_include_rules = { "+pc", "+p2p", ], + ".*test_peer_factory\.(h|cc)": [ + "+pc", + "+p2p", + ], ".*network_emulation_pc_unittest\.cc": [ "+pc/peer_connection_wrapper.h", "+pc/test/mock_peer_connection_observers.h", diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn index 492736fb33..c01c749dc8 100644 --- a/test/pc/e2e/BUILD.gn +++ b/test/pc/e2e/BUILD.gn @@ -220,35 +220,41 @@ if (rtc_include_tests) { "test_peer.cc", "test_peer.h", ] + deps = [ + ":peer_connection_quality_test_params", + "../../../api:frame_generator_api", + "../../../api:scoped_refptr", + "../../../modules/audio_processing:api", + "../../../pc:peerconnection_wrapper", + "//third_party/abseil-cpp/absl/memory", + ] + } + + rtc_library("test_peer_factory") { + visibility = [ "*" ] + testonly = true + sources = [ + "test_peer_factory.cc", + "test_peer_factory.h", + ] deps = [ ":echo_emulation", ":peer_connection_quality_test_params", + ":test_peer", ":video_quality_analyzer_injection_helper", - "../../../api:frame_generator_api", + "../..:copy_to_file_audio_capturer", "../../../api:peer_connection_quality_test_fixture_api", - "../../../api:scoped_refptr", "../../../api/rtc_event_log:rtc_event_log_factory", - "../../../api/task_queue", "../../../api/task_queue:default_task_queue_factory", "../../../api/video_codecs:builtin_video_decoder_factory", "../../../api/video_codecs:builtin_video_encoder_factory", "../../../media:rtc_audio_video", - "../../../media:rtc_media_base", "../../../media:rtc_media_engine_defaults", - "../../../modules/audio_device:audio_device_api", "../../../modules/audio_device:audio_device_impl", - "../../../modules/audio_processing:api", - "../../../modules/audio_processing/aec_dump:aec_dump", + "../../../modules/audio_processing/aec_dump", "../../../p2p:rtc_p2p", - "../../../pc:pc_test_utils", - "../../../pc:peerconnection_wrapper", - "../../../rtc_base", - "../../../rtc_base:rtc_base_approved", "../../../rtc_base:rtc_task_queue", - "../../../test:copy_to_file_audio_capturer", - "../../../test:video_test_common", "//third_party/abseil-cpp/absl/memory", - "//third_party/abseil-cpp/absl/types:optional", ] } @@ -269,6 +275,7 @@ if (rtc_include_tests) { ":single_process_encoded_image_data_injector", ":stats_poller", ":test_peer", + ":test_peer_factory", ":video_quality_analyzer_injection_helper", ":video_quality_metrics_reporter", "../..:field_trial", diff --git a/test/pc/e2e/peer_connection_quality_test.cc b/test/pc/e2e/peer_connection_quality_test.cc index f16389ff69..bf25443eab 100644 --- a/test/pc/e2e/peer_connection_quality_test.cc +++ b/test/pc/e2e/peer_connection_quality_test.cc @@ -37,6 +37,7 @@ #include "test/pc/e2e/analyzer/video/default_video_quality_analyzer.h" #include "test/pc/e2e/analyzer/video/video_quality_metrics_reporter.h" #include "test/pc/e2e/stats_poller.h" +#include "test/pc/e2e/test_peer_factory.h" #include "test/platform_video_capturer.h" #include "test/testsupport/file_utils.h" @@ -278,15 +279,15 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) { // Audio streams are intercepted in AudioDeviceModule, so if it is required to // catch output of Alice's stream, Alice's output_dump_file_name should be // passed to Bob's TestPeer setup as audio output file name. - absl::optional alice_remote_audio_config = - TestPeer::CreateRemoteAudioConfig(bob_params->audio_config); - absl::optional bob_remote_audio_config = - TestPeer::CreateRemoteAudioConfig(alice_params->audio_config); + absl::optional alice_remote_audio_config = + RemotePeerAudioConfig::Create(bob_params->audio_config); + absl::optional bob_remote_audio_config = + RemotePeerAudioConfig::Create(alice_params->audio_config); // Copy Alice and Bob video configs to correctly pass them into lambdas. std::vector alice_video_configs = alice_params->video_configs; std::vector bob_video_configs = bob_params->video_configs; - alice_ = TestPeer::CreateTestPeer( + alice_ = TestPeerFactory::CreateTestPeer( std::move(alice_components), std::move(alice_params), std::move(alice_video_generators), std::make_unique( @@ -298,7 +299,7 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) { video_quality_analyzer_injection_helper_.get(), signaling_thread.get(), alice_remote_audio_config, run_params.video_encoder_bitrate_multiplier, run_params.echo_emulation_config, task_queue_.get()); - bob_ = TestPeer::CreateTestPeer( + bob_ = TestPeerFactory::CreateTestPeer( std::move(bob_components), std::move(bob_params), std::move(bob_video_generators), std::make_unique( diff --git a/test/pc/e2e/test_peer.cc b/test/pc/e2e/test_peer.cc index 1b80633a0b..a95cd8db5a 100644 --- a/test/pc/e2e/test_peer.cc +++ b/test/pc/e2e/test_peer.cc @@ -9,356 +9,15 @@ */ #include "test/pc/e2e/test_peer.h" +#include #include #include "absl/memory/memory.h" -#include "absl/types/optional.h" -#include "api/rtc_event_log/rtc_event_log_factory.h" #include "api/scoped_refptr.h" -#include "api/task_queue/default_task_queue_factory.h" -#include "api/task_queue/task_queue_factory.h" -#include "api/video_codecs/builtin_video_decoder_factory.h" -#include "api/video_codecs/builtin_video_encoder_factory.h" -#include "media/engine/webrtc_media_engine.h" -#include "media/engine/webrtc_media_engine_defaults.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_processing/aec_dump/aec_dump_factory.h" #include "modules/audio_processing/include/audio_processing.h" -#include "p2p/client/basic_port_allocator.h" -#include "rtc_base/location.h" -#include "test/pc/e2e/echo/echo_emulation.h" -#include "test/testsupport/copy_to_file_audio_capturer.h" namespace webrtc { namespace webrtc_pc_e2e { -namespace { - -using RemotePeerAudioConfig = - ::webrtc::webrtc_pc_e2e::TestPeer::RemotePeerAudioConfig; -using AudioConfig = - ::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::AudioConfig; -using EchoEmulationConfig = ::webrtc::webrtc_pc_e2e:: - PeerConnectionE2EQualityTestFixture::EchoEmulationConfig; - -constexpr int16_t kGeneratedAudioMaxAmplitude = 32000; -constexpr int kDefaultSamplingFrequencyInHz = 48000; - -// Sets mandatory entities in injectable components like |pcf_dependencies| -// and |pc_dependencies| if they are omitted. Also setup required -// dependencies, that won't be specially provided by factory and will be just -// transferred to peer connection creation code. -void SetMandatoryEntities(InjectableComponents* components) { - RTC_DCHECK(components->pcf_dependencies); - RTC_DCHECK(components->pc_dependencies); - - // Setup required peer connection factory dependencies. - if (components->pcf_dependencies->task_queue_factory == nullptr) { - components->pcf_dependencies->task_queue_factory = - CreateDefaultTaskQueueFactory(); - } - if (components->pcf_dependencies->call_factory == nullptr) { - components->pcf_dependencies->call_factory = webrtc::CreateCallFactory(); - } - if (components->pcf_dependencies->event_log_factory == nullptr) { - components->pcf_dependencies->event_log_factory = - std::make_unique( - components->pcf_dependencies->task_queue_factory.get()); - } -} - -class TestPeerComponents { - public: - TestPeerComponents(std::unique_ptr components, - const Params& params, - MockPeerConnectionObserver* observer, - VideoQualityAnalyzerInjectionHelper* video_analyzer_helper, - rtc::Thread* signaling_thread, - absl::optional remote_audio_config, - double bitrate_multiplier, - absl::optional echo_emulation_config, - rtc::TaskQueue* task_queue) - : audio_config_opt_(params.audio_config), - observer_(observer), - video_analyzer_helper_(video_analyzer_helper), - signaling_thread_(signaling_thread), - remote_audio_config_(std::move(remote_audio_config)), - bitrate_multiplier_(bitrate_multiplier), - echo_emulation_config_(std::move(echo_emulation_config)) { - for (auto& video_config : params.video_configs) { - // Stream label should be set by fixture implementation here. - RTC_DCHECK(video_config.stream_label); - bool res = - stream_required_spatial_index_ - .insert({*video_config.stream_label, - video_config.simulcast_config - ? absl::optional(video_config.simulcast_config - ->target_spatial_index) - : absl::nullopt}) - .second; - RTC_DCHECK(res) << "Duplicate video_config.stream_label=" - << *video_config.stream_label; - } - - // Create audio processing, that will be used to create media engine that - // then will be added into peer connection. See CreateMediaEngine(...). - audio_processing_ = webrtc::AudioProcessingBuilder().Create(); - if (params.aec_dump_path) { - audio_processing_->AttachAecDump( - AecDumpFactory::Create(*params.aec_dump_path, -1, task_queue)); - } - - // Create peer connection factory. - PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies( - std::move(components->pcf_dependencies), components->network_thread); - peer_connection_factory_ = - CreateModularPeerConnectionFactory(std::move(pcf_deps)); - - // Create peer connection. - PeerConnectionDependencies pc_deps = - CreatePCDependencies(std::move(components->pc_dependencies)); - peer_connection_ = peer_connection_factory_->CreatePeerConnection( - params.rtc_configuration, std::move(pc_deps)); - peer_connection_->SetBitrate(params.bitrate_params); - } - - rtc::scoped_refptr peer_connection_factory() - const { - return peer_connection_factory_; - } - rtc::scoped_refptr peer_connection() const { - return peer_connection_; - } - rtc::scoped_refptr audio_processing() const { - return audio_processing_; - } - - private: - // Creates PeerConnectionFactoryDependencies objects, providing entities - // from InjectableComponents::PeerConnectionFactoryComponents and also - // creating entities, that are required for correct injection of media quality - // analyzers. - PeerConnectionFactoryDependencies CreatePCFDependencies( - std::unique_ptr pcf_dependencies, - rtc::Thread* network_thread) { - PeerConnectionFactoryDependencies pcf_deps; - pcf_deps.network_thread = network_thread; - pcf_deps.signaling_thread = signaling_thread_; - pcf_deps.media_engine = CreateMediaEngine(pcf_dependencies.get()); - - pcf_deps.call_factory = std::move(pcf_dependencies->call_factory); - pcf_deps.event_log_factory = std::move(pcf_dependencies->event_log_factory); - pcf_deps.task_queue_factory = - std::move(pcf_dependencies->task_queue_factory); - - if (pcf_dependencies->fec_controller_factory != nullptr) { - pcf_deps.fec_controller_factory = - std::move(pcf_dependencies->fec_controller_factory); - } - if (pcf_dependencies->network_controller_factory != nullptr) { - pcf_deps.network_controller_factory = - std::move(pcf_dependencies->network_controller_factory); - } - if (pcf_dependencies->media_transport_factory != nullptr) { - pcf_deps.media_transport_factory = - std::move(pcf_dependencies->media_transport_factory); - } - if (pcf_dependencies->neteq_factory != nullptr) { - pcf_deps.neteq_factory = std::move(pcf_dependencies->neteq_factory); - } - - return pcf_deps; - } - - std::unique_ptr CreateMediaEngine( - PeerConnectionFactoryComponents* pcf_dependencies) { - cricket::MediaEngineDependencies media_deps; - media_deps.task_queue_factory = pcf_dependencies->task_queue_factory.get(); - media_deps.adm = CreateAudioDeviceModule(media_deps.task_queue_factory); - media_deps.audio_processing = audio_processing_; - media_deps.video_encoder_factory = - CreateVideoEncoderFactory(pcf_dependencies); - media_deps.video_decoder_factory = - CreateVideoDecoderFactory(pcf_dependencies); - webrtc::SetMediaEngineDefaults(&media_deps); - return cricket::CreateMediaEngine(std::move(media_deps)); - } - - rtc::scoped_refptr CreateAudioDeviceModule( - TaskQueueFactory* task_queue_factory) { - std::unique_ptr renderer = - CreateAudioRenderer(remote_audio_config_); - std::unique_ptr capturer = - CreateAudioCapturer(audio_config_opt_); - RTC_DCHECK(renderer); - RTC_DCHECK(capturer); - - // Setup echo emulation if required. - if (echo_emulation_config_) { - capturer = std::make_unique( - std::move(capturer), *echo_emulation_config_); - renderer = std::make_unique( - std::move(renderer), - static_cast(capturer.get())); - } - - // Setup input stream dumping if required. - if (audio_config_opt_ && audio_config_opt_->input_dump_file_name) { - capturer = std::make_unique( - std::move(capturer), audio_config_opt_->input_dump_file_name.value()); - } - - return TestAudioDeviceModule::Create(task_queue_factory, - std::move(capturer), - std::move(renderer), /*speed=*/1.f); - } - - std::unique_ptr CreateAudioRenderer( - const absl::optional& config) { - if (!config) { - // Return default renderer because we always require some renderer. - return TestAudioDeviceModule::CreateDiscardRenderer( - kDefaultSamplingFrequencyInHz); - } - if (config->output_file_name) { - return TestAudioDeviceModule::CreateBoundedWavFileWriter( - config->output_file_name.value(), config->sampling_frequency_in_hz); - } - return TestAudioDeviceModule::CreateDiscardRenderer( - config->sampling_frequency_in_hz); - } - - std::unique_ptr CreateAudioCapturer( - const absl::optional& audio_config) { - if (!audio_config) { - // If we have no audio config we still need to provide some audio device. - // In such case use generated capturer. Despite of we provided audio here, - // in test media setup audio stream won't be added into peer connection. - return TestAudioDeviceModule::CreatePulsedNoiseCapturer( - kGeneratedAudioMaxAmplitude, kDefaultSamplingFrequencyInHz); - } - - switch (audio_config->mode) { - case AudioConfig::Mode::kGenerated: - return TestAudioDeviceModule::CreatePulsedNoiseCapturer( - kGeneratedAudioMaxAmplitude, - audio_config->sampling_frequency_in_hz); - case AudioConfig::Mode::kFile: - RTC_DCHECK(audio_config->input_file_name); - return TestAudioDeviceModule::CreateWavFileReader( - audio_config->input_file_name.value(), /*repeat=*/true); - } - } - - std::unique_ptr CreateVideoEncoderFactory( - PeerConnectionFactoryComponents* pcf_dependencies) { - std::unique_ptr video_encoder_factory; - if (pcf_dependencies->video_encoder_factory != nullptr) { - video_encoder_factory = - std::move(pcf_dependencies->video_encoder_factory); - } else { - video_encoder_factory = CreateBuiltinVideoEncoderFactory(); - } - return video_analyzer_helper_->WrapVideoEncoderFactory( - std::move(video_encoder_factory), bitrate_multiplier_, - stream_required_spatial_index_); - } - - std::unique_ptr CreateVideoDecoderFactory( - PeerConnectionFactoryComponents* pcf_dependencies) { - std::unique_ptr video_decoder_factory; - if (pcf_dependencies->video_decoder_factory != nullptr) { - video_decoder_factory = - std::move(pcf_dependencies->video_decoder_factory); - } else { - video_decoder_factory = CreateBuiltinVideoDecoderFactory(); - } - return video_analyzer_helper_->WrapVideoDecoderFactory( - std::move(video_decoder_factory)); - } - - // Creates PeerConnectionDependencies objects, providing entities - // from InjectableComponents::PeerConnectionComponents. - PeerConnectionDependencies CreatePCDependencies( - std::unique_ptr pc_dependencies) { - PeerConnectionDependencies pc_deps(observer_); - - auto port_allocator = std::make_unique( - pc_dependencies->network_manager); - - // This test does not support TCP - int flags = cricket::PORTALLOCATOR_DISABLE_TCP; - port_allocator->set_flags(port_allocator->flags() | flags); - - pc_deps.allocator = std::move(port_allocator); - - if (pc_dependencies->async_resolver_factory != nullptr) { - pc_deps.async_resolver_factory = - std::move(pc_dependencies->async_resolver_factory); - } - if (pc_dependencies->cert_generator != nullptr) { - pc_deps.cert_generator = std::move(pc_dependencies->cert_generator); - } - if (pc_dependencies->tls_cert_verifier != nullptr) { - pc_deps.tls_cert_verifier = std::move(pc_dependencies->tls_cert_verifier); - } - if (pc_dependencies->ice_transport_factory != nullptr) { - pc_deps.ice_transport_factory = - std::move(pc_dependencies->ice_transport_factory); - } - return pc_deps; - } - - rtc::scoped_refptr peer_connection_factory_; - rtc::scoped_refptr peer_connection_; - rtc::scoped_refptr audio_processing_; - - std::map> stream_required_spatial_index_; - absl::optional audio_config_opt_; - MockPeerConnectionObserver* observer_; - VideoQualityAnalyzerInjectionHelper* video_analyzer_helper_; - rtc::Thread* signaling_thread_; - absl::optional remote_audio_config_; - double bitrate_multiplier_; - absl::optional echo_emulation_config_; -}; - -} // namespace - -absl::optional TestPeer::CreateRemoteAudioConfig( - absl::optional config) { - if (!config) { - return absl::nullopt; - } - return RemotePeerAudioConfig(config.value()); -} - -std::unique_ptr TestPeer::CreateTestPeer( - std::unique_ptr components, - std::unique_ptr params, - std::vector> - video_generators, - std::unique_ptr observer, - VideoQualityAnalyzerInjectionHelper* video_analyzer_helper, - rtc::Thread* signaling_thread, - absl::optional remote_audio_config, - double bitrate_multiplier, - absl::optional echo_emulation_config, - rtc::TaskQueue* task_queue) { - RTC_DCHECK(components); - RTC_DCHECK(params); - RTC_DCHECK_EQ(params->video_configs.size(), video_generators.size()); - SetMandatoryEntities(components.get()); - params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan; - - TestPeerComponents tpc(std::move(components), *params, observer.get(), - video_analyzer_helper, signaling_thread, - std::move(remote_audio_config), bitrate_multiplier, - echo_emulation_config, task_queue); - - return absl::WrapUnique(new TestPeer( - tpc.peer_connection_factory(), tpc.peer_connection(), std::move(observer), - std::move(params), std::move(video_generators), tpc.audio_processing())); -} bool TestPeer::AddIceCandidates( std::vector> candidates) { diff --git a/test/pc/e2e/test_peer.h b/test/pc/e2e/test_peer.h index 3487720887..cd6435ca40 100644 --- a/test/pc/e2e/test_peer.h +++ b/test/pc/e2e/test_peer.h @@ -12,20 +12,11 @@ #define TEST_PC_E2E_TEST_PEER_H_ #include -#include #include #include "absl/memory/memory.h" #include "api/test/frame_generator_interface.h" -#include "api/test/peerconnection_quality_test_fixture.h" -#include "media/base/media_engine.h" -#include "modules/audio_device/include/test_audio_device.h" #include "pc/peer_connection_wrapper.h" -#include "pc/test/mock_peer_connection_observers.h" -#include "rtc_base/network.h" -#include "rtc_base/task_queue.h" -#include "rtc_base/thread.h" -#include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h" #include "test/pc/e2e/peer_connection_quality_test_params.h" namespace webrtc { @@ -35,43 +26,6 @@ namespace webrtc_pc_e2e { class TestPeer final : public PeerConnectionWrapper { public: using PeerConnectionWrapper::PeerConnectionWrapper; - using VideoConfig = PeerConnectionE2EQualityTestFixture::VideoConfig; - using AudioConfig = PeerConnectionE2EQualityTestFixture::AudioConfig; - using EchoEmulationConfig = - PeerConnectionE2EQualityTestFixture::EchoEmulationConfig; - - struct RemotePeerAudioConfig { - RemotePeerAudioConfig(AudioConfig config) - : sampling_frequency_in_hz(config.sampling_frequency_in_hz), - output_file_name(config.output_dump_file_name) {} - - int sampling_frequency_in_hz; - absl::optional output_file_name; - }; - - static absl::optional CreateRemoteAudioConfig( - absl::optional config); - - // Setups all components, that should be provided to WebRTC - // PeerConnectionFactory and PeerConnection creation methods, - // also will setup dependencies, that are required for media analyzers - // injection. - // - // |signaling_thread| will be provided by test fixture implementation. - // |params| - describes current peer parameters, like current peer video - // streams and audio streams - static std::unique_ptr CreateTestPeer( - std::unique_ptr components, - std::unique_ptr params, - std::vector> - video_generators, - std::unique_ptr observer, - VideoQualityAnalyzerInjectionHelper* video_analyzer_helper, - rtc::Thread* signaling_thread, - absl::optional remote_audio_config, - double bitrate_multiplier, - absl::optional echo_emulation_config, - rtc::TaskQueue* task_queue); Params* params() const { return params_.get(); } std::unique_ptr ReleaseVideoGenerator( @@ -85,7 +39,8 @@ class TestPeer final : public PeerConnectionWrapper { bool AddIceCandidates( std::vector> candidates); - private: + protected: + friend class TestPeerFactory; TestPeer(rtc::scoped_refptr pc_factory, rtc::scoped_refptr pc, std::unique_ptr observer, @@ -94,6 +49,7 @@ class TestPeer final : public PeerConnectionWrapper { video_generators, rtc::scoped_refptr audio_processing); + private: std::unique_ptr params_; std::vector> video_generators_; rtc::scoped_refptr audio_processing_; diff --git a/test/pc/e2e/test_peer_factory.cc b/test/pc/e2e/test_peer_factory.cc new file mode 100644 index 0000000000..84045091ce --- /dev/null +++ b/test/pc/e2e/test_peer_factory.cc @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2020 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 "test/pc/e2e/test_peer_factory.h" + +#include + +#include "absl/memory/memory.h" +#include "api/task_queue/default_task_queue_factory.h" +#include "api/video_codecs/builtin_video_decoder_factory.h" +#include "api/video_codecs/builtin_video_encoder_factory.h" +#include "media/engine/webrtc_media_engine.h" +#include "media/engine/webrtc_media_engine_defaults.h" +#include "modules/audio_processing/aec_dump/aec_dump_factory.h" +#include "p2p/client/basic_port_allocator.h" +#include "test/pc/e2e/echo/echo_emulation.h" +#include "test/testsupport/copy_to_file_audio_capturer.h" + +namespace webrtc { +namespace webrtc_pc_e2e { +namespace { + +using AudioConfig = + ::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::AudioConfig; +using VideoConfig = + ::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::VideoConfig; +using EchoEmulationConfig = ::webrtc::webrtc_pc_e2e:: + PeerConnectionE2EQualityTestFixture::EchoEmulationConfig; + +constexpr int16_t kGeneratedAudioMaxAmplitude = 32000; +constexpr int kDefaultSamplingFrequencyInHz = 48000; + +// Sets mandatory entities in injectable components like |pcf_dependencies| +// and |pc_dependencies| if they are omitted. Also setup required +// dependencies, that won't be specially provided by factory and will be just +// transferred to peer connection creation code. +void SetMandatoryEntities(InjectableComponents* components) { + RTC_DCHECK(components->pcf_dependencies); + RTC_DCHECK(components->pc_dependencies); + + // Setup required peer connection factory dependencies. + if (components->pcf_dependencies->task_queue_factory == nullptr) { + components->pcf_dependencies->task_queue_factory = + CreateDefaultTaskQueueFactory(); + } + if (components->pcf_dependencies->call_factory == nullptr) { + components->pcf_dependencies->call_factory = webrtc::CreateCallFactory(); + } + if (components->pcf_dependencies->event_log_factory == nullptr) { + components->pcf_dependencies->event_log_factory = + std::make_unique( + components->pcf_dependencies->task_queue_factory.get()); + } +} + +std::map> +CalculateRequiredSpatialIndexPerStream( + const std::vector& video_configs) { + std::map> out; + for (auto& video_config : video_configs) { + // Stream label should be set by fixture implementation here. + RTC_DCHECK(video_config.stream_label); + absl::optional spatial_index; + if (video_config.simulcast_config) { + spatial_index = video_config.simulcast_config->target_spatial_index; + } + bool res = out.insert({*video_config.stream_label, spatial_index}).second; + RTC_DCHECK(res) << "Duplicate video_config.stream_label=" + << *video_config.stream_label; + } + return out; +} + +std::unique_ptr CreateAudioRenderer( + const absl::optional& config) { + if (!config) { + // Return default renderer because we always require some renderer. + return TestAudioDeviceModule::CreateDiscardRenderer( + kDefaultSamplingFrequencyInHz); + } + if (config->output_file_name) { + return TestAudioDeviceModule::CreateBoundedWavFileWriter( + config->output_file_name.value(), config->sampling_frequency_in_hz); + } + return TestAudioDeviceModule::CreateDiscardRenderer( + config->sampling_frequency_in_hz); +} + +std::unique_ptr CreateAudioCapturer( + const absl::optional& audio_config) { + if (!audio_config) { + // If we have no audio config we still need to provide some audio device. + // In such case use generated capturer. Despite of we provided audio here, + // in test media setup audio stream won't be added into peer connection. + return TestAudioDeviceModule::CreatePulsedNoiseCapturer( + kGeneratedAudioMaxAmplitude, kDefaultSamplingFrequencyInHz); + } + + switch (audio_config->mode) { + case AudioConfig::Mode::kGenerated: + return TestAudioDeviceModule::CreatePulsedNoiseCapturer( + kGeneratedAudioMaxAmplitude, audio_config->sampling_frequency_in_hz); + case AudioConfig::Mode::kFile: + RTC_DCHECK(audio_config->input_file_name); + return TestAudioDeviceModule::CreateWavFileReader( + audio_config->input_file_name.value(), /*repeat=*/true); + } +} + +rtc::scoped_refptr CreateAudioDeviceModule( + absl::optional audio_config, + absl::optional remote_audio_config, + absl::optional echo_emulation_config, + TaskQueueFactory* task_queue_factory) { + std::unique_ptr renderer = + CreateAudioRenderer(remote_audio_config); + std::unique_ptr capturer = + CreateAudioCapturer(audio_config); + RTC_DCHECK(renderer); + RTC_DCHECK(capturer); + + // Setup echo emulation if required. + if (echo_emulation_config) { + capturer = std::make_unique(std::move(capturer), + *echo_emulation_config); + renderer = std::make_unique( + std::move(renderer), + static_cast(capturer.get())); + } + + // Setup input stream dumping if required. + if (audio_config && audio_config->input_dump_file_name) { + capturer = std::make_unique( + std::move(capturer), audio_config->input_dump_file_name.value()); + } + + return TestAudioDeviceModule::Create(task_queue_factory, std::move(capturer), + std::move(renderer), /*speed=*/1.f); +} + +std::unique_ptr CreateMediaEngine( + PeerConnectionFactoryComponents* pcf_dependencies, + rtc::scoped_refptr audio_device_module, + rtc::scoped_refptr audio_processing) { + cricket::MediaEngineDependencies media_deps; + media_deps.task_queue_factory = pcf_dependencies->task_queue_factory.get(); + media_deps.adm = audio_device_module; + media_deps.audio_processing = audio_processing; + media_deps.video_encoder_factory = + std::move(pcf_dependencies->video_encoder_factory); + media_deps.video_decoder_factory = + std::move(pcf_dependencies->video_decoder_factory); + webrtc::SetMediaEngineDefaults(&media_deps); + return cricket::CreateMediaEngine(std::move(media_deps)); +} + +void WrapVideoEncoderFactory( + double bitrate_multiplier, + std::map> stream_required_spatial_index, + PeerConnectionFactoryComponents* pcf_dependencies, + VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) { + std::unique_ptr video_encoder_factory; + if (pcf_dependencies->video_encoder_factory != nullptr) { + video_encoder_factory = std::move(pcf_dependencies->video_encoder_factory); + } else { + video_encoder_factory = CreateBuiltinVideoEncoderFactory(); + } + pcf_dependencies->video_encoder_factory = + video_analyzer_helper->WrapVideoEncoderFactory( + std::move(video_encoder_factory), bitrate_multiplier, + std::move(stream_required_spatial_index)); +} + +void WrapVideoDecoderFactory( + PeerConnectionFactoryComponents* pcf_dependencies, + VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) { + std::unique_ptr video_decoder_factory; + if (pcf_dependencies->video_decoder_factory != nullptr) { + video_decoder_factory = std::move(pcf_dependencies->video_decoder_factory); + } else { + video_decoder_factory = CreateBuiltinVideoDecoderFactory(); + } + pcf_dependencies->video_decoder_factory = + video_analyzer_helper->WrapVideoDecoderFactory( + std::move(video_decoder_factory)); +} + +// Creates PeerConnectionFactoryDependencies objects, providing entities +// from InjectableComponents::PeerConnectionFactoryComponents. +PeerConnectionFactoryDependencies CreatePCFDependencies( + std::unique_ptr pcf_dependencies, + std::unique_ptr media_engine, + rtc::Thread* signaling_thread, + rtc::Thread* network_thread) { + PeerConnectionFactoryDependencies pcf_deps; + pcf_deps.network_thread = network_thread; + pcf_deps.signaling_thread = signaling_thread; + pcf_deps.media_engine = std::move(media_engine); + + pcf_deps.call_factory = std::move(pcf_dependencies->call_factory); + pcf_deps.event_log_factory = std::move(pcf_dependencies->event_log_factory); + pcf_deps.task_queue_factory = std::move(pcf_dependencies->task_queue_factory); + + if (pcf_dependencies->fec_controller_factory != nullptr) { + pcf_deps.fec_controller_factory = + std::move(pcf_dependencies->fec_controller_factory); + } + if (pcf_dependencies->network_controller_factory != nullptr) { + pcf_deps.network_controller_factory = + std::move(pcf_dependencies->network_controller_factory); + } + if (pcf_dependencies->media_transport_factory != nullptr) { + pcf_deps.media_transport_factory = + std::move(pcf_dependencies->media_transport_factory); + } + if (pcf_dependencies->neteq_factory != nullptr) { + pcf_deps.neteq_factory = std::move(pcf_dependencies->neteq_factory); + } + + return pcf_deps; +} + +// Creates PeerConnectionDependencies objects, providing entities +// from InjectableComponents::PeerConnectionComponents. +PeerConnectionDependencies CreatePCDependencies( + MockPeerConnectionObserver* observer, + std::unique_ptr pc_dependencies) { + PeerConnectionDependencies pc_deps(observer); + + auto port_allocator = std::make_unique( + pc_dependencies->network_manager); + + // This test does not support TCP + int flags = cricket::PORTALLOCATOR_DISABLE_TCP; + port_allocator->set_flags(port_allocator->flags() | flags); + + pc_deps.allocator = std::move(port_allocator); + + if (pc_dependencies->async_resolver_factory != nullptr) { + pc_deps.async_resolver_factory = + std::move(pc_dependencies->async_resolver_factory); + } + if (pc_dependencies->cert_generator != nullptr) { + pc_deps.cert_generator = std::move(pc_dependencies->cert_generator); + } + if (pc_dependencies->tls_cert_verifier != nullptr) { + pc_deps.tls_cert_verifier = std::move(pc_dependencies->tls_cert_verifier); + } + if (pc_dependencies->ice_transport_factory != nullptr) { + pc_deps.ice_transport_factory = + std::move(pc_dependencies->ice_transport_factory); + } + return pc_deps; +} + +} // namespace + +absl::optional RemotePeerAudioConfig::Create( + absl::optional config) { + if (!config) { + return absl::nullopt; + } + return RemotePeerAudioConfig(config.value()); +} + +std::unique_ptr TestPeerFactory::CreateTestPeer( + std::unique_ptr components, + std::unique_ptr params, + std::vector> + video_generators, + std::unique_ptr observer, + VideoQualityAnalyzerInjectionHelper* video_analyzer_helper, + rtc::Thread* signaling_thread, + absl::optional remote_audio_config, + double bitrate_multiplier, + absl::optional echo_emulation_config, + rtc::TaskQueue* task_queue) { + RTC_DCHECK(components); + RTC_DCHECK(params); + RTC_DCHECK_EQ(params->video_configs.size(), video_generators.size()); + SetMandatoryEntities(components.get()); + params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan; + + // Create peer connection factory. + rtc::scoped_refptr audio_processing = + webrtc::AudioProcessingBuilder().Create(); + if (params->aec_dump_path) { + audio_processing->AttachAecDump( + AecDumpFactory::Create(*params->aec_dump_path, -1, task_queue)); + } + rtc::scoped_refptr audio_device_module = + CreateAudioDeviceModule( + params->audio_config, remote_audio_config, echo_emulation_config, + components->pcf_dependencies->task_queue_factory.get()); + WrapVideoEncoderFactory( + bitrate_multiplier, + CalculateRequiredSpatialIndexPerStream(params->video_configs), + components->pcf_dependencies.get(), video_analyzer_helper); + WrapVideoDecoderFactory(components->pcf_dependencies.get(), + video_analyzer_helper); + std::unique_ptr media_engine = + CreateMediaEngine(components->pcf_dependencies.get(), audio_device_module, + audio_processing); + PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies( + std::move(components->pcf_dependencies), std::move(media_engine), + signaling_thread, components->network_thread); + rtc::scoped_refptr peer_connection_factory = + CreateModularPeerConnectionFactory(std::move(pcf_deps)); + + // Create peer connection. + PeerConnectionDependencies pc_deps = CreatePCDependencies( + observer.get(), std::move(components->pc_dependencies)); + rtc::scoped_refptr peer_connection = + peer_connection_factory->CreatePeerConnection(params->rtc_configuration, + std::move(pc_deps)); + peer_connection->SetBitrate(params->bitrate_params); + + return absl::WrapUnique(new TestPeer( + peer_connection_factory, peer_connection, std::move(observer), + std::move(params), std::move(video_generators), audio_processing)); +} + +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/test/pc/e2e/test_peer_factory.h b/test/pc/e2e/test_peer_factory.h new file mode 100644 index 0000000000..155449eb2a --- /dev/null +++ b/test/pc/e2e/test_peer_factory.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 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 TEST_PC_E2E_TEST_PEER_FACTORY_H_ +#define TEST_PC_E2E_TEST_PEER_FACTORY_H_ + +#include +#include +#include +#include + +#include "api/rtc_event_log/rtc_event_log_factory.h" +#include "api/test/peerconnection_quality_test_fixture.h" +#include "modules/audio_device/include/test_audio_device.h" +#include "rtc_base/task_queue.h" +#include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h" +#include "test/pc/e2e/peer_connection_quality_test_params.h" +#include "test/pc/e2e/test_peer.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +struct RemotePeerAudioConfig { + explicit RemotePeerAudioConfig( + PeerConnectionE2EQualityTestFixture::AudioConfig config) + : sampling_frequency_in_hz(config.sampling_frequency_in_hz), + output_file_name(config.output_dump_file_name) {} + + static absl::optional Create( + absl::optional config); + + int sampling_frequency_in_hz; + absl::optional output_file_name; +}; + +class TestPeerFactory { + public: + // Setups all components, that should be provided to WebRTC + // PeerConnectionFactory and PeerConnection creation methods, + // also will setup dependencies, that are required for media analyzers + // injection. + // + // |signaling_thread| will be provided by test fixture implementation. + // |params| - describes current peer parameters, like current peer video + // streams and audio streams + static std::unique_ptr CreateTestPeer( + std::unique_ptr components, + std::unique_ptr params, + std::vector> + video_generators, + std::unique_ptr observer, + VideoQualityAnalyzerInjectionHelper* video_analyzer_helper, + rtc::Thread* signaling_thread, + absl::optional remote_audio_config, + double bitrate_multiplier, + absl::optional + echo_emulation_config, + rtc::TaskQueue* task_queue); +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // TEST_PC_E2E_TEST_PEER_FACTORY_H_