Add support for creation of AEC dump during the test with PC framework.

Also add conversational speech into PC smoke test (with resource files).

Bug: webrtc:10138
Change-Id: I415a5565bc9146821476ffc60f57f47ed51f89c4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132323
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27592}
diff --git a/api/test/peerconnection_quality_test_fixture.h b/api/test/peerconnection_quality_test_fixture.h
index b22b392..9538194 100644
--- a/api/test/peerconnection_quality_test_fixture.h
+++ b/api/test/peerconnection_quality_test_fixture.h
@@ -167,6 +167,9 @@
     // If is set, an RTCEventLog will be saved in that location and it will be
     // available for further analysis.
     virtual PeerConfigurer* SetRtcEventLogPath(std::string path) = 0;
+    // If is set, an AEC dump will be saved in that location and it will be
+    // available for further analysis.
+    virtual PeerConfigurer* SetAecDumpPath(std::string path) = 0;
     virtual PeerConfigurer* SetRTCConfiguration(
         PeerConnectionInterface::RTCConfiguration configuration) = 0;
   };
diff --git a/resources/pc_quality_smoke_test_alice_source.wav.sha1 b/resources/pc_quality_smoke_test_alice_source.wav.sha1
new file mode 100644
index 0000000..dd973ff
--- /dev/null
+++ b/resources/pc_quality_smoke_test_alice_source.wav.sha1
@@ -0,0 +1 @@
+28738955a60b9559b58b232e4d2d9cb7a1dd9b2a
\ No newline at end of file
diff --git a/resources/pc_quality_smoke_test_bob_source.wav.sha1 b/resources/pc_quality_smoke_test_bob_source.wav.sha1
new file mode 100644
index 0000000..73b1e60
--- /dev/null
+++ b/resources/pc_quality_smoke_test_bob_source.wav.sha1
@@ -0,0 +1 @@
+b18e0d654b84e6150dc79140f40dac3f8e675e7d
\ No newline at end of file
diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn
index f11c89e..e46f33d 100644
--- a/test/pc/e2e/BUILD.gn
+++ b/test/pc/e2e/BUILD.gn
@@ -208,11 +208,13 @@
       "../../../modules/audio_device:audio_device_api",
       "../../../modules/audio_device:audio_device_impl",
       "../../../modules/audio_processing:api",
+      "../../../modules/audio_processing/aec_dump: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",
@@ -286,6 +288,20 @@
     ]
   }
 
+  peer_connection_e2e_smoke_test_resources = [
+    "../../../resources/pc_quality_smoke_test_alice_source.wav",
+    "../../../resources/pc_quality_smoke_test_bob_source.wav",
+  ]
+  if (is_ios) {
+    bundle_data("peer_connection_e2e_smoke_test_resources_bundle_data") {
+      testonly = true
+      sources = peer_connection_e2e_smoke_test_resources
+      outputs = [
+        "{{bundle_resources_dir}}/{{source_file_part}}",
+      ]
+    }
+  }
+
   rtc_source_set("peer_connection_e2e_smoke_test") {
     testonly = true
     sources = [
@@ -321,6 +337,10 @@
       "../../../test:test_support",
       "//third_party/abseil-cpp/absl/memory",
     ]
+    data = peer_connection_e2e_smoke_test_resources
+    if (is_ios) {
+      deps += [ ":peer_connection_e2e_smoke_test_resources_bundle_data" ]
+    }
   }
 
   rtc_source_set("stats_poller") {
diff --git a/test/pc/e2e/peer_connection_e2e_smoke_test.cc b/test/pc/e2e/peer_connection_e2e_smoke_test.cc
index 4bba7e9..f32e972 100644
--- a/test/pc/e2e/peer_connection_e2e_smoke_test.cc
+++ b/test/pc/e2e/peer_connection_e2e_smoke_test.cc
@@ -85,6 +85,9 @@
                      alice->AddVideoConfig(std::move(video_config));
                      AudioConfig audio_config;
                      audio_config.stream_label = "alice-audio";
+                     audio_config.mode = AudioConfig::Mode::kFile;
+                     audio_config.input_file_name = test::ResourcePath(
+                         "pc_quality_smoke_test_alice_source", "wav");
                      alice->SetAudioConfig(std::move(audio_config));
                    });
 
