1 use super::*;
2 use crate::error::Result;
3 use rtcp::packet::Packet;
4 use util::Marshal;
5
6 #[test]
test_chunk_add() -> Result<()>7 fn test_chunk_add() -> Result<()> {
8 //"fill with not received"
9 {
10 let mut c = Chunk::default();
11
12 for i in 0..MAX_RUN_LENGTH_CAP {
13 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16), "{}", i);
14 c.add(SymbolTypeTcc::PacketNotReceived as u16);
15 }
16 assert_eq!(c.deltas, vec![0u16; MAX_RUN_LENGTH_CAP]);
17 assert!(!c.has_different_types);
18
19 assert!(!c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
20 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16));
21 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
22
23 let status_chunk = c.encode();
24 match status_chunk {
25 PacketStatusChunk::RunLengthChunk(_) => {}
26 _ => panic!(),
27 };
28
29 let buf = status_chunk.marshal()?;
30 assert_eq!(&buf[..], &[0x1f, 0xff]);
31 }
32
33 //"fill with small delta"
34 {
35 let mut c = Chunk::default();
36
37 for i in 0..MAX_ONE_BIT_CAP {
38 assert!(
39 c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16),
40 "{}",
41 i
42 );
43 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16);
44 }
45
46 assert_eq!(c.deltas, vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
47 assert!(!c.has_different_types);
48
49 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
50 assert!(!c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
51
52 let status_chunk = c.encode();
53 match status_chunk {
54 PacketStatusChunk::RunLengthChunk(_) => {}
55 _ => panic!(),
56 };
57
58 let buf = status_chunk.marshal()?;
59 assert_eq!(&buf[..], &[0x20, 0xe]);
60 }
61
62 //"fill with large delta"
63 {
64 let mut c = Chunk::default();
65
66 for i in 0..MAX_TWO_BIT_CAP {
67 assert!(
68 c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16),
69 "{}",
70 i
71 );
72 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16);
73 }
74
75 assert_eq!(c.deltas, vec![2, 2, 2, 2, 2, 2, 2]);
76 assert!(c.has_large_delta);
77 assert!(!c.has_different_types);
78
79 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16));
80 assert!(!c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
81
82 let status_chunk = c.encode();
83 match status_chunk {
84 PacketStatusChunk::RunLengthChunk(_) => {}
85 _ => panic!(),
86 };
87
88 let buf = status_chunk.marshal()?;
89 assert_eq!(&buf[..], &[0x40, 0x7]);
90 }
91
92 // "fill with different types"
93 {
94 let mut c = Chunk::default();
95
96 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16));
97 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16);
98 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16));
99 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16);
100 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16));
101 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16);
102 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16));
103 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16);
104
105 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
106 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16);
107 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
108 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16);
109 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
110 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16);
111
112 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
113
114 let status_chunk = c.encode();
115 match status_chunk {
116 PacketStatusChunk::StatusVectorChunk(_) => {}
117 _ => panic!(),
118 };
119
120 let buf = status_chunk.marshal()?;
121 assert_eq!(&buf[..], &[0xd5, 0x6a]);
122 }
123
124 //"overfill and encode"
125 {
126 let mut c = Chunk::default();
127
128 assert!(c.can_add(SymbolTypeTcc::PacketReceivedSmallDelta as u16));
129 c.add(SymbolTypeTcc::PacketReceivedSmallDelta as u16);
130 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
131 c.add(SymbolTypeTcc::PacketNotReceived as u16);
132 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
133 c.add(SymbolTypeTcc::PacketNotReceived as u16);
134 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
135 c.add(SymbolTypeTcc::PacketNotReceived as u16);
136 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
137 c.add(SymbolTypeTcc::PacketNotReceived as u16);
138 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
139 c.add(SymbolTypeTcc::PacketNotReceived as u16);
140 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
141 c.add(SymbolTypeTcc::PacketNotReceived as u16);
142 assert!(c.can_add(SymbolTypeTcc::PacketNotReceived as u16));
143 c.add(SymbolTypeTcc::PacketNotReceived as u16);
144
145 assert!(!c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
146
147 let status_chunk1 = c.encode();
148 match status_chunk1 {
149 PacketStatusChunk::StatusVectorChunk(_) => {}
150 _ => panic!(),
151 };
152 assert_eq!(c.deltas.len(), 1);
153
154 assert!(c.can_add(SymbolTypeTcc::PacketReceivedLargeDelta as u16));
155 c.add(SymbolTypeTcc::PacketReceivedLargeDelta as u16);
156
157 let status_chunk2 = c.encode();
158 match status_chunk2 {
159 PacketStatusChunk::StatusVectorChunk(_) => {}
160 _ => panic!(),
161 };
162 assert_eq!(c.deltas.len(), 0);
163
164 assert_eq!(
165 PacketStatusChunk::StatusVectorChunk(StatusVectorChunk {
166 type_tcc: StatusChunkTypeTcc::StatusVectorChunk,
167 symbol_size: SymbolSizeTypeTcc::TwoBit,
168 symbol_list: vec![
169 SymbolTypeTcc::PacketNotReceived,
170 SymbolTypeTcc::PacketReceivedLargeDelta
171 ],
172 }),
173 status_chunk2
174 );
175 }
176
177 Ok(())
178 }
179
180 #[test]
test_feedback() -> Result<()>181 fn test_feedback() -> Result<()> {
182 //"add simple"
183 {
184 let mut f = Feedback::default();
185 let got = f.add_received(0, 10);
186 assert!(got);
187 }
188
189 //"add too large"
190 {
191 let mut f = Feedback::default();
192
193 assert!(!f.add_received(12, 8200 * 1000 * 250));
194 }
195
196 // "add received 1"
197 {
198 let mut f = Feedback::default();
199 f.set_base(1, 1000 * 1000);
200
201 let got = f.add_received(1, 1023 * 1000);
202
203 assert!(got);
204 assert_eq!(f.next_sequence_number, 2);
205 assert_eq!(f.ref_timestamp64ms, 15);
206
207 let got = f.add_received(4, 1086 * 1000);
208 assert!(got);
209 assert_eq!(f.next_sequence_number, 5);
210 assert_eq!(f.ref_timestamp64ms, 15);
211
212 assert!(f.last_chunk.has_different_types);
213 assert_eq!(f.last_chunk.deltas.len(), 4);
214 assert!(!f
215 .last_chunk
216 .deltas
217 .contains(&(SymbolTypeTcc::PacketReceivedLargeDelta as u16)));
218 }
219
220 //"add received 2"
221 {
222 let mut f = Feedback::new(0, 0, 0);
223 f.set_base(5, 320 * 1000);
224
225 let mut got = f.add_received(5, 320 * 1000);
226 assert!(got);
227 got = f.add_received(7, 448 * 1000);
228 assert!(got);
229 got = f.add_received(8, 512 * 1000);
230 assert!(got);
231 got = f.add_received(11, 768 * 1000);
232 assert!(got);
233
234 let pkt = f.get_rtcp();
235
236 assert!(pkt.header().padding);
237 assert_eq!(pkt.header().length, 7);
238 assert_eq!(pkt.base_sequence_number, 5);
239 assert_eq!(pkt.packet_status_count, 7);
240 assert_eq!(pkt.reference_time, 5);
241 assert_eq!(pkt.fb_pkt_count, 0);
242 assert_eq!(pkt.packet_chunks.len(), 1);
243
244 assert_eq!(
245 vec![PacketStatusChunk::StatusVectorChunk(StatusVectorChunk {
246 type_tcc: StatusChunkTypeTcc::StatusVectorChunk,
247 symbol_size: SymbolSizeTypeTcc::TwoBit,
248 symbol_list: vec![
249 SymbolTypeTcc::PacketReceivedSmallDelta,
250 SymbolTypeTcc::PacketNotReceived,
251 SymbolTypeTcc::PacketReceivedLargeDelta,
252 SymbolTypeTcc::PacketReceivedLargeDelta,
253 SymbolTypeTcc::PacketNotReceived,
254 SymbolTypeTcc::PacketNotReceived,
255 SymbolTypeTcc::PacketReceivedLargeDelta,
256 ],
257 })],
258 pkt.packet_chunks
259 );
260
261 let expected_deltas = vec![
262 RecvDelta {
263 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
264 delta: 0,
265 },
266 RecvDelta {
267 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta,
268 delta: 0x0200 * TYPE_TCC_DELTA_SCALE_FACTOR,
269 },
270 RecvDelta {
271 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta,
272 delta: 0x0100 * TYPE_TCC_DELTA_SCALE_FACTOR,
273 },
274 RecvDelta {
275 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta,
276 delta: 0x0400 * TYPE_TCC_DELTA_SCALE_FACTOR,
277 },
278 ];
279 assert_eq!(pkt.recv_deltas.len(), expected_deltas.len());
280 for (i, expected) in expected_deltas.iter().enumerate() {
281 assert_eq!(&pkt.recv_deltas[i], expected);
282 }
283 }
284
285 //"add received wrapped sequence number"
286 {
287 let mut f = Feedback::new(0, 0, 0);
288 f.set_base(65535, 320 * 1000);
289
290 let mut got = f.add_received(65535, 320 * 1000);
291 assert!(got);
292 got = f.add_received(7, 448 * 1000);
293 assert!(got);
294 got = f.add_received(8, 512 * 1000);
295 assert!(got);
296 got = f.add_received(11, 768 * 1000);
297 assert!(got);
298
299 let pkt = f.get_rtcp();
300
301 assert!(pkt.header().padding);
302 assert_eq!(pkt.header().length, 7);
303 assert_eq!(pkt.base_sequence_number, 65535);
304 assert_eq!(pkt.packet_status_count, 13);
305 assert_eq!(pkt.reference_time, 5);
306 assert_eq!(pkt.fb_pkt_count, 0);
307 assert_eq!(pkt.packet_chunks.len(), 2);
308
309 assert_eq!(
310 vec![
311 PacketStatusChunk::StatusVectorChunk(StatusVectorChunk {
312 type_tcc: StatusChunkTypeTcc::StatusVectorChunk,
313 symbol_size: SymbolSizeTypeTcc::TwoBit,
314 symbol_list: vec![
315 SymbolTypeTcc::PacketReceivedSmallDelta,
316 SymbolTypeTcc::PacketNotReceived,
317 SymbolTypeTcc::PacketNotReceived,
318 SymbolTypeTcc::PacketNotReceived,
319 SymbolTypeTcc::PacketNotReceived,
320 SymbolTypeTcc::PacketNotReceived,
321 SymbolTypeTcc::PacketNotReceived,
322 ],
323 }),
324 PacketStatusChunk::StatusVectorChunk(StatusVectorChunk {
325 type_tcc: StatusChunkTypeTcc::StatusVectorChunk,
326 symbol_size: SymbolSizeTypeTcc::TwoBit,
327 symbol_list: vec![
328 SymbolTypeTcc::PacketNotReceived,
329 SymbolTypeTcc::PacketReceivedLargeDelta,
330 SymbolTypeTcc::PacketReceivedLargeDelta,
331 SymbolTypeTcc::PacketNotReceived,
332 SymbolTypeTcc::PacketNotReceived,
333 SymbolTypeTcc::PacketReceivedLargeDelta,
334 ],
335 }),
336 ],
337 pkt.packet_chunks
338 );
339
340 let expected_deltas = vec![
341 RecvDelta {
342 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
343 delta: 0,
344 },
345 RecvDelta {
346 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta,
347 delta: 0x0200 * TYPE_TCC_DELTA_SCALE_FACTOR,
348 },
349 RecvDelta {
350 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta,
351 delta: 0x0100 * TYPE_TCC_DELTA_SCALE_FACTOR,
352 },
353 RecvDelta {
354 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta,
355 delta: 0x0400 * TYPE_TCC_DELTA_SCALE_FACTOR,
356 },
357 ];
358 assert_eq!(pkt.recv_deltas.len(), expected_deltas.len());
359 for (i, expected) in expected_deltas.iter().enumerate() {
360 assert_eq!(&pkt.recv_deltas[i], expected);
361 }
362 }
363
364 //"get RTCP"
365 {
366 let tests = vec![(320, 1, 5, 1), (1000, 2, 15, 2)];
367 for (arrival_ts, sequence_number, want_ref_time, want_base_sequence_number) in tests {
368 let mut f = Feedback::new(0, 0, 0);
369 f.set_base(sequence_number, arrival_ts * 1000);
370
371 let got = f.get_rtcp();
372 assert_eq!(got.reference_time, want_ref_time);
373 assert_eq!(got.base_sequence_number, want_base_sequence_number);
374 }
375 }
376
377 Ok(())
378 }
379
add_run(r: &mut Recorder, sequence_numbers: &[u16], arrival_times: &[i64])380 fn add_run(r: &mut Recorder, sequence_numbers: &[u16], arrival_times: &[i64]) {
381 assert_eq!(sequence_numbers.len(), arrival_times.len());
382
383 for i in 0..sequence_numbers.len() {
384 r.record(5000, sequence_numbers[i], arrival_times[i]);
385 }
386 }
387
388 const TYPE_TCC_DELTA_SCALE_FACTOR: i64 = 250;
389 const SCALE_FACTOR_REFERENCE_TIME: i64 = 64000;
390
increase_time(arrival_time: &mut i64, increase_amount: i64) -> i64391 fn increase_time(arrival_time: &mut i64, increase_amount: i64) -> i64 {
392 *arrival_time += increase_amount;
393 *arrival_time
394 }
395
marshal_all(pkts: &[Box<dyn rtcp::packet::Packet + Send + Sync>]) -> Result<()>396 fn marshal_all(pkts: &[Box<dyn rtcp::packet::Packet + Send + Sync>]) -> Result<()> {
397 for pkt in pkts {
398 let _ = pkt.marshal()?;
399 }
400 Ok(())
401 }
402
403 #[test]
test_build_feedback_packet() -> Result<()>404 fn test_build_feedback_packet() -> Result<()> {
405 let mut r = Recorder::new(5000);
406
407 let mut arrival_time = SCALE_FACTOR_REFERENCE_TIME;
408 add_run(
409 &mut r,
410 &[0, 1, 2, 3, 4, 5, 6, 7],
411 &[
412 SCALE_FACTOR_REFERENCE_TIME,
413 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
414 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
415 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
416 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
417 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
418 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
419 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR * 256),
420 ],
421 );
422
423 let rtcp_packets = r.build_feedback_packet();
424 assert_eq!(1, rtcp_packets.len());
425
426 let expected = TransportLayerCc {
427 sender_ssrc: 5000,
428 media_ssrc: 5000,
429 base_sequence_number: 0,
430 reference_time: 1,
431 fb_pkt_count: 0,
432 packet_status_count: 8,
433 packet_chunks: vec![
434 PacketStatusChunk::RunLengthChunk(RunLengthChunk {
435 type_tcc: StatusChunkTypeTcc::RunLengthChunk,
436 packet_status_symbol: SymbolTypeTcc::PacketReceivedSmallDelta,
437 run_length: 7,
438 }),
439 PacketStatusChunk::RunLengthChunk(RunLengthChunk {
440 type_tcc: StatusChunkTypeTcc::RunLengthChunk,
441 packet_status_symbol: SymbolTypeTcc::PacketReceivedLargeDelta,
442 run_length: 1,
443 }),
444 ],
445 recv_deltas: vec![
446 RecvDelta {
447 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
448 delta: 0,
449 },
450 RecvDelta {
451 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
452 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
453 },
454 RecvDelta {
455 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
456 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
457 },
458 RecvDelta {
459 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
460 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
461 },
462 RecvDelta {
463 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
464 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
465 },
466 RecvDelta {
467 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
468 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
469 },
470 RecvDelta {
471 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
472 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
473 },
474 RecvDelta {
475 type_tcc_packet: SymbolTypeTcc::PacketReceivedLargeDelta,
476 delta: TYPE_TCC_DELTA_SCALE_FACTOR * 256,
477 },
478 ],
479 };
480
481 if let Some(tcc) = rtcp_packets[0].as_any().downcast_ref::<TransportLayerCc>() {
482 assert_eq!(tcc, &expected);
483 } else {
484 panic!();
485 }
486
487 marshal_all(&rtcp_packets[..])?;
488
489 Ok(())
490 }
491
492 #[test]
test_build_feedback_packet_rolling() -> Result<()>493 fn test_build_feedback_packet_rolling() -> Result<()> {
494 let mut r = Recorder::new(5000);
495
496 let mut arrival_time = SCALE_FACTOR_REFERENCE_TIME;
497 add_run(&mut r, &[3], &[arrival_time]);
498
499 let rtcp_packets = r.build_feedback_packet();
500 assert_eq!(0, rtcp_packets.len());
501
502 add_run(
503 &mut r,
504 &[4, 8, 9],
505 &[
506 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
507 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
508 increase_time(&mut arrival_time, TYPE_TCC_DELTA_SCALE_FACTOR),
509 ],
510 );
511
512 let rtcp_packets = r.build_feedback_packet();
513 assert_eq!(rtcp_packets.len(), 1);
514
515 let expected = TransportLayerCc {
516 sender_ssrc: 5000,
517 media_ssrc: 5000,
518 base_sequence_number: 3,
519 reference_time: 1,
520 fb_pkt_count: 0,
521 packet_status_count: 7,
522 packet_chunks: vec![PacketStatusChunk::StatusVectorChunk(StatusVectorChunk {
523 type_tcc: StatusChunkTypeTcc::StatusVectorChunk,
524 symbol_size: SymbolSizeTypeTcc::TwoBit,
525 symbol_list: vec![
526 SymbolTypeTcc::PacketReceivedSmallDelta,
527 SymbolTypeTcc::PacketReceivedSmallDelta,
528 SymbolTypeTcc::PacketNotReceived,
529 SymbolTypeTcc::PacketNotReceived,
530 SymbolTypeTcc::PacketNotReceived,
531 SymbolTypeTcc::PacketReceivedSmallDelta,
532 SymbolTypeTcc::PacketReceivedSmallDelta,
533 ],
534 })],
535 recv_deltas: vec![
536 RecvDelta {
537 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
538 delta: 0,
539 },
540 RecvDelta {
541 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
542 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
543 },
544 RecvDelta {
545 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
546 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
547 },
548 RecvDelta {
549 type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
550 delta: TYPE_TCC_DELTA_SCALE_FACTOR,
551 },
552 ],
553 };
554
555 if let Some(tcc) = rtcp_packets[0].as_any().downcast_ref::<TransportLayerCc>() {
556 assert_eq!(tcc, &expected);
557 } else {
558 panic!();
559 }
560
561 marshal_all(&rtcp_packets[..])?;
562
563 Ok(())
564 }
565