Skip to content
File

Blob: firmware/vendor/str0m/tests/abs-capture-time.rs

rust143 lines
1use std::net::Ipv4Addr;
2use std::time::Duration;
3 
4use str0m::format::Codec;
5use str0m::media::{Direction, MediaKind};
6use str0m::rtp::{Extension, ExtensionMap};
7use str0m::{Event, Rtc, RtcError};
8 
9mod common;
10use common::{Peer, TestRtc, init_crypto_default, init_log, progress};
11 
12#[test]
13pub fn abs_capture_time_negotiation() -> Result<(), RtcError> {
14 init_log();
15 init_crypto_default();
16 
17 // Configure abs-capture-time extension on both peers
18 let mut exts = ExtensionMap::standard();
19 exts.set(9, Extension::AbsoluteCaptureTime);
20 
21 let now = std::time::Instant::now();
22 let mut l_rtc = Rtc::builder();
23 *l_rtc.extension_map() = exts.clone();
24 let mut l = TestRtc::new_with_rtc(Peer::Left.span(), l_rtc.build(now));
25 
26 let mut r_rtc = Rtc::builder();
27 *r_rtc.extension_map() = exts.clone();
28 let mut r = TestRtc::new_with_rtc(Peer::Right.span(), r_rtc.build(now));
29 
30 l.set_forced_time_advance(Duration::from_millis(1));
31 r.set_forced_time_advance(Duration::from_millis(1));
32 
33 l.add_host_candidate((Ipv4Addr::new(1, 1, 1, 1), 1000).into());
34 r.add_host_candidate((Ipv4Addr::new(2, 2, 2, 2), 2000).into());
35 
36 // Setup audio media
37 let mut change = l.sdp_api();
38 let mid = change.add_media(MediaKind::Audio, Direction::SendRecv, None, None, None);
39 let (offer, pending) = change.apply().unwrap();
40 
41 // Verify the offer contains abs-capture-time extension
42 let offer_str = offer.to_sdp_string();
43 assert!(
44 offer_str.contains("abs-capture-time"),
45 "SDP offer should contain abs-capture-time extension"
46 );
47 
48 let answer = r.rtc.sdp_api().accept_offer(offer)?;
49 l.rtc.sdp_api().accept_answer(pending, answer)?;
50 
51 // Wait for connection
52 loop {
53 if l.is_connected() || r.is_connected() {
54 break;
55 }
56 progress(&mut l, &mut r)?;
57 }
58 
59 let max = l.last.max(r.last);
60 l.last = max;
61 r.last = max;
62 
63 let params = l.params_opus();
64 assert_eq!(params.spec().codec, Codec::Opus);
65 let pt = params.pt();
66 
67 let data = vec![1_u8; 80];
68 
69 // Send some packets
70 for _ in 0..10 {
71 let wallclock = l.start + l.duration();
72 let time = l.duration().into();
73 
74 l.writer(mid)
75 .unwrap()
76 .write(pt, wallclock, time, data.clone())?;
77 
78 progress(&mut l, &mut r)?;
79 }
80 
81 // Verify we received MediaData events
82 let media_count = r
83 .events
84 .iter()
85 .filter(|(_, e)| matches!(e, Event::MediaData(_)))
86 .count();
87 
88 assert!(
89 media_count >= 5,
90 "Should have received at least 5 media packets, got {}",
91 media_count
92 );
93 
94 Ok(())
95}
96 
97#[test]
98pub fn abs_capture_time_sdp_roundtrip() -> Result<(), RtcError> {
99 init_log();
100 init_crypto_default();
101 
102 // Test that abs-capture-time extension properly roundtrips through SDP
103 let mut exts = ExtensionMap::standard();
104 exts.set(9, Extension::AbsoluteCaptureTime);
105 
106 let now = std::time::Instant::now();
107 let mut l_rtc = Rtc::builder();
108 *l_rtc.extension_map() = exts.clone();
109 let mut l = TestRtc::new_with_rtc(Peer::Left.span(), l_rtc.build(now));
110 
111 let mut r = TestRtc::new(Peer::Right);
112 
113 l.set_forced_time_advance(Duration::from_millis(1));
114 r.set_forced_time_advance(Duration::from_millis(1));
115 
116 l.add_host_candidate((Ipv4Addr::new(1, 1, 1, 1), 1000).into());
117 r.add_host_candidate((Ipv4Addr::new(2, 2, 2, 2), 2000).into());
118 
119 let mut change = l.sdp_api();
120 let _mid = change.add_media(MediaKind::Video, Direction::SendRecv, None, None, None);
121 let (offer, pending) = change.apply().unwrap();
122 
123 // Verify offer contains abs-capture-time
124 let offer_sdp = offer.to_sdp_string();
125 assert!(
126 offer_sdp.contains("http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time"),
127 "Offer SDP should contain abs-capture-time URI"
128 );
129 
130 let answer = r.rtc.sdp_api().accept_offer(offer)?;
131 
132 // Verify answer also contains abs-capture-time (if receiver supports it)
133 let answer_sdp = answer.to_sdp_string();
134 assert!(
135 answer_sdp.contains("abs-capture-time") || answer_sdp.contains("a=extmap"),
136 "Answer SDP should contain extension mapping"
137 );
138 
139 l.rtc.sdp_api().accept_answer(pending, answer)?;
140 
141 Ok(())
142}