rtp_parse/rtcp/
rtcp_sr.rs

1use std::fmt::Debug;
2
3use anyhow::{Context, Result};
4use bit_cursor::{
5    bit_read_exts::BitReadExts, bit_write::BitWrite, bit_write_exts::BitWriteExts,
6    byte_order::NetworkOrder,
7};
8
9use crate::{
10    rtcp::{
11        rtcp_header::write_rtcp_header,
12        rtcp_report_block::{read_rtcp_report_block, write_rtcp_report_block},
13        rtcp_sender_info::{read_rtcp_sender_info, write_rtcp_sender_info},
14    },
15    PacketBuffer,
16};
17
18use super::{
19    rtcp_header::RtcpHeader, rtcp_report_block::RtcpReportBlock, rtcp_sender_info::RtcpSenderInfo,
20};
21
22/// https://datatracker.ietf.org/doc/html/rfc3550#section-6.4.1
23///         0                   1                   2                   3
24///         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
25///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26/// header |V=2|P|    RC   |   PT=SR=200   |             length            |
27///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28///        |                         SSRC of sender                        |
29///        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
30/// sender |              NTP timestamp, most significant word             |
31/// info   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32///        |             NTP timestamp, least significant word             |
33///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34///        |                         RTP timestamp                         |
35///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36///        |                     sender's packet count                     |
37///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38///        |                      sender's octet count                     |
39///        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
40/// report |                 SSRC_1 (SSRC of first source)                 |
41/// block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42///   1    | fraction lost |       cumulative number of packets lost       |
43///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44///        |           extended highest sequence number received           |
45///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46///        |                      interarrival jitter                      |
47///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48///        |                         last SR (LSR)                         |
49///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50///        |                   delay since last SR (DLSR)                  |
51///        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
52/// report |                 SSRC_2 (SSRC of second source)                |
53/// block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54///   2    :                               ...                             :
55///        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
56///        |                  profile-specific extensions                  |
57///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58#[derive(Debug)]
59pub struct RtcpSrPacket {
60    pub header: RtcpHeader,
61    pub sender_ssrc: u32,
62    pub sender_info: RtcpSenderInfo,
63    pub report_blocks: Vec<RtcpReportBlock>,
64}
65
66impl RtcpSrPacket {
67    pub const PT: u8 = 200;
68}
69
70pub fn read_rtcp_sr<B: PacketBuffer>(buf: &mut B, header: RtcpHeader) -> Result<RtcpSrPacket> {
71    let sender_ssrc = buf.read_u32::<NetworkOrder>().context("sender ssrc")?;
72    let sender_info = read_rtcp_sender_info(buf).context("sender info")?;
73    let report_blocks = (0u32..header.report_count.into())
74        .map(|i| read_rtcp_report_block(buf).with_context(|| format!("report block {i}")))
75        .collect::<Result<Vec<RtcpReportBlock>>>()
76        .context("report blocks")?;
77
78    Ok(RtcpSrPacket {
79        header,
80        sender_ssrc,
81        sender_info,
82        report_blocks,
83    })
84}
85
86pub fn write_rtcp_sr<W: BitWrite>(buf: &mut W, packet: &RtcpSrPacket) -> Result<()> {
87    write_rtcp_header(buf, &packet.header).context("header")?;
88    buf.write_u32::<NetworkOrder>(packet.sender_ssrc)
89        .context("sender ssrc")?;
90    write_rtcp_sender_info(buf, &packet.sender_info).context("sender info")?;
91    packet
92        .report_blocks
93        .iter()
94        .enumerate()
95        .map(|(i, rb)| {
96            write_rtcp_report_block(buf, rb).with_context(|| format!("report block {i}"))
97        })
98        .collect::<Result<Vec<()>>>()
99        .context("report blocks")?;
100    todo!()
101}