Skip to content
File

Blob: firmware/vendor/str0m/tests/twcc.rs

rust121 lines
1use std::net::Ipv4Addr;
2use std::time::{Duration, Instant};
3 
4use str0m::format::Codec;
5use str0m::media::{Direction, MediaKind};
6use str0m::rtp::rtcp::Twcc;
7use str0m::{Rtc, RtcError};
8use tracing::info_span;
9 
10mod common;
11use common::{TestRtc, init_crypto_default, init_log, negotiate, progress};
12 
13#[test]
14pub fn twcc() -> Result<(), RtcError> {
15 init_log();
16 init_crypto_default();
17 
18 let now = Instant::now();
19 let l_rtc = Rtc::builder().enable_raw_packets(true).build(now);
20 let r_rtc = Rtc::builder().enable_raw_packets(true).build(now);
21 
22 let mut l = TestRtc::new_with_rtc(info_span!("L"), l_rtc);
23 let mut r = TestRtc::new_with_rtc(info_span!("R"), r_rtc);
24 
25 l.add_host_candidate((Ipv4Addr::new(1, 1, 1, 1), 1000).into());
26 r.add_host_candidate((Ipv4Addr::new(2, 2, 2, 2), 2000).into());
27 
28 let mid = negotiate(&mut l, &mut r, |change| {
29 change.add_media(MediaKind::Video, Direction::SendOnly, None, None, None)
30 });
31 
32 loop {
33 if l.is_connected() || r.is_connected() {
34 break;
35 }
36 progress(&mut l, &mut r)?;
37 }
38 
39 let max = l.last.max(r.last);
40 l.last = max;
41 r.last = max;
42 
43 let params = l.params_vp8();
44 assert_eq!(params.spec().codec, Codec::Vp8);
45 let pt = params.pt();
46 
47 let data_a = [1_u8; 80];
48 
49 loop {
50 {
51 let wallclock = l.start + l.duration();
52 let time = l.duration().into();
53 l.writer(mid).unwrap().write(pt, wallclock, time, data_a)?;
54 }
55 
56 progress(&mut l, &mut r)?;
57 
58 if l.duration() > Duration::from_secs(10) {
59 break;
60 }
61 }
62 
63 let (sent_twcc, received_twcc) = {
64 use str0m::rtp::{RawPacket, rtcp::Rtcp};
65 let r_twcc: Vec<_> = r
66 .events
67 .iter()
68 .filter_map(|(_, e)| {
69 if let Some(RawPacket::RtcpTx(Rtcp::Twcc(twcc))) = e.as_raw_packet() {
70 Some(twcc)
71 } else {
72 None
73 }
74 })
75 .collect();
76 
77 let l_twcc: Vec<_> = l
78 .events
79 .iter()
80 .filter_map(|(_, e)| {
81 if let Some(RawPacket::RtcpRx(Rtcp::Twcc(twcc))) = e.as_raw_packet() {
82 Some(twcc)
83 } else {
84 None
85 }
86 })
87 .collect();
88 (r_twcc, l_twcc)
89 };
90 
91 assert!(!sent_twcc.is_empty(), "Should've sent TWCC");
92 assert!(
93 sent_twcc.len() == received_twcc.len(),
94 "The number of TWCC packets received should match what was sent"
95 );
96 assert!(
97 sent_twcc == received_twcc,
98 "The same TWCC packets that were sent should be received"
99 );
100 
101 let sent_is_consecutive = sent_twcc
102 .iter()
103 .fold((true, None), |(consecutive, last), packet| {
104 let consecutive = consecutive
105 && last
106 .map(|l: &Twcc| l.feedback_count.wrapping_add(1) == packet.feedback_count)
107 .unwrap_or(true);
108 
109 (consecutive, Some(packet))
110 })
111 .0;
112 
113 assert!(!sent_twcc.is_empty(), "Should have sent some TWCC");
114 assert!(
115 sent_is_consecutive,
116 "Sent TWCC packets should contain no gaps in terms of `feedback_count`"
117 );
118 
119 Ok(())
120}