/* * Copyright 2023 LiveKit * * Licensed under the Apache License, Version 2.0 (the “License”); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an “AS IS” BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "livekit/webrtc.h" #include #include #include #include #include "livekit/audio_track.h" #include "livekit/media_stream_track.h" #include "livekit/rtp_receiver.h" #include "livekit/rtp_sender.h" #include "livekit/video_track.h" #include "rtc_base/helpers.h" #include "rtc_base/logging.h" #include "rtc_base/synchronization/mutex.h" #ifdef WEBRTC_WIN #include "rtc_base/win32.h" #endif namespace livekit { static webrtc::Mutex g_mutex{}; // Can't be atomic, we're using a Mutex because we need to wait for the // execution of the first init static uint32_t g_release_counter(0); RtcRuntime::RtcRuntime() { rtc::LogMessage::LogToDebug(rtc::LS_INFO); RTC_LOG(LS_VERBOSE) << "RtcRuntime()"; { // Not the best way to do it... webrtc::MutexLock lock(&g_mutex); if (g_release_counter == 0) { RTC_CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()"; #ifdef WEBRTC_WIN WSADATA data; WSAStartup(MAKEWORD(1, 0), &data); #endif } g_release_counter++; } network_thread_ = rtc::Thread::CreateWithSocketServer(); network_thread_->SetName("network_thread", &network_thread_); network_thread_->Start(); worker_thread_ = rtc::Thread::Create(); worker_thread_->SetName("worker_thread", &worker_thread_); worker_thread_->Start(); signaling_thread_ = rtc::Thread::Create(); signaling_thread_->SetName("signaling_thread", &signaling_thread_); signaling_thread_->Start(); } RtcRuntime::~RtcRuntime() { RTC_LOG(LS_VERBOSE) << "~RtcRuntime()"; worker_thread_->Stop(); signaling_thread_->Stop(); network_thread_->Stop(); { webrtc::MutexLock lock(&g_mutex); g_release_counter--; if (g_release_counter == 0) { RTC_CHECK(rtc::CleanupSSL()) << "Failed to CleanupSSL()"; #ifdef WEBRTC_WIN WSACleanup(); #endif } } } rtc::Thread* RtcRuntime::network_thread() const { return network_thread_.get(); } rtc::Thread* RtcRuntime::worker_thread() const { return worker_thread_.get(); } rtc::Thread* RtcRuntime::signaling_thread() const { return signaling_thread_.get(); } std::shared_ptr RtcRuntime::get_or_create_media_stream_track( rtc::scoped_refptr rtc_track) { webrtc::MutexLock lock(&mutex_); for (std::weak_ptr weak_existing_track : media_stream_tracks_) { if (std::shared_ptr existing_track = weak_existing_track.lock()) { if (existing_track->rtc_track() == rtc_track) { return existing_track; } } } if (rtc_track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) { std::shared_ptr video_track = std::shared_ptr(new VideoTrack( shared_from_this(), rtc::scoped_refptr( static_cast(rtc_track.get())))); media_stream_tracks_.push_back( std::static_pointer_cast(video_track)); return video_track; } else { std::shared_ptr audio_track = std::shared_ptr(new AudioTrack( shared_from_this(), rtc::scoped_refptr( static_cast(rtc_track.get())))); media_stream_tracks_.push_back( std::static_pointer_cast(audio_track)); return audio_track; } } std::shared_ptr RtcRuntime::get_or_create_audio_track( rtc::scoped_refptr track) { return std::static_pointer_cast( get_or_create_media_stream_track(track)); } std::shared_ptr RtcRuntime::get_or_create_video_track( rtc::scoped_refptr track) { return std::static_pointer_cast( get_or_create_media_stream_track(track)); } LogSink::LogSink( rust::Fn fnc) : fnc_(fnc) { rtc::LogMessage::AddLogToStream(this, rtc::LoggingSeverity::LS_VERBOSE); } LogSink::~LogSink() { rtc::LogMessage::RemoveLogToStream(this); } void LogSink::OnLogMessage(const std::string& message, rtc::LoggingSeverity severity) { fnc_(rust::String(message), static_cast(severity)); } std::unique_ptr new_log_sink( rust::Fn fnc) { return std::make_unique(fnc); } rust::String create_random_uuid() { return rtc::CreateRandomUuid(); } } // namespace livekit