1use crate::report::receiver_stream::ReceiverStream;
4use crate::stream_info::StreamInfo;
5use crate::{Interceptor, Packet, TaggedPacket, interceptor};
6use shared::TransportContext;
7use shared::error::Error;
8use std::collections::{HashMap, VecDeque};
9use std::marker::PhantomData;
10use std::time::{Duration, Instant};
11
12pub struct ReceiverReportBuilder<P> {
31 interval: Duration,
33 _phantom: PhantomData<P>,
34}
35
36impl<P> Default for ReceiverReportBuilder<P> {
37 fn default() -> Self {
38 Self {
39 interval: Duration::from_secs(1),
40 _phantom: PhantomData,
41 }
42 }
43}
44
45impl<P> ReceiverReportBuilder<P> {
46 pub fn new() -> Self {
50 Self::default()
51 }
52
53 pub fn with_interval(mut self, interval: Duration) -> Self {
69 self.interval = interval;
70 self
71 }
72
73 pub fn build(self) -> impl FnOnce(P) -> ReceiverReportInterceptor<P> {
86 move |inner| ReceiverReportInterceptor::new(inner, self.interval)
87 }
88}
89
90#[derive(Interceptor)]
109pub struct ReceiverReportInterceptor<P> {
110 #[next]
111 inner: P,
112
113 interval: Duration,
114 next_timeout: Option<Instant>,
115
116 streams: HashMap<u32, ReceiverStream>,
117
118 read_queue: VecDeque<TaggedPacket>,
119 write_queue: VecDeque<TaggedPacket>,
120}
121
122impl<P> ReceiverReportInterceptor<P> {
123 fn new(inner: P, interval: Duration) -> Self {
125 Self {
126 inner,
127
128 interval,
129 next_timeout: None,
130
131 streams: HashMap::new(),
132
133 read_queue: VecDeque::new(),
134 write_queue: VecDeque::new(),
135 }
136 }
137
138 fn process_rtp(&mut self, now: Instant, ssrc: u32, seq: u16, timestamp: u32) {
140 let stream = self.streams.entry(ssrc).or_insert_with(|| {
142 ReceiverStream::new(ssrc, 90000)
144 });
145
146 let pkt = rtp::packet::Packet {
148 header: rtp::header::Header {
149 ssrc,
150 sequence_number: seq,
151 timestamp,
152 ..Default::default()
153 },
154 ..Default::default()
155 };
156
157 stream.process_rtp(now, &pkt);
158 }
159
160 fn process_sender_report(&mut self, now: Instant, sr: &rtcp::sender_report::SenderReport) {
162 if let Some(stream) = self.streams.get_mut(&sr.ssrc) {
163 stream.process_sender_report(now, sr);
164 }
165 }
166
167 fn generate_reports(&mut self, now: Instant) -> Vec<rtcp::receiver_report::ReceiverReport> {
169 self.streams
170 .values_mut()
171 .map(|stream| stream.generate_report(now))
172 .collect()
173 }
174
175 fn register_stream(&mut self, ssrc: u32, clock_rate: u32) {
177 self.streams
178 .entry(ssrc)
179 .or_insert_with(|| ReceiverStream::new(ssrc, clock_rate));
180 }
181}
182
183#[interceptor]
184impl<P: Interceptor> ReceiverReportInterceptor<P> {
185 #[overrides]
186 fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
187 if let Packet::Rtcp(rtcp_packets) = &msg.message {
188 for rtcp_packet in rtcp_packets {
189 if let Some(sr) = rtcp_packet
190 .as_any()
191 .downcast_ref::<rtcp::sender_report::SenderReport>()
192 && let Some(stream) = self.streams.get_mut(&sr.ssrc)
193 {
194 stream.process_sender_report(msg.now, sr);
195 }
196 }
197 } else if let Packet::Rtp(rtp_packet) = &msg.message
198 && let Some(stream) = self.streams.get_mut(&rtp_packet.header.ssrc)
199 {
200 stream.process_rtp(msg.now, rtp_packet);
201
202 if self.next_timeout.is_none() {
204 self.next_timeout = Some(msg.now + self.interval);
205 }
206 }
207
208 self.inner.handle_read(msg)
209 }
210
211 #[overrides]
212 fn poll_write(&mut self) -> Option<Self::Wout> {
213 if let Some(pkt) = self.write_queue.pop_front() {
215 return Some(pkt);
216 }
217 self.inner.poll_write()
218 }
219
220 #[overrides]
221 fn handle_timeout(&mut self, now: Self::Time) -> Result<(), Self::Error> {
222 if let Some(next_timeout) = self.next_timeout
223 && now >= next_timeout
224 {
225 self.next_timeout = Some(now + self.interval);
226
227 for stream in self.streams.values_mut() {
228 let rr = stream.generate_report(now);
229 self.write_queue.push_back(TaggedPacket {
230 now,
231 transport: TransportContext::default(),
232 message: Packet::Rtcp(vec![Box::new(rr)]),
233 });
234 }
235 }
236
237 self.inner.handle_timeout(now)
238 }
239
240 #[overrides]
241 fn poll_timeout(&mut self) -> Option<Self::Time> {
242 match (self.next_timeout, self.inner.poll_timeout()) {
243 (Some(a), Some(b)) => Some(a.min(b)),
244 (Some(a), None) => Some(a),
245 (None, Some(b)) => Some(b),
246 (None, None) => None,
247 }
248 }
249
250 #[overrides]
251 fn bind_remote_stream(&mut self, info: &StreamInfo) {
252 let stream = ReceiverStream::new(info.ssrc, info.clock_rate);
253 self.streams.insert(info.ssrc, stream);
254
255 self.inner.bind_remote_stream(info);
256 }
257
258 #[overrides]
259 fn unbind_remote_stream(&mut self, info: &StreamInfo) {
260 self.streams.remove(&info.ssrc);
261
262 self.inner.unbind_remote_stream(info);
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269 use crate::Registry;
270 use sansio::Protocol;
271
272 fn dummy_rtp_packet() -> TaggedPacket {
273 TaggedPacket {
274 now: Instant::now(),
275 transport: Default::default(),
276 message: crate::Packet::Rtp(rtp::Packet::default()),
277 }
278 }
279
280 #[test]
281 fn test_receiver_report_builder_default() {
282 let chain = Registry::new()
284 .with(ReceiverReportBuilder::default().build())
285 .build();
286
287 assert_eq!(chain.interval, Duration::from_secs(1));
288 assert!(chain.streams.is_empty());
289 }
290
291 #[test]
292 fn test_receiver_report_builder_with_custom_interval() {
293 let chain = Registry::new()
295 .with(
296 ReceiverReportBuilder::default()
297 .with_interval(Duration::from_millis(500))
298 .build(),
299 )
300 .build();
301
302 assert_eq!(chain.interval, Duration::from_millis(500));
303 }
304
305 #[test]
306 fn test_receiver_report_chain_handle_read_write() {
307 let mut chain = Registry::new()
309 .with(ReceiverReportBuilder::default().build())
310 .build();
311
312 let pkt = dummy_rtp_packet();
314 chain.handle_read(pkt).unwrap();
315 assert!(chain.poll_read().is_some());
316
317 let pkt2 = dummy_rtp_packet();
319 let pkt2_message = pkt2.message.clone();
320 chain.handle_write(pkt2).unwrap();
321 assert_eq!(chain.poll_write().unwrap().message, pkt2_message);
322 }
323
324 #[test]
325 fn test_register_stream() {
326 let mut chain = Registry::new()
327 .with(ReceiverReportBuilder::default().build())
328 .build();
329
330 chain.register_stream(12345, 48000);
331 assert!(chain.streams.contains_key(&12345));
332 }
333
334 #[test]
335 fn test_process_rtp() {
336 let mut chain = Registry::new()
337 .with(ReceiverReportBuilder::default().build())
338 .build();
339
340 let now = Instant::now();
341 chain.process_rtp(now, 12345, 1, 1000);
342
343 assert!(chain.streams.contains_key(&12345));
344 }
345
346 #[test]
347 fn test_generate_reports() {
348 let mut chain = Registry::new()
349 .with(ReceiverReportBuilder::default().build())
350 .build();
351
352 let now = Instant::now();
353 chain.process_rtp(now, 12345, 1, 1000);
354 chain.process_rtp(now, 12345, 2, 2000);
355
356 let reports = chain.generate_reports(now);
357 assert_eq!(reports.len(), 1);
358 }
359
360 #[test]
361 fn test_chained_interceptors() {
362 use crate::report::sender::SenderReportBuilder;
363
364 let mut chain = Registry::new()
366 .with(ReceiverReportBuilder::default().build())
367 .with(
368 SenderReportBuilder::default()
369 .with_interval(Duration::from_millis(250))
370 .build(),
371 )
372 .build();
373
374 let pkt = dummy_rtp_packet();
376 chain.handle_read(pkt).unwrap();
377 assert!(chain.poll_read().is_some());
378
379 let pkt2 = dummy_rtp_packet();
380 let pkt2_message = pkt2.message.clone();
381 chain.handle_write(pkt2).unwrap();
382 assert_eq!(chain.poll_write().unwrap().message, pkt2_message);
383 }
384
385 #[test]
386 fn test_receiver_report_generation_on_timeout() {
387 let mut chain = Registry::new()
390 .with(
391 ReceiverReportBuilder::default()
392 .with_interval(Duration::from_secs(1))
393 .build(),
394 )
395 .build();
396
397 let info = StreamInfo {
399 ssrc: 123456,
400 clock_rate: 90000,
401 ..Default::default()
402 };
403 chain.bind_remote_stream(&info);
404
405 let base_time = Instant::now();
406
407 for i in 0..10u16 {
409 let pkt = TaggedPacket {
410 now: base_time,
411 transport: Default::default(),
412 message: Packet::Rtp(rtp::Packet {
413 header: rtp::header::Header {
414 ssrc: 123456,
415 sequence_number: i,
416 timestamp: i as u32 * 3000,
417 ..Default::default()
418 },
419 ..Default::default()
420 }),
421 };
422 chain.handle_read(pkt).unwrap();
423 chain.poll_read();
424 }
425
426 chain.handle_timeout(base_time).unwrap();
428
429 while chain.poll_write().is_some() {}
431
432 let later_time = base_time + Duration::from_secs(2);
434 chain.handle_timeout(later_time).unwrap();
435
436 let report = chain.poll_write();
438 assert!(report.is_some());
439
440 if let Some(tagged) = report {
441 if let Packet::Rtcp(rtcp_packets) = tagged.message {
442 assert_eq!(rtcp_packets.len(), 1);
443 let rr = rtcp_packets[0]
444 .as_any()
445 .downcast_ref::<rtcp::receiver_report::ReceiverReport>()
446 .expect("Expected ReceiverReport");
447 assert_eq!(rr.reports.len(), 1);
448 assert_eq!(rr.reports[0].ssrc, 123456);
449 assert_eq!(rr.reports[0].last_sequence_number, 9);
450 assert_eq!(rr.reports[0].fraction_lost, 0);
451 assert_eq!(rr.reports[0].total_lost, 0);
452 } else {
453 panic!("Expected RTCP packet");
454 }
455 }
456 }
457
458 #[test]
459 fn test_receiver_report_with_packet_loss() {
460 let mut chain = Registry::new()
462 .with(
463 ReceiverReportBuilder::default()
464 .with_interval(Duration::from_secs(1))
465 .build(),
466 )
467 .build();
468
469 let info = StreamInfo {
470 ssrc: 123456,
471 clock_rate: 90000,
472 ..Default::default()
473 };
474 chain.bind_remote_stream(&info);
475
476 let base_time = Instant::now();
477
478 let pkt = TaggedPacket {
480 now: base_time,
481 transport: Default::default(),
482 message: Packet::Rtp(rtp::Packet {
483 header: rtp::header::Header {
484 ssrc: 123456,
485 sequence_number: 1,
486 timestamp: 3000,
487 ..Default::default()
488 },
489 ..Default::default()
490 }),
491 };
492 chain.handle_read(pkt).unwrap();
493 chain.poll_read();
494
495 let pkt = TaggedPacket {
497 now: base_time,
498 transport: Default::default(),
499 message: Packet::Rtp(rtp::Packet {
500 header: rtp::header::Header {
501 ssrc: 123456,
502 sequence_number: 3,
503 timestamp: 9000,
504 ..Default::default()
505 },
506 ..Default::default()
507 }),
508 };
509 chain.handle_read(pkt).unwrap();
510 chain.poll_read();
511
512 let later_time = base_time + Duration::from_secs(2);
514 chain.handle_timeout(later_time).unwrap();
515
516 let report = chain.poll_write();
517 assert!(report.is_some());
518
519 if let Some(tagged) = report {
520 if let Packet::Rtcp(rtcp_packets) = tagged.message {
521 let rr = rtcp_packets[0]
522 .as_any()
523 .downcast_ref::<rtcp::receiver_report::ReceiverReport>()
524 .expect("Expected ReceiverReport");
525 assert_eq!(rr.reports[0].last_sequence_number, 3);
526 assert_eq!(rr.reports[0].total_lost, 1);
528 assert_eq!(rr.reports[0].fraction_lost, (256u32 * 1 / 3) as u8);
530 } else {
531 panic!("Expected RTCP packet");
532 }
533 }
534 }
535
536 #[test]
537 fn test_receiver_report_with_sender_report() {
538 let mut chain = Registry::new()
540 .with(
541 ReceiverReportBuilder::default()
542 .with_interval(Duration::from_secs(1))
543 .build(),
544 )
545 .build();
546
547 let info = StreamInfo {
548 ssrc: 123456,
549 clock_rate: 90000,
550 ..Default::default()
551 };
552 chain.bind_remote_stream(&info);
553
554 let base_time = Instant::now();
555
556 let pkt = TaggedPacket {
558 now: base_time,
559 transport: Default::default(),
560 message: Packet::Rtp(rtp::Packet {
561 header: rtp::header::Header {
562 ssrc: 123456,
563 sequence_number: 1,
564 timestamp: 3000,
565 ..Default::default()
566 },
567 ..Default::default()
568 }),
569 };
570 chain.handle_read(pkt).unwrap();
571 chain.poll_read();
572
573 let sr = rtcp::sender_report::SenderReport {
575 ssrc: 123456,
576 ntp_time: 0x1234_5678_0000_0000,
577 rtp_time: 3000,
578 packet_count: 100,
579 octet_count: 10000,
580 ..Default::default()
581 };
582 let sr_pkt = TaggedPacket {
583 now: base_time,
584 transport: Default::default(),
585 message: Packet::Rtcp(vec![Box::new(sr)]),
586 };
587 chain.handle_read(sr_pkt).unwrap();
588
589 let later_time = base_time + Duration::from_secs(1);
591 chain.handle_timeout(later_time).unwrap();
592
593 let report = chain.poll_write();
594 assert!(report.is_some());
595
596 if let Some(tagged) = report {
597 if let Packet::Rtcp(rtcp_packets) = tagged.message {
598 let rr = rtcp_packets[0]
599 .as_any()
600 .downcast_ref::<rtcp::receiver_report::ReceiverReport>()
601 .expect("Expected ReceiverReport");
602 assert_eq!(rr.reports[0].delay, 65536);
604 assert_eq!(rr.reports[0].last_sender_report, 0x5678_0000);
606 } else {
607 panic!("Expected RTCP packet");
608 }
609 }
610 }
611
612 #[test]
613 fn test_receiver_report_multiple_streams() {
614 let mut chain = Registry::new()
616 .with(
617 ReceiverReportBuilder::default()
618 .with_interval(Duration::from_secs(1))
619 .build(),
620 )
621 .build();
622
623 let info1 = StreamInfo {
624 ssrc: 111111,
625 clock_rate: 90000,
626 ..Default::default()
627 };
628 let info2 = StreamInfo {
629 ssrc: 222222,
630 clock_rate: 48000,
631 ..Default::default()
632 };
633 chain.bind_remote_stream(&info1);
634 chain.bind_remote_stream(&info2);
635
636 let base_time = Instant::now();
637
638 for i in 0..5u16 {
640 let pkt = TaggedPacket {
641 now: base_time,
642 transport: Default::default(),
643 message: Packet::Rtp(rtp::Packet {
644 header: rtp::header::Header {
645 ssrc: 111111,
646 sequence_number: i,
647 timestamp: i as u32 * 3000,
648 ..Default::default()
649 },
650 ..Default::default()
651 }),
652 };
653 chain.handle_read(pkt).unwrap();
654 chain.poll_read();
655 }
656
657 let pkt = TaggedPacket {
659 now: base_time,
660 transport: Default::default(),
661 message: Packet::Rtp(rtp::Packet {
662 header: rtp::header::Header {
663 ssrc: 222222,
664 sequence_number: 0,
665 timestamp: 0,
666 ..Default::default()
667 },
668 ..Default::default()
669 }),
670 };
671 chain.handle_read(pkt).unwrap();
672 chain.poll_read();
673
674 let pkt = TaggedPacket {
675 now: base_time,
676 transport: Default::default(),
677 message: Packet::Rtp(rtp::Packet {
678 header: rtp::header::Header {
679 ssrc: 222222,
680 sequence_number: 5, timestamp: 5 * 960,
682 ..Default::default()
683 },
684 ..Default::default()
685 }),
686 };
687 chain.handle_read(pkt).unwrap();
688 chain.poll_read();
689
690 let later_time = base_time + Duration::from_secs(2);
692 chain.handle_timeout(later_time).unwrap();
693
694 let mut ssrcs = vec![];
696 let mut total_lost = vec![];
697
698 while let Some(tagged) = chain.poll_write() {
699 if let Packet::Rtcp(rtcp_packets) = tagged.message {
700 for rtcp_pkt in rtcp_packets {
701 if let Some(rr) = rtcp_pkt
702 .as_any()
703 .downcast_ref::<rtcp::receiver_report::ReceiverReport>()
704 {
705 for report in &rr.reports {
706 ssrcs.push(report.ssrc);
707 total_lost.push(report.total_lost);
708 }
709 }
710 }
711 }
712 }
713
714 assert_eq!(ssrcs.len(), 2);
715 assert!(ssrcs.contains(&111111));
716 assert!(ssrcs.contains(&222222));
717
718 let idx1 = ssrcs.iter().position(|&s| s == 111111).unwrap();
720 assert_eq!(total_lost[idx1], 0);
721
722 let idx2 = ssrcs.iter().position(|&s| s == 222222).unwrap();
724 assert_eq!(total_lost[idx2], 4);
725 }
726
727 #[test]
728 fn test_receiver_report_unbind_stream() {
729 let mut chain = Registry::new()
731 .with(
732 ReceiverReportBuilder::default()
733 .with_interval(Duration::from_secs(1))
734 .build(),
735 )
736 .build();
737
738 let info = StreamInfo {
739 ssrc: 123456,
740 clock_rate: 90000,
741 ..Default::default()
742 };
743 chain.bind_remote_stream(&info);
744
745 let base_time = Instant::now();
746
747 let pkt = TaggedPacket {
749 now: base_time,
750 transport: Default::default(),
751 message: Packet::Rtp(rtp::Packet {
752 header: rtp::header::Header {
753 ssrc: 123456,
754 sequence_number: 0,
755 timestamp: 0,
756 ..Default::default()
757 },
758 ..Default::default()
759 }),
760 };
761 chain.handle_read(pkt).unwrap();
762 chain.poll_read();
763
764 chain.unbind_remote_stream(&info);
766
767 let later_time = base_time + Duration::from_secs(2);
769 chain.handle_timeout(later_time).unwrap();
770
771 assert!(chain.poll_write().is_none());
773 }
774
775 #[test]
776 fn test_receiver_report_sequence_wrap() {
777 let mut chain = Registry::new()
779 .with(
780 ReceiverReportBuilder::default()
781 .with_interval(Duration::from_secs(1))
782 .build(),
783 )
784 .build();
785
786 let info = StreamInfo {
787 ssrc: 123456,
788 clock_rate: 90000,
789 ..Default::default()
790 };
791 chain.bind_remote_stream(&info);
792
793 let base_time = Instant::now();
794
795 let pkt = TaggedPacket {
797 now: base_time,
798 transport: Default::default(),
799 message: Packet::Rtp(rtp::Packet {
800 header: rtp::header::Header {
801 ssrc: 123456,
802 sequence_number: 0xffff,
803 timestamp: 0,
804 ..Default::default()
805 },
806 ..Default::default()
807 }),
808 };
809 chain.handle_read(pkt).unwrap();
810 chain.poll_read();
811
812 let pkt = TaggedPacket {
814 now: base_time,
815 transport: Default::default(),
816 message: Packet::Rtp(rtp::Packet {
817 header: rtp::header::Header {
818 ssrc: 123456,
819 sequence_number: 0x00,
820 timestamp: 3000,
821 ..Default::default()
822 },
823 ..Default::default()
824 }),
825 };
826 chain.handle_read(pkt).unwrap();
827 chain.poll_read();
828
829 let later_time = base_time + Duration::from_secs(2);
831 chain.handle_timeout(later_time).unwrap();
832
833 let report = chain.poll_write();
834 assert!(report.is_some());
835
836 if let Some(tagged) = report {
837 if let Packet::Rtcp(rtcp_packets) = tagged.message {
838 let rr = rtcp_packets[0]
839 .as_any()
840 .downcast_ref::<rtcp::receiver_report::ReceiverReport>()
841 .expect("Expected ReceiverReport");
842 assert_eq!(rr.reports[0].last_sequence_number, 1 << 16);
844 assert_eq!(rr.reports[0].fraction_lost, 0);
845 assert_eq!(rr.reports[0].total_lost, 0);
846 } else {
847 panic!("Expected RTCP packet");
848 }
849 }
850 }
851}