1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! WASM side representation of an [RTCRtpCodecCapability].
//!
//! [RTCRtpCodecCapability]: https://w3.org/TR/webrtc#dom-rtcrtpcodeccapability
use std::collections::HashMap;
use web_sys::{RtcRtpCodecCapability, RtcRtpReceiver, RtcRtpSender};
use crate::{
media::MediaKind, platform::codec_capability::CodecCapabilityError as Error,
};
/// WASM side representation of an [RTCRtpCodecCapability].
///
/// [RTCRtpCodecCapability]: https://w3.org/TR/webrtc#dom-rtcrtpcodeccapability
#[derive(Clone, Debug)]
pub struct CodecCapability(RtcRtpCodecCapability);
impl CodecCapability {
/// Returns available [RTCRtpSender]'s [`CodecCapability`]s.
///
/// # Errors
///
/// With [`Error::FailedToGetCapabilities`] if fails to retrieve
/// capabilities.
///
/// [RTCRtpSender]: https://w3.org/TR/webrtc#dom-rtcrtpsender
#[expect(clippy::unused_async, reason = "`cfg` code uniformity")]
pub async fn get_sender_codec_capabilities(
kind: MediaKind,
) -> Result<Vec<Self>, Error> {
let mut result = Vec::new();
let Some(caps) = RtcRtpSender::get_capabilities(&kind.to_string())
else {
return Err(Error::FailedToGetCapabilities);
};
for codec in caps.get_codecs().values() {
let Ok(codec) = codec else {
continue;
};
result.push(Self(RtcRtpCodecCapability::from(codec)));
}
Ok(result)
}
/// Returns available [RTCRtpReceiver]'s [`CodecCapability`]s.
///
/// # Errors
///
/// With [`Error::FailedToGetCapabilities`] if fails to retrieve
/// [`CodecCapability`]s.
///
/// [RTCRtpReceiver]: https://w3.org/TR/webrtc#dom-rtcrtpreceiver
#[expect(clippy::unused_async, reason = "`cfg` code uniformity")]
pub async fn get_receiver_codec_capabilities(
kind: MediaKind,
) -> Result<Vec<Self>, Error> {
let mut result = Vec::new();
let Some(caps) = RtcRtpReceiver::get_capabilities(&kind.to_string())
else {
return Err(Error::FailedToGetCapabilities);
};
for codec in caps.get_codecs().values() {
let Ok(codec) = codec else {
continue;
};
result.push(Self(RtcRtpCodecCapability::from(codec)));
}
Ok(result)
}
/// Returns [mimeType][2] of this [`CodecCapability`].
///
/// [2]: https://w3.org/TR/webrtc#dom-rtcrtpcodec-mimetype
#[must_use]
pub fn mime_type(&self) -> String {
self.0.get_mime_type()
}
/// Returns [clockRate][2] of this [`CodecCapability`].
///
/// [2]: https://w3.org/TR/webrtc#dom-rtcrtpcodec-clockrate
#[must_use]
pub fn clock_rate(&self) -> u32 {
self.0.get_clock_rate()
}
/// Returns [channels][2] of this [`CodecCapability`].
///
/// [2]: https://w3.org/TR/webrtc#dom-rtcrtpcodec-channels
#[must_use]
pub fn channels(&self) -> Option<u16> {
self.0.get_channels()
}
/// Returns [sdpFmtpLine][2] of this [`CodecCapability`].
///
/// [2]: https://w3.org/TR/webrtc#dom-rtcrtpcodec-sdpfmtpline
#[must_use]
pub fn parameters(&self) -> HashMap<String, String> {
self.0
.get_sdp_fmtp_line()
.unwrap_or_default()
.split(';')
.filter_map(|pair| {
let mut kv = pair.split('=');
match (kv.next(), kv.next()) {
(Some(k), Some(v)) => {
Some((k.trim().to_owned(), v.trim().to_owned()))
}
_ => None,
}
})
.collect::<HashMap<String, String>>()
}
/// Returns the underlying [`RtcRtpCodecCapability`] of this
/// [`CodecCapability`].
#[must_use]
pub const fn handle(&self) -> &RtcRtpCodecCapability {
&self.0
}
}