skyway_webrtc_gateway_api/media/mod.rs
1pub(crate) mod api;
2pub(crate) mod formats;
3
4use futures::channel::mpsc;
5use futures::*;
6use serde::{Deserialize, Serialize};
7
8use crate::common::formats::{PhantomId, SerializableId, SocketInfo};
9use crate::error;
10
11pub use formats::{
12 AnswerQuery, AnswerResponse, AnswerResponseParams, CallQuery, CallResponse, Constraints,
13 MediaConnectionId, MediaConnectionIdWrapper, MediaConnectionStatus, MediaId, MediaParams,
14 RedirectParameters, RtcpId, SsrcPair,
15};
16
17/// Shows DataConnection events.
18///
19/// It's response from GET /media/connections/{media_connection_id}/events
20///
21/// [API](http://35.200.46.204/#/3.media/media_connection_event)
22#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)]
23#[serde(tag = "event")]
24pub enum MediaConnectionEventEnum {
25 READY(MediaConnectionIdWrapper),
26 STREAM(MediaConnectionIdWrapper),
27 CLOSE(MediaConnectionIdWrapper),
28 ERROR((MediaConnectionId, String)),
29 TIMEOUT,
30}
31
32/// Have WebRTC Gateway open a socket for feeding media.
33///
34/// This API need to identify whether the media is video or audio.
35/// If is_video is true, it's video. Otherwise, it's audio.
36///
37/// It's bindings for POST /media.
38///
39/// [API](http://35.200.46.204/#/3.media/media)
40///
41/// # Examples
42/// ```
43/// use skyway_webrtc_gateway_api::media::open_media_socket;
44///
45/// async fn example() {
46/// let result = open_media_socket(true).await; //video
47/// let result = open_media_socket(false).await; //audio
48/// }
49/// ```
50pub async fn open_media_socket(is_video: bool) -> Result<SocketInfo<MediaId>, error::Error> {
51 let base_url = super::base_url();
52 api::create_media(base_url, is_video).await
53}
54
55/// Have WebRTC Gateway close a media socket.
56///
57/// It's bindings for DELETE /media/{media_id}
58///
59/// [API](http://35.200.46.204/#/3.media/streams_delete)
60///
61/// # Examples
62/// ```
63/// use skyway_webrtc_gateway_api::media::delete_media;
64/// use skyway_webrtc_gateway_api::prelude::{MediaId, SerializableId};
65///
66/// async fn example() {
67/// let media_id = MediaId::try_create("vi-4d053831-5dc2-461b-a358-d062d6115216").unwrap();
68/// let result = delete_media(&media_id).await;
69/// }
70/// ```
71pub async fn delete_media(media_id: &MediaId) -> Result<(), error::Error> {
72 let base_url = super::base_url();
73 api::delete_media(base_url, media_id.as_str()).await
74}
75
76/// Have WebRTC Gateway open a socket for feeding rtcp.
77///
78/// It's bindings for POST /media/rtcp.
79///
80/// [API](http://35.200.46.204/#/3.media/media_rtcp_create)
81///
82/// # Examples
83/// ```
84/// use skyway_webrtc_gateway_api::media::open_rtcp_socket;
85///
86/// async fn example() {
87/// let result = open_rtcp_socket().await;
88/// }
89/// ```
90pub async fn open_rtcp_socket() -> Result<SocketInfo<RtcpId>, error::Error> {
91 let base_url = super::base_url();
92 api::create_rtcp(base_url).await
93}
94
95/// Have WebRTC Gateway close a rtcp socket.
96///
97/// It's bindings for DELETE /media/rtcp/{rtcp_id}
98///
99/// [API](http://35.200.46.204/#/3.media/media_rtcp_delete)
100///
101/// # Examples
102/// ```
103/// use skyway_webrtc_gateway_api::media::delete_rtcp;
104/// use skyway_webrtc_gateway_api::prelude::{RtcpId, SerializableId};
105///
106/// async fn example() {
107/// let rtcp_id = RtcpId::try_create("rc-970f2e5d-4da0-43e7-92b6-796678c104ad").unwrap();
108/// let result = delete_rtcp(&rtcp_id).await;
109/// }
110/// ```
111pub async fn delete_rtcp(rtcp_id: &RtcpId) -> Result<(), error::Error> {
112 let base_url = super::base_url();
113 api::delete_rtcp(base_url, rtcp_id.as_str()).await
114}
115
116/// Have WebRTC Gateway start establishing MediaConnection to neighbour.
117///
118/// It's bindings for POST /media/connections.
119///
120/// [API](http://35.200.46.204/#/3.media/media_connection_create)
121///
122/// # Examples
123/// ```
124/// use skyway_webrtc_gateway_api::media::{call, CallQuery, Constraints};
125/// use skyway_webrtc_gateway_api::prelude::{PeerId, MediaConnectionId, Token};
126///
127/// async fn example() {
128/// let media_connection_id = MediaConnectionId::try_create("mc-102127d9-30de-413b-93f7-41a33e39d82b").unwrap();
129/// let query = CallQuery {
130/// peer_id: PeerId::new("peer_id"),
131/// token: Token::try_create("token").unwrap(),
132/// target_id: PeerId::new("target_id"),
133/// constraints: Some(Constraints {
134/// video: true,
135/// videoReceiveEnabled: Some(false),
136/// audio: false,
137/// audioReceiveEnabled: Some(false),
138/// video_params: None,
139/// audio_params: None,
140/// metadata: None,
141/// }),
142/// redirect_params: None,
143/// };
144/// let result = call(&query).await;
145/// }
146/// ```
147pub async fn call(call_params: &CallQuery) -> Result<CallResponse, error::Error> {
148 let base_url = super::base_url();
149 api::create_call(base_url, call_params).await
150}
151
152/// Have WebRTC Gateway accept to a request of establishing MediaConnection from neighbours.
153///
154/// It's bindings for POST /media/connections/{media_connection_id}/answer
155///
156/// [API](http://35.200.46.204/#/3.media/media_connection_answer)
157///
158/// # Examples
159/// ```
160/// use skyway_webrtc_gateway_api::media::{answer, AnswerQuery, Constraints};
161/// use skyway_webrtc_gateway_api::prelude::MediaConnectionId;
162///
163/// async fn example() {
164/// let media_connection_id = MediaConnectionId::try_create("mc-102127d9-30de-413b-93f7-41a33e39d82b").unwrap();
165/// let query = AnswerQuery {
166/// constraints: Constraints {
167/// video: true,
168/// videoReceiveEnabled: Some(false),
169/// audio: false,
170/// audioReceiveEnabled: Some(false),
171/// video_params: None,
172/// audio_params: None,
173/// metadata: None,
174/// },
175/// redirect_params: None,
176/// };
177/// let result = answer(&media_connection_id, &query).await;
178/// }
179/// ```
180pub async fn answer(
181 media_connection_id: &MediaConnectionId,
182 params: &AnswerQuery,
183) -> Result<AnswerResponse, error::Error> {
184 let base_url = super::base_url();
185 api::answer(base_url, media_connection_id.as_str(), params).await
186}
187
188/// Have WebRTC Gateway close a MediaConnection
189///
190/// It's bindings for DELETE /media/connections/{media_connection_id}.
191///
192/// [API](http://35.200.46.204/#/3.media/media_connection_close)
193///
194/// # Examples
195/// ```
196/// use skyway_webrtc_gateway_api::media::disconnect;
197/// use skyway_webrtc_gateway_api::prelude::MediaConnectionId;
198///
199/// async fn example() {
200/// let media_connection_id = MediaConnectionId::try_create("mc-102127d9-30de-413b-93f7-41a33e39d82b").unwrap();
201/// let result = disconnect(&media_connection_id).await;
202/// }
203/// ```
204pub async fn disconnect(media_connection_id: &MediaConnectionId) -> Result<(), error::Error> {
205 let base_url = super::base_url();
206 api::delete_call(base_url, media_connection_id.as_str()).await
207}
208
209/// Have WebRTC Gateway send a PLI(Picture Less Indication) packet
210///
211/// A PLI packets informs the encoder about the loss of an undefined amount of coded video data
212/// belonging to one or more pictures([RFC](https://tools.ietf.org/html/rfc4585#section-6.3.1)).
213///
214/// It's bindings for POST /media/connections/{media_connection_id}/pli
215///
216/// [API](http://35.200.46.204/#/3.media/media_connection_pli)
217///
218/// # Examples
219/// ```
220/// use skyway_webrtc_gateway_api::media::send_pli;
221/// use skyway_webrtc_gateway_api::prelude::{MediaConnectionId, PhantomId, SerializableSocket, SocketInfo, SerializableId};
222///
223/// async fn example() {
224/// let media_connection_id = MediaConnectionId::try_create("mc-102127d9-30de-413b-93f7-41a33e39d82b").unwrap();
225/// let socket = SocketInfo::<PhantomId>::try_create(None, "127.0.0.1", 8000).unwrap();
226/// let result = send_pli(&media_connection_id, &socket).await;
227/// }
228/// ```
229pub async fn send_pli(
230 media_connection_id: &MediaConnectionId,
231 params: &SocketInfo<PhantomId>,
232) -> Result<(), error::Error> {
233 let base_url = super::base_url();
234 api::pli(base_url, media_connection_id.as_str(), params).await
235}
236
237/// Request an event of MediaConnection
238///
239/// This function try to fetch an event message from WebRTC GW.
240/// It returns events or TIMEOUT message
241///
242/// [API](http://35.200.46.204/#/3.media/media_connection_event)
243///
244/// # Examples
245/// ```
246/// use futures::channel::mpsc;
247/// use futures::future::{self, *};
248/// use futures::stream::*;
249/// use futures::*;
250///
251/// use skyway_webrtc_gateway_api::media::{MediaConnectionEventEnum, event};
252/// use skyway_webrtc_gateway_api::prelude::MediaConnectionId;
253///
254/// async fn example() {
255/// let media_connection_id = MediaConnectionId::try_create("mc-102127d9-30de-413b-93f7-41a33e39d82b").unwrap();
256/// let event = event(&media_connection_id).await;
257/// }
258/// ```
259pub async fn event<'a>(
260 media_connection_id: &MediaConnectionId,
261) -> Result<MediaConnectionEventEnum, error::Error> {
262 use crate::media::formats::EventEnum;
263
264 let base_url = super::base_url();
265 Ok(
266 match api::event(base_url, media_connection_id.as_str()).await? {
267 EventEnum::CLOSE => MediaConnectionEventEnum::CLOSE(MediaConnectionIdWrapper {
268 media_connection_id: media_connection_id.clone(),
269 }),
270 EventEnum::READY => MediaConnectionEventEnum::READY(MediaConnectionIdWrapper {
271 media_connection_id: media_connection_id.clone(),
272 }),
273 EventEnum::STREAM => MediaConnectionEventEnum::STREAM(MediaConnectionIdWrapper {
274 media_connection_id: media_connection_id.clone(),
275 }),
276 EventEnum::TIMEOUT => MediaConnectionEventEnum::TIMEOUT,
277 EventEnum::ERROR { error_message } => {
278 MediaConnectionEventEnum::ERROR((media_connection_id.clone(), error_message))
279 }
280 },
281 )
282}
283
284/// Request status of MediaConnection
285///
286/// This function keep listening events with GET /media/connections/{media_connection_id}/events
287/// until it receives a CLOSE event or an Error event.
288/// If it receives timeout, it ignores the event and listen events again.
289///
290/// [API](http://35.200.46.204/#/3.media/media_connection_event)
291///
292/// # Examples
293/// ```
294/// use futures::channel::mpsc;
295/// use futures::future::{self, *};
296/// use futures::stream::*;
297/// use futures::*;
298///
299/// use skyway_webrtc_gateway_api::media::{MediaConnectionEventEnum, listen_events};
300/// use skyway_webrtc_gateway_api::prelude::MediaConnectionId;
301///
302/// async fn example() {
303/// let media_connection_id = MediaConnectionId::try_create("mc-102127d9-30de-413b-93f7-41a33e39d82b").unwrap();
304/// let (mc_event_notifier, mc_event_observer) = mpsc::channel::<MediaConnectionEventEnum>(0);
305/// let mc_event_observer = mc_event_observer.for_each(|event| async move {
306/// // Do something
307/// });
308/// let events_fut = listen_events(media_connection_id, mc_event_notifier);
309/// let _ = join!(mc_event_observer, events_fut);
310/// }
311/// ```
312pub async fn listen_events<'a>(
313 media_connection_id: MediaConnectionId,
314 mut event_notifier: mpsc::Sender<MediaConnectionEventEnum>,
315) -> Result<(), error::Error> {
316 let base_url = super::base_url();
317
318 loop {
319 let result = api::event(base_url, media_connection_id.as_str()).await?;
320 match result {
321 formats::EventEnum::READY => {
322 if event_notifier
323 .send(MediaConnectionEventEnum::READY(MediaConnectionIdWrapper {
324 media_connection_id: media_connection_id.clone(),
325 }))
326 .await
327 .is_err()
328 {
329 return Err(error::Error::create_local_error("fail to notify an event"));
330 };
331 }
332 formats::EventEnum::CLOSE => {
333 if event_notifier
334 .send(MediaConnectionEventEnum::CLOSE(MediaConnectionIdWrapper {
335 media_connection_id: media_connection_id.clone(),
336 }))
337 .await
338 .is_err()
339 {
340 return Err(error::Error::create_local_error("fail to notify an event"));
341 };
342 break;
343 }
344 formats::EventEnum::STREAM => {
345 if event_notifier
346 .send(MediaConnectionEventEnum::STREAM(MediaConnectionIdWrapper {
347 media_connection_id: media_connection_id.clone(),
348 }))
349 .await
350 .is_err()
351 {
352 return Err(error::Error::create_local_error("fail to notify an event"));
353 };
354 }
355 formats::EventEnum::ERROR {
356 error_message: message,
357 } => {
358 if event_notifier
359 .send(MediaConnectionEventEnum::ERROR((
360 media_connection_id.clone(),
361 message,
362 )))
363 .await
364 .is_err()
365 {
366 return Err(error::Error::create_local_error("fail to notify an event"));
367 };
368 }
369 formats::EventEnum::TIMEOUT => {}
370 }
371 }
372
373 Ok(())
374}
375
376/// Request status of MediaConnection
377///
378/// It's bindings for GET /media/connections/{media_connection_id}/events.
379///
380/// [API](http://35.200.46.204/#/3.media/media_connection_status)
381///
382/// # Examples
383/// ```
384/// use skyway_webrtc_gateway_api::media::status;
385/// use skyway_webrtc_gateway_api::prelude::MediaConnectionId;
386///
387/// async fn example() {
388/// let media_connection_id = MediaConnectionId::try_create("mc-102127d9-30de-413b-93f7-41a33e39d82b").unwrap();
389/// let result = status(&media_connection_id).await;
390/// }
391/// ```
392pub async fn status(
393 media_connection_id: &MediaConnectionId,
394) -> Result<MediaConnectionStatus, error::Error> {
395 let base_url = super::base_url();
396 api::status(base_url, media_connection_id.as_str()).await
397}