Skip to content
File

Blob: firmware/vendor/str0m/tests/rtp-direct-csrc.rs

rust274 lines
1use std::time::Duration;
2 
3use str0m::format::Codec;
4use str0m::media::{MediaKind, Pt};
5use str0m::rtp::{ExtensionValues, RtpWrite, Ssrc, Vp8Descriptor};
6use str0m::{Event, RtcError};
7 
8mod common;
9use common::{connect_l_r, init_crypto_default, init_log, progress};
10 
11const VP8_PAYLOAD: [u8; 6] = [0x90, 0xf0, 0x01, 0x02, 0xa3, 0x00];
12const VP8_REWRITTEN_PICTURE_ID_PAYLOAD: [u8; 6] = [0x90, 0xf0, 0x7e, 0x02, 0xa3, 0x00];
13 
14#[test]
15pub fn rtp_direct_csrc_basic() -> Result<(), RtcError> {
16 init_log();
17 init_crypto_default();
18 
19 let (mut l, mut r) = connect_l_r();
20 
21 let mid = "aud".into();
22 let ssrc: Ssrc = 1.into();
23 
24 l.direct_api().declare_media(mid, MediaKind::Audio);
25 l.direct_api().declare_stream_tx(ssrc, None, mid, None);
26 
27 r.direct_api().declare_media(mid, MediaKind::Audio);
28 r.direct_api().expect_stream_rx(ssrc, None, mid, None);
29 
30 let max = l.last.max(r.last);
31 l.last = max;
32 r.last = max;
33 
34 let params = l.params_opus();
35 assert_eq!(params.spec().codec, Codec::Opus);
36 let pt = params.pt();
37 
38 let csrc_values: [u32; 15] = [
39 u32::MAX,
40 0x12_34_56_78,
41 1,
42 0,
43 0,
44 0,
45 0,
46 0,
47 0,
48 0,
49 0,
50 0,
51 0,
52 0,
53 0,
54 ];
55 
56 let wallclock = l.start + l.duration();
57 let exts = ExtensionValues {
58 audio_level: Some(-42),
59 voice_activity: Some(false),
60 ..Default::default()
61 };
62 
63 l.direct_api().stream_tx(&ssrc).unwrap().write_rtp(
64 RtpWrite::new(
65 pt,
66 47_000.into(),
67 47_000_000,
68 wallclock,
69 [0x1, 0x2, 0x3, 0x4],
70 )
71 .ext_vals(exts)
72 .csrc(&csrc_values[..3]),
73 );
74 
75 loop {
76 progress(&mut l, &mut r)?;
77 
78 let has_media_packet = r
79 .events
80 .iter()
81 .any(|(_, e)| matches!(e, Event::RtpPacket(_)));
82 
83 if has_media_packet || l.duration() > Duration::from_secs(10) {
84 break;
85 }
86 }
87 
88 let media: Vec<_> = r
89 .events
90 .iter()
91 .filter_map(|(_, e)| {
92 if let Event::RtpPacket(v) = e {
93 Some(v)
94 } else {
95 None
96 }
97 })
98 .collect();
99 
100 assert_eq!(media.len(), 1);
101 
102 let h = &media[0].header;
103 assert_eq!(h.csrc_count, 3);
104 assert_eq!(h.csrc[0], u32::MAX);
105 assert_eq!(h.csrc[1], 0x12_34_56_78);
106 assert_eq!(h.csrc[2], 1);
107 // Remaining slots should be zero
108 for i in 3..15 {
109 assert_eq!(h.csrc[i], 0, "csrc[{i}] should be 0");
110 }
111 
112 Ok(())
113}
114 
115#[test]
116pub fn rtp_direct_csrc_max_entries() -> Result<(), RtcError> {
117 init_log();
118 init_crypto_default();
119 
120 let (mut l, mut r) = connect_l_r();
121 
122 let mid = "aud".into();
123 let ssrc: Ssrc = 2.into();
124 
125 l.direct_api().declare_media(mid, MediaKind::Audio);
126 l.direct_api().declare_stream_tx(ssrc, None, mid, None);
127 
128 r.direct_api().declare_media(mid, MediaKind::Audio);
129 r.direct_api().expect_stream_rx(ssrc, None, mid, None);
130 
131 let max = l.last.max(r.last);
132 l.last = max;
133 r.last = max;
134 
135 let params = l.params_opus();
136 let pt = params.pt();
137 
138 let csrc_values: [u32; 15] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
139 
140 let wallclock = l.start + l.duration();
141 l.direct_api().stream_tx(&ssrc).unwrap().write_rtp(
142 RtpWrite::new(
143 pt,
144 48_000.into(),
145 48_000_000,
146 wallclock,
147 [0xa, 0xb, 0xc, 0xd],
148 )
149 .csrc(&csrc_values),
150 );
151 
152 loop {
153 progress(&mut l, &mut r)?;
154 
155 let has_media_packet = r
156 .events
157 .iter()
158 .any(|(_, e)| matches!(e, Event::RtpPacket(_)));
159 
160 if has_media_packet || l.duration() > Duration::from_secs(10) {
161 break;
162 }
163 }
164 
165 let media: Vec<_> = r
166 .events
167 .iter()
168 .filter_map(|(_, e)| {
169 if let Event::RtpPacket(v) = e {
170 Some(v)
171 } else {
172 None
173 }
174 })
175 .collect();
176 
177 assert_eq!(media.len(), 1);
178 
179 let h = &media[0].header;
180 assert_eq!(h.csrc_count, 15);
181 for i in 0..15 {
182 assert_eq!(h.csrc[i], (i + 1) as u32, "csrc[{i}] mismatch");
183 }
184 
185 Ok(())
186}
187 
188#[test]
189#[should_panic(expected = "CSRC count must be <= 15")]
190pub fn rtp_direct_csrc_panics_on_too_many_entries() {
191 let csrc_values = [0; 16];
192 RtpWrite::new(
193 Pt::new_with_value(96),
194 47_000.into(),
195 47_000_000,
196 std::time::Instant::now(),
197 [0],
198 )
199 .csrc(&csrc_values);
200}
201 
202#[test]
203pub fn rtp_direct_csrc_with_vp8_patch() -> Result<(), RtcError> {
204 init_log();
205 init_crypto_default();
206 
207 let (mut l, mut r) = connect_l_r();
208 
209 let mid = "vid".into();
210 let ssrc: Ssrc = 3.into();
211 
212 l.direct_api().declare_media(mid, MediaKind::Video);
213 l.direct_api().declare_stream_tx(ssrc, None, mid, None);
214 
215 r.direct_api().declare_media(mid, MediaKind::Video);
216 r.direct_api().expect_stream_rx(ssrc, None, mid, None);
217 
218 let max = l.last.max(r.last);
219 l.last = max;
220 r.last = max;
221 
222 let params = l.params_vp8();
223 assert_eq!(params.spec().codec, Codec::Vp8);
224 let pt = params.pt();
225 let csrc_values = [0x12_34_56_78, 7];
226 let wallclock = l.start + l.duration();
227 let vp8_patch = Vp8Descriptor::parse(&VP8_PAYLOAD)
228 .expect("valid VP8 descriptor")
229 .patch()
230 .picture_id(0x7e)
231 .build()
232 .expect("valid VP8 patch");
233 
234 l.direct_api().stream_tx(&ssrc).unwrap().write_rtp(
235 RtpWrite::new(pt, 49_000.into(), 49_000_000, wallclock, VP8_PAYLOAD)
236 .csrc(&csrc_values)
237 .vp8_patch(vp8_patch),
238 );
239 
240 loop {
241 progress(&mut l, &mut r)?;
242 
243 let has_media_packet = r
244 .events
245 .iter()
246 .any(|(_, e)| matches!(e, Event::RtpPacket(_)));
247 
248 if has_media_packet || l.duration() > Duration::from_secs(10) {
249 break;
250 }
251 }
252 
253 let mut media = r.events.iter().filter_map(|(_, e)| {
254 if let Event::RtpPacket(v) = e {
255 Some(v)
256 } else {
257 None
258 }
259 });
260 
261 let packet = media.next().expect("one RTP packet");
262 assert!(media.next().is_none());
263 
264 assert_eq!(
265 packet.payload.as_ref(),
266 VP8_REWRITTEN_PICTURE_ID_PAYLOAD.as_slice()
267 );
268 assert_eq!(packet.header.csrc_count, 2);
269 assert_eq!(packet.header.csrc[0], csrc_values[0]);
270 assert_eq!(packet.header.csrc[1], csrc_values[1]);
271 
272 Ok(())
273}