@@ -98,10 +101,13 @@
                      bob->AddVideoConfig(std::move(video_config));
                      AudioConfig audio_config;
                      audio_config.stream_label = "bob-audio";
+                     audio_config.mode = AudioConfig::Mode::kFile;
+                     audio_config.input_file_name = test::ResourcePath(
+                         "pc_quality_smoke_test_bob_source", "wav");
                      bob->SetAudioConfig(std::move(audio_config));
                    });
 
-  RunParams run_params(TimeDelta::seconds(5));
+  RunParams run_params(TimeDelta::seconds(7));
   run_params.video_encoder_bitrate_multiplier = 1.1;
   fixture->Run(run_params);
 
diff --git a/test/pc/e2e/peer_connection_quality_test.cc b/test/pc/e2e/peer_connection_quality_test.cc
index dfee644..24d778b 100644
--- a/test/pc/e2e/peer_connection_quality_test.cc
+++ b/test/pc/e2e/peer_connection_quality_test.cc
@@ -234,6 +234,9 @@
   signaling_thread->SetName(kSignalThreadName, nullptr);
   signaling_thread->Start();
 
+  // Create a |task_queue_|.
+  task_queue_ = absl::make_unique<TaskQueueForTest>("pc_e2e_quality_test");
+
   // Create call participants: Alice and Bob.
   // 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
@@ -259,7 +262,7 @@
           [this]() { StartVideo(alice_video_sources_); }),
       video_quality_analyzer_injection_helper_.get(), signaling_thread.get(),
       alice_audio_output_dump_file_name,
-      run_params.video_encoder_bitrate_multiplier);
+      run_params.video_encoder_bitrate_multiplier, task_queue_.get());
   bob_ = TestPeer::CreateTestPeer(
       std::move(bob_components), std::move(bob_params),
       absl::make_unique<FixturePeerConnectionObserver>(
@@ -270,7 +273,7 @@
           [this]() { StartVideo(bob_video_sources_); }),
       video_quality_analyzer_injection_helper_.get(), signaling_thread.get(),
       bob_audio_output_dump_file_name,
-      run_params.video_encoder_bitrate_multiplier);
+      run_params.video_encoder_bitrate_multiplier, task_queue_.get());
 
   int num_cores = CpuInfo::DetectNumberOfCores();
   RTC_DCHECK_GE(num_cores, 1);
@@ -302,8 +305,6 @@
                                  webrtc::RtcEventLog::kImmediateOutput);
   }
 
-  // Create a |task_queue_|.
-  task_queue_ = absl::make_unique<TaskQueueForTest>("pc_e2e_quality_test");
   // Setup call.
   signaling_thread->Invoke<void>(
       RTC_FROM_HERE,
@@ -345,6 +346,10 @@
   RTC_CHECK(no_timeout) << "Failed to stop Stats polling after "
                         << kStatsPollingStopTimeout.seconds() << " seconds.";
 
+  // We need to detach AEC dumping from peers, because dump uses |task_queue_|
+  // inside.
+  alice_->DetachAecDump();
+  bob_->DetachAecDump();
   // Destroy |task_queue_|. It is done to stop all running tasks and prevent
   // their access to any call related objects after these objects will be
   // destroyed during call tear down.
@@ -449,7 +454,9 @@
       if (p->audio_config.value().mode == AudioConfig::Mode::kFile) {
         RTC_CHECK(p->audio_config.value().input_file_name);
         RTC_CHECK(
-            test::FileExists(p->audio_config.value().input_file_name.value()));
+            test::FileExists(p->audio_config.value().input_file_name.value()))
+            << p->audio_config.value().input_file_name.value()
+            << " doesn't exist";
       }
     }
   }
