@@ -12,10 +12,9 @@ use glib::translate::*;
12
12
use gst:: prelude:: * ;
13
13
use gst:: { BinExt , ElementExt } ;
14
14
use rand:: Rng ;
15
- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
16
- use std:: sync:: Arc ;
15
+ use std:: sync:: { Arc , Mutex } ;
17
16
18
- #[ derive( PartialEq , Eq , Debug ) ]
17
+ #[ derive( PartialEq , PartialOrd , Eq , Debug ) ]
19
18
enum AppState {
20
19
// AppStateUnknown = 0,
21
20
AppStateErr = 1 ,
@@ -31,12 +30,13 @@ enum AppState {
31
30
PeerConnected ,
32
31
PeerCallNegotiating = 4000 ,
33
32
PeerCallStarted ,
34
- PeerCallStopping ,
35
- PeerCallStopped ,
36
33
PeerCallError ,
37
- None ,
38
34
}
39
35
36
+ const STUN_SERVER : & ' static str = "stun-server=stun://stun.l.google.com:19302 " ;
37
+ const RTP_CAPS_OPUS : & ' static str = "application/x-rtp,media=audio,encoding-name=OPUS,payload=" ;
38
+ const RTP_CAPS_VP8 : & ' static str = "application/x-rtp,media=video,encoding-name=VP8,payload=" ;
39
+
40
40
fn check_plugins ( ) -> bool {
41
41
let needed = vec ! [
42
42
"opus" ,
@@ -61,15 +61,15 @@ fn check_plugins() -> bool {
61
61
return ret;
62
62
}
63
63
64
- fn setup_call ( app_state : & Arc < AtomicUsize > , out : & ws:: Sender ) -> AppState {
65
- app_state. store ( AppState :: PeerConnecting as usize , Ordering :: Relaxed ) ;
64
+ fn setup_call ( app_state : & Arc < Mutex < AppState > > , out : & ws:: Sender ) -> AppState {
65
+ * app_state. lock ( ) . unwrap ( ) = AppState :: PeerConnecting ;
66
66
println ! ( "Setting up signalling server call with 1" ) ;
67
67
out. send ( "SESSION 1" ) . unwrap ( ) ;
68
68
return AppState :: PeerConnecting ;
69
69
}
70
70
71
- fn register_with_server ( app_state : & Arc < AtomicUsize > , out : & ws:: Sender ) -> AppState {
72
- app_state. store ( AppState :: ServerRegistering as usize , Ordering :: Relaxed ) ;
71
+ fn register_with_server ( app_state : & Arc < Mutex < AppState > > , out : & ws:: Sender ) -> AppState {
72
+ * app_state. lock ( ) . unwrap ( ) = AppState :: ServerRegistering ;
73
73
let our_id = rand:: thread_rng ( ) . gen_range ( 10 , 10_000 ) ;
74
74
println ! ( "Registering id {} with server" , our_id) ;
75
75
out. send ( format ! ( "HELLO {}" , our_id) ) . unwrap ( ) ;
@@ -85,11 +85,11 @@ fn sdp_message_as_text(offer: gstreamer_webrtc::WebRTCSessionDescription) -> Opt
85
85
}
86
86
87
87
fn send_sdp_offer (
88
- app_state : & Arc < AtomicUsize > ,
88
+ app_state : & Arc < Mutex < AppState > > ,
89
89
offer : gstreamer_webrtc:: WebRTCSessionDescription ,
90
90
out : & ws:: Sender ,
91
91
) {
92
- if app_state. load ( Ordering :: Relaxed ) < ( AppState :: PeerCallNegotiating as usize ) {
92
+ if * app_state. lock ( ) . unwrap ( ) < AppState :: PeerCallNegotiating {
93
93
// TODO signal and cleanup
94
94
panic ! ( "Can't send offer, not in call" ) ;
95
95
} ;
@@ -103,39 +103,32 @@ fn send_sdp_offer(
103
103
}
104
104
105
105
fn on_offer_created (
106
- app_state : & Arc < AtomicUsize > ,
106
+ app_state : & Arc < Mutex < AppState > > ,
107
107
webrtc : gst:: Element ,
108
108
promise : & gst:: Promise ,
109
109
out : & ws:: Sender ,
110
110
) {
111
- assert_eq ! (
112
- app_state. load( Ordering :: Relaxed ) ,
113
- AppState :: PeerCallNegotiating as usize
114
- ) ;
111
+ assert_eq ! ( * app_state. lock( ) . unwrap( ) , AppState :: PeerCallNegotiating ) ;
115
112
let reply = promise. get_reply ( ) . unwrap ( ) ;
116
113
117
114
let offer = reply
118
115
. get_value ( "offer" )
119
116
. unwrap ( )
120
117
. get :: < gstreamer_webrtc:: WebRTCSessionDescription > ( )
121
118
. expect ( "Invalid argument" ) ;
122
- let promise = gst:: Promise :: new ( ) ;
123
119
webrtc
124
- . emit (
125
- "set-local-description" ,
126
- & [ & offer. to_value ( ) , & promise. to_value ( ) ] ,
127
- )
120
+ . emit ( "set-local-description" , & [ & offer, & None :: < gst:: Promise > ] )
128
121
. unwrap ( ) ;
122
+
129
123
send_sdp_offer ( app_state, offer, out)
130
124
}
131
125
132
126
fn on_negotiation_needed (
133
- app_state : & Arc < AtomicUsize > ,
127
+ app_state : & Arc < Mutex < AppState > > ,
134
128
values : & [ glib:: Value ] ,
135
129
out : & ws:: Sender ,
136
130
) -> Option < glib:: Value > {
137
- app_state. store ( AppState :: PeerCallNegotiating as usize , Ordering :: Relaxed ) ;
138
-
131
+ * app_state. lock ( ) . unwrap ( ) = AppState :: PeerCallNegotiating ;
139
132
let webrtc = values[ 0 ] . get :: < gst:: Element > ( ) . expect ( "Invalid argument" ) ;
140
133
let webrtc_clone = webrtc. clone ( ) ;
141
134
let out_clone = out. clone ( ) ;
@@ -145,7 +138,7 @@ fn on_negotiation_needed(
145
138
} ) ;
146
139
let options = gst:: Structure :: new_empty ( "options" ) ;
147
140
webrtc_clone
148
- . emit ( "create-offer" , & [ & options. to_value ( ) , & promise. to_value ( ) ] )
141
+ . emit ( "create-offer" , & [ & options, & promise] )
149
142
. unwrap ( ) ;
150
143
None
151
144
}
@@ -159,24 +152,18 @@ fn handle_media_stream(pad: &gst::Pad, pipe: &gst::Element, convert_name: &str,
159
152
let conv = gst:: ElementFactory :: make ( convert_name, None ) . unwrap ( ) ;
160
153
let sink = gst:: ElementFactory :: make ( sink_name, None ) . unwrap ( ) ;
161
154
155
+ let pipe_bin = pipe. clone ( ) . dynamic_cast :: < gst:: Bin > ( ) . unwrap ( ) ;
156
+
162
157
if convert_name == "audioconvert" {
163
158
let resample = gst:: ElementFactory :: make ( "audioresample" , None ) . unwrap ( ) ;
164
- pipe. clone ( )
165
- . dynamic_cast :: < gst:: Bin > ( )
166
- . unwrap ( )
167
- . add_many ( & [ & q, & conv, & resample, & sink] )
168
- . unwrap ( ) ;
159
+ pipe_bin. add_many ( & [ & q, & conv, & resample, & sink] ) . unwrap ( ) ;
169
160
q. sync_state_with_parent ( ) . unwrap ( ) ;
170
161
conv. sync_state_with_parent ( ) . unwrap ( ) ;
171
162
resample. sync_state_with_parent ( ) . unwrap ( ) ;
172
163
sink. sync_state_with_parent ( ) . unwrap ( ) ;
173
164
gst:: Element :: link_many ( & [ & q, & conv, & resample, & sink] ) . unwrap ( ) ;
174
165
} else {
175
- pipe. clone ( )
176
- . dynamic_cast :: < gst:: Bin > ( )
177
- . unwrap ( )
178
- . add_many ( & [ & q, & conv, & sink] )
179
- . unwrap ( ) ;
166
+ pipe_bin. add_many ( & [ & q, & conv, & sink] ) . unwrap ( ) ;
180
167
q. sync_state_with_parent ( ) . unwrap ( ) ;
181
168
conv. sync_state_with_parent ( ) . unwrap ( ) ;
182
169
sink. sync_state_with_parent ( ) . unwrap ( ) ;
@@ -228,11 +215,11 @@ fn on_incoming_stream(values: &[glib::Value], pipe: &gst::Element) -> Option<gli
228
215
}
229
216
230
217
fn send_ice_candidate_message (
231
- app_state : & Arc < AtomicUsize > ,
218
+ app_state : & Arc < Mutex < AppState > > ,
232
219
values : & [ glib:: Value ] ,
233
220
out : & ws:: Sender ,
234
221
) -> Option < glib:: Value > {
235
- if app_state. load ( Ordering :: Relaxed ) < ( AppState :: PeerCallNegotiating as usize ) {
222
+ if * app_state. lock ( ) . unwrap ( ) < AppState :: PeerCallNegotiating {
236
223
panic ! ( "Can't send ICE, not in call" ) ;
237
224
}
238
225
@@ -249,18 +236,16 @@ fn send_ice_candidate_message(
249
236
None
250
237
}
251
238
252
- fn start_pipeline ( app_state : & Arc < AtomicUsize > , out : & ws:: Sender ) -> gst:: Element {
253
- let pipe = gst:: parse_launch (
254
- "webrtcbin name=sendrecv
255
- stun-server=stun://stun.l.google.com:19302
239
+ fn start_pipeline ( app_state : & Arc < Mutex < AppState > > , out : & ws:: Sender ) -> gst:: Element {
240
+ let pipe = gst:: parse_launch ( & format ! (
241
+ "webrtcbin name=sendrecv {}
256
242
videotestsrc pattern=ball ! videoconvert ! queue ! vp8enc deadline=1 ! rtpvp8pay !
257
- queue !
258
- application/x-rtp,media=video,encoding-name=VP8,payload=96 ! sendrecv.
243
+ queue ! {}96 ! sendrecv.
259
244
audiotestsrc wave=red-noise ! audioconvert ! audioresample ! queue ! opusenc ! rtpopuspay !
260
- queue !
261
- application/x-rtp,media=audio,encoding-name=OPUS,payload=97 ! sendrecv.
245
+ queue ! {}97 ! sendrecv.
262
246
" ,
263
- ) . unwrap ( ) ;
247
+ STUN_SERVER , RTP_CAPS_VP8 , RTP_CAPS_OPUS
248
+ ) ) . unwrap ( ) ;
264
249
265
250
let webrtc = pipe. clone ( )
266
251
. dynamic_cast :: < gst:: Bin > ( )
@@ -292,21 +277,20 @@ fn start_pipeline(app_state: &Arc<AtomicUsize>, out: &ws::Sender) -> gst::Elemen
292
277
} )
293
278
. unwrap ( ) ;
294
279
295
- let ret = pipe. set_state ( gst:: State :: Playing ) ;
296
- assert_ne ! ( ret, gst:: StateChangeReturn :: Failure ) ;
280
+ pipe. set_state ( gst:: State :: Playing ) . into_result ( ) . unwrap ( ) ;
297
281
298
282
return webrtc;
299
283
}
300
284
301
285
struct WsClient {
302
286
out : ws:: Sender ,
303
287
webrtc : Option < gst:: Element > ,
304
- app_state : Arc < AtomicUsize > ,
288
+ app_state : Arc < Mutex < AppState > > ,
305
289
}
306
290
307
291
impl WsClient {
308
292
fn update_state ( & self , state : AppState ) {
309
- self . app_state . store ( state as usize , Ordering :: Relaxed ) ;
293
+ * self . app_state . lock ( ) . unwrap ( ) = state
310
294
}
311
295
}
312
296
@@ -322,7 +306,7 @@ impl ws::Handler for WsClient {
322
306
// Close the connection when we get a response from the server
323
307
let msg_text = msg. into_text ( ) . unwrap ( ) ;
324
308
if msg_text == "HELLO" {
325
- if self . app_state . load ( Ordering :: Relaxed ) != ( AppState :: ServerRegistering as usize ) {
309
+ if * self . app_state . lock ( ) . unwrap ( ) != AppState :: ServerRegistering {
326
310
// TODO: signal and cleanup
327
311
panic ! ( "ERROR: Received HELLO when not registering" ) ;
328
312
}
@@ -331,7 +315,7 @@ impl ws::Handler for WsClient {
331
315
return Ok ( ( ) ) ;
332
316
}
333
317
if msg_text == "SESSION_OK" {
334
- if self . app_state . load ( Ordering :: Relaxed ) != ( AppState :: PeerConnecting as usize ) {
318
+ if * self . app_state . lock ( ) . unwrap ( ) != AppState :: PeerConnecting {
335
319
// TODO: signal and cleanup
336
320
panic ! ( "ERROR: Received SESSION_OK when not calling" ) ;
337
321
}
@@ -342,12 +326,12 @@ impl ws::Handler for WsClient {
342
326
343
327
if msg_text. starts_with ( "ERROR" ) {
344
328
println ! ( "Got error message! {}" , msg_text) ;
345
- let error = match self . app_state . load ( Ordering :: Relaxed ) {
346
- x if x == AppState :: ServerConnecting as usize => AppState :: ServerConnectionError ,
347
- x if x == AppState :: ServerRegistering as usize => AppState :: ServerRegisteringError ,
348
- x if x == AppState :: PeerConnecting as usize => AppState :: PeerConnectionError ,
349
- x if x == AppState :: PeerConnected as usize => AppState :: PeerCallError ,
350
- x if x == AppState :: PeerCallNegotiating as usize => AppState :: PeerCallError ,
329
+ let error = match * self . app_state . lock ( ) . unwrap ( ) {
330
+ AppState :: ServerConnecting => AppState :: ServerConnectionError ,
331
+ AppState :: ServerRegistering => AppState :: ServerRegisteringError ,
332
+ AppState :: PeerConnecting => AppState :: PeerConnectionError ,
333
+ AppState :: PeerConnected => AppState :: PeerCallError ,
334
+ AppState :: PeerCallNegotiating => AppState :: PeerCallError ,
351
335
_ => AppState :: AppStateErr ,
352
336
} ;
353
337
panic ! ( "Got websocket error {:?}" , error) ;
@@ -357,8 +341,8 @@ impl ws::Handler for WsClient {
357
341
let json_msg: serde_json:: Value = serde_json:: from_str ( & msg_text) . unwrap ( ) ;
358
342
if json_msg. get ( "sdp" ) . is_some ( ) {
359
343
assert_eq ! (
360
- self . app_state. load ( Ordering :: Relaxed ) ,
361
- ( AppState :: PeerCallNegotiating as usize )
344
+ * self . app_state. lock ( ) . unwrap ( ) ,
345
+ AppState :: PeerCallNegotiating
362
346
) ;
363
347
364
348
if !json_msg[ "sdp" ] . get ( "type" ) . is_some ( ) {
@@ -380,10 +364,7 @@ impl ws::Handler for WsClient {
380
364
self . webrtc
381
365
. as_ref ( )
382
366
. unwrap ( )
383
- . emit (
384
- "set-remote-description" ,
385
- & [ & answer. to_value ( ) , & promise. to_value ( ) ] ,
386
- )
367
+ . emit ( "set-remote-description" , & [ & answer, & promise] )
387
368
. unwrap ( ) ;
388
369
self . update_state ( AppState :: PeerCallStarted ) ;
389
370
}
@@ -393,10 +374,7 @@ impl ws::Handler for WsClient {
393
374
self . webrtc
394
375
. as_ref ( )
395
376
. unwrap ( )
396
- . emit (
397
- "add-ice-candidate" ,
398
- & [ & sdpmlineindex. to_value ( ) , & candidate. to_value ( ) ] ,
399
- )
377
+ . emit ( "add-ice-candidate" , & [ & sdpmlineindex, & candidate] )
400
378
. unwrap ( ) ;
401
379
}
402
380
@@ -408,7 +386,7 @@ impl ws::Handler for WsClient {
408
386
fn connect_to_websocket_server_async ( ) {
409
387
ws:: connect ( "ws://signalling:8443" , |out| WsClient {
410
388
out : out,
411
- app_state : Arc :: new ( AtomicUsize :: new ( AppState :: ServerConnecting as usize ) ) ,
389
+ app_state : Arc :: new ( Mutex :: new ( AppState :: ServerConnecting ) ) ,
412
390
webrtc : None ,
413
391
} ) . unwrap ( ) ;
414
392
}
0 commit comments