webrtc_sys/
peer_connection_factory.rs

1// Copyright 2025 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::Arc;
16
17use cxx::SharedPtr;
18
19use crate::{
20    candidate::ffi::Candidate, data_channel::ffi::DataChannel, impl_thread_safety,
21    jsep::ffi::IceCandidate, media_stream::ffi::MediaStream, rtp_receiver::ffi::RtpReceiver,
22    rtp_transceiver::ffi::RtpTransceiver,
23};
24
25#[cxx::bridge(namespace = "livekit_ffi")]
26pub mod ffi {
27    pub struct CandidatePair {
28        local: SharedPtr<Candidate>,
29        remote: SharedPtr<Candidate>,
30    }
31
32    pub struct CandidatePairChangeEvent {
33        selected_candidate_pair: CandidatePair,
34        last_data_received_ms: i64,
35        reason: String,
36        estimated_disconnected_time_ms: i64,
37    }
38
39    extern "C++" {
40        include!("livekit/rtp_parameters.h");
41        include!("livekit/rtc_error.h");
42        include!("livekit/helper.h");
43        include!("livekit/candidate.h");
44        include!("livekit/media_stream.h");
45        include!("livekit/rtp_transceiver.h");
46        include!("livekit/rtp_sender.h");
47        include!("livekit/rtp_receiver.h");
48        include!("livekit/data_channel.h");
49        include!("livekit/jsep.h");
50        include!("livekit/webrtc.h");
51        include!("livekit/peer_connection.h");
52        include!("livekit/audio_track.h");
53
54        type RtcConfiguration = crate::peer_connection::ffi::RtcConfiguration;
55        type PeerConnectionState = crate::peer_connection::ffi::PeerConnectionState;
56        type SignalingState = crate::peer_connection::ffi::SignalingState;
57        type IceConnectionState = crate::peer_connection::ffi::IceConnectionState;
58        type IceGatheringState = crate::peer_connection::ffi::IceGatheringState;
59        type AudioTrackSource = crate::audio_track::ffi::AudioTrackSource;
60        type VideoTrackSource = crate::video_track::ffi::VideoTrackSource;
61        type RtpCapabilities = crate::rtp_parameters::ffi::RtpCapabilities;
62        type AudioTrack = crate::audio_track::ffi::AudioTrack;
63        type VideoTrack = crate::video_track::ffi::VideoTrack;
64        type MediaStreamPtr = crate::helper::ffi::MediaStreamPtr;
65        type CandidatePtr = crate::helper::ffi::CandidatePtr;
66        type RtpSenderPtr = crate::helper::ffi::RtpSenderPtr;
67        type RtpReceiverPtr = crate::helper::ffi::RtpReceiverPtr;
68        type RtpTransceiverPtr = crate::helper::ffi::RtpTransceiverPtr;
69        type RtcError = crate::rtc_error::ffi::RtcError;
70        type Candidate = crate::candidate::ffi::Candidate;
71        type IceCandidate = crate::jsep::ffi::IceCandidate;
72        type DataChannel = crate::data_channel::ffi::DataChannel;
73        type DataChannelInit = crate::data_channel::ffi::DataChannelInit;
74        type RtpSender = crate::rtp_sender::ffi::RtpSender;
75        type RtpReceiver = crate::rtp_receiver::ffi::RtpReceiver;
76        type RtpTransceiver = crate::rtp_transceiver::ffi::RtpTransceiver;
77        type RtpTransceiverInit = crate::rtp_transceiver::ffi::RtpTransceiverInit;
78        type MediaStream = crate::media_stream::ffi::MediaStream;
79        type MediaStreamTrack = crate::media_stream::ffi::MediaStreamTrack;
80        type SessionDescription = crate::jsep::ffi::SessionDescription;
81        type MediaType = crate::webrtc::ffi::MediaType;
82    }
83
84    unsafe extern "C++" {
85        include!("livekit/peer_connection_factory.h");
86
87        type PeerConnection = crate::peer_connection::ffi::PeerConnection;
88        type PeerConnectionFactory;
89
90        fn create_peer_connection_factory() -> SharedPtr<PeerConnectionFactory>;
91
92        fn create_peer_connection(
93            self: &PeerConnectionFactory,
94            config: RtcConfiguration,
95            observer: Box<PeerConnectionObserverWrapper>,
96        ) -> Result<SharedPtr<PeerConnection>>;
97
98        fn create_video_track(
99            self: &PeerConnectionFactory,
100            label: String,
101            source: SharedPtr<VideoTrackSource>,
102        ) -> SharedPtr<VideoTrack>;
103
104        fn create_audio_track(
105            self: &PeerConnectionFactory,
106            label: String,
107            source: SharedPtr<AudioTrackSource>,
108        ) -> SharedPtr<AudioTrack>;
109
110        fn rtp_sender_capabilities(
111            self: &PeerConnectionFactory,
112            kind: MediaType,
113        ) -> RtpCapabilities;
114
115        fn rtp_receiver_capabilities(
116            self: &PeerConnectionFactory,
117            kind: MediaType,
118        ) -> RtpCapabilities;
119    }
120
121    extern "Rust" {
122        type PeerConnectionObserverWrapper;
123
124        fn on_signaling_change(self: &PeerConnectionObserverWrapper, new_state: SignalingState);
125        fn on_add_stream(self: &PeerConnectionObserverWrapper, stream: SharedPtr<MediaStream>);
126        fn on_remove_stream(self: &PeerConnectionObserverWrapper, stream: SharedPtr<MediaStream>);
127        fn on_data_channel(
128            self: &PeerConnectionObserverWrapper,
129            data_channel: SharedPtr<DataChannel>,
130        );
131        fn on_renegotiation_needed(self: &PeerConnectionObserverWrapper);
132        fn on_negotiation_needed_event(self: &PeerConnectionObserverWrapper, event: u32);
133        fn on_ice_connection_change(
134            self: &PeerConnectionObserverWrapper,
135            new_state: IceConnectionState,
136        );
137        fn on_standardized_ice_connection_change(
138            self: &PeerConnectionObserverWrapper,
139            new_state: IceConnectionState,
140        );
141        fn on_connection_change(
142            self: &PeerConnectionObserverWrapper,
143            new_state: PeerConnectionState,
144        );
145        fn on_ice_gathering_change(
146            self: &PeerConnectionObserverWrapper,
147            new_state: IceGatheringState,
148        );
149        fn on_ice_candidate(
150            self: &PeerConnectionObserverWrapper,
151            candidate: SharedPtr<IceCandidate>,
152        );
153        fn on_ice_candidate_error(
154            self: &PeerConnectionObserverWrapper,
155            address: String,
156            port: i32,
157            url: String,
158            error_code: i32,
159            error_text: String,
160        );
161        fn on_ice_candidates_removed(
162            self: &PeerConnectionObserverWrapper,
163            removed: Vec<CandidatePtr>,
164        );
165        fn on_ice_connection_receiving_change(
166            self: &PeerConnectionObserverWrapper,
167            receiving: bool,
168        );
169        fn on_ice_selected_candidate_pair_changed(
170            self: &PeerConnectionObserverWrapper,
171            event: CandidatePairChangeEvent,
172        );
173        fn on_add_track(
174            self: &PeerConnectionObserverWrapper,
175            receiver: SharedPtr<RtpReceiver>,
176            streams: Vec<MediaStreamPtr>,
177        );
178        fn on_track(self: &PeerConnectionObserverWrapper, transceiver: SharedPtr<RtpTransceiver>);
179        fn on_remove_track(self: &PeerConnectionObserverWrapper, receiver: SharedPtr<RtpReceiver>);
180        fn on_interesting_usage(self: &PeerConnectionObserverWrapper, usage_pattern: i32);
181    }
182}
183
184impl_thread_safety!(ffi::PeerConnectionFactory, Send + Sync);
185
186pub trait PeerConnectionObserver: Send + Sync {
187    fn on_signaling_change(&self, new_state: ffi::SignalingState);
188    fn on_add_stream(&self, stream: SharedPtr<MediaStream>);
189    fn on_remove_stream(&self, stream: SharedPtr<MediaStream>);
190    fn on_data_channel(&self, data_channel: SharedPtr<DataChannel>);
191    fn on_renegotiation_needed(&self);
192    fn on_negotiation_needed_event(&self, event: u32);
193    fn on_ice_connection_change(&self, new_state: ffi::IceConnectionState);
194    fn on_standardized_ice_connection_change(&self, new_state: ffi::IceConnectionState);
195    fn on_connection_change(&self, new_state: ffi::PeerConnectionState);
196    fn on_ice_gathering_change(&self, new_state: ffi::IceGatheringState);
197    fn on_ice_candidate(&self, candidate: SharedPtr<IceCandidate>);
198    fn on_ice_candidate_error(
199        &self,
200        address: String,
201        port: i32,
202        url: String,
203        error_code: i32,
204        error_text: String,
205    );
206    fn on_ice_candidates_removed(&self, removed: Vec<SharedPtr<Candidate>>);
207    fn on_ice_connection_receiving_change(&self, receiving: bool);
208    fn on_ice_selected_candidate_pair_changed(&self, event: ffi::CandidatePairChangeEvent);
209    fn on_add_track(&self, receiver: SharedPtr<RtpReceiver>, streams: Vec<SharedPtr<MediaStream>>);
210    fn on_track(&self, transceiver: SharedPtr<RtpTransceiver>);
211    fn on_remove_track(&self, receiver: SharedPtr<RtpReceiver>);
212    fn on_interesting_usage(&self, usage_pattern: i32);
213}
214
215// Wrapper for PeerConnectionObserver because cxx doesn't support dyn Trait on c++
216// https://github.com/dtolnay/cxx/issues/665
217pub struct PeerConnectionObserverWrapper {
218    observer: Arc<dyn PeerConnectionObserver>,
219}
220
221impl PeerConnectionObserverWrapper {
222    pub fn new(observer: Arc<dyn PeerConnectionObserver>) -> Self {
223        Self { observer }
224    }
225
226    fn on_signaling_change(&self, new_state: ffi::SignalingState) {
227        self.observer.on_signaling_change(new_state);
228    }
229
230    fn on_add_stream(&self, stream: SharedPtr<MediaStream>) {
231        self.observer.on_add_stream(stream);
232    }
233
234    fn on_remove_stream(&self, stream: SharedPtr<MediaStream>) {
235        self.observer.on_remove_stream(stream);
236    }
237
238    fn on_data_channel(&self, data_channel: SharedPtr<DataChannel>) {
239        self.observer.on_data_channel(data_channel);
240    }
241
242    fn on_renegotiation_needed(&self) {
243        self.observer.on_renegotiation_needed();
244    }
245
246    fn on_negotiation_needed_event(&self, event: u32) {
247        self.observer.on_negotiation_needed_event(event);
248    }
249
250    fn on_ice_connection_change(&self, new_state: ffi::IceConnectionState) {
251        self.observer.on_ice_connection_change(new_state);
252    }
253
254    fn on_standardized_ice_connection_change(&self, new_state: ffi::IceConnectionState) {
255        self.observer.on_standardized_ice_connection_change(new_state);
256    }
257
258    fn on_connection_change(&self, new_state: ffi::PeerConnectionState) {
259        self.observer.on_connection_change(new_state);
260    }
261
262    fn on_ice_gathering_change(&self, new_state: ffi::IceGatheringState) {
263        self.observer.on_ice_gathering_change(new_state);
264    }
265
266    fn on_ice_candidate(&self, candidate: SharedPtr<IceCandidate>) {
267        self.observer.on_ice_candidate(candidate);
268    }
269
270    fn on_ice_candidate_error(
271        &self,
272        address: String,
273        port: i32,
274        url: String,
275        error_code: i32,
276        error_text: String,
277    ) {
278        self.observer.on_ice_candidate_error(address, port, url, error_code, error_text);
279    }
280
281    fn on_ice_candidates_removed(&self, candidates: Vec<ffi::CandidatePtr>) {
282        self.observer.on_ice_candidates_removed(candidates.into_iter().map(|v| v.ptr).collect());
283    }
284
285    fn on_ice_connection_receiving_change(&self, receiving: bool) {
286        self.observer.on_ice_connection_receiving_change(receiving);
287    }
288
289    fn on_ice_selected_candidate_pair_changed(&self, event: ffi::CandidatePairChangeEvent) {
290        self.observer.on_ice_selected_candidate_pair_changed(event);
291    }
292
293    fn on_add_track(&self, receiver: SharedPtr<RtpReceiver>, streams: Vec<ffi::MediaStreamPtr>) {
294        self.observer.on_add_track(receiver, streams.into_iter().map(|v| v.ptr).collect());
295    }
296
297    fn on_track(&self, transceiver: SharedPtr<RtpTransceiver>) {
298        self.observer.on_track(transceiver);
299    }
300
301    fn on_remove_track(&self, receiver: SharedPtr<RtpReceiver>) {
302        self.observer.on_remove_track(receiver);
303    }
304
305    fn on_interesting_usage(&self, usage_pattern: i32) {
306        self.observer.on_interesting_usage(usage_pattern);
307    }
308}