Windows + Initial WebRTC sys & Safe WebRTC + Initial livekit-core

This commit is contained in:
Théo Monnom
2022-09-12 12:51:54 +02:00
parent 7b09d6dd51
commit d9fd69b5c0
128 changed files with 4282 additions and 2282 deletions
@@ -0,0 +1,11 @@
//
// Created by Théo Monnom on 01/09/2022.
//
#include "livekit/candidate.h"
namespace livekit {
Candidate::Candidate(const cricket::Candidate &candidate) : candidate_(candidate) {
}
} // livekit
@@ -0,0 +1,12 @@
use cxx::UniquePtr;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
unsafe extern "C++" {
include!("livekit/candidate.h");
type Candidate; // cricket::Candidate
fn _unique_candidate() -> UniquePtr<Candidate>; // Ignore
}
}
@@ -0,0 +1,12 @@
//
// Created by Théo Monnom on 01/09/2022.
//
#include "livekit/data_channel.h"
namespace livekit {
DataChannel::DataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) : data_channel_(data_channel) {
}
} // livekit
@@ -0,0 +1,12 @@
use cxx::UniquePtr;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
unsafe extern "C++" {
include!("livekit/data_channel.h");
type DataChannel;
fn _unique_data_channel() -> UniquePtr<DataChannel>; // Ignore
}
}
@@ -0,0 +1,83 @@
//
// Created by Théo Monnom on 01/09/2022.
//
#include <memory>
#include "livekit/jsep.h"
#include "libwebrtc-sys/src/jsep.rs.h"
#include "api/make_ref_counted.h"
namespace livekit {
IceCandidate::IceCandidate(std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate) : ice_candidate_(std::move(ice_candidate)){
}
SessionDescription::SessionDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> session_description) : session_description_(std::move(session_description)){
}
std::unique_ptr<SessionDescription> SessionDescription::clone() const {
return std::make_unique<SessionDescription>(session_description_->Clone());
}
std::unique_ptr<webrtc::SessionDescriptionInterface> SessionDescription::release() {
return std::move(session_description_);
}
// CreateSdpObserver
NativeCreateSdpObserver::NativeCreateSdpObserver(
rust::Box<CreateSdpObserverWrapper> observer) : observer_(std::move(observer)) {
}
void NativeCreateSdpObserver::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
// We have ownership of desc
observer_->on_success(std::make_unique<SessionDescription>(std::unique_ptr<webrtc::SessionDescriptionInterface>(desc)));
}
void NativeCreateSdpObserver::OnFailure(webrtc::RTCError error) {
observer_->on_failure(std::make_unique<RTCError>(error));
}
std::unique_ptr<NativeCreateSdpObserverHandle> create_native_create_sdp_observer(rust::Box<CreateSdpObserverWrapper> observer){
return std::make_unique<NativeCreateSdpObserverHandle>(NativeCreateSdpObserverHandle {
rtc::make_ref_counted<NativeCreateSdpObserver>(std::move(observer))
});
}
// SetLocalSdpObserver
NativeSetLocalSdpObserver::NativeSetLocalSdpObserver(rust::Box<SetLocalSdpObserverWrapper> observer) : observer_(std::move(observer)) {
}
void NativeSetLocalSdpObserver::OnSetLocalDescriptionComplete(webrtc::RTCError error) {
observer_->on_set_local_description_complete(std::make_unique<RTCError>(error));
}
std::unique_ptr<NativeSetLocalSdpObserverHandle> create_native_set_local_sdp_observer(rust::Box<SetLocalSdpObserverWrapper> observer){
return std::make_unique<NativeSetLocalSdpObserverHandle>(NativeSetLocalSdpObserverHandle {
rtc::make_ref_counted<NativeSetLocalSdpObserver>(std::move(observer))
});
}
// SetRemoteSdpObserver
NativeSetRemoteSdpObserver::NativeSetRemoteSdpObserver(rust::Box<SetRemoteSdpObserverWrapper> observer) : observer_(std::move(observer)) {
}
void NativeSetRemoteSdpObserver::OnSetRemoteDescriptionComplete(webrtc::RTCError error) {
observer_->on_set_remote_description_complete(std::make_unique<RTCError>(error));
}
std::unique_ptr<NativeSetRemoteSdpObserverHandle> create_native_set_remote_sdp_observer(rust::Box<SetRemoteSdpObserverWrapper> observer){
return std::make_unique<NativeSetRemoteSdpObserverHandle>(NativeSetRemoteSdpObserverHandle {
rtc::make_ref_counted<NativeSetRemoteSdpObserver>(std::move(observer))
});
}
} // livekit
@@ -0,0 +1,109 @@
use cxx::UniquePtr;
use cxx::{type_id, ExternType};
use crate::rtc_error::ffi::RTCError;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
extern "Rust" {
type CreateSdpObserverWrapper;
fn on_success(self: &CreateSdpObserverWrapper, session_description: UniquePtr<SessionDescription>);
fn on_failure(self: &CreateSdpObserverWrapper, error: UniquePtr<RTCError>);
type SetLocalSdpObserverWrapper;
fn on_set_local_description_complete(self: &SetLocalSdpObserverWrapper, error: UniquePtr<RTCError>);
type SetRemoteSdpObserverWrapper;
fn on_set_remote_description_complete(self: &SetRemoteSdpObserverWrapper, error: UniquePtr<RTCError>);
}
unsafe extern "C++" {
include!("livekit/jsep.h");
include!("livekit/rtc_error.h");
type RTCError = crate::rtc_error::ffi::RTCError;
type IceCandidate;
type SessionDescription;
type NativeCreateSdpObserverHandle;
type NativeSetLocalSdpObserverHandle;
type NativeSetRemoteSdpObserverHandle;
fn create_native_create_sdp_observer(observer: Box<CreateSdpObserverWrapper>) -> UniquePtr<NativeCreateSdpObserverHandle>;
fn create_native_set_local_sdp_observer(observer: Box<SetLocalSdpObserverWrapper>) -> UniquePtr<NativeSetLocalSdpObserverHandle>;
fn create_native_set_remote_sdp_observer(observer: Box<SetRemoteSdpObserverWrapper>) -> UniquePtr<NativeSetRemoteSdpObserverHandle>;
fn _unique_ice_candidate() -> UniquePtr<IceCandidate>; // Ignore
fn _unique_session_description() -> UniquePtr<SessionDescription>; // Ignore
}
}
// CreateSdpObserver
pub trait CreateSdpObserver: Send + Sync {
fn on_success(&self, session_description: UniquePtr<ffi::SessionDescription>);
fn on_failure(&self, error: UniquePtr<RTCError>);
}
pub struct CreateSdpObserverWrapper {
observer: Box<dyn CreateSdpObserver>,
}
impl CreateSdpObserverWrapper {
pub fn new(observer: Box<dyn CreateSdpObserver>) -> Self {
Self {
observer
}
}
fn on_success(&self, session_description: UniquePtr<ffi::SessionDescription>) {
self.observer.on_success(session_description);
}
fn on_failure(&self, error: UniquePtr<RTCError>) {
self.observer.on_failure(error);
}
}
// SetLocalSdpObserver
pub trait SetLocalSdpObserver: Send + Sync {
fn on_set_local_description_complete(&self, error: UniquePtr<RTCError>);
}
pub struct SetLocalSdpObserverWrapper {
observer: Box<dyn SetLocalSdpObserver>,
}
impl SetLocalSdpObserverWrapper {
pub fn new(observer: Box<dyn SetLocalSdpObserver>) -> Self {
Self {
observer
}
}
fn on_set_local_description_complete(&self, error: UniquePtr<RTCError>) {
self.observer.on_set_local_description_complete(error);
}
}
// SetRemoteSdpObserver
pub trait SetRemoteSdpObserver: Send + Sync {
fn on_set_remote_description_complete(&self, error: UniquePtr<RTCError>);
}
pub struct SetRemoteSdpObserverWrapper {
observer: Box<dyn SetRemoteSdpObserver>,
}
impl SetRemoteSdpObserverWrapper {
pub fn new(observer: Box<dyn SetRemoteSdpObserver>) -> Self {
Self {
observer
}
}
fn on_set_remote_description_complete(&self, error: UniquePtr<RTCError>) {
self.observer.on_set_remote_description_complete(error);
}
}
@@ -0,0 +1,10 @@
pub mod media_stream_interface;
pub mod peer_connection;
pub mod peer_connection_factory;
pub mod data_channel;
pub mod jsep;
pub mod candidate;
pub mod rtp_receiver;
pub mod rtp_transceiver;
pub mod rtc_error;
@@ -0,0 +1,12 @@
//
// Created by Théo Monnom on 31/08/2022.
//
#include "livekit/media_stream_interface.h"
namespace livekit {
MediaStreamInterface::MediaStreamInterface(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) : media_stream_(stream) {
}
} // livekit
@@ -0,0 +1,13 @@
use cxx::UniquePtr;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
unsafe extern "C++" {
include!("livekit/media_stream_interface.h");
type MediaStreamInterface;
fn _unique_media_stream() -> UniquePtr<MediaStreamInterface>; // Ignore
}
}
@@ -0,0 +1,166 @@
//
// Created by Théo Monnom on 30/08/2022.
//
#include "livekit/peer_connection.h"
#include "libwebrtc-sys/src/peer_connection.rs.h"
namespace livekit {
inline webrtc::PeerConnectionInterface::RTCOfferAnswerOptions toNativeOfferAnswerOptions(const RTCOfferAnswerOptions& options) {
webrtc::PeerConnectionInterface::RTCOfferAnswerOptions rtc_options;
rtc_options.offer_to_receive_video = options.offer_to_receive_video;
rtc_options.offer_to_receive_audio = options.offer_to_receive_audio;
rtc_options.voice_activity_detection = options.voice_activity_detection;
rtc_options.ice_restart = options.ice_restart;
rtc_options.use_rtp_mux = options.use_rtp_mux;
rtc_options.raw_packetization_for_video = options.raw_packetization_for_video;
rtc_options.num_simulcast_layers = options.num_simulcast_layers;
rtc_options.use_obsolete_sctp_sdp = options.use_obsolete_sctp_sdp;
return rtc_options;
}
PeerConnection::PeerConnection(rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection,
std::unique_ptr<NativePeerConnectionObserver> observer) : peer_connection_(
std::move(peer_connection)), observer_(std::move(observer)) {
}
void PeerConnection::close() {
peer_connection_->Close();
}
void PeerConnection::create_offer(std::unique_ptr<NativeCreateSdpObserverHandle> observer_handle, RTCOfferAnswerOptions options) {
peer_connection_->CreateOffer(observer_handle->observer.get(), toNativeOfferAnswerOptions(options));
}
void PeerConnection::create_answer(std::unique_ptr<NativeCreateSdpObserverHandle> observer_handle, RTCOfferAnswerOptions options) {
peer_connection_->CreateAnswer(observer_handle->observer.get(), toNativeOfferAnswerOptions(options));
}
void PeerConnection::set_local_description(std::unique_ptr<SessionDescription> desc, std::unique_ptr<NativeSetLocalSdpObserverHandle> observer) {
peer_connection_->SetLocalDescription(desc->clone()->release(), observer->observer);
}
void PeerConnection::set_remote_description(std::unique_ptr<SessionDescription> desc, std::unique_ptr<NativeSetRemoteSdpObserverHandle> observer) {
peer_connection_->SetRemoteDescription(desc->clone()->release(), observer->observer);
}
/* Observer */
NativePeerConnectionObserver::NativePeerConnectionObserver(rust::Box<PeerConnectionObserverWrapper> observer) : observer_(std::move(observer)) {
}
void NativePeerConnectionObserver::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) {
observer_->on_signaling_change(static_cast<SignalingState>(new_state));
}
void NativePeerConnectionObserver::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
observer_->on_add_stream(std::make_unique<MediaStreamInterface>(stream));
}
void NativePeerConnectionObserver::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
observer_->on_remove_stream(std::make_unique<MediaStreamInterface>(stream));
}
void NativePeerConnectionObserver::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
observer_->on_data_channel(std::make_unique<DataChannel>(data_channel));
}
void NativePeerConnectionObserver::OnRenegotiationNeeded() {
observer_->on_renegotiation_needed();
}
void NativePeerConnectionObserver::OnNegotiationNeededEvent(uint32_t event_id) {
observer_->on_negotiation_needed_event(event_id);
}
void
NativePeerConnectionObserver::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {
observer_->on_ice_connection_change(static_cast<IceConnectionState>(new_state));
}
void NativePeerConnectionObserver::OnStandardizedIceConnectionChange(
webrtc::PeerConnectionInterface::IceConnectionState new_state) {
observer_->on_standardized_ice_connection_change(static_cast<IceConnectionState>(new_state));
}
void
NativePeerConnectionObserver::OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) {
observer_->on_connection_change(static_cast<PeerConnectionState>(new_state));
}
void
NativePeerConnectionObserver::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) {
observer_->on_ice_gathering_change(static_cast<IceGatheringState>(new_state));
}
void NativePeerConnectionObserver::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) {
auto new_candidate = webrtc::CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(),
candidate->candidate());
observer_->on_ice_candidate(std::make_unique<IceCandidate>(std::move(new_candidate)));
}
void NativePeerConnectionObserver::OnIceCandidateError(const std::string &address, int port, const std::string &url,
int error_code, const std::string &error_text) {
observer_->on_ice_candidate_error(address, port, url, error_code, error_text);
}
void NativePeerConnectionObserver::OnIceCandidatesRemoved(const std::vector<cricket::Candidate> &candidates) {
rust::Vec<CandidatePtr> vec;
for (const auto &item: candidates) {
vec.push_back(CandidatePtr{
std::make_unique<Candidate>(item)
});
}
observer_->on_ice_candidates_removed(std::move(vec));
}
void NativePeerConnectionObserver::OnIceConnectionReceivingChange(bool receiving) {
observer_->on_ice_connection_receiving_change(receiving);
}
void
NativePeerConnectionObserver::OnIceSelectedCandidatePairChanged(const cricket::CandidatePairChangeEvent &event) {
CandidatePairChangeEvent e;
e.selected_candidate_pair.local = std::make_unique<Candidate>(event.selected_candidate_pair.local);
e.selected_candidate_pair.remote = std::make_unique<Candidate>(event.selected_candidate_pair.remote);
e.last_data_received_ms = event.last_data_received_ms;
e.reason = event.reason;
e.estimated_disconnected_time_ms = event.estimated_disconnected_time_ms;
observer_->on_ice_selected_candidate_pair_changed(std::move(e));
}
void NativePeerConnectionObserver::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) {
rust::Vec<MediaStreamPtr> vec;
for (const auto &item: streams) {
vec.push_back(MediaStreamPtr{
std::make_unique<MediaStreamInterface>(item)
});
}
observer_->on_add_track(std::make_unique<RtpReceiver>(receiver), std::move(vec));
}
void NativePeerConnectionObserver::OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) {
observer_->on_track(std::make_unique<RtpTransceiver>(transceiver));
}
void NativePeerConnectionObserver::OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
observer_->on_remove_track(std::make_unique<RtpReceiver>(receiver));
}
void NativePeerConnectionObserver::OnInterestingUsage(int usage_pattern) {
observer_->on_interesting_usage(usage_pattern);
}
std::unique_ptr<NativePeerConnectionObserver> create_native_peer_connection_observer(rust::Box<PeerConnectionObserverWrapper> observer) {
return std::make_unique<NativePeerConnectionObserver>(std::move(observer));
}
} // livekit
@@ -0,0 +1,293 @@
use cxx::UniquePtr;
use crate::candidate::ffi::Candidate;
use crate::data_channel::ffi::DataChannel;
use crate::jsep::ffi::IceCandidate;
use crate::media_stream_interface::ffi::MediaStreamInterface;
use crate::rtp_receiver::ffi::RtpReceiver;
use crate::rtp_transceiver::ffi::RtpTransceiver;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
struct CandidatePair {
local: UniquePtr<Candidate>,
remote: UniquePtr<Candidate>,
}
struct CandidatePairChangeEvent {
selected_candidate_pair: CandidatePair,
last_data_received_ms: i64,
reason: String,
estimated_disconnected_time_ms: i64,
}
#[derive(Debug)]
#[repr(u32)]
pub enum PeerConnectionState {
kNew,
kConnecting,
kConnected,
kDisconnected,
kFailed,
kClosed,
}
#[derive(Debug)]
#[repr(u32)]
pub enum SignalingState {
kStable,
kHaveLocalOffer,
kHaveLocalPrAnswer,
kHaveRemoteOffer,
kHaveRemotePrAnswer,
kClosed,
}
#[derive(Debug)]
#[repr(u32)]
pub enum IceConnectionState {
kIceConnectionNew,
kIceConnectionChecking,
kIceConnectionConnected,
kIceConnectionCompleted,
kIceConnectionFailed,
kIceConnectionDisconnected,
kIceConnectionClosed,
kIceConnectionMax,
}
#[derive(Debug)]
#[repr(u32)]
pub enum IceGatheringState {
kIceGatheringNew,
kIceGatheringGathering,
kIceGatheringComplete
}
#[derive(Debug)]
pub struct RTCOfferAnswerOptions {
offer_to_receive_video: i32,
offer_to_receive_audio: i32,
voice_activity_detection: bool,
ice_restart: bool,
use_rtp_mux: bool,
raw_packetization_for_video: bool,
num_simulcast_layers: i32,
use_obsolete_sctp_sdp: bool,
}
// Wrapper to opaque C++ objects
// https://github.com/dtolnay/cxx/issues/741
struct MediaStreamPtr {
pub ptr: UniquePtr<MediaStreamInterface>
}
struct CandidatePtr {
pub ptr: UniquePtr<Candidate>
}
unsafe extern "C++" {
include!("livekit/peer_connection.h");
include!("livekit/jsep.h");
include!("livekit/data_channel.h");
include!("livekit/rtp_receiver.h");
include!("livekit/rtp_transceiver.h");
include!("livekit/media_stream_interface.h");
include!("livekit/candidate.h");
type Candidate = crate::candidate::ffi::Candidate;
type IceCandidate = crate::jsep::ffi::IceCandidate;
type DataChannel = crate::data_channel::ffi::DataChannel;
type RtpReceiver = crate::rtp_receiver::ffi::RtpReceiver;
type RtpTransceiver = crate::rtp_transceiver::ffi::RtpTransceiver;
type MediaStreamInterface = crate::media_stream_interface::ffi::MediaStreamInterface;
type NativeCreateSdpObserverHandle = crate::jsep::ffi::NativeCreateSdpObserverHandle;
type NativeSetLocalSdpObserverHandle = crate::jsep::ffi::NativeSetLocalSdpObserverHandle;
type NativeSetRemoteSdpObserverHandle = crate::jsep::ffi::NativeSetRemoteSdpObserverHandle;
type SessionDescription = crate::jsep::ffi::SessionDescription;
type NativePeerConnectionObserver;
type PeerConnection;
fn create_offer(self: Pin<&mut PeerConnection>, observer: UniquePtr<NativeCreateSdpObserverHandle>, options: RTCOfferAnswerOptions);
fn create_answer(self: Pin<&mut PeerConnection>, observer: UniquePtr<NativeCreateSdpObserverHandle>, options: RTCOfferAnswerOptions);
fn set_local_description(self: Pin<&mut PeerConnection>, desc: UniquePtr<SessionDescription>, observer: UniquePtr<NativeSetLocalSdpObserverHandle>);
fn set_remote_description(self: Pin<&mut PeerConnection>, desc: UniquePtr<SessionDescription>, observer: UniquePtr<NativeSetRemoteSdpObserverHandle>);
fn close(self: Pin<&mut PeerConnection>);
fn create_native_peer_connection_observer(observer: Box<PeerConnectionObserverWrapper>) -> UniquePtr<NativePeerConnectionObserver>;
fn _unique_peer_connection() -> UniquePtr<PeerConnection>; // Ignore
}
extern "Rust" {
type PeerConnectionObserverWrapper;
fn on_signaling_change(self: &mut PeerConnectionObserverWrapper, new_state: SignalingState);
fn on_add_stream(self: &mut PeerConnectionObserverWrapper, stream: UniquePtr<MediaStreamInterface>);
fn on_remove_stream(self: &mut PeerConnectionObserverWrapper, stream: UniquePtr<MediaStreamInterface>);
fn on_data_channel(self: &mut PeerConnectionObserverWrapper, data_channel: UniquePtr<DataChannel>);
fn on_renegotiation_needed(self: &mut PeerConnectionObserverWrapper);
fn on_negotiation_needed_event(self: &mut PeerConnectionObserverWrapper, event: u32);
fn on_ice_connection_change(self: &mut PeerConnectionObserverWrapper, new_state: IceConnectionState);
fn on_standardized_ice_connection_change(self: &mut PeerConnectionObserverWrapper, new_state: IceConnectionState);
fn on_connection_change(self: &mut PeerConnectionObserverWrapper, new_state: PeerConnectionState);
fn on_ice_gathering_change(self: &mut PeerConnectionObserverWrapper, new_state: IceGatheringState);
fn on_ice_candidate(self: &mut PeerConnectionObserverWrapper, candidate: UniquePtr<IceCandidate>);
fn on_ice_candidate_error(self: &mut PeerConnectionObserverWrapper, address: String, port: i32, url: String, error_code: i32, error_text: String);
fn on_ice_candidates_removed(self: &mut PeerConnectionObserverWrapper, removed: Vec<CandidatePtr>);
fn on_ice_connection_receiving_change(self: &mut PeerConnectionObserverWrapper, receiving: bool);
fn on_ice_selected_candidate_pair_changed(self: &mut PeerConnectionObserverWrapper, event: CandidatePairChangeEvent);
fn on_add_track(self: &mut PeerConnectionObserverWrapper, receiver: UniquePtr<RtpReceiver>, streams: Vec<MediaStreamPtr>);
fn on_track(self: &mut PeerConnectionObserverWrapper, transceiver: UniquePtr<RtpTransceiver>);
fn on_remove_track(self: &mut PeerConnectionObserverWrapper, receiver: UniquePtr<RtpReceiver>);
fn on_interesting_usage(self: &mut PeerConnectionObserverWrapper, usage_pattern: i32);
}
}
// https://webrtc.github.io/webrtc-org/native-code/native-apis/
unsafe impl Sync for ffi::PeerConnection {}
unsafe impl Send for ffi::PeerConnection {}
impl Default for ffi::RTCOfferAnswerOptions {
/*
static const int kUndefined = -1;
static const int kMaxOfferToReceiveMedia = 1;
static const int kOfferToReceiveMediaTrue = 1;
*/
fn default() -> Self {
Self {
offer_to_receive_video: -1,
offer_to_receive_audio: -1,
voice_activity_detection: true,
ice_restart: false,
use_rtp_mux: true,
raw_packetization_for_video: false,
num_simulcast_layers: 1,
use_obsolete_sctp_sdp: false
}
}
}
pub trait PeerConnectionObserver: Send + Sync {
fn on_signaling_change(&mut self, new_state: ffi::SignalingState);
fn on_add_stream(&mut self, stream: UniquePtr<MediaStreamInterface>);
fn on_remove_stream(&mut self, stream: UniquePtr<MediaStreamInterface>);
fn on_data_channel(&mut self, data_channel: UniquePtr<DataChannel>);
fn on_renegotiation_needed(&mut self);
fn on_negotiation_needed_event(&mut self, event: u32);
fn on_ice_connection_change(&mut self, new_state: ffi::IceConnectionState);
fn on_standardized_ice_connection_change(&mut self, new_state: ffi::IceConnectionState);
fn on_connection_change(&mut self, new_state: ffi::PeerConnectionState);
fn on_ice_gathering_change(&mut self, new_state: ffi::IceGatheringState);
fn on_ice_candidate(&mut self, candidate: UniquePtr<IceCandidate>);
fn on_ice_candidate_error(&mut self, address: String, port: i32, url: String, error_code: i32, error_text: String);
fn on_ice_candidates_removed(&mut self, removed: Vec<UniquePtr<Candidate>>);
fn on_ice_connection_receiving_change(&mut self, receiving: bool);
fn on_ice_selected_candidate_pair_changed(&mut self, event: ffi::CandidatePairChangeEvent);
fn on_add_track(&mut self, receiver: UniquePtr<RtpReceiver>, streams: Vec<UniquePtr<MediaStreamInterface>>);
fn on_track(&mut self, transceiver: UniquePtr<RtpTransceiver>);
fn on_remove_track(&mut self, receiver: UniquePtr<RtpReceiver>);
fn on_interesting_usage(&mut self, usage_pattern: i32);
}
pub struct PeerConnectionObserverWrapper {
observer: Box<dyn PeerConnectionObserver>,
}
impl PeerConnectionObserverWrapper {
pub fn new(observer: Box<dyn PeerConnectionObserver>) -> Self {
Self {
observer
}
}
fn on_signaling_change(&mut self, new_state: ffi::SignalingState) {
self.observer.on_signaling_change(new_state);
}
fn on_add_stream(&mut self, stream: UniquePtr<MediaStreamInterface>) {
self.observer.on_add_stream(stream);
}
fn on_remove_stream(&mut self, stream: UniquePtr<MediaStreamInterface>) {
self.observer.on_remove_stream(stream);
}
fn on_data_channel(&mut self, data_channel: UniquePtr<DataChannel>) {
self.observer.on_data_channel(data_channel);
}
fn on_renegotiation_needed(&mut self) {
self.observer.on_renegotiation_needed();
}
fn on_negotiation_needed_event(&mut self, event: u32) {
self.observer.on_negotiation_needed_event(event);
}
fn on_ice_connection_change(&mut self, new_state: ffi::IceConnectionState) {
self.observer.on_ice_connection_change(new_state);
}
fn on_standardized_ice_connection_change(&mut self, new_state: ffi::IceConnectionState) {
self.observer.on_standardized_ice_connection_change(new_state);
}
fn on_connection_change(&mut self, new_state: ffi::PeerConnectionState) {
self.observer.on_connection_change(new_state);
}
fn on_ice_gathering_change(&mut self, new_state: ffi::IceGatheringState) {
self.observer.on_ice_gathering_change(new_state);
}
fn on_ice_candidate(&mut self, candidate: UniquePtr<IceCandidate>) {
self.observer.on_ice_candidate(candidate);
}
fn on_ice_candidate_error(&mut self, address: String, port: i32, url: String, error_code: i32, error_text: String) {
self.observer.on_ice_candidate_error(address, port, url, error_code, error_text);
}
fn on_ice_candidates_removed(&mut self, removed: Vec<ffi::CandidatePtr>) {
let mut vec = Vec::new();
for v in removed {
vec.push(v.ptr);
}
self.observer.on_ice_candidates_removed(vec);
}
fn on_ice_connection_receiving_change(&mut self, receiving: bool) {
self.observer.on_ice_connection_receiving_change(receiving);
}
fn on_ice_selected_candidate_pair_changed(&mut self, event: ffi::CandidatePairChangeEvent) {
self.observer.on_ice_selected_candidate_pair_changed(event);
}
fn on_add_track(&mut self, receiver: UniquePtr<RtpReceiver>, streams: Vec<ffi::MediaStreamPtr>) {
let mut vec = Vec::new();
for v in streams {
vec.push(v.ptr);
}
self.observer.on_add_track(receiver, vec);
}
fn on_track(&mut self, transceiver: UniquePtr<RtpTransceiver>) {
self.observer.on_track(transceiver);
}
fn on_remove_track(&mut self, receiver: UniquePtr<RtpReceiver>) {
self.observer.on_remove_track(receiver);
}
fn on_interesting_usage(&mut self, usage_pattern: i32) {
self.observer.on_interesting_usage(usage_pattern);
}
}
@@ -0,0 +1,87 @@
//
// Created by Théo Monnom on 03/08/2022.
//
#include "livekit/peer_connection_factory.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "media/engine/webrtc_media_engine.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
#include "libwebrtc-sys/src/peer_connection_factory.rs.h"
namespace livekit{
PeerConnectionFactory::PeerConnectionFactory(){
rtc::LogMessage::LogToDebug(rtc::LS_INFO);
RTC_LOG(LS_INFO) << "PeerConnectionFactory::PeerConnectionFactory()";
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();
webrtc::PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = network_thread_.get();
dependencies.worker_thread = worker_thread_.get();
dependencies.signaling_thread = signaling_thread_.get();
dependencies.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
dependencies.event_log_factory = std::make_unique<webrtc::RtcEventLogFactory>(dependencies.task_queue_factory.get());
cricket::MediaEngineDependencies media_deps;
media_deps.task_queue_factory = dependencies.task_queue_factory.get();
media_deps.video_encoder_factory = webrtc::CreateBuiltinVideoEncoderFactory();
media_deps.video_decoder_factory = webrtc::CreateBuiltinVideoDecoderFactory();
media_deps.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
media_deps.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
peer_factory_ = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
if (peer_factory_.get() == nullptr) {
RTC_LOG_ERR(LS_ERROR) << "Failed to create PeerConnectionFactory";
return;
}
}
std::unique_ptr<PeerConnection> PeerConnectionFactory::create_peer_connection(std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config, std::unique_ptr<NativePeerConnectionObserver> observer) const {
webrtc::PeerConnectionDependencies deps{observer.get()};
auto result = peer_factory_->CreatePeerConnectionOrError(*config, std::move(deps));
if(!result.ok()){
throw std::runtime_error(result.error().message()); // TODO(theomonnom) Bridge RTCError - Mb use ProtoBuf
}
return std::make_unique<PeerConnection>(std::move(result.value()), std::move(observer));
}
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory() {
return std::make_unique<PeerConnectionFactory>();
}
std::unique_ptr<NativeRTCConfiguration> create_rtc_configuration(RTCConfiguration conf){
auto rtc = std::make_unique<webrtc::PeerConnectionInterface::RTCConfiguration>();
for (auto &item: conf.ice_servers){
webrtc::PeerConnectionInterface::IceServer ice_server;
ice_server.username = item.username.c_str();
ice_server.password = item.password.c_str();
for (auto &url: item.urls){
ice_server.urls.push_back(url.c_str());
}
rtc->servers.push_back(ice_server);
}
return rtc;
}
} // namespace lk
@@ -0,0 +1,186 @@
use std::any::Any;
use std::thread::sleep;
use std::time::Duration;
use cxx::UniquePtr;
use log::info;
use crate::candidate::ffi::Candidate;
use crate::data_channel::ffi::DataChannel;
use crate::jsep::ffi::IceCandidate;
use crate::media_stream_interface::ffi::MediaStreamInterface;
use crate::{jsep, peer_connection};
use crate::jsep::CreateSdpObserver;
use crate::peer_connection::ffi::{CandidatePairChangeEvent, IceConnectionState, IceGatheringState, PeerConnectionState, SignalingState};
use crate::peer_connection::PeerConnectionObserver;
use crate::rtp_receiver::ffi::RtpReceiver;
use crate::rtp_transceiver::ffi::RtpTransceiver;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
#[derive(Debug, Clone)]
pub struct ICEServer {
urls: Vec<String>,
username: String,
password: String,
}
#[derive(Debug)]
pub struct RTCConfiguration {
pub ice_servers: Vec<ICEServer>,
}
unsafe extern "C++" {
include!("livekit/peer_connection_factory.h");
type PeerConnection = crate::peer_connection::ffi::PeerConnection;
type NativePeerConnectionObserver = crate::peer_connection::ffi::NativePeerConnectionObserver;
type PeerConnectionFactory;
type NativeRTCConfiguration;
fn create_peer_connection_factory() -> UniquePtr<PeerConnectionFactory>;
fn create_rtc_configuration(conf: RTCConfiguration) -> UniquePtr<NativeRTCConfiguration>;
unsafe fn create_peer_connection(self: &PeerConnectionFactory, config: UniquePtr<NativeRTCConfiguration>, observer: UniquePtr<NativePeerConnectionObserver>) -> Result<UniquePtr<PeerConnection>>;
}
}
#[cfg(test)]
mod test {
struct TestObserver {
}
impl PeerConnectionObserver for TestObserver {
fn on_signaling_change(&self, new_state: SignalingState) {
log::debug!("Signaling state changed: {:?}", new_state);
}
fn on_add_stream(&self, stream: UniquePtr<MediaStreamInterface>) {
todo!()
}
fn on_remove_stream(&self, stream: UniquePtr<MediaStreamInterface>) {
todo!()
}
fn on_data_channel(&self, data_channel: UniquePtr<DataChannel>) {
todo!()
}
fn on_renegotiation_needed(&self) {
todo!()
}
fn on_negotiation_needed_event(&self, event: u32) {
todo!()
}
fn on_ice_connection_change(&self, new_state: IceConnectionState) {
log::debug!("ICE connection state changed: {:?}", new_state);
}
fn on_standardized_ice_connection_change(&self, new_state: IceConnectionState) {
todo!()
}
fn on_connection_change(&self, new_state: PeerConnectionState) {
log::debug!("PeerConnection state changed: {:?}", new_state);
}
fn on_ice_gathering_change(&self, new_state: IceGatheringState) {
todo!()
}
fn on_ice_candidate(&self, candidate: UniquePtr<IceCandidate>) {
todo!()
}
fn on_ice_candidate_error(&self, address: String, port: i32, url: String, error_code: i32, error_text: String) {
todo!()
}
fn on_ice_candidates_removed(&self, removed: Vec<UniquePtr<Candidate>>) {
todo!()
}
fn on_ice_connection_receiving_change(&self, receiving: bool) {
todo!()
}
fn on_ice_selected_candidate_pair_changed(&self, event: CandidatePairChangeEvent) {
todo!()
}
fn on_add_track(&self, receiver: UniquePtr<RtpReceiver>, streams: Vec<UniquePtr<MediaStreamInterface>>) {
todo!()
}
fn on_track(&self, transceiver: UniquePtr<RtpTransceiver>) {
todo!()
}
fn on_remove_track(&self, receiver: UniquePtr<RtpReceiver>) {
todo!()
}
fn on_interesting_usage(&self, usage_pattern: i32) {
todo!()
}
}
struct SessionObserver {
}
impl CreateSdpObserver for SessionObserver {
fn on_success(&self, session_description: UniquePtr<crate::jsep::ffi::SessionDescription>) {
info!("on_success");
}
fn on_failure(&self, error: UniquePtr<crate::rtc_error::ffi::RTCError>) {
info!("on_failure");
}
}
#[test]
fn create_pc_test() {
env_logger::init();
let factory = ffi::create_peer_connection_factory(); // Default factory config is defined on the c++ side atm
unsafe {
let mut pc = factory.create_peer_connection(ffi::create_rtc_configuration(ffi::RTCConfiguration {
ice_servers: vec![ffi::ICEServer {
urls: vec!["stun:stun.l.google.com:19302".to_string()],
username: "".to_string(),
password: "".to_string(),
}],
}), peer_connection::ffi::create_native_peer_connection_observer(Box::new(peer_connection::PeerConnectionObserverWrapper::new(Box::new(TestObserver{}))))).unwrap();
let options = peer_connection::ffi::RTCOfferAnswerOptions::default();
let sdp_observer = jsep::ffi::create_native_create_sdp_observer(Box::new(jsep::CreateSdpObserverWrapper::new(Box::new(SessionObserver{}))));
pc.pin_mut().create_offer(sdp_observer, options);
sleep(Duration::from_secs(2));
pc.pin_mut().close();
}
}
}
@@ -0,0 +1,11 @@
//
// Created by theom on 04/09/2022.
//
#include "livekit/rtc_error.h"
namespace livekit {
RTCError::RTCError(webrtc::RTCError error) : rtc_error_(std::move(error)) {
}
} // livekit
@@ -0,0 +1,13 @@
// TODO(theomonnom) Don't use RTCError as Opaque. I should use a Struct and serialize/deserialize when needed for Result<>
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
unsafe extern "C++" {
include!("livekit/rtc_error.h");
type RTCError;
fn _unique_rtc_error() -> UniquePtr<RTCError>;
}
}
@@ -0,0 +1,11 @@
//
// Created by Théo Monnom on 01/09/2022.
//
#include "livekit/rtp_receiver.h"
namespace livekit {
RtpReceiver::RtpReceiver(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) : receiver_(std::move(receiver)) {
}
} // livekit
@@ -0,0 +1,12 @@
use cxx::UniquePtr;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
unsafe extern "C++" {
include!("livekit/rtp_receiver.h");
type RtpReceiver;
fn _unique_rtp_receiver() -> UniquePtr<RtpReceiver>; // Ignore
}
}
@@ -0,0 +1,11 @@
//
// Created by Théo Monnom on 02/09/2022.
//
#include "livekit/rtp_transceiver.h"
namespace livekit {
RtpTransceiver::RtpTransceiver(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) : transceiver_(std::move(transceiver)) {
}
} // livekit
@@ -0,0 +1,12 @@
use cxx::UniquePtr;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
unsafe extern "C++" {
include!("livekit/rtp_transceiver.h");
type RtpTransceiver;
fn _unique_rtp_transceiver() -> UniquePtr<RtpTransceiver>; // Ignore
}
}