rtc_media/io/sample_builder/
mod.rs1#[cfg(test)]
2mod sample_builder_test;
3#[cfg(test)]
4mod sample_sequence_location_test;
5
6pub mod sample_sequence_location;
8
9use self::sample_sequence_location::{Comparison, SampleSequenceLocation};
10use crate::Sample;
11use bytes::Bytes;
12use rtp::Packet;
13use rtp::packetizer::Depacketizer;
14use shared::time::SystemInstant;
15use std::time::Duration;
16
17pub struct SampleBuilder<T: Depacketizer> {
19 max_late: u16,
21 max_late_timestamp: u32,
23 buffer: Vec<Option<Packet>>,
24 prepared_samples: Vec<Option<Sample>>,
25 last_sample_timestamp: Option<u32>,
26
27 depacketizer: T,
29
30 sample_rate: u32,
32
33 filled: SampleSequenceLocation,
35
36 active: SampleSequenceLocation,
38
39 prepared: SampleSequenceLocation,
41
42 dropped_packets: u16,
44
45 padding_packets: u16,
48}
49
50impl<T: Depacketizer> SampleBuilder<T> {
51 pub fn new(max_late: u16, depacketizer: T, sample_rate: u32) -> Self {
57 Self {
58 max_late,
59 max_late_timestamp: 0,
60 buffer: vec![None; u16::MAX as usize + 1],
61 prepared_samples: (0..=u16::MAX as usize).map(|_| None).collect(),
62 last_sample_timestamp: None,
63 depacketizer,
64 sample_rate,
65 filled: SampleSequenceLocation::new(),
66 active: SampleSequenceLocation::new(),
67 prepared: SampleSequenceLocation::new(),
68 dropped_packets: 0,
69 padding_packets: 0,
70 }
71 }
72
73 pub fn with_max_time_delay(mut self, max_late_duration: Duration) -> Self {
78 self.max_late_timestamp =
79 (self.sample_rate as u128 * max_late_duration.as_millis() / 1000) as u32;
80 self
81 }
82
83 fn too_old(&self, location: &SampleSequenceLocation) -> bool {
84 if self.max_late_timestamp == 0 {
85 return false;
86 }
87
88 let mut found_head: Option<u32> = None;
89 let mut found_tail: Option<u32> = None;
90
91 let mut i = location.head;
92 while i != location.tail {
93 if let Some(ref packet) = self.buffer[i as usize] {
94 found_head = Some(packet.header.timestamp);
95 break;
96 }
97 i = i.wrapping_add(1);
98 }
99
100 if found_head.is_none() {
101 return false;
102 }
103
104 let mut i = location.tail.wrapping_sub(1);
105 while i != location.head {
106 if let Some(ref packet) = self.buffer[i as usize] {
107 found_tail = Some(packet.header.timestamp);
108 break;
109 }
110 i = i.wrapping_sub(1);
111 }
112
113 if found_tail.is_none() {
114 return false;
115 }
116
117 found_tail.unwrap().wrapping_sub(found_head.unwrap()) > self.max_late_timestamp
118 }
119
120 fn fetch_timestamp(&self, location: &SampleSequenceLocation) -> Option<u32> {
122 if location.empty() {
123 None
124 } else {
125 Some(
126 (self.buffer[location.head as usize])
127 .as_ref()?
128 .header
129 .timestamp,
130 )
131 }
132 }
133
134 fn release_packet(&mut self, i: u16) {
135 self.buffer[i as usize] = None;
136 }
137
138 fn purge_consumed_buffers(&mut self) {
141 let active = self.active;
142 self.purge_consumed_location(&active, false);
143 }
144
145 fn purge_consumed_location(&mut self, consume: &SampleSequenceLocation, force_consume: bool) {
148 if !self.filled.has_data() {
149 return;
150 }
151 match consume.compare(self.filled.head) {
152 Comparison::Inside if force_consume => {
153 self.release_packet(self.filled.head);
154 self.filled.head = self.filled.head.wrapping_add(1);
155 }
156 Comparison::Before => {
157 self.release_packet(self.filled.head);
158 self.filled.head = self.filled.head.wrapping_add(1);
159 }
160 _ => {}
161 }
162 }
163
164 fn purge_buffers(&mut self) {
167 self.purge_consumed_buffers();
168
169 while (self.too_old(&self.filled) || (self.filled.count() > self.max_late))
170 && self.filled.has_data()
171 {
172 if self.active.empty() {
173 self.active = self.filled;
175 }
176
177 if self.active.has_data() && (self.active.head == self.filled.head) {
178 let err = match self.build_sample(true) {
181 Ok(_) => continue,
182 Err(e) => e,
183 };
184
185 if !matches!(err, BuildError::InvalidPartition(_)) {
186 self.dropped_packets += 1;
188 }
189
190 self.active.head = self.active.head.wrapping_add(1);
192 }
193
194 self.release_packet(self.filled.head);
195 self.filled.head = self.filled.head.wrapping_add(1);
196 }
197 }
198
199 pub fn push(&mut self, p: Packet) {
204 let sequence_number = p.header.sequence_number;
205 self.buffer[sequence_number as usize] = Some(p);
206 match self.filled.compare(sequence_number) {
207 Comparison::Void => {
208 self.filled.head = sequence_number;
209 self.filled.tail = sequence_number.wrapping_add(1);
210 }
211 Comparison::Before => {
212 self.filled.head = sequence_number;
213 }
214 Comparison::After => {
215 self.filled.tail = sequence_number.wrapping_add(1);
216 }
217 _ => {}
218 }
219 self.purge_buffers();
220 }
221
222 fn build_sample(
226 &mut self,
227 purging_buffers: bool,
228 ) -> Result<SampleSequenceLocation, BuildError> {
229 if self.active.empty() {
230 self.active = self.filled;
231 }
232
233 if self.active.empty() {
234 return Err(BuildError::NoActiveSegment);
235 }
236
237 if self.filled.compare(self.active.tail) == Comparison::Inside {
238 self.active.tail = self.filled.tail;
239 }
240
241 let mut consume = SampleSequenceLocation::new();
242
243 let mut i = self.active.head;
244 let head_timestamp = self.fetch_timestamp(&self.active);
246 while let Some(ref packet) = self.buffer[i as usize] {
247 if self.active.compare(i) == Comparison::After {
248 break;
249 }
250 let is_same_timestamp = head_timestamp.map(|t| packet.header.timestamp == t);
251 let is_different_timestamp = is_same_timestamp.map(std::ops::Not::not);
252 let is_partition_tail = self
253 .depacketizer
254 .is_partition_tail(packet.header.marker, &packet.payload);
255
256 if is_partition_tail && is_same_timestamp.unwrap_or(true) {
265 consume.head = self.active.head;
266 consume.tail = i.wrapping_add(1);
267 break;
268 }
269
270 if is_different_timestamp.unwrap_or(false) {
271 consume.head = self.active.head;
272 consume.tail = i;
273 break;
274 }
275 i = i.wrapping_add(1);
276 }
277
278 if consume.empty() {
279 return Err(BuildError::NothingToConsume);
280 }
281
282 if !purging_buffers && self.buffer[consume.tail as usize].is_none() {
283 return Err(BuildError::PendingTimestampPacket);
287 }
288
289 let sample_timestamp = self.fetch_timestamp(&self.active).unwrap_or(0);
290 let mut after_timestamp = sample_timestamp;
291
292 for i in consume.tail..self.active.tail {
294 if let Some(ref packet) = self.buffer[i as usize] {
295 after_timestamp = packet.header.timestamp;
296 break;
297 }
298 }
299
300 let head_payload = self.buffer[consume.head as usize]
303 .as_ref()
304 .map(|p| &p.payload)
305 .ok_or(BuildError::GapInSegment)?;
306 if !self.depacketizer.is_partition_head(head_payload) {
307 let is_padding = consume.range(&self.buffer).all(|p| {
310 p.map(|p| {
311 self.last_sample_timestamp == Some(p.header.timestamp) && p.payload.is_empty()
312 })
313 .unwrap_or(false)
314 });
315
316 self.dropped_packets += consume.count();
317 if is_padding {
318 self.padding_packets += consume.count();
319 }
320 self.purge_consumed_location(&consume, true);
321 self.purge_consumed_buffers();
322
323 self.active.head = consume.tail;
324 return Err(BuildError::InvalidPartition(consume));
325 }
326
327 self.active.head = consume.tail;
329
330 let sample_data: Bytes = if consume.count() == 1 {
337 let payload = self.buffer[consume.head as usize]
338 .as_ref()
339 .map(|p| &p.payload)
340 .ok_or(BuildError::GapInSegment)?;
341 self.depacketizer
342 .depacketize(payload)
343 .map_err(|_| BuildError::DepacketizerFailed)?
344 } else {
345 let mut data: Vec<u8> = Vec::new();
346 let mut i = consume.head;
347 while i != consume.tail {
348 let payload = self.buffer[i as usize]
349 .as_ref()
350 .map(|p| &p.payload)
351 .ok_or(BuildError::GapInSegment)?;
352
353 let p = self
354 .depacketizer
355 .depacketize(payload)
356 .map_err(|_| BuildError::DepacketizerFailed)?;
357
358 data.extend_from_slice(&p);
359 i = i.wrapping_add(1);
360 }
361 Bytes::from(data)
362 };
363 let samples = after_timestamp.wrapping_sub(sample_timestamp);
364
365 let sample = Sample {
366 data: sample_data,
367 timestamp: SystemInstant::now(),
368 duration: Duration::from_secs_f64((samples as f64) / (self.sample_rate as f64)),
369 packet_timestamp: sample_timestamp,
370 prev_dropped_packets: self.dropped_packets,
371 prev_padding_packets: self.padding_packets,
372 };
373
374 self.dropped_packets = 0;
375 self.padding_packets = 0;
376 self.last_sample_timestamp = Some(sample_timestamp);
377
378 self.prepared_samples[self.prepared.tail as usize] = Some(sample);
379 self.prepared.tail = self.prepared.tail.wrapping_add(1);
380
381 self.purge_consumed_location(&consume, true);
382 self.purge_consumed_buffers();
383
384 Ok(consume)
385 }
386
387 pub fn pop(&mut self) -> Option<Sample> {
390 let _ = self.build_sample(false);
391
392 if self.prepared.empty() {
393 return None;
394 }
395 let result = self.prepared_samples[self.prepared.head as usize].take();
396 self.prepared.head = self.prepared.head.wrapping_add(1);
397 result
398 }
399
400 pub fn pop_with_timestamp(&mut self) -> Option<(Sample, u32)> {
404 if let Some(sample) = self.pop() {
405 let timestamp = sample.packet_timestamp;
406 Some((sample, timestamp))
407 } else {
408 None
409 }
410 }
411}
412
413pub(crate) fn seqnum_distance(x: u16, y: u16) -> u16 {
423 let diff = x.wrapping_sub(y);
424 if diff > 0xFFFF / 2 {
425 0xFFFF - diff + 1
426 } else {
427 diff
428 }
429}
430
431#[derive(Debug)]
432enum BuildError {
433 NoActiveSegment,
435
436 NothingToConsume,
438
439 PendingTimestampPacket,
442
443 InvalidPartition(SampleSequenceLocation),
446
447 GapInSegment,
449
450 DepacketizerFailed,
452}