Extract test peer creation into separate file

Extract test peer creation into separate file to simplify code and
increase readability. Also it is 1st step in bigger refactoring of PC
level test fixture implementation to make it more granular and reusable.

Change-Id: I687a17bda33a8eebc1ef0ddc0d54572e095fd709
Bug: webrtc:11479
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/172628
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30980}
This commit is contained in:
Artem Titov
2020-04-02 00:07:23 +02:00
committed by Commit Bot
parent c6b2f34f35
commit b907f1f9f8
7 changed files with 437 additions and 409 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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<TestPeer::RemotePeerAudioConfig> alice_remote_audio_config =
TestPeer::CreateRemoteAudioConfig(bob_params->audio_config);
absl::optional<TestPeer::RemotePeerAudioConfig> bob_remote_audio_config =
TestPeer::CreateRemoteAudioConfig(alice_params->audio_config);
absl::optional<RemotePeerAudioConfig> alice_remote_audio_config =
RemotePeerAudioConfig::Create(bob_params->audio_config);
absl::optional<RemotePeerAudioConfig> bob_remote_audio_config =
RemotePeerAudioConfig::Create(alice_params->audio_config);
// Copy Alice and Bob video configs to correctly pass them into lambdas.
std::vector<VideoConfig> alice_video_configs = alice_params->video_configs;
std::vector<VideoConfig> 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<FixturePeerConnectionObserver>(
@ -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<FixturePeerConnectionObserver>(

View File

@ -9,356 +9,15 @@
*/
#include "test/pc/e2e/test_peer.h"
#include <string>
#include <utility>
#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<RtcEventLogFactory>(
components->pcf_dependencies->task_queue_factory.get());
}
}
class TestPeerComponents {
public:
TestPeerComponents(std::unique_ptr<InjectableComponents> components,
const Params& params,
MockPeerConnectionObserver* observer,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
rtc::Thread* signaling_thread,
absl::optional<RemotePeerAudioConfig> remote_audio_config,
double bitrate_multiplier,
absl::optional<EchoEmulationConfig> 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<int>(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<PeerConnectionFactoryInterface> peer_connection_factory()
const {
return peer_connection_factory_;
}
rtc::scoped_refptr<PeerConnectionInterface> peer_connection() const {
return peer_connection_;
}
rtc::scoped_refptr<AudioProcessing> 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<PeerConnectionFactoryComponents> 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<cricket::MediaEngineInterface> 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<AudioDeviceModule> CreateAudioDeviceModule(
TaskQueueFactory* task_queue_factory) {
std::unique_ptr<TestAudioDeviceModule::Renderer> renderer =
CreateAudioRenderer(remote_audio_config_);
std::unique_ptr<TestAudioDeviceModule::Capturer> capturer =
CreateAudioCapturer(audio_config_opt_);
RTC_DCHECK(renderer);
RTC_DCHECK(capturer);
// Setup echo emulation if required.
if (echo_emulation_config_) {
capturer = std::make_unique<EchoEmulatingCapturer>(
std::move(capturer), *echo_emulation_config_);
renderer = std::make_unique<EchoEmulatingRenderer>(
std::move(renderer),
static_cast<EchoEmulatingCapturer*>(capturer.get()));
}
// Setup input stream dumping if required.
if (audio_config_opt_ && audio_config_opt_->input_dump_file_name) {
capturer = std::make_unique<test::CopyToFileAudioCapturer>(
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<TestAudioDeviceModule::Renderer> CreateAudioRenderer(
const absl::optional<RemotePeerAudioConfig>& 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<TestAudioDeviceModule::Capturer> CreateAudioCapturer(
const absl::optional<AudioConfig>& 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<VideoEncoderFactory> CreateVideoEncoderFactory(
PeerConnectionFactoryComponents* pcf_dependencies) {
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_,
stream_required_spatial_index_);
}
std::unique_ptr<VideoDecoderFactory> CreateVideoDecoderFactory(
PeerConnectionFactoryComponents* pcf_dependencies) {
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));
}
// Creates PeerConnectionDependencies objects, providing entities
// from InjectableComponents::PeerConnectionComponents.
PeerConnectionDependencies CreatePCDependencies(
std::unique_ptr<PeerConnectionComponents> pc_dependencies) {
PeerConnectionDependencies pc_deps(observer_);
auto port_allocator = std::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);
}
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<PeerConnectionFactoryInterface> peer_connection_factory_;
rtc::scoped_refptr<PeerConnectionInterface> peer_connection_;
rtc::scoped_refptr<AudioProcessing> audio_processing_;
std::map<std::string, absl::optional<int>> stream_required_spatial_index_;
absl::optional<AudioConfig> audio_config_opt_;
MockPeerConnectionObserver* observer_;
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper_;
rtc::Thread* signaling_thread_;
absl::optional<RemotePeerAudioConfig> remote_audio_config_;
double bitrate_multiplier_;
absl::optional<EchoEmulationConfig> echo_emulation_config_;
};
} // namespace
absl::optional<RemotePeerAudioConfig> TestPeer::CreateRemoteAudioConfig(
absl::optional<AudioConfig> config) {
if (!config) {
return absl::nullopt;
}
return RemotePeerAudioConfig(config.value());
}
std::unique_ptr<TestPeer> TestPeer::CreateTestPeer(
std::unique_ptr<InjectableComponents> components,
std::unique_ptr<Params> params,
std::vector<std::unique_ptr<test::FrameGeneratorInterface>>
video_generators,
std::unique_ptr<MockPeerConnectionObserver> observer,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
rtc::Thread* signaling_thread,
absl::optional<RemotePeerAudioConfig> remote_audio_config,
double bitrate_multiplier,
absl::optional<EchoEmulationConfig> 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<std::unique_ptr<IceCandidateInterface>> candidates) {

View File

@ -12,20 +12,11 @@
#define TEST_PC_E2E_TEST_PEER_H_
#include <memory>
#include <string>
#include <vector>
#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<std::string> output_file_name;
};
static absl::optional<RemotePeerAudioConfig> CreateRemoteAudioConfig(
absl::optional<AudioConfig> 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<TestPeer> CreateTestPeer(
std::unique_ptr<InjectableComponents> components,
std::unique_ptr<Params> params,
std::vector<std::unique_ptr<test::FrameGeneratorInterface>>
video_generators,
std::unique_ptr<MockPeerConnectionObserver> observer,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
rtc::Thread* signaling_thread,
absl::optional<RemotePeerAudioConfig> remote_audio_config,
double bitrate_multiplier,
absl::optional<EchoEmulationConfig> echo_emulation_config,
rtc::TaskQueue* task_queue);
Params* params() const { return params_.get(); }
std::unique_ptr<test::FrameGeneratorInterface> ReleaseVideoGenerator(
@ -85,7 +39,8 @@ class TestPeer final : public PeerConnectionWrapper {
bool AddIceCandidates(
std::vector<std::unique_ptr<IceCandidateInterface>> candidates);
private:
protected:
friend class TestPeerFactory;
TestPeer(rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
rtc::scoped_refptr<PeerConnectionInterface> pc,
std::unique_ptr<MockPeerConnectionObserver> observer,
@ -94,6 +49,7 @@ class TestPeer final : public PeerConnectionWrapper {
video_generators,
rtc::scoped_refptr<AudioProcessing> audio_processing);
private:
std::unique_ptr<Params> params_;
std::vector<std::unique_ptr<test::FrameGeneratorInterface>> video_generators_;
rtc::scoped_refptr<AudioProcessing> audio_processing_;

View File

@ -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 <utility>
#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<RtcEventLogFactory>(
components->pcf_dependencies->task_queue_factory.get());
}
}
std::map<std::string, absl::optional<int>>
CalculateRequiredSpatialIndexPerStream(
const std::vector<VideoConfig>& video_configs) {
std::map<std::string, absl::optional<int>> out;
for (auto& video_config : video_configs) {
// Stream label should be set by fixture implementation here.
RTC_DCHECK(video_config.stream_label);
absl::optional<int> 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<TestAudioDeviceModule::Renderer> CreateAudioRenderer(
const absl::optional<RemotePeerAudioConfig>& 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<TestAudioDeviceModule::Capturer> CreateAudioCapturer(
const absl::optional<AudioConfig>& 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<AudioDeviceModule> CreateAudioDeviceModule(
absl::optional<AudioConfig> audio_config,
absl::optional<RemotePeerAudioConfig> remote_audio_config,
absl::optional<EchoEmulationConfig> echo_emulation_config,
TaskQueueFactory* task_queue_factory) {
std::unique_ptr<TestAudioDeviceModule::Renderer> renderer =
CreateAudioRenderer(remote_audio_config);
std::unique_ptr<TestAudioDeviceModule::Capturer> capturer =
CreateAudioCapturer(audio_config);
RTC_DCHECK(renderer);
RTC_DCHECK(capturer);
// Setup echo emulation if required.
if (echo_emulation_config) {
capturer = std::make_unique<EchoEmulatingCapturer>(std::move(capturer),
*echo_emulation_config);
renderer = std::make_unique<EchoEmulatingRenderer>(
std::move(renderer),
static_cast<EchoEmulatingCapturer*>(capturer.get()));
}
// Setup input stream dumping if required.
if (audio_config && audio_config->input_dump_file_name) {
capturer = std::make_unique<test::CopyToFileAudioCapturer>(
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<cricket::MediaEngineInterface> CreateMediaEngine(
PeerConnectionFactoryComponents* pcf_dependencies,
rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
rtc::scoped_refptr<AudioProcessing> 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<std::string, absl::optional<int>> stream_required_spatial_index,
PeerConnectionFactoryComponents* pcf_dependencies,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) {
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();
}
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<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();
}
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<PeerConnectionFactoryComponents> pcf_dependencies,
std::unique_ptr<cricket::MediaEngineInterface> 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<PeerConnectionComponents> pc_dependencies) {
PeerConnectionDependencies pc_deps(observer);
auto port_allocator = std::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);
}
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> RemotePeerAudioConfig::Create(
absl::optional<AudioConfig> config) {
if (!config) {
return absl::nullopt;
}
return RemotePeerAudioConfig(config.value());
}
std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
std::unique_ptr<InjectableComponents> components,
std::unique_ptr<Params> params,
std::vector<std::unique_ptr<test::FrameGeneratorInterface>>
video_generators,
std::unique_ptr<MockPeerConnectionObserver> observer,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
rtc::Thread* signaling_thread,
absl::optional<RemotePeerAudioConfig> remote_audio_config,
double bitrate_multiplier,
absl::optional<EchoEmulationConfig> 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<AudioProcessing> 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<AudioDeviceModule> 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<cricket::MediaEngineInterface> 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<PeerConnectionFactoryInterface> 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<PeerConnectionInterface> 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

View File

@ -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 <map>
#include <memory>
#include <string>
#include <vector>
#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<RemotePeerAudioConfig> Create(
absl::optional<PeerConnectionE2EQualityTestFixture::AudioConfig> config);
int sampling_frequency_in_hz;
absl::optional<std::string> 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<TestPeer> CreateTestPeer(
std::unique_ptr<InjectableComponents> components,
std::unique_ptr<Params> params,
std::vector<std::unique_ptr<test::FrameGeneratorInterface>>
video_generators,
std::unique_ptr<MockPeerConnectionObserver> observer,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
rtc::Thread* signaling_thread,
absl::optional<RemotePeerAudioConfig> remote_audio_config,
double bitrate_multiplier,
absl::optional<PeerConnectionE2EQualityTestFixture::EchoEmulationConfig>
echo_emulation_config,
rtc::TaskQueue* task_queue);
};
} // namespace webrtc_pc_e2e
} // namespace webrtc
#endif // TEST_PC_E2E_TEST_PEER_FACTORY_H_