rtc_interceptor/rfc8888/
sender.rs1use super::recorder::CcFeedbackRecorder;
4use crate::Interceptor;
5use crate::stream_info::StreamInfo;
6use crate::{AttributedPacket, Packet, TaggedPacket};
7use rtcp::transport_feedbacks::cc_feedback_report::Ecn;
8use sansio::Protocol;
9use shared::TransportContext;
10use shared::error::Error;
11use shared::time::SystemInstant;
12use std::collections::HashSet;
13use std::collections::VecDeque;
14use std::time::{Duration, Instant};
15
16pub const DEFAULT_INTERVAL: Duration = Duration::from_millis(100);
18
19pub const DEFAULT_MAX_REPORT_SIZE: usize = 1200;
21
22pub struct Rfc8888Builder {
35 interval: Duration,
36 max_report_size: usize,
37 sender_ssrc: u32,
38}
39
40impl Default for Rfc8888Builder {
41 fn default() -> Self {
42 Self {
43 interval: DEFAULT_INTERVAL,
44 max_report_size: DEFAULT_MAX_REPORT_SIZE,
45 sender_ssrc: 0,
46 }
47 }
48}
49
50impl Rfc8888Builder {
51 pub fn new() -> Self {
53 Self::default()
54 }
55
56 pub fn with_interval(mut self, interval: Duration) -> Self {
61 self.interval = interval;
62 self
63 }
64
65 pub fn with_max_report_size(mut self, max_report_size: usize) -> Self {
70 self.max_report_size = max_report_size;
71 self
72 }
73
74 pub fn with_sender_ssrc(mut self, sender_ssrc: u32) -> Self {
76 self.sender_ssrc = sender_ssrc;
77 self
78 }
79
80 pub fn build(self) -> Rfc8888Interceptor {
82 Rfc8888Interceptor::new(self.interval, self.max_report_size, self.sender_ssrc)
83 }
84}
85
86pub struct Rfc8888Interceptor {
99 interval: Duration,
100 max_report_size: usize,
101 sender_ssrc: u32,
102 recorder: CcFeedbackRecorder,
103 streams: HashSet<u32>,
105 next_timeout: Option<Instant>,
106 epoch: Option<SystemInstant>,
109 write_queue: VecDeque<TaggedPacket>,
110 read_queue: VecDeque<TaggedPacket>,
112}
113
114impl Rfc8888Interceptor {
115 fn new(interval: Duration, max_report_size: usize, sender_ssrc: u32) -> Self {
116 Self {
117 read_queue: VecDeque::new(),
118 interval,
119 max_report_size,
120 sender_ssrc,
121 recorder: CcFeedbackRecorder::new(),
122 streams: HashSet::new(),
123 next_timeout: None,
124 epoch: None,
125 write_queue: VecDeque::new(),
126 }
127 }
128
129 fn report_timestamp(&mut self, now: Instant) -> u32 {
131 let epoch = self.epoch.get_or_insert_with(|| SystemInstant::now(now));
132 (epoch.ntp(now) >> 16) as u32
133 }
134
135 fn arm(&mut self, now: Instant) {
137 if self.next_timeout.is_none() && !self.streams.is_empty() && !self.interval.is_zero() {
138 self.next_timeout = Some(now + self.interval);
139 }
140 }
141}
142
143impl Protocol<TaggedPacket, TaggedPacket, ()> for Rfc8888Interceptor {
144 type Rout = TaggedPacket;
145 type Wout = TaggedPacket;
146 type Eout = ();
147 type Error = Error;
148 type Time = Instant;
149
150 fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
151 if let Packet::Rtp(rtp_packet) = &msg.message.packet
152 && self.streams.contains(&rtp_packet.header.ssrc)
153 {
154 self.recorder.add_packet(
158 msg.now,
159 rtp_packet.header.ssrc,
160 rtp_packet.header.sequence_number,
161 Ecn::NotEct,
162 );
163 self.arm(msg.now);
164 }
165 self.read_queue.push_back(msg);
166 Ok(())
167 }
168
169 fn poll_read(&mut self) -> Option<Self::Rout> {
170 self.read_queue.pop_front()
171 }
172
173 fn handle_write(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
174 self.write_queue.push_back(msg);
175 Ok(())
176 }
177
178 fn poll_write(&mut self) -> Option<TaggedPacket> {
179 self.write_queue.pop_front()
182 }
183
184 fn handle_timeout(&mut self, now: Instant) -> Result<(), Error> {
185 self.arm(now);
186
187 if let Some(next_timeout) = self.next_timeout
188 && now >= next_timeout
189 {
190 self.next_timeout = Some(now + self.interval);
191
192 if !self.recorder.is_empty() {
193 let report_timestamp = self.report_timestamp(now);
194 let report = self.recorder.build_report(
195 now,
196 self.sender_ssrc,
197 report_timestamp,
198 self.max_report_size,
199 );
200 if !report.report_blocks.is_empty() {
201 self.write_queue.push_back(TaggedPacket {
202 now,
203 transport: TransportContext::default(),
204 message: AttributedPacket::new(Packet::Rtcp(vec![Box::new(report)])),
205 });
206 }
207 }
208 }
209 Ok(())
210 }
211
212 fn poll_timeout(&mut self) -> Option<Instant> {
213 self.next_timeout
214 }
215}
216
217impl Interceptor for Rfc8888Interceptor {
218 fn bind_remote_stream(&mut self, info: &StreamInfo) {
219 self.streams.insert(info.ssrc);
220 }
221
222 fn unbind_remote_stream(&mut self, info: &StreamInfo) {
223 self.streams.remove(&info.ssrc);
224 self.recorder.remove_stream(info.ssrc);
225 if self.streams.is_empty() {
226 self.next_timeout = None;
227 }
228 }
229
230 fn bind_local_stream(&mut self, _info: &StreamInfo) {}
231
232 fn unbind_local_stream(&mut self, _info: &StreamInfo) {}
233}