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