#include "livekit/peer_connection_factory.h"
#include <memory>
#include <utility>
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/audio/builtin_audio_processing_builder.h"
#include "api/create_modular_peer_connection_factory.h"
#include "api/environment/environment_factory.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/enable_media.h"
#include "api/rtc_event_log/rtc_event_log_factory.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 "api/audio/audio_device.h"
#include "api/audio_options.h"
#include "livekit/adm_proxy.h"
#include "livekit/audio_track.h"
#include "livekit/peer_connection.h"
#include "livekit/rtc_error.h"
#include "livekit/rtp_parameters.h"
#include "livekit/video_decoder_factory.h"
#include "livekit/video_encoder_factory.h"
#include "livekit/webrtc.h"
#include "rtc_base/thread.h"
#include "webrtc-sys/src/peer_connection.rs.h"
#include "webrtc-sys/src/peer_connection_factory.rs.h"
namespace livekit_ffi {
class PeerConnectionObserver;
PeerConnectionFactory::PeerConnectionFactory(
std::shared_ptr<RtcRuntime> rtc_runtime)
: rtc_runtime_(rtc_runtime),
env_(webrtc::EnvironmentFactory().Create()) {
webrtc::PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = rtc_runtime_->network_thread();
dependencies.worker_thread = rtc_runtime_->worker_thread();
dependencies.signaling_thread = rtc_runtime_->signaling_thread();
dependencies.socket_factory = rtc_runtime_->network_thread()->socketserver();
dependencies.event_log_factory = std::make_unique<webrtc::RtcEventLogFactory>();
adm_proxy_ = rtc_runtime_->worker_thread()->BlockingCall([&] {
return webrtc::make_ref_counted<livekit_ffi::AdmProxy>(
env_, rtc_runtime_->worker_thread());
});
audio_device_ = std::make_shared<AudioDeviceController>(adm_proxy_);
dependencies.adm = adm_proxy_;
dependencies.video_encoder_factory =
std::move(std::make_unique<livekit_ffi::VideoEncoderFactory>());
dependencies.video_decoder_factory =
std::move(std::make_unique<livekit_ffi::VideoDecoderFactory>());
dependencies.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
dependencies.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
dependencies.audio_processing_builder = std::make_unique<webrtc::BuiltinAudioProcessingBuilder>();
webrtc::EnableMedia(dependencies);
peer_factory_ =
webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
if (peer_factory_.get() == nullptr) {
RTC_LOG_ERR(LS_ERROR) << "Failed to create PeerConnectionFactory";
return;
}
}
PeerConnectionFactory::~PeerConnectionFactory() {
RTC_LOG(LS_VERBOSE) << "PeerConnectionFactory::~PeerConnectionFactory()";
peer_factory_ = nullptr;
audio_device_ = nullptr;
rtc_runtime_->worker_thread()->BlockingCall(
[this] { adm_proxy_ = nullptr; });
}
std::shared_ptr<PeerConnection> PeerConnectionFactory::create_peer_connection(
RtcConfiguration config,
rust::Box<PeerConnectionObserverWrapper> observer) const {
std::shared_ptr<PeerConnection> pc = std::make_shared<PeerConnection>(
rtc_runtime_, peer_factory_, std::move(observer));
if (!pc->Initialize(to_native_rtc_configuration(config))) {
throw std::runtime_error(serialize_error(to_error(webrtc::RTCError(
webrtc::RTCErrorType::INTERNAL_ERROR, "failed to initialize pc"))));
}
return pc;
}
std::shared_ptr<VideoTrack> PeerConnectionFactory::create_video_track(
rust::String label,
std::shared_ptr<VideoTrackSource> source) const {
return std::static_pointer_cast<VideoTrack>(
rtc_runtime_->get_or_create_media_stream_track(
peer_factory_->CreateVideoTrack(source->get(), label.c_str())));
}
std::shared_ptr<AudioTrack> PeerConnectionFactory::create_audio_track(
rust::String label,
std::shared_ptr<AudioTrackSource> source) const {
return std::static_pointer_cast<AudioTrack>(
rtc_runtime_->get_or_create_media_stream_track(
peer_factory_->CreateAudioTrack(label.c_str(), source->get().get())));
}
std::shared_ptr<AudioTrack> PeerConnectionFactory::create_device_audio_track(
rust::String label) const {
webrtc::AudioOptions audio_options;
audio_options.echo_cancellation = true;
audio_options.auto_gain_control = true;
audio_options.noise_suppression = true;
webrtc::scoped_refptr<webrtc::AudioSourceInterface> audio_source =
peer_factory_->CreateAudioSource(audio_options);
if (!audio_source) {
RTC_LOG(LS_ERROR) << "Failed to create device audio source";
return nullptr;
}
return std::static_pointer_cast<AudioTrack>(
rtc_runtime_->get_or_create_media_stream_track(
peer_factory_->CreateAudioTrack(label.c_str(), audio_source.get())));
}
RtpCapabilities PeerConnectionFactory::rtp_sender_capabilities(
MediaType type) const {
return to_rust_rtp_capabilities(peer_factory_->GetRtpSenderCapabilities(
static_cast<webrtc::MediaType>(type)));
}
RtpCapabilities PeerConnectionFactory::rtp_receiver_capabilities(
MediaType type) const {
return to_rust_rtp_capabilities(peer_factory_->GetRtpReceiverCapabilities(
static_cast<webrtc::MediaType>(type)));
}
std::shared_ptr<AudioDeviceController> PeerConnectionFactory::audio_device() const {
return audio_device_;
}
std::shared_ptr<PeerConnectionFactory> create_peer_connection_factory() {
return std::make_shared<PeerConnectionFactory>(RtcRuntime::create());
}
}