xref: /aosp_15_r20/external/webrtc/test/pc/e2e/test_peer_factory.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include "test/pc/e2e/test_peer_factory.h"
11 
12 #include <utility>
13 
14 #include "absl/memory/memory.h"
15 #include "absl/strings/string_view.h"
16 #include "api/task_queue/default_task_queue_factory.h"
17 #include "api/test/create_time_controller.h"
18 #include "api/test/pclf/media_configuration.h"
19 #include "api/test/pclf/peer_configurer.h"
20 #include "api/test/time_controller.h"
21 #include "api/transport/field_trial_based_config.h"
22 #include "api/video_codecs/builtin_video_decoder_factory.h"
23 #include "api/video_codecs/builtin_video_encoder_factory.h"
24 #include "media/engine/webrtc_media_engine.h"
25 #include "media/engine/webrtc_media_engine_defaults.h"
26 #include "modules/audio_processing/aec_dump/aec_dump_factory.h"
27 #include "p2p/client/basic_port_allocator.h"
28 #include "rtc_base/thread.h"
29 #include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h"
30 #include "test/pc/e2e/echo/echo_emulation.h"
31 #include "test/testsupport/copy_to_file_audio_capturer.h"
32 
33 namespace webrtc {
34 namespace webrtc_pc_e2e {
35 namespace {
36 
37 using EmulatedSFUConfigMap =
38     ::webrtc::webrtc_pc_e2e::QualityAnalyzingVideoEncoder::EmulatedSFUConfigMap;
39 
40 constexpr int16_t kGeneratedAudioMaxAmplitude = 32000;
41 constexpr int kDefaultSamplingFrequencyInHz = 48000;
42 
43 // Sets mandatory entities in injectable components like `pcf_dependencies`
44 // and `pc_dependencies` if they are omitted. Also setup required
45 // dependencies, that won't be specially provided by factory and will be just
46 // transferred to peer connection creation code.
SetMandatoryEntities(InjectableComponents * components,TimeController & time_controller)47 void SetMandatoryEntities(InjectableComponents* components,
48                           TimeController& time_controller) {
49   RTC_DCHECK(components->pcf_dependencies);
50   RTC_DCHECK(components->pc_dependencies);
51 
52   // Setup required peer connection factory dependencies.
53   if (components->pcf_dependencies->task_queue_factory == nullptr) {
54     components->pcf_dependencies->task_queue_factory =
55         time_controller.CreateTaskQueueFactory();
56   }
57   if (components->pcf_dependencies->call_factory == nullptr) {
58     components->pcf_dependencies->call_factory =
59         CreateTimeControllerBasedCallFactory(&time_controller);
60   }
61   if (components->pcf_dependencies->event_log_factory == nullptr) {
62     components->pcf_dependencies->event_log_factory =
63         std::make_unique<RtcEventLogFactory>(
64             components->pcf_dependencies->task_queue_factory.get());
65   }
66   if (!components->pcf_dependencies->trials) {
67     components->pcf_dependencies->trials =
68         std::make_unique<FieldTrialBasedConfig>();
69   }
70 }
71 
72 // Returns mapping from stream label to optional spatial index.
73 // If we have stream label "Foo" and mapping contains
74 // 1. `absl::nullopt` means all simulcast/SVC streams are required
75 // 2. Concrete value means that particular simulcast/SVC stream have to be
76 //    analyzed.
CalculateRequiredSpatialIndexPerStream(const std::vector<VideoConfig> & video_configs)77 EmulatedSFUConfigMap CalculateRequiredSpatialIndexPerStream(
78     const std::vector<VideoConfig>& video_configs) {
79   EmulatedSFUConfigMap result;
80   for (auto& video_config : video_configs) {
81     // Stream label should be set by fixture implementation here.
82     RTC_DCHECK(video_config.stream_label);
83     bool res = result
84                    .insert({*video_config.stream_label,
85                             video_config.emulated_sfu_config})
86                    .second;
87     RTC_DCHECK(res) << "Duplicate video_config.stream_label="
88                     << *video_config.stream_label;
89   }
90   return result;
91 }
92 
CreateAudioRenderer(const absl::optional<RemotePeerAudioConfig> & config)93 std::unique_ptr<TestAudioDeviceModule::Renderer> CreateAudioRenderer(
94     const absl::optional<RemotePeerAudioConfig>& config) {
95   if (!config) {
96     // Return default renderer because we always require some renderer.
97     return TestAudioDeviceModule::CreateDiscardRenderer(
98         kDefaultSamplingFrequencyInHz);
99   }
100   if (config->output_file_name) {
101     return TestAudioDeviceModule::CreateBoundedWavFileWriter(
102         config->output_file_name.value(), config->sampling_frequency_in_hz);
103   }
104   return TestAudioDeviceModule::CreateDiscardRenderer(
105       config->sampling_frequency_in_hz);
106 }
107 
CreateAudioCapturer(const absl::optional<AudioConfig> & audio_config)108 std::unique_ptr<TestAudioDeviceModule::Capturer> CreateAudioCapturer(
109     const absl::optional<AudioConfig>& audio_config) {
110   if (!audio_config) {
111     // If we have no audio config we still need to provide some audio device.
112     // In such case use generated capturer. Despite of we provided audio here,
113     // in test media setup audio stream won't be added into peer connection.
114     return TestAudioDeviceModule::CreatePulsedNoiseCapturer(
115         kGeneratedAudioMaxAmplitude, kDefaultSamplingFrequencyInHz);
116   }
117 
118   switch (audio_config->mode) {
119     case AudioConfig::Mode::kGenerated:
120       return TestAudioDeviceModule::CreatePulsedNoiseCapturer(
121           kGeneratedAudioMaxAmplitude, audio_config->sampling_frequency_in_hz);
122     case AudioConfig::Mode::kFile:
123       RTC_DCHECK(audio_config->input_file_name);
124       return TestAudioDeviceModule::CreateWavFileReader(
125           audio_config->input_file_name.value(), /*repeat=*/true);
126   }
127 }
128 
CreateAudioDeviceModule(absl::optional<AudioConfig> audio_config,absl::optional<RemotePeerAudioConfig> remote_audio_config,absl::optional<EchoEmulationConfig> echo_emulation_config,TaskQueueFactory * task_queue_factory)129 rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModule(
130     absl::optional<AudioConfig> audio_config,
131     absl::optional<RemotePeerAudioConfig> remote_audio_config,
132     absl::optional<EchoEmulationConfig> echo_emulation_config,
133     TaskQueueFactory* task_queue_factory) {
134   std::unique_ptr<TestAudioDeviceModule::Renderer> renderer =
135       CreateAudioRenderer(remote_audio_config);
136   std::unique_ptr<TestAudioDeviceModule::Capturer> capturer =
137       CreateAudioCapturer(audio_config);
138   RTC_DCHECK(renderer);
139   RTC_DCHECK(capturer);
140 
141   // Setup echo emulation if required.
142   if (echo_emulation_config) {
143     capturer = std::make_unique<EchoEmulatingCapturer>(std::move(capturer),
144                                                        *echo_emulation_config);
145     renderer = std::make_unique<EchoEmulatingRenderer>(
146         std::move(renderer),
147         static_cast<EchoEmulatingCapturer*>(capturer.get()));
148   }
149 
150   // Setup input stream dumping if required.
151   if (audio_config && audio_config->input_dump_file_name) {
152     capturer = std::make_unique<test::CopyToFileAudioCapturer>(
153         std::move(capturer), audio_config->input_dump_file_name.value());
154   }
155 
156   return TestAudioDeviceModule::Create(task_queue_factory, std::move(capturer),
157                                        std::move(renderer), /*speed=*/1.f);
158 }
159 
CreateMediaEngine(PeerConnectionFactoryComponents * pcf_dependencies,rtc::scoped_refptr<AudioDeviceModule> audio_device_module)160 std::unique_ptr<cricket::MediaEngineInterface> CreateMediaEngine(
161     PeerConnectionFactoryComponents* pcf_dependencies,
162     rtc::scoped_refptr<AudioDeviceModule> audio_device_module) {
163   cricket::MediaEngineDependencies media_deps;
164   media_deps.task_queue_factory = pcf_dependencies->task_queue_factory.get();
165   media_deps.adm = audio_device_module;
166   media_deps.audio_processing = pcf_dependencies->audio_processing;
167   media_deps.audio_mixer = pcf_dependencies->audio_mixer;
168   media_deps.video_encoder_factory =
169       std::move(pcf_dependencies->video_encoder_factory);
170   media_deps.video_decoder_factory =
171       std::move(pcf_dependencies->video_decoder_factory);
172   webrtc::SetMediaEngineDefaults(&media_deps);
173   RTC_DCHECK(pcf_dependencies->trials);
174   media_deps.trials = pcf_dependencies->trials.get();
175 
176   return cricket::CreateMediaEngine(std::move(media_deps));
177 }
178 
WrapVideoEncoderFactory(absl::string_view peer_name,double bitrate_multiplier,EmulatedSFUConfigMap stream_to_sfu_config,PeerConnectionFactoryComponents * pcf_dependencies,VideoQualityAnalyzerInjectionHelper * video_analyzer_helper)179 void WrapVideoEncoderFactory(
180     absl::string_view peer_name,
181     double bitrate_multiplier,
182     EmulatedSFUConfigMap stream_to_sfu_config,
183     PeerConnectionFactoryComponents* pcf_dependencies,
184     VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) {
185   std::unique_ptr<VideoEncoderFactory> video_encoder_factory;
186   if (pcf_dependencies->video_encoder_factory != nullptr) {
187     video_encoder_factory = std::move(pcf_dependencies->video_encoder_factory);
188   } else {
189     video_encoder_factory = CreateBuiltinVideoEncoderFactory();
190   }
191   pcf_dependencies->video_encoder_factory =
192       video_analyzer_helper->WrapVideoEncoderFactory(
193           peer_name, std::move(video_encoder_factory), bitrate_multiplier,
194           std::move(stream_to_sfu_config));
195 }
196 
WrapVideoDecoderFactory(absl::string_view peer_name,PeerConnectionFactoryComponents * pcf_dependencies,VideoQualityAnalyzerInjectionHelper * video_analyzer_helper)197 void WrapVideoDecoderFactory(
198     absl::string_view peer_name,
199     PeerConnectionFactoryComponents* pcf_dependencies,
200     VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) {
201   std::unique_ptr<VideoDecoderFactory> video_decoder_factory;
202   if (pcf_dependencies->video_decoder_factory != nullptr) {
203     video_decoder_factory = std::move(pcf_dependencies->video_decoder_factory);
204   } else {
205     video_decoder_factory = CreateBuiltinVideoDecoderFactory();
206   }
207   pcf_dependencies->video_decoder_factory =
208       video_analyzer_helper->WrapVideoDecoderFactory(
209           peer_name, std::move(video_decoder_factory));
210 }
211 
212 // Creates PeerConnectionFactoryDependencies objects, providing entities
213 // from InjectableComponents::PeerConnectionFactoryComponents.
CreatePCFDependencies(std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies,std::unique_ptr<cricket::MediaEngineInterface> media_engine,rtc::Thread * signaling_thread,rtc::Thread * worker_thread,rtc::Thread * network_thread)214 PeerConnectionFactoryDependencies CreatePCFDependencies(
215     std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies,
216     std::unique_ptr<cricket::MediaEngineInterface> media_engine,
217     rtc::Thread* signaling_thread,
218     rtc::Thread* worker_thread,
219     rtc::Thread* network_thread) {
220   PeerConnectionFactoryDependencies pcf_deps;
221   pcf_deps.signaling_thread = signaling_thread;
222   pcf_deps.worker_thread = worker_thread;
223   pcf_deps.network_thread = network_thread;
224   pcf_deps.media_engine = std::move(media_engine);
225 
226   pcf_deps.call_factory = std::move(pcf_dependencies->call_factory);
227   pcf_deps.event_log_factory = std::move(pcf_dependencies->event_log_factory);
228   pcf_deps.task_queue_factory = std::move(pcf_dependencies->task_queue_factory);
229 
230   if (pcf_dependencies->fec_controller_factory != nullptr) {
231     pcf_deps.fec_controller_factory =
232         std::move(pcf_dependencies->fec_controller_factory);
233   }
234   if (pcf_dependencies->network_controller_factory != nullptr) {
235     pcf_deps.network_controller_factory =
236         std::move(pcf_dependencies->network_controller_factory);
237   }
238   if (pcf_dependencies->neteq_factory != nullptr) {
239     pcf_deps.neteq_factory = std::move(pcf_dependencies->neteq_factory);
240   }
241   if (pcf_dependencies->trials != nullptr) {
242     pcf_deps.trials = std::move(pcf_dependencies->trials);
243   }
244 
245   return pcf_deps;
246 }
247 
248 // Creates PeerConnectionDependencies objects, providing entities
249 // from InjectableComponents::PeerConnectionComponents.
CreatePCDependencies(MockPeerConnectionObserver * observer,uint32_t port_allocator_extra_flags,std::unique_ptr<PeerConnectionComponents> pc_dependencies)250 PeerConnectionDependencies CreatePCDependencies(
251     MockPeerConnectionObserver* observer,
252     uint32_t port_allocator_extra_flags,
253     std::unique_ptr<PeerConnectionComponents> pc_dependencies) {
254   PeerConnectionDependencies pc_deps(observer);
255 
256   auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
257       pc_dependencies->network_manager, pc_dependencies->packet_socket_factory);
258 
259   // This test does not support TCP
260   int flags = port_allocator_extra_flags | cricket::PORTALLOCATOR_DISABLE_TCP;
261   port_allocator->set_flags(port_allocator->flags() | flags);
262 
263   pc_deps.allocator = std::move(port_allocator);
264 
265   if (pc_dependencies->async_resolver_factory != nullptr) {
266     pc_deps.async_resolver_factory =
267         std::move(pc_dependencies->async_resolver_factory);
268   }
269   if (pc_dependencies->cert_generator != nullptr) {
270     pc_deps.cert_generator = std::move(pc_dependencies->cert_generator);
271   }
272   if (pc_dependencies->tls_cert_verifier != nullptr) {
273     pc_deps.tls_cert_verifier = std::move(pc_dependencies->tls_cert_verifier);
274   }
275   if (pc_dependencies->ice_transport_factory != nullptr) {
276     pc_deps.ice_transport_factory =
277         std::move(pc_dependencies->ice_transport_factory);
278   }
279   return pc_deps;
280 }
281 
282 }  // namespace
283 
Create(absl::optional<AudioConfig> config)284 absl::optional<RemotePeerAudioConfig> RemotePeerAudioConfig::Create(
285     absl::optional<AudioConfig> config) {
286   if (!config) {
287     return absl::nullopt;
288   }
289   return RemotePeerAudioConfig(config.value());
290 }
291 
CreateTestPeer(std::unique_ptr<PeerConfigurer> configurer,std::unique_ptr<MockPeerConnectionObserver> observer,absl::optional<RemotePeerAudioConfig> remote_audio_config,absl::optional<EchoEmulationConfig> echo_emulation_config)292 std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
293     std::unique_ptr<PeerConfigurer> configurer,
294     std::unique_ptr<MockPeerConnectionObserver> observer,
295     absl::optional<RemotePeerAudioConfig> remote_audio_config,
296     absl::optional<EchoEmulationConfig> echo_emulation_config) {
297   std::unique_ptr<InjectableComponents> components =
298       configurer->ReleaseComponents();
299   std::unique_ptr<Params> params = configurer->ReleaseParams();
300   std::unique_ptr<ConfigurableParams> configurable_params =
301       configurer->ReleaseConfigurableParams();
302   std::vector<PeerConfigurer::VideoSource> video_sources =
303       configurer->ReleaseVideoSources();
304   RTC_DCHECK(components);
305   RTC_DCHECK(params);
306   RTC_DCHECK(configurable_params);
307   RTC_DCHECK_EQ(configurable_params->video_configs.size(),
308                 video_sources.size());
309   SetMandatoryEntities(components.get(), time_controller_);
310   params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
311 
312   // Create peer connection factory.
313   if (components->pcf_dependencies->audio_processing == nullptr) {
314     components->pcf_dependencies->audio_processing =
315         webrtc::AudioProcessingBuilder().Create();
316   }
317   if (params->aec_dump_path) {
318     components->pcf_dependencies->audio_processing->CreateAndAttachAecDump(
319         *params->aec_dump_path, -1, task_queue_);
320   }
321   rtc::scoped_refptr<AudioDeviceModule> audio_device_module =
322       CreateAudioDeviceModule(
323           params->audio_config, remote_audio_config, echo_emulation_config,
324           components->pcf_dependencies->task_queue_factory.get());
325   WrapVideoEncoderFactory(
326       params->name.value(), params->video_encoder_bitrate_multiplier,
327       CalculateRequiredSpatialIndexPerStream(
328           configurable_params->video_configs),
329       components->pcf_dependencies.get(), video_analyzer_helper_);
330   WrapVideoDecoderFactory(params->name.value(),
331                           components->pcf_dependencies.get(),
332                           video_analyzer_helper_);
333   std::unique_ptr<cricket::MediaEngineInterface> media_engine =
334       CreateMediaEngine(components->pcf_dependencies.get(),
335                         audio_device_module);
336 
337   std::unique_ptr<rtc::Thread> owned_worker_thread =
338       components->worker_thread != nullptr
339           ? nullptr
340           : time_controller_.CreateThread("worker_thread");
341   if (components->worker_thread == nullptr) {
342     components->worker_thread = owned_worker_thread.get();
343   }
344 
345   // Store `webrtc::AudioProcessing` into local variable before move of
346   // `components->pcf_dependencies`
347   rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing =
348       components->pcf_dependencies->audio_processing;
349   PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies(
350       std::move(components->pcf_dependencies), std::move(media_engine),
351       signaling_thread_, components->worker_thread, components->network_thread);
352   rtc::scoped_refptr<PeerConnectionFactoryInterface> peer_connection_factory =
353       CreateModularPeerConnectionFactory(std::move(pcf_deps));
354 
355   // Create peer connection.
356   PeerConnectionDependencies pc_deps =
357       CreatePCDependencies(observer.get(), params->port_allocator_extra_flags,
358                            std::move(components->pc_dependencies));
359   rtc::scoped_refptr<PeerConnectionInterface> peer_connection =
360       peer_connection_factory
361           ->CreatePeerConnectionOrError(params->rtc_configuration,
362                                         std::move(pc_deps))
363           .MoveValue();
364   peer_connection->SetBitrate(params->bitrate_settings);
365 
366   return absl::WrapUnique(
367       new TestPeer(peer_connection_factory, peer_connection,
368                    std::move(observer), std::move(*params),
369                    std::move(*configurable_params), std::move(video_sources),
370                    audio_processing, std::move(owned_worker_thread)));
371 }
372 
373 }  // namespace webrtc_pc_e2e
374 }  // namespace webrtc
375