diff --git a/test/pc/e2e/peer_connection_quality_test.h b/test/pc/e2e/peer_connection_quality_test.h
index 1be72e7..556c2fa 100644
--- a/test/pc/e2e/peer_connection_quality_test.h
+++ b/test/pc/e2e/peer_connection_quality_test.h
@@ -123,6 +123,10 @@
     params_->rtc_event_log_path = std::move(path);
     return this;
   }
+  PeerConfigurer* SetAecDumpPath(std::string path) override {
+    params_->aec_dump_path = std::move(path);
+    return this;
+  }
   PeerConfigurer* SetRTCConfiguration(
       PeerConnectionInterface::RTCConfiguration configuration) override {
     params_->rtc_configuration = std::move(configuration);
diff --git a/test/pc/e2e/peer_connection_quality_test_params.h b/test/pc/e2e/peer_connection_quality_test_params.h
index 079e5eb..76dd406 100644
--- a/test/pc/e2e/peer_connection_quality_test_params.h
+++ b/test/pc/e2e/peer_connection_quality_test_params.h
@@ -104,6 +104,9 @@
   // If |rtc_event_log_path| is set, an RTCEventLog will be saved in that
   // location and it will be available for further analysis.
   absl::optional<std::string> rtc_event_log_path;
+  // If |aec_dump_path| is set, an AEC dump will be saved in that location and
+  // it will be available for further analysis.
+  absl::optional<std::string> aec_dump_path;
 
   PeerConnectionInterface::RTCConfiguration rtc_configuration;
 };
diff --git a/test/pc/e2e/test_peer.cc b/test/pc/e2e/test_peer.cc
index 1726fe6..d5e4379 100644
--- a/test/pc/e2e/test_peer.cc
+++ b/test/pc/e2e/test_peer.cc
@@ -21,6 +21,7 @@
 #include "logging/rtc_event_log/rtc_event_log_factory.h"
 #include "media/engine/webrtc_media_engine.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"
@@ -33,8 +34,6 @@
 constexpr int16_t kGeneratedAudioMaxAmplitude = 32000;
 constexpr int kSamplingFrequencyInHz = 48000;
 
-using AudioConfig = PeerConnectionE2EQualityTestFixture::AudioConfig;
-
 // 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
@@ -53,175 +52,232 @@
   }
 }
 
-std::unique_ptr<TestAudioDeviceModule::Capturer> CreateAudioCapturer(
-    AudioConfig audio_config) {
-  if (audio_config.mode == AudioConfig::Mode::kGenerated) {
-    return TestAudioDeviceModule::CreatePulsedNoiseCapturer(
-        kGeneratedAudioMaxAmplitude, kSamplingFrequencyInHz);
-  }
-  if (audio_config.mode == AudioConfig::Mode::kFile) {
-    RTC_DCHECK(audio_config.input_file_name);
-    return TestAudioDeviceModule::CreateWavFileReader(
-        audio_config.input_file_name.value());
-  }
-  RTC_NOTREACHED() << "Unknown audio_config->mode";
-  return nullptr;
-}
+struct TestPeerComponents {
+  using AudioConfig = PeerConnectionE2EQualityTestFixture::AudioConfig;
 
-rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModule(
-    absl::optional<AudioConfig> audio_config,
-    absl::optional<std::string> audio_output_file_name) {
-  std::unique_ptr<TestAudioDeviceModule::Capturer> capturer;
-  if (audio_config) {
-    capturer = CreateAudioCapturer(audio_config.value());
-  } else {
-    // 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.
-    capturer = TestAudioDeviceModule::CreatePulsedNoiseCapturer(
-        kGeneratedAudioMaxAmplitude, kSamplingFrequencyInHz);
-  }
-  RTC_DCHECK(capturer);
+  rtc::scoped_refptr<PeerConnectionFactoryInterface> peer_connection_factory;
+  rtc::scoped_refptr<PeerConnectionInterface> peer_connection;
+  rtc::scoped_refptr<AudioProcessing> audio_processing;
 
-  if (audio_config && audio_config->input_dump_file_name) {
-    capturer = absl::make_unique<test::CopyToFileAudioCapturer>(
-        std::move(capturer), audio_config->input_dump_file_name.value());
+  TestPeerComponents(std::unique_ptr<InjectableComponents> components,
+                     const Params& params,
+                     MockPeerConnectionObserver* observer,
+                     VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
+                     rtc::Thread* signaling_thread,
+                     absl::optional<std::string> audio_output_file_name,
+                     double bitrate_multiplier,
+                     rtc::TaskQueue* task_queue) {
+    std::map<std::string, absl::optional<int>> stream_required_spatial_index;
+    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.target_spatial_index})
+                     .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), params.audio_config,
+        bitrate_multiplier, std::move(stream_required_spatial_index),
+        video_analyzer_helper, components->network_thread, signaling_thread,
+        std::move(audio_output_file_name), task_queue);
+    peer_connection_factory =
+        CreateModularPeerConnectionFactory(std::move(pcf_deps));
+
+    // Create peer connection.
+    PeerConnectionDependencies pc_deps =
+        CreatePCDependencies(std::move(components->pc_dependencies), observer);
+    peer_connection = peer_connection_factory->CreatePeerConnection(
+        params.rtc_configuration, std::move(pc_deps));
   }
 
