rtp_parse/rtcp/
rtcp_fb_fir.rs1use crate::{PacketBuffer, PacketBufferMut};
2use anyhow::{bail, Context, Result};
3use bit_cursor::{
4 bit_read_exts::BitReadExts,
5 bit_write_exts::BitWriteExts,
6 byte_order::NetworkOrder,
7 nsw_types::{u24, u5},
8};
9
10use super::{
11 rtcp_fb_header::{write_rtcp_fb_header, RtcpFbHeader},
12 rtcp_header::{write_rtcp_header, RtcpHeader},
13};
14
15#[derive(Debug)]
34pub struct RtcpFbFirPacket {
35 pub header: RtcpHeader,
36 pub fb_header: RtcpFbHeader,
37 pub fcis: Vec<RtcpFbFirFci>,
38}
39
40impl RtcpFbFirPacket {
41 pub const FMT: u5 = u5::new(4);
42}
43
44pub fn read_rtcp_fb_fir<B: PacketBuffer>(
45 buf: &mut B,
46 header: RtcpHeader,
47 fb_header: RtcpFbHeader,
48) -> Result<RtcpFbFirPacket> {
49 if fb_header.media_source_ssrc != 0 {
53 bail!("SSRC of media source must be set to 0");
54 }
55 let mut num_fci = 1;
56 let mut fcis = Vec::new();
57 while buf.bytes_remaining() >= RtcpFbFirFci::SIZE_BYTES {
58 let fci = read_rtcp_fb_fir_fci(buf).with_context(|| format!("fci {num_fci}"))?;
59 fcis.push(fci);
60 num_fci += 1;
61 }
62 Ok(RtcpFbFirPacket {
63 header,
64 fb_header,
65 fcis,
66 })
67}
68
69pub fn write_rtcp_fb_fir<B: PacketBufferMut>(buf: &mut B, fb_fir: &RtcpFbFirPacket) -> Result<()> {
70 write_rtcp_header(buf, &fb_fir.header).context("header")?;
71 write_rtcp_fb_header(buf, &fb_fir.fb_header).context("fb header")?;
72 for (i, fci) in fb_fir.fcis.iter().enumerate() {
73 write_rtcp_fb_fir_fci(buf, fci).with_context(|| format!("fci {i}"))?;
74 }
75
76 Ok(())
77}
78
79#[derive(Debug)]
80pub struct RtcpFbFirFci {
81 ssrc: u32,
82 seq_num: u8,
83}
84
85impl RtcpFbFirFci {
86 pub const SIZE_BYTES: usize = 8;
87}
88
89pub fn read_rtcp_fb_fir_fci<B: PacketBuffer>(buf: &mut B) -> Result<RtcpFbFirFci> {
90 let ssrc = buf.read_u32::<NetworkOrder>().context("source")?;
91 let seq_num = buf.read_u8().context("seq num")?;
92 let _ = buf.read_u24::<NetworkOrder>().context("reserved")?;
94
95 Ok(RtcpFbFirFci { ssrc, seq_num })
96}
97
98pub fn write_rtcp_fb_fir_fci<B: PacketBufferMut>(
99 buf: &mut B,
100 fb_fir_fci: &RtcpFbFirFci,
101) -> Result<()> {
102 buf.write_u32::<NetworkOrder>(fb_fir_fci.ssrc)
103 .context("source")?;
104 buf.write_u8(fb_fir_fci.seq_num).context("seq num")?;
105 buf.write_u24::<NetworkOrder>(u24::new(0))
106 .context("reserved")?;
107
108 Ok(())
109}