rtc_interceptor/nack/
responder.rs1use super::send_buffer::SendBuffer;
4use super::stream_supports_nack;
5use crate::Interceptor;
6use crate::stream_info::StreamInfo;
7use crate::{Attribute, 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 version: 2,
153 ssrc: ssrc_rtx,
154 payload_type: pt_rtx,
155 sequence_number: rtx_seq,
156 timestamp: original_packet.header.timestamp,
157 marker: original_packet.header.marker,
158 ..Default::default()
159 },
160 payload: rtx_payload.into(),
161 }
162 } else {
163 original_packet.clone()
165 };
166
167 self.write_queue.push_back(TaggedPacket {
172 now,
173 transport: TransportContext::default(),
174 message: AttributedPacket::new(Packet::Rtp(packet)).with(Attribute::Retransmission),
175 });
176 }
177 }
178}
179
180impl Protocol<TaggedPacket, TaggedPacket, ()> for NackResponderInterceptor {
181 type Rout = TaggedPacket;
182 type Wout = TaggedPacket;
183 type Eout = ();
184 type Error = Error;
185 type Time = Instant;
186
187 fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
188 if let Packet::Rtcp(ref rtcp_packets) = msg.message.packet {
190 for rtcp_packet in rtcp_packets {
191 if let Some(nack) = rtcp_packet
192 .as_any()
193 .downcast_ref::<rtcp::transport_feedbacks::transport_layer_nack::TransportLayerNack>()
194 {
195 self.handle_nack(msg.now, nack);
196 }
197 }
198 }
199
200 self.read_queue.push_back(msg);
201
202 Ok(())
203 }
204
205 fn poll_read(&mut self) -> Option<Self::Rout> {
206 self.read_queue.pop_front()
207 }
208
209 fn handle_write(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
210 if let Packet::Rtp(ref rtp_packet) = msg.message.packet
212 && let Some(stream) = self.streams.get_mut(&rtp_packet.header.ssrc)
213 {
214 stream.send_buffer.add(rtp_packet.clone());
215 }
216
217 self.write_queue.push_back(msg);
218
219 Ok(())
220 }
221
222 fn poll_write(&mut self) -> Option<TaggedPacket> {
223 self.write_queue.pop_front()
225 }
226
227 fn handle_timeout(&mut self, _now: Instant) -> Result<(), Self::Error> {
228 Ok(())
229 }
230
231 fn poll_timeout(&mut self) -> Option<Self::Time> {
232 None
233 }
234}
235
236impl Interceptor for NackResponderInterceptor {
237 fn bind_local_stream(&mut self, info: &StreamInfo) {
238 if stream_supports_nack(info)
239 && let Some(send_buffer) = SendBuffer::new(self.size)
240 {
241 self.streams.insert(
242 info.ssrc,
243 LocalStream {
244 send_buffer,
245 ssrc_rtx: info.ssrc_rtx,
246 payload_type_rtx: info.payload_type_rtx,
247 rtx_sequence_number: 0,
248 },
249 );
250 }
251 }
252
253 fn unbind_local_stream(&mut self, info: &StreamInfo) {
254 self.streams.remove(&info.ssrc);
255 }
256
257 fn bind_remote_stream(&mut self, _info: &StreamInfo) {}
258
259 fn unbind_remote_stream(&mut self, _info: &StreamInfo) {}
260}