1use bytes::{BufMut, BytesMut};
2
3use super::{RtcpPacket, RtcpPacketType};
4
5#[derive(Clone)]
7pub struct SourceDescription {
8 ssrc: u32,
9 cname: String,
10}
11
12impl SourceDescription {
13 pub fn new<T>(ssrc: u32, cname: T) -> Self
15 where
16 T: Into<String>,
17 {
18 let cname = cname.into();
19
20 assert!(cname.len() < 256);
21
22 Self { ssrc, cname }
23 }
24
25 fn encode(&self, buf: &mut BytesMut) {
27 let old_buffer_length = buf.len();
28
29 buf.put_u32(self.ssrc);
30
31 let data = self.cname.as_bytes();
32
33 buf.put_u8(1);
34 buf.put_u8(data.len() as u8);
35 buf.extend_from_slice(data);
36 buf.put_u8(0);
37
38 while ((buf.len() - old_buffer_length) & 0x03) != 0 {
39 buf.put_u8(0);
40 }
41 }
42
43 fn raw_size(&self) -> usize {
45 let len = std::mem::size_of::<u32>() + self.cname.len() + 3;
46
47 (len + 3) & !3
48 }
49}
50
51#[derive(Clone)]
53pub struct SourceDescriptionPacket {
54 chunks: Vec<SourceDescription>,
55}
56
57impl SourceDescriptionPacket {
58 #[inline]
60 pub const fn new() -> Self {
61 Self { chunks: Vec::new() }
62 }
63
64 pub fn with_source_descriptions<T>(mut self, descriptions: T) -> Self
70 where
71 T: Into<Vec<SourceDescription>>,
72 {
73 let chunks = descriptions.into();
74
75 assert!(chunks.len() < 32);
76
77 self.chunks = chunks;
78 self
79 }
80
81 pub fn encode(&self) -> RtcpPacket {
83 let mut payload = BytesMut::with_capacity(self.raw_size());
84
85 for chunk in &self.chunks {
86 chunk.encode(&mut payload);
87 }
88
89 RtcpPacket::new(RtcpPacketType::SDES)
90 .with_item_count(self.chunks.len() as u8)
91 .with_payload(payload.freeze(), 0)
92 }
93
94 pub fn raw_size(&self) -> usize {
96 self.chunks.iter().map(|chunk| chunk.raw_size()).sum()
97 }
98}
99
100impl Default for SourceDescriptionPacket {
101 #[inline]
102 fn default() -> Self {
103 Self::new()
104 }
105}