Files
client-sdk-rust/webrtc-sys/src/webrtc.cpp
T
Théo Monnom 33dfcb27b0 fix: datachannel deadlocks & dispose crashes (#87)
- 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)
2023-06-10 18:49:00 +02:00

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