rtc_interceptor/nack/
responder.rs1use super::send_buffer::SendBuffer;
4use super::stream_supports_nack;
5use crate::Interceptor;
6use crate::stream_info::StreamInfo;
7use crate::{AttributedPacket, Packet, TaggedPacket};
8use sansio::Protocol;
9use shared::TransportContext;
10use shared::error::Error;
11use std::collections::{HashMap, VecDeque};
12use std::time::Instant;
13
14pub struct NackResponderBuilder {
28 size: u16,
30}
31
32impl Default for NackResponderBuilder {
33 fn default() -> Self {
34 Self { size: 1024 }
35 }
36}
37
38impl NackResponderBuilder {
39 pub fn new() -> Self {
41 Self::default()
42 }
43
44 pub fn with_size(mut self, size: u16) -> Self {
49 self.size = size;
50 self
51 }
52
53 pub fn build(self) -> NackResponderInterceptor {
55 NackResponderInterceptor::new(self.size)
56 }
57}
58
59struct LocalStream {
61 send_buffer: SendBuffer,
63 ssrc_rtx: Option<u32>,
65 payload_type_rtx: Option<u8>,
67 rtx_sequence_number: u16,
69}
70
71pub struct NackResponderInterceptor {
76 size: u16,
78
79 streams: HashMap<u32, LocalStream>,
81
82 write_queue: VecDeque<TaggedPacket>,
84 read_queue: VecDeque<TaggedPacket>,
86}
87
88impl NackResponderInterceptor {
89 fn new(size: u16) -> Self {
90 Self {
91 read_queue: VecDeque::new(),
92 size,
93 streams: HashMap::new(),
94 write_queue: VecDeque::new(),
95 }
96 }
97
98 fn handle_nack(
100 &mut self,
101 now: Instant,
102 nack: &rtcp::transport_feedbacks::transport_layer_nack::TransportLayerNack,
103 ) {
104 let mut seqs_to_retransmit = Vec::new();
106
107 for nack_pair in &nack.nacks {
108 seqs_to_retransmit.push(nack_pair.packet_id);
110
111 for i in 0..16 {
113 if nack_pair.lost_packets & (1 << i) != 0 {
114 let seq = nack_pair.packet_id.wrapping_add(i + 1);
115 seqs_to_retransmit.push(seq);
116 }
117 }
118 }
119
120 let Some(stream) = self.streams.get_mut(&nack.media_ssrc) else {
121 return;
122 };
123
124 for seq in seqs_to_retransmit {
126 let Some(original_packet) = stream.send_buffer.get(seq) else {
127 continue;
128 };
129
130 let packet = if let (Some(ssrc_rtx), Some(pt_rtx)) =
131 (stream.ssrc_rtx, stream.payload_type_rtx)
132 {
133 let original_seq = original_packet.header.sequence_number;
138 let mut rtx_payload = Vec::with_capacity(2 + original_packet.payload.len());
139 rtx_payload.extend_from_slice(&original_seq.to_be_bytes());
140 rtx_payload.extend_from_slice(&original_packet.payload);
141
142 let rtx_seq = stream.rtx_sequence_number;
143 stream.rtx_sequence_number = stream.rtx_sequence_number.wrapping_add(1);
144
145 rtp::Packet {
146 header: rtp::header::Header {
147 ssrc: ssrc_rtx,
148 payload_type: pt_rtx,
149 sequence_number: rtx_seq,
150 timestamp: original_packet.header.timestamp,
151 marker: original_packet.header.marker,
152 ..Default::default()
153 },
154 payload: rtx_payload.into(),
155 }
156 } else {
157 original_packet.clone()
159 };
160
161 self.write_queue.push_back(TaggedPacket {
162 now,
163 transport: TransportContext::default(),
164 message: AttributedPacket::new(Packet::Rtp(packet)),
165 });
166 }
167 }
168}
169
170impl Protocol<TaggedPacket, TaggedPacket, ()> for NackResponderInterceptor {
171 type Rout = TaggedPacket;
172 type Wout = TaggedPacket;
173 type Eout = ();
174 type Error = Error;
175 type Time = Instant;
176
177 fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
178 if let Packet::Rtcp(ref rtcp_packets) = msg.message.packet {
180 for rtcp_packet in rtcp_packets {
181 if let Some(nack) = rtcp_packet
182 .as_any()
183 .downcast_ref::<rtcp::transport_feedbacks::transport_layer_nack::TransportLayerNack>()
184 {
185 self.handle_nack(msg.now, nack);
186 }
187 }
188 }
189
190 self.read_queue.push_back(msg);
191
192 Ok(())
193 }
194
195 fn poll_read(&mut self) -> Option<Self::Rout> {
196 self.read_queue.pop_front()
197 }
198
199 fn handle_write(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
200 if let Packet::Rtp(ref rtp_packet) = msg.message.packet
202 && let Some(stream) = self.streams.get_mut(&rtp_packet.header.ssrc)
203 {
204 stream.send_buffer.add(rtp_packet.clone());
205 }
206
207 self.write_queue.push_back(msg);
208
209 Ok(())
210 }
211
212 fn poll_write(&mut self) -> Option<TaggedPacket> {
213 self.write_queue.pop_front()
215 }
216
217 fn handle_timeout(&mut self, _now: Instant) -> Result<(), Self::Error> {
218 Ok(())
219 }
220
221 fn poll_timeout(&mut self) -> Option<Self::Time> {
222 None
223 }
224}
225
226impl Interceptor for NackResponderInterceptor {
227 fn bind_local_stream(&mut self, info: &StreamInfo) {
228 if stream_supports_nack(info)
229 && let Some(send_buffer) = SendBuffer::new(self.size)
230 {
231 self.streams.insert(
232 info.ssrc,
233 LocalStream {
234 send_buffer,
235 ssrc_rtx: info.ssrc_rtx,
236 payload_type_rtx: info.payload_type_rtx,
237 rtx_sequence_number: 0,
238 },
239 );
240 }
241 }
242
243 fn unbind_local_stream(&mut self, info: &StreamInfo) {
244 self.streams.remove(&info.ssrc);
245 }
246
247 fn bind_remote_stream(&mut self, _info: &StreamInfo) {}
248
249 fn unbind_remote_stream(&mut self, _info: &StreamInfo) {}
250}