Introduce new way to enable media in PeerConnectionFactory instead of requiring to pass in call_factory and media_engine webrtc users should set media_factory member and media dependencies into PeerConnectionFactoryDependencies Bug: webrtc:15574 Change-Id: I2dc584fe7afa41c9f170bdc51533396155cdcb06 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/325320 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41049}
diff --git a/api/BUILD.gn b/api/BUILD.gn index 1eb3876..bd0f52e 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn
@@ -35,6 +35,20 @@ ] } +rtc_source_set("enable_media") { + visibility = [ "*" ] + sources = [ + "enable_media.cc", + "enable_media.h", + ] + deps = [ + ":libjingle_peerconnection_api", + "../call", + "../media:rtc_audio_video", + "../pc:media_factory", + ] +} + if (!build_with_chromium) { rtc_library("create_peerconnection_factory") { visibility = [ "*" ] @@ -305,6 +319,7 @@ ":turn_customizer", "../call:rtp_interfaces", "../p2p:rtc_p2p", + "../pc:media_factory", "../rtc_base:copy_on_write_buffer", "../rtc_base:logging", "../rtc_base:network",
diff --git a/api/call/call_factory_interface.h b/api/call/call_factory_interface.h index fde8cba..1c12352 100644 --- a/api/call/call_factory_interface.h +++ b/api/call/call_factory_interface.h
@@ -24,6 +24,9 @@ // This interface exists to allow webrtc to be optionally built without media // support (i.e., if only being used for data channels). PeerConnectionFactory // is constructed with a CallFactoryInterface, which may or may not be null. +// TODO(bugs.webrtc.org/15574): Delete this interface when +// `PeerConnectionFactoryDependencies::call_factory` is removed in favor of +// `PeerConnectionFactoryDependencies::media_factory`. class CallFactoryInterface { public: virtual ~CallFactoryInterface() = default;
diff --git a/api/enable_media.cc b/api/enable_media.cc new file mode 100644 index 0000000..4c97ace --- /dev/null +++ b/api/enable_media.cc
@@ -0,0 +1,75 @@ +/* + * Copyright 2023 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 "api/enable_media.h" + +#include <memory> +#include <utility> + +#include "api/peer_connection_interface.h" +#include "call/call_factory.h" +#include "media/engine/webrtc_media_engine.h" +#include "media/engine/webrtc_video_engine.h" +#include "media/engine/webrtc_voice_engine.h" +#include "pc/media_factory.h" + +namespace webrtc { +namespace { + +using ::cricket::CompositeMediaEngine; +using ::cricket::MediaEngineInterface; +using ::cricket::WebRtcVideoEngine; +using ::cricket::WebRtcVoiceEngine; + +class MediaFactoryImpl : public MediaFactory { + public: + MediaFactoryImpl() = default; + MediaFactoryImpl(const MediaFactoryImpl&) = delete; + MediaFactoryImpl& operator=(const MediaFactoryImpl&) = delete; + ~MediaFactoryImpl() override = default; + + std::unique_ptr<Call> CreateCall(const CallConfig& config) override { + CallFactory call_factory; + return static_cast<CallFactoryInterface&>(call_factory).CreateCall(config); + } + + std::unique_ptr<MediaEngineInterface> CreateMediaEngine( + PeerConnectionFactoryDependencies& deps) override { + std::unique_ptr<FieldTrialsView> fallback_trials; + const FieldTrialsView* trials; + if (deps.trials) { + trials = deps.trials.get(); + } else { + fallback_trials = std::make_unique<FieldTrialBasedConfig>(); + trials = fallback_trials.get(); + } + auto audio_engine = std::make_unique<WebRtcVoiceEngine>( + deps.task_queue_factory.get(), deps.adm.get(), + std::move(deps.audio_encoder_factory), + std::move(deps.audio_decoder_factory), std::move(deps.audio_mixer), + std::move(deps.audio_processing), /*audio_frame_processor=*/nullptr, + /*owned_audio_frame_processor=*/std::move(deps.audio_frame_processor), + *trials); + auto video_engine = std::make_unique<WebRtcVideoEngine>( + std::move(deps.video_encoder_factory), + std::move(deps.video_decoder_factory), *trials); + return std::make_unique<CompositeMediaEngine>(std::move(fallback_trials), + std::move(audio_engine), + std::move(video_engine)); + } +}; + +} // namespace + +void EnableMedia(PeerConnectionFactoryDependencies& deps) { + deps.media_factory = std::make_unique<MediaFactoryImpl>(); +} + +} // namespace webrtc
diff --git a/api/enable_media.h b/api/enable_media.h new file mode 100644 index 0000000..8e0b66b --- /dev/null +++ b/api/enable_media.h
@@ -0,0 +1,26 @@ +/* + * Copyright 2023 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 API_ENABLE_MEDIA_H_ +#define API_ENABLE_MEDIA_H_ + +#include "api/peer_connection_interface.h" + +namespace webrtc { + +// Enables media support for PeerConnnectionFactory created from `deps` +// This function is located in its own build target to allow webrtc users that +// do not need any media to avoid linking media specific code and thus to reduce +// binary size. +void EnableMedia(PeerConnectionFactoryDependencies& deps); + +} // namespace webrtc + +#endif // API_ENABLE_MEDIA_H_
diff --git a/api/peer_connection_interface.cc b/api/peer_connection_interface.cc index 050b61d..dedfd35 100644 --- a/api/peer_connection_interface.cc +++ b/api/peer_connection_interface.cc
@@ -12,6 +12,8 @@ #include <utility> +#include "pc/media_factory.h" + namespace webrtc { PeerConnectionInterface::IceServer::IceServer() = default;
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h index 9243190..7c81b16 100644 --- a/api/peer_connection_interface.h +++ b/api/peer_connection_interface.h
@@ -120,6 +120,8 @@ #include "api/transport/sctp_transport_factory_interface.h" #include "api/turn_customizer.h" #include "api/video/video_bitrate_allocator_factory.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" #include "call/rtp_transport_controller_send_factory_interface.h" #include "media/base/media_config.h" #include "media/base/media_engine.h" @@ -145,6 +147,9 @@ namespace webrtc { +// MediaFactory class definition is not part of the api. +class MediaFactory; + // MediaStream container interface. class StreamCollectionInterface : public rtc::RefCountInterface { public: @@ -1427,6 +1432,8 @@ // called without a `port_allocator`. std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory; std::unique_ptr<TaskQueueFactory> task_queue_factory; + // TODO(bugs.webrtc.org/15574): Deprecate `media_engine` and `call_factory` + // when chromium and webrtc are updated to use `media_factory` instead. std::unique_ptr<cricket::MediaEngineInterface> media_engine; std::unique_ptr<CallFactoryInterface> call_factory; std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory; @@ -1447,6 +1454,23 @@ std::unique_ptr<RtpTransportControllerSendFactoryInterface> transport_controller_send_factory; std::unique_ptr<Metronome> metronome; + + // Media specific dependencies. Unused when `media_factory == nullptr`. + rtc::scoped_refptr<AudioDeviceModule> adm; + rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory; + rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory; + rtc::scoped_refptr<AudioMixer> audio_mixer; + rtc::scoped_refptr<AudioProcessing> audio_processing; + std::unique_ptr<AudioFrameProcessor> audio_frame_processor; + std::unique_ptr<VideoEncoderFactory> video_encoder_factory; + std::unique_ptr<VideoDecoderFactory> video_decoder_factory; + + // The `media_factory` members allows webrtc to be optionally built without + // media support (i.e., if only being used for data channels). + // By default media is disabled. To enable media call + // `EnableMedia(PeerConnectionFactoryDependencies&)`. Definition of the + // `MediaFactory` interface is a webrtc implementation detail. + std::unique_ptr<MediaFactory> media_factory; }; // PeerConnectionFactoryInterface is the factory interface used for creating
diff --git a/media/engine/webrtc_media_engine.h b/media/engine/webrtc_media_engine.h index 0f6dce3..fa4046b 100644 --- a/media/engine/webrtc_media_engine.h +++ b/media/engine/webrtc_media_engine.h
@@ -63,6 +63,8 @@ // CreateMediaEngine may be called on any thread, though the engine is // only expected to be used on one thread, internally called the "worker // thread". This is the thread Init must be called on. +// TODO(bugs.webrtc.org/15574): Deprecate this helper in favor of creating +// media engine with `PeerConnectionFactoryDependencies::media_factory`. RTC_EXPORT std::unique_ptr<MediaEngineInterface> CreateMediaEngine( MediaEngineDependencies dependencies);
diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 7c22a26..7952ffd 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn
@@ -314,6 +314,15 @@ ] } +rtc_source_set("media_factory") { + sources = [ "media_factory.h" ] + deps = [ + "../api:callfactory_api", + "../call:call_interfaces", + "../media:rtc_media_base", + ] +} + rtc_source_set("media_session") { visibility = [ "*" ] # Used by Chrome sources = [ @@ -919,6 +928,7 @@ "connection_context.h", ] deps = [ + ":media_factory", "../api:callfactory_api", "../api:field_trials_view", "../api:libjingle_peerconnection_api", @@ -2405,6 +2415,7 @@ "../api:create_peerconnection_factory", "../api:dtls_transport_interface", "../api:dtmf_sender_interface", + "../api:enable_media", "../api:fake_frame_decryptor", "../api:fake_frame_encryptor", "../api:field_trials_view",
diff --git a/pc/connection_context.cc b/pc/connection_context.cc index f436e27..1347008 100644 --- a/pc/connection_context.cc +++ b/pc/connection_context.cc
@@ -17,6 +17,7 @@ #include "api/transport/field_trial_based_config.h" #include "media/base/media_engine.h" #include "media/sctp/sctp_transport_factory.h" +#include "pc/media_factory.h" #include "rtc_base/helpers.h" #include "rtc_base/internal/default_socket_server.h" #include "rtc_base/socket_server.h" @@ -78,6 +79,13 @@ // Static rtc::scoped_refptr<ConnectionContext> ConnectionContext::Create( PeerConnectionFactoryDependencies* dependencies) { + if (dependencies->media_factory != nullptr) { + RTC_CHECK(dependencies->media_engine == nullptr) + << "media_factory replaces media_engine. Do not set media_engine."; + RTC_CHECK(dependencies->call_factory == nullptr) + << "media_factory replaces call_factory. Do not set call_factory."; + } + return rtc::scoped_refptr<ConnectionContext>( new ConnectionContext(dependencies)); } @@ -98,11 +106,16 @@ wraps_current_thread_)), trials_(dependencies->trials ? std::move(dependencies->trials) : std::make_unique<FieldTrialBasedConfig>()), - media_engine_(std::move(dependencies->media_engine)), + media_engine_( + dependencies->media_factory != nullptr + ? dependencies->media_factory->CreateMediaEngine(*dependencies) + : std::move(dependencies->media_engine)), network_monitor_factory_( std::move(dependencies->network_monitor_factory)), default_network_manager_(std::move(dependencies->network_manager)), - call_factory_(std::move(dependencies->call_factory)), + call_factory_(dependencies->media_factory != nullptr + ? std::move(dependencies->media_factory) + : std::move(dependencies->call_factory)), default_socket_factory_(std::move(dependencies->packet_socket_factory)), sctp_factory_( MaybeCreateSctpFactory(std::move(dependencies->sctp_factory),
diff --git a/pc/media_factory.h b/pc/media_factory.h new file mode 100644 index 0000000..323744a --- /dev/null +++ b/pc/media_factory.h
@@ -0,0 +1,46 @@ +/* + * Copyright 2023 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 PC_MEDIA_FACTORY_H_ +#define PC_MEDIA_FACTORY_H_ + +#include <memory> + +#include "api/call/call_factory_interface.h" +#include "call/call.h" +#include "call/call_config.h" +#include "media/base/media_engine.h" + +namespace webrtc { + +// PeerConnectionFactoryDependencies is forward declared because of circular +// dependency between MediaFactory and PeerConnectionFactoryDependencies: +// PeerConnectionFactoryDependencies keeps an instance of MediaFactory and thus +// needs to know how to destroy it. +// MediaFactory mentions PeerConnectionFactoryDependencies in api, but does not +// need its full definition. +struct PeerConnectionFactoryDependencies; + +// Interface repsponsible for constructing media specific classes for +// PeerConnectionFactory and PeerConnection. +// TODO(bugs.webrtc.org/15574): Delete CallFactoryInterface inheritance +// when call_factory is removed from PeerConnectionFactoryDependencies. +class MediaFactory : public CallFactoryInterface { + public: + virtual ~MediaFactory() = default; + + std::unique_ptr<Call> CreateCall(const CallConfig& config) override = 0; + virtual std::unique_ptr<cricket::MediaEngineInterface> CreateMediaEngine( + PeerConnectionFactoryDependencies& dependencies) = 0; +}; + +} // namespace webrtc + +#endif // PC_MEDIA_FACTORY_H_
diff --git a/pc/peer_connection_factory_unittest.cc b/pc/peer_connection_factory_unittest.cc index 11e232c..91772ec 100644 --- a/pc/peer_connection_factory_unittest.cc +++ b/pc/peer_connection_factory_unittest.cc
@@ -20,6 +20,7 @@ #include "api/audio_codecs/builtin_audio_encoder_factory.h" #include "api/create_peerconnection_factory.h" #include "api/data_channel_interface.h" +#include "api/enable_media.h" #include "api/jsep.h" #include "api/media_stream_interface.h" #include "api/task_queue/default_task_queue_factory.h" @@ -35,7 +36,6 @@ #include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h" #include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h" #include "media/base/fake_frame_source.h" -#include "media/engine/webrtc_media_engine.h" #include "modules/audio_device/include/audio_device.h" #include "modules/audio_processing/include/audio_processing.h" #include "p2p/base/fake_port_allocator.h" @@ -272,29 +272,20 @@ pcf_dependencies.worker_thread = rtc::Thread::Current(); pcf_dependencies.network_thread = rtc::Thread::Current(); pcf_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory(); - pcf_dependencies.call_factory = CreateCallFactory(); - pcf_dependencies.trials = std::make_unique<webrtc::FieldTrialBasedConfig>(); + pcf_dependencies.trials = std::make_unique<FieldTrialBasedConfig>(); - cricket::MediaEngineDependencies media_dependencies; - media_dependencies.task_queue_factory = - pcf_dependencies.task_queue_factory.get(); - media_dependencies.adm = rtc::scoped_refptr<webrtc::AudioDeviceModule>( - FakeAudioCaptureModule::Create()); - media_dependencies.audio_encoder_factory = - webrtc::CreateBuiltinAudioEncoderFactory(); - media_dependencies.audio_decoder_factory = - webrtc::CreateBuiltinAudioDecoderFactory(); - media_dependencies.video_encoder_factory = + pcf_dependencies.adm = FakeAudioCaptureModule::Create(); + pcf_dependencies.audio_encoder_factory = CreateBuiltinAudioEncoderFactory(); + pcf_dependencies.audio_decoder_factory = CreateBuiltinAudioDecoderFactory(); + pcf_dependencies.video_encoder_factory = std::make_unique<VideoEncoderFactoryTemplate< LibvpxVp8EncoderTemplateAdapter, LibvpxVp9EncoderTemplateAdapter, OpenH264EncoderTemplateAdapter, LibaomAv1EncoderTemplateAdapter>>(); - media_dependencies.video_decoder_factory = + pcf_dependencies.video_decoder_factory = std::make_unique<VideoDecoderFactoryTemplate< LibvpxVp8DecoderTemplateAdapter, LibvpxVp9DecoderTemplateAdapter, OpenH264DecoderTemplateAdapter, Dav1dDecoderTemplateAdapter>>(), - media_dependencies.trials = pcf_dependencies.trials.get(); - pcf_dependencies.media_engine = - cricket::CreateMediaEngine(std::move(media_dependencies)); + EnableMedia(pcf_dependencies); rtc::scoped_refptr<webrtc::ConnectionContext> context = ConnectionContext::Create(&pcf_dependencies);