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