33dfcb27b0
- Fix datachannel deadlock on dispose - Fix audio device being disposed on the wrong thread - Allow multiple RtcRuntime to be created (Useful for unit tests where we use multiple PeerConnectionFactory)
178 lines
5.1 KiB
C++
178 lines
5.1 KiB
C++
/*
|
|
* 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 <algorithm>
|
|
#include <atomic>
|
|
#include <iostream>
|
|
#include <memory>
|
|
|
|
#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<MediaStreamTrack> RtcRuntime::get_or_create_media_stream_track(
|
|
rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> rtc_track) {
|
|
webrtc::MutexLock lock(&mutex_);
|
|
for (std::weak_ptr<MediaStreamTrack> weak_existing_track :
|
|
media_stream_tracks_) {
|
|
if (std::shared_ptr<MediaStreamTrack> 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<VideoTrack> video_track =
|
|
std::shared_ptr<VideoTrack>(new VideoTrack(
|
|
shared_from_this(),
|
|
rtc::scoped_refptr<webrtc::VideoTrackInterface>(
|
|
static_cast<webrtc::VideoTrackInterface*>(rtc_track.get()))));
|
|
|
|
media_stream_tracks_.push_back(
|
|
std::static_pointer_cast<MediaStreamTrack>(video_track));
|
|
return video_track;
|
|
} else {
|
|
std::shared_ptr<AudioTrack> audio_track =
|
|
std::shared_ptr<AudioTrack>(new AudioTrack(
|
|
shared_from_this(),
|
|
rtc::scoped_refptr<webrtc::AudioTrackInterface>(
|
|
static_cast<webrtc::AudioTrackInterface*>(rtc_track.get()))));
|
|
|
|
media_stream_tracks_.push_back(
|
|
std::static_pointer_cast<MediaStreamTrack>(audio_track));
|
|
return audio_track;
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<AudioTrack> RtcRuntime::get_or_create_audio_track(
|
|
rtc::scoped_refptr<webrtc::AudioTrackInterface> track) {
|
|
return std::static_pointer_cast<AudioTrack>(
|
|
get_or_create_media_stream_track(track));
|
|
}
|
|
|
|
std::shared_ptr<VideoTrack> RtcRuntime::get_or_create_video_track(
|
|
rtc::scoped_refptr<webrtc::VideoTrackInterface> track) {
|
|
return std::static_pointer_cast<VideoTrack>(
|
|
get_or_create_media_stream_track(track));
|
|
}
|
|
|
|
LogSink::LogSink(
|
|
rust::Fn<void(rust::String message, LoggingSeverity severity)> 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<LoggingSeverity>(severity));
|
|
}
|
|
|
|
std::unique_ptr<LogSink> new_log_sink(
|
|
rust::Fn<void(rust::String, LoggingSeverity)> fnc) {
|
|
return std::make_unique<LogSink>(fnc);
|
|
}
|
|
|
|
rust::String create_random_uuid() {
|
|
return rtc::CreateRandomUuid();
|
|
}
|
|
|
|
} // namespace livekit
|