xmpp_parsers/
jingle_rtp.rs1use xso::{AsXml, FromXml};
8
9use crate::jingle_rtcp_fb::RtcpFb;
10use crate::jingle_rtp_hdrext::RtpHdrext;
11use crate::jingle_ssma::{Group, Source};
12use crate::ns;
13
14#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
17#[xml(namespace = ns::JINGLE_RTP, name = "rtcp-mux")]
18pub struct RtcpMux;
19
20#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
22#[xml(namespace = ns::JINGLE_RTP, name = "description")]
23pub struct Description {
24 #[xml(attribute)]
27 pub media: String,
28
29 #[xml(attribute(default))]
31 pub ssrc: Option<u32>,
32
33 #[xml(child(n = ..))]
35 pub payload_types: Vec<PayloadType>,
36
37 #[xml(child(default))]
40 pub rtcp_mux: Option<RtcpMux>,
41
42 #[xml(child(n = ..))]
44 pub ssrc_groups: Vec<Group>,
45
46 #[xml(child(n = ..))]
48 pub ssrcs: Vec<Source>,
49
50 #[xml(child(n = ..))]
52 pub hdrexts: Vec<RtpHdrext>,
53 }
55
56impl Description {
57 pub fn new(media: String) -> Description {
59 Description {
60 media,
61 ssrc: None,
62 payload_types: Vec::new(),
63 rtcp_mux: None,
64 ssrc_groups: Vec::new(),
65 ssrcs: Vec::new(),
66 hdrexts: Vec::new(),
67 }
68 }
69}
70
71generate_attribute!(
72 Channels,
74 "channels",
75 u8,
76 Default = 1
77);
78
79#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
81#[xml(namespace = ns::JINGLE_RTP, name = "payload-type")]
82pub struct PayloadType {
83 #[xml(attribute(default))]
85 pub channels: Channels,
86
87 #[xml(attribute(default))]
89 pub clockrate: Option<u32>,
90
91 #[xml(attribute)]
93 pub id: u8,
94
95 #[xml(attribute(default))]
97 pub maxptime: Option<u32>,
98
99 #[xml(attribute(default))]
101 pub name: Option<String>,
102
103 #[xml(attribute(default))]
105 pub ptime: Option<u32>,
106
107 #[xml(child(n = ..))]
111 pub parameters: Vec<Parameter>,
112
113 #[xml(child(n = ..))]
115 pub rtcp_fbs: Vec<RtcpFb>,
116}
117
118impl PayloadType {
119 pub fn new(id: u8, name: String, clockrate: u32, channels: u8) -> PayloadType {
121 PayloadType {
122 channels: Channels(channels),
123 clockrate: Some(clockrate),
124 id,
125 maxptime: None,
126 name: Some(name),
127 ptime: None,
128 parameters: Vec::new(),
129 rtcp_fbs: Vec::new(),
130 }
131 }
132
133 pub fn without_clockrate(id: u8, name: String) -> PayloadType {
136 PayloadType {
137 channels: Default::default(),
138 clockrate: None,
139 id,
140 maxptime: None,
141 name: Some(name),
142 ptime: None,
143 parameters: Vec::new(),
144 rtcp_fbs: Vec::new(),
145 }
146 }
147}
148
149#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
151#[xml(namespace = ns::JINGLE_RTP, name = "parameter")]
152pub struct Parameter {
153 #[xml(attribute)]
156 pub name: String,
157
158 #[xml(attribute)]
160 pub value: String,
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166 use minidom::Element;
167
168 #[cfg(target_pointer_width = "32")]
169 #[test]
170 fn test_size() {
171 assert_size!(Description, 72);
172 assert_size!(Channels, 1);
173 assert_size!(PayloadType, 64);
174 assert_size!(Parameter, 24);
175 }
176
177 #[cfg(target_pointer_width = "64")]
178 #[test]
179 fn test_size() {
180 assert_size!(Description, 136);
181 assert_size!(Channels, 1);
182 assert_size!(PayloadType, 104);
183 assert_size!(Parameter, 48);
184 }
185
186 #[test]
187 fn test_simple() {
188 let elem: Element = "<description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>
189 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='2' clockrate='48000' id='96' name='OPUS'/>
190 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='32000' id='105' name='SPEEX'/>
191 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='9' name='G722'/>
192 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='16000' id='106' name='SPEEX'/>
193 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='8' name='PCMA'/>
194 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='0' name='PCMU'/>
195 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='107' name='SPEEX'/>
196 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='99' name='AMR'>
197 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='octet-align' value='1'/>
198 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='crc' value='0'/>
199 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='robust-sorting' value='0'/>
200 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='interleaving' value='0'/>
201 </payload-type>
202 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='48000' id='100' name='telephone-event'>
203 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
204 </payload-type>
205 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='16000' id='101' name='telephone-event'>
206 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
207 </payload-type>
208 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='102' name='telephone-event'>
209 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
210 </payload-type>
211</description>"
212 .parse()
213 .unwrap();
214 let desc = Description::try_from(elem).unwrap();
215 assert_eq!(desc.media, "audio");
216 assert_eq!(desc.ssrc, None);
217 }
218}