-  std::unique_ptr<TestAudioDeviceModule::Renderer> renderer;
-  if (audio_output_file_name) {
-    renderer = TestAudioDeviceModule::CreateBoundedWavFileWriter(
-        audio_output_file_name.value(), kSamplingFrequencyInHz);
-  } else {
-    renderer =
-        TestAudioDeviceModule::CreateDiscardRenderer(kSamplingFrequencyInHz);
+  std::unique_ptr<TestAudioDeviceModule::Capturer> CreateAudioCapturer(
+      AudioConfig audio_config) {
+    if (audio_config.mode == AudioConfig::Mode::kGenerated) {
+      return TestAudioDeviceModule::CreatePulsedNoiseCapturer(
+          kGeneratedAudioMaxAmplitude, kSamplingFrequencyInHz);
+    }
+    if (audio_config.mode == AudioConfig::Mode::kFile) {
+      RTC_DCHECK(audio_config.input_file_name);
+      return TestAudioDeviceModule::CreateWavFileReader(
+          audio_config.input_file_name.value());
+    }
+    RTC_NOTREACHED() << "Unknown audio_config->mode";
+    return nullptr;
   }
 
-  return TestAudioDeviceModule::CreateTestAudioDeviceModule(
-      std::move(capturer), std::move(renderer), /*speed=*/1.f);
-}
+  rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModule(
+      absl::optional<AudioConfig> audio_config,
+      absl::optional<std::string> audio_output_file_name) {
+    std::unique_ptr<TestAudioDeviceModule::Capturer> capturer;
+    if (audio_config) {
+      capturer = CreateAudioCapturer(audio_config.value());
+    } else {
+      // 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.
+      capturer = TestAudioDeviceModule::CreatePulsedNoiseCapturer(
+          kGeneratedAudioMaxAmplitude, kSamplingFrequencyInHz);
+    }
+    RTC_DCHECK(capturer);
 
-std::unique_ptr<VideoEncoderFactory> CreateVideoEncoderFactory(
-    PeerConnectionFactoryComponents* pcf_dependencies,
-    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
-    double bitrate_multiplier,
-    std::map<std::string, absl::optional<int>> stream_required_spatial_index) {
-  std::unique_ptr<VideoEncoderFactory> 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,
-      std::move(stream_required_spatial_index));
-}
+    if (audio_config && audio_config->input_dump_file_name) {
+      capturer = absl::make_unique<test::CopyToFileAudioCapturer>(
+          std::move(capturer), audio_config->input_dump_file_name.value());
+    }
 
