Windows + Initial WebRTC sys & Safe WebRTC + Initial livekit-core
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user