xref: /webrtc/interceptor/src/twcc/twcc_test.rs (revision 2e7ce1eb)
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