-std::unique_ptr<VideoDecoderFactory> CreateVideoDecoderFactory(
-    PeerConnectionFactoryComponents* pcf_dependencies,
-    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) {
-  std::unique_ptr<VideoDecoderFactory> 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));
-}
+    std::unique_ptr<TestAudioDeviceModule::Renderer> renderer;
+    if (audio_output_file_name) {
+      renderer = TestAudioDeviceModule::CreateBoundedWavFileWriter(
+          audio_output_file_name.value(), kSamplingFrequencyInHz);
+    } else {
+      renderer =
+          TestAudioDeviceModule::CreateDiscardRenderer(kSamplingFrequencyInHz);
+    }
 
-std::unique_ptr<cricket::MediaEngineInterface> CreateMediaEngine(
-    PeerConnectionFactoryComponents* pcf_dependencies,
-    absl::optional<AudioConfig> audio_config,
-    double bitrate_multiplier,
-    std::map<std::string, absl::optional<int>> stream_required_spatial_index,
-    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
-    absl::optional<std::string> audio_output_file_name) {
-  rtc::scoped_refptr<AudioDeviceModule> adm = CreateAudioDeviceModule(
-      std::move(audio_config), std::move(audio_output_file_name));
-
-  std::unique_ptr<VideoEncoderFactory> video_encoder_factory =
-      CreateVideoEncoderFactory(pcf_dependencies, video_analyzer_helper,
-                                bitrate_multiplier,
-                                std::move(stream_required_spatial_index));
-  std::unique_ptr<VideoDecoderFactory> video_decoder_factory =
-      CreateVideoDecoderFactory(pcf_dependencies, video_analyzer_helper);
-
-  return cricket::WebRtcMediaEngineFactory::Create(
-      adm, webrtc::CreateBuiltinAudioEncoderFactory(),
-      webrtc::CreateBuiltinAudioDecoderFactory(),
-      std::move(video_encoder_factory), std::move(video_decoder_factory),
-      /*audio_mixer=*/nullptr, webrtc::AudioProcessingBuilder().Create());
-}
-
-// 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<PeerConnectionFactoryComponents> pcf_dependencies,
-    absl::optional<AudioConfig> audio_config,
-    double bitrate_multiplier,
-    std::map<std::string, absl::optional<int>> stream_required_spatial_index,
-    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
-    rtc::Thread* network_thread,
-    rtc::Thread* signaling_thread,
-    absl::optional<std::string> audio_output_file_name) {
-  PeerConnectionFactoryDependencies pcf_deps;
-  pcf_deps.network_thread = network_thread;
-  pcf_deps.signaling_thread = signaling_thread;
-  pcf_deps.media_engine = CreateMediaEngine(
-      pcf_dependencies.get(), std::move(audio_config), bitrate_multiplier,
-      std::move(stream_required_spatial_index), video_analyzer_helper,
-      std::move(audio_output_file_name));
-
-  pcf_deps.call_factory = std::move(pcf_dependencies->call_factory);
-  pcf_deps.event_log_factory = std::move(pcf_dependencies->event_log_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);
+    return TestAudioDeviceModule::CreateTestAudioDeviceModule(
+        std::move(capturer), std::move(renderer), /*speed=*/1.f);
   }
 
-  return pcf_deps;
-}
-
-// Creates PeerConnectionDependencies objects, providing entities
-// from InjectableComponents::PeerConnectionComponents.
-PeerConnectionDependencies CreatePCDependencies(
-    std::unique_ptr<PeerConnectionComponents> pc_dependencies,
-    PeerConnectionObserver* observer) {
-  PeerConnectionDependencies pc_deps(observer);
-
-  auto port_allocator = absl::make_unique<cricket::BasicPortAllocator>(
-      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);
+  std::unique_ptr<VideoEncoderFactory> CreateVideoEncoderFactory(
+      PeerConnectionFactoryComponents* pcf_dependencies,
+      VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
+      double bitrate_multiplier,
+      std::map<std::string, absl::optional<int>>
+          stream_required_spatial_index) {
+    std::unique_ptr<VideoEncoderFactory> 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,
+        std::move(stream_required_spatial_index));
   }
-  if (pc_dependencies->cert_generator != nullptr) {
-    pc_deps.cert_generator = std::move(pc_dependencies->cert_generator);
+
+  std::unique_ptr<VideoDecoderFactory> CreateVideoDecoderFactory(
+      PeerConnectionFactoryComponents* pcf_dependencies,
+      VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) {
+    std::unique_ptr<VideoDecoderFactory> 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));
   }
-  if (pc_dependencies->tls_cert_verifier != nullptr) {
-    pc_deps.tls_cert_verifier = std::move(pc_dependencies->tls_cert_verifier);
+
+  std::unique_ptr<cricket::MediaEngineInterface> CreateMediaEngine(
+      PeerConnectionFactoryComponents* pcf_dependencies,
+      absl::optional<AudioConfig> audio_config,
+      double bitrate_multiplier,
+      std::map<std::string, absl::optional<int>> stream_required_spatial_index,
+      VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
+      absl::optional<std::string> audio_output_file_name,
+      rtc::TaskQueue* task_queue) {
+    rtc::scoped_refptr<AudioDeviceModule> adm = CreateAudioDeviceModule(
+        std::move(audio_config), std::move(audio_output_file_name));
+
+    std::unique_ptr<VideoEncoderFactory> video_encoder_factory =
+        CreateVideoEncoderFactory(pcf_dependencies, video_analyzer_helper,
+                                  bitrate_multiplier,
+                                  std::move(stream_required_spatial_index));
+    std::unique_ptr<VideoDecoderFactory> video_decoder_factory =
+        CreateVideoDecoderFactory(pcf_dependencies, video_analyzer_helper);
+
+    return cricket::WebRtcMediaEngineFactory::Create(
+        adm, webrtc::CreateBuiltinAudioEncoderFactory(),
+        webrtc::CreateBuiltinAudioDecoderFactory(),
+        std::move(video_encoder_factory), std::move(video_decoder_factory),
+        /*audio_mixer=*/nullptr, audio_processing);
   }
-  return pc_deps;
-}
+
+  // 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<PeerConnectionFactoryComponents> pcf_dependencies,
+      absl::optional<AudioConfig> audio_config,
+      double bitrate_multiplier,
+      std::map<std::string, absl::optional<int>> stream_required_spatial_index,
+      VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
+      rtc::Thread* network_thread,
+      rtc::Thread* signaling_thread,
+      absl::optional<std::string> audio_output_file_name,
+      rtc::TaskQueue* task_queue) {
+    PeerConnectionFactoryDependencies pcf_deps;
+    pcf_deps.network_thread = network_thread;
+    pcf_deps.signaling_thread = signaling_thread;
+    pcf_deps.media_engine = CreateMediaEngine(
+        pcf_dependencies.get(), std::move(audio_config), bitrate_multiplier,
+        std::move(stream_required_spatial_index), video_analyzer_helper,
+        std::move(audio_output_file_name), task_queue);
+
+    pcf_deps.call_factory = std::move(pcf_dependencies->call_factory);
+    pcf_deps.event_log_factory = std::move(pcf_dependencies->event_log_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);
+    }
+
+    return pcf_deps;
+  }
+
+  // Creates PeerConnectionDependencies objects, providing entities
+  // from InjectableComponents::PeerConnectionComponents.
+  PeerConnectionDependencies CreatePCDependencies(
+      std::unique_ptr<PeerConnectionComponents> pc_dependencies,
+      PeerConnectionObserver* observer) {
+    PeerConnectionDependencies pc_deps(observer);
+
+    auto port_allocator = absl::make_unique<cricket::BasicPortAllocator>(
+        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);
+    }
+    return pc_deps;
+  }
+};
 
 }  // namespace
 
@@ -232,41 +288,21 @@
     VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
     rtc::Thread* signaling_thread,
     absl::optional<std::string> audio_output_file_name,
-    double bitrate_multiplier) {
+    double bitrate_multiplier,
+    rtc::TaskQueue* task_queue) {
   RTC_DCHECK(components);
   RTC_DCHECK(params);
   SetMandatoryEntities(components.get());
   params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
 
-  std::map<std::string, absl::optional<int>> stream_required_spatial_index;
-  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.target_spatial_index})
-                   .second;
-    RTC_DCHECK(res) << "Duplicate video_config.stream_label="
-                    << *video_config.stream_label;
-  }
+  TestPeerComponents tpc(std::move(components), *params, observer.get(),
+                         video_analyzer_helper, signaling_thread,
+                         std::move(audio_output_file_name), bitrate_multiplier,
+                         task_queue);
 
-  // Create peer connection factory.
-  PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies(
-      std::move(components->pcf_dependencies), params->audio_config,
-      bitrate_multiplier, std::move(stream_required_spatial_index),
-      video_analyzer_helper, components->network_thread, signaling_thread,
-      std::move(audio_output_file_name));
-  rtc::scoped_refptr<PeerConnectionFactoryInterface> pcf =
-      CreateModularPeerConnectionFactory(std::move(pcf_deps));
-
-  // Create peer connection.
-  PeerConnectionDependencies pc_deps = CreatePCDependencies(
-      std::move(components->pc_dependencies), observer.get());
-  rtc::scoped_refptr<PeerConnectionInterface> pc =
-      pcf->CreatePeerConnection(params->rtc_configuration, std::move(pc_deps));
-
-  return absl::WrapUnique(
-      new TestPeer(pcf, pc, std::move(observer), std::move(params)));
+  return absl::WrapUnique(new TestPeer(
+      tpc.peer_connection_factory, tpc.peer_connection, std::move(observer),
+      std::move(params), tpc.audio_processing));
 }
 
 bool TestPeer::AddIceCandidates(
@@ -289,11 +325,13 @@
     rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
     rtc::scoped_refptr<PeerConnectionInterface> pc,
     std::unique_ptr<MockPeerConnectionObserver> observer,
-    std::unique_ptr<Params> params)
+    std::unique_ptr<Params> params,
+    rtc::scoped_refptr<AudioProcessing> audio_processing)
     : PeerConnectionWrapper::PeerConnectionWrapper(std::move(pc_factory),
                                                    std::move(pc),
                                                    std::move(observer)),
-      params_(std::move(params)) {}
+      params_(std::move(params)),
+      audio_processing_(audio_processing) {}
 
 }  // namespace webrtc_pc_e2e
 }  // namespace webrtc
diff --git a/test/pc/e2e/test_peer.h b/test/pc/e2e/test_peer.h
index 0cc9389..decc418 100644
--- a/test/pc/e2e/test_peer.h
+++ b/test/pc/e2e/test_peer.h
@@ -22,6 +22,7 @@
 #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"
@@ -54,9 +55,11 @@
       VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
       rtc::Thread* signaling_thread,
       absl::optional<std::string> audio_output_file_name,
-      double bitrate_multiplier);
+      double bitrate_multiplier,
+      rtc::TaskQueue* task_queue);
 
   Params* params() const { return params_.get(); }
+  void DetachAecDump() { audio_processing_->DetachAecDump(); }
 
   // Adds provided |candidates| to the owned peer connection.
   bool AddIceCandidates(
@@ -66,9 +69,11 @@
   TestPeer(rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
            rtc::scoped_refptr<PeerConnectionInterface> pc,
            std::unique_ptr<MockPeerConnectionObserver> observer,
-           std::unique_ptr<Params> params);
+           std::unique_ptr<Params> params,
+           rtc::scoped_refptr<AudioProcessing> audio_processing);
 
   std::unique_ptr<Params> params_;
+  rtc::scoped_refptr<AudioProcessing> audio_processing_;
 };
 
 }  // namespace webrtc_pc_e2e