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}