Skip to main content

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
15pub use cxx::SharedPtr;
16
17use std::sync::Arc;
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        // Create an audio track that uses the ADM for capture (Platform ADM mode)
111        fn create_device_audio_track(
112            self: &PeerConnectionFactory,
113            label: String,
114        ) -> SharedPtr<AudioTrack>;
115
116        fn rtp_sender_capabilities(
117            self: &PeerConnectionFactory,
118            kind: MediaType,
119        ) -> RtpCapabilities;
120
121        fn rtp_receiver_capabilities(
122            self: &PeerConnectionFactory,
123            kind: MediaType,
124        ) -> RtpCapabilities;
125    }
126
127    extern "Rust" {
128        type PeerConnectionObserverWrapper;
129
130        fn on_signaling_change(self: &PeerConnectionObserverWrapper, new_state: SignalingState);
131        fn on_add_stream(self: &PeerConnectionObserverWrapper, stream: SharedPtr<MediaStream>);
132        fn on_remove_stream(self: &PeerConnectionObserverWrapper, stream: SharedPtr<MediaStream>);
133        fn on_data_channel(
134            self: &PeerConnectionObserverWrapper,
135            data_channel: SharedPtr<DataChannel>,
136        );
137        fn on_renegotiation_needed(self: &PeerConnectionObserverWrapper);
138        fn on_negotiation_needed_event(self: &PeerConnectionObserverWrapper, event: u32);
139        fn on_ice_connection_change(
140            self: &PeerConnectionObserverWrapper,
141            new_state: IceConnectionState,
142        );
143        fn on_standardized_ice_connection_change(
144            self: &PeerConnectionObserverWrapper,
145            new_state: IceConnectionState,
146        );
147        fn on_connection_change(
148            self: &PeerConnectionObserverWrapper,
149            new_state: PeerConnectionState,
150        );
151        fn on_ice_gathering_change(
152            self: &PeerConnectionObserverWrapper,
153            new_state: IceGatheringState,
154        );
155        fn on_ice_candidate(
156            self: &PeerConnectionObserverWrapper,
157            candidate: SharedPtr<IceCandidate>,
158        );
159        fn on_ice_candidate_error(
160            self: &PeerConnectionObserverWrapper,
161            address: String,
162            port: i32,
163            url: String,
164            error_code: i32,
165            error_text: String,
166        );
167        fn on_ice_candidates_removed(
168            self: &PeerConnectionObserverWrapper,
169            removed: Vec<CandidatePtr>,
170        );
171        fn on_ice_connection_receiving_change(
172            self: &PeerConnectionObserverWrapper,
173            receiving: bool,
174        );
175        fn on_ice_selected_candidate_pair_changed(
176            self: &PeerConnectionObserverWrapper,
177            event: CandidatePairChangeEvent,
178        );
179        fn on_add_track(
180            self: &PeerConnectionObserverWrapper,
181            receiver: SharedPtr<RtpReceiver>,
182            streams: Vec<MediaStreamPtr>,
183        );
184        fn on_track(self: &PeerConnectionObserverWrapper, transceiver: SharedPtr<RtpTransceiver>);
185        fn on_remove_track(self: &PeerConnectionObserverWrapper, receiver: SharedPtr<RtpReceiver>);
186        fn on_interesting_usage(self: &PeerConnectionObserverWrapper, usage_pattern: i32);
187    }
188}
189
190impl_thread_safety!(ffi::PeerConnectionFactory, Send + Sync);
191
192pub trait PeerConnectionObserver: Send + Sync {
193    fn on_signaling_change(&self, new_state: ffi::SignalingState);
194    fn on_add_stream(&self, stream: SharedPtr<MediaStream>);
195    fn on_remove_stream(&self, stream: SharedPtr<MediaStream>);
196    fn on_data_channel(&self, data_channel: SharedPtr<DataChannel>);
197    fn on_renegotiation_needed(&self);
198    fn on_negotiation_needed_event(&self, event: u32);
199    fn on_ice_connection_change(&self, new_state: ffi::IceConnectionState);
200    fn on_standardized_ice_connection_change(&self, new_state: ffi::IceConnectionState);
201    fn on_connection_change(&self, new_state: ffi::PeerConnectionState);
202    fn on_ice_gathering_change(&self, new_state: ffi::IceGatheringState);
203    fn on_ice_candidate(&self, candidate: SharedPtr<IceCandidate>);
204    fn on_ice_candidate_error(
205        &self,
206        address: String,
207        port: i32,
208        url: String,
209        error_code: i32,
210        error_text: String,
211    );
212    fn on_ice_candidates_removed(&self, removed: Vec<SharedPtr<Candidate>>);
213    fn on_ice_connection_receiving_change(&self, receiving: bool);
214    fn on_ice_selected_candidate_pair_changed(&self, event: ffi::CandidatePairChangeEvent);
215    fn on_add_track(&self, receiver: SharedPtr<RtpReceiver>, streams: Vec<SharedPtr<MediaStream>>);
216    fn on_track(&self, transceiver: SharedPtr<RtpTransceiver>);
217    fn on_remove_track(&self, receiver: SharedPtr<RtpReceiver>);
218    fn on_interesting_usage(&self, usage_pattern: i32);
219}
220
221// Wrapper for PeerConnectionObserver because cxx doesn't support dyn Trait on c++
222// https://github.com/dtolnay/cxx/issues/665
223pub struct PeerConnectionObserverWrapper {
224    observer: Arc<dyn PeerConnectionObserver>,
225}
226
227impl PeerConnectionObserverWrapper {
228    pub fn new(observer: Arc<dyn PeerConnectionObserver>) -> Self {
229        Self { observer }
230    }
231
232    fn on_signaling_change(&self, new_state: ffi::SignalingState) {
233        self.observer.on_signaling_change(new_state);
234    }
235
236    fn on_add_stream(&self, stream: SharedPtr<MediaStream>) {
237        self.observer.on_add_stream(stream);
238    }
239
240    fn on_remove_stream(&self, stream: SharedPtr<MediaStream>) {
241        self.observer.on_remove_stream(stream);
242    }
243
244    fn on_data_channel(&self, data_channel: SharedPtr<DataChannel>) {
245        self.observer.on_data_channel(data_channel);
246    }
247
248    fn on_renegotiation_needed(&self) {
249        self.observer.on_renegotiation_needed();
250    }
251
252    fn on_negotiation_needed_event(&self, event: u32) {
253        self.observer.on_negotiation_needed_event(event);
254    }
255
256    fn on_ice_connection_change(&self, new_state: ffi::IceConnectionState) {
257        self.observer.on_ice_connection_change(new_state);
258    }
259
260    fn on_standardized_ice_connection_change(&self, new_state: ffi::IceConnectionState) {
261        self.observer.on_standardized_ice_connection_change(new_state);
262    }
263
264    fn on_connection_change(&self, new_state: ffi::PeerConnectionState) {
265        self.observer.on_connection_change(new_state);
266    }
267
268    fn on_ice_gathering_change(&self, new_state: ffi::IceGatheringState) {
269        self.observer.on_ice_gathering_change(new_state);
270    }
271
272    fn on_ice_candidate(&self, candidate: SharedPtr<IceCandidate>) {
273        self.observer.on_ice_candidate(candidate);
274    }
275
276    fn on_ice_candidate_error(
277        &self,
278        address: String,
279        port: i32,
280        url: String,
281        error_code: i32,
282        error_text: String,
283    ) {
284        self.observer.on_ice_candidate_error(address, port, url, error_code, error_text);
285    }
286
287    fn on_ice_candidates_removed(&self, candidates: Vec<ffi::CandidatePtr>) {
288        self.observer.on_ice_candidates_removed(candidates.into_iter().map(|v| v.ptr).collect());
289    }
290
291    fn on_ice_connection_receiving_change(&self, receiving: bool) {
292        self.observer.on_ice_connection_receiving_change(receiving);
293    }
294
295    fn on_ice_selected_candidate_pair_changed(&self, event: ffi::CandidatePairChangeEvent) {
296        self.observer.on_ice_selected_candidate_pair_changed(event);
297    }
298
299    fn on_add_track(&self, receiver: SharedPtr<RtpReceiver>, streams: Vec<ffi::MediaStreamPtr>) {
300        self.observer.on_add_track(receiver, streams.into_iter().map(|v| v.ptr).collect());
301    }
302
303    fn on_track(&self, transceiver: SharedPtr<RtpTransceiver>) {
304        self.observer.on_track(transceiver);
305    }
306
307    fn on_remove_track(&self, receiver: SharedPtr<RtpReceiver>) {
308        self.observer.on_remove_track(receiver);
309    }
310
311    fn on_interesting_usage(&self, usage_pattern: i32) {
312        self.observer.on_interesting_usage(usage_pattern);
313    }
314}