1use std::borrow::Cow;
2
3use derive_into_owned::IntoOwned;
4
5use crate::{
6 attributes::{
7 candidate, dtls, extmap, ice::IceParameter, msid, rtcp, rtpmap, AttributeLine, BundleGroup,
8 Control, Direction, Fingerprint, Fmtp, Ice, RtcpOption, Rtp, Ssrc, SsrcGroup,
9 },
10 lines::{connection::Connection, media::Media, SessionLine},
11 SdpLine,
12};
13
14#[derive(Default, IntoOwned, PartialEq, Eq)]
15#[cfg_attr(feature = "debug", derive(Debug))]
16#[cfg_attr(
17 feature = "serde",
18 derive(serde::Serialize, serde::Deserialize),
19 serde(rename_all = "camelCase")
20)]
21pub struct MediaSection<'a> {
22 pub r#type: Cow<'a, str>,
23 pub port: u32,
24 pub protocol: Vec<Cow<'a, str>>,
25 pub payloads: Vec<Cow<'a, str>>,
26
27 pub connection: Option<Connection>,
28 pub candidates: Vec<candidate::Candidate<'a>>,
29 pub ice: Ice<'a>,
31 pub mid: Option<Cow<'a, str>>,
32 pub msid_semantic: Option<msid::MsidSemantic<'a>>,
33 pub msid: Option<msid::Msid<'a>>,
34 pub rtp_map: Vec<rtpmap::RtpMap<'a>>,
35 pub p_time: Option<rtpmap::PTime>,
36 pub ssrc: Vec<Ssrc<'a>>,
37 pub bundle_group: Option<BundleGroup<'a>>,
38 pub bundle_only: bool,
39 pub ssrc_group: Option<SsrcGroup>,
40 pub fingerprint: Option<Fingerprint<'a>>,
41 pub direction: Option<Direction>,
42 pub rtp: Option<Rtp<'a>>,
43 pub rtcp: Option<rtcp::Rtcp>,
44 pub fmtp: Vec<Fmtp<'a>>,
45 pub rtcp_fb: Vec<rtcp::Fb<'a>>,
46 pub rtcp_option: Vec<RtcpOption>,
47 pub control: Option<Control<'a>>,
48 pub setup_role: Option<dtls::SetupRole>,
49 pub extmap: Vec<extmap::Extmap<'a>>,
50
51 pub attributes: Vec<AttributeLine<'a>>,
52}
53
54impl<'a> MediaSection<'a> {
55 pub fn media(&self) -> Media<'a> {
56 Media {
57 r#type: self.r#type.clone(),
58 port: self.port,
59 protocol: self.protocol.clone(),
60 payloads: self.payloads.clone(),
61 }
62 }
63 pub(crate) fn add_line(&mut self, line: SdpLine<'a>) {
64 use AttributeLine::*;
65 use SessionLine::*;
66 match line {
67 SdpLine::Session(Media(_)) => unreachable!(),
68 SdpLine::Session(SessionLine::Connection(conn)) => self.connection = Some(conn),
69 #[cfg(feature = "debug")]
70 SdpLine::Session(session) => eprintln!("🔥 {:#?}", session),
71 #[cfg(all(feature = "udisplay", not(feature = "debug")))]
72 SdpLine::Session(session) => eprintln!("🔥 {}", crate::ufmt_to_string(&session)),
73 #[cfg(not(all(feature = "udisplay", feature = "debug")))]
74 SdpLine::Session(_session) => {},
75
76 SdpLine::Attribute(Candidate(candidate)) => self.candidates.push(candidate),
77 SdpLine::Attribute(Ice(IceParameter::Options(o))) => self.ice.options = Some(o),
78 SdpLine::Attribute(Ice(IceParameter::Ufrag(o))) => self.ice.ufrag = Some(o),
79 SdpLine::Attribute(Ice(IceParameter::Pwd(o))) => self.ice.pwd = Some(o),
80 SdpLine::Attribute(attr @ Ice(_)) => self.attributes.push(attr),
81 SdpLine::Attribute(Mid(mid)) => self.mid = Some(mid.0),
82 SdpLine::Attribute(MsidSemantic(semantic)) => self.msid_semantic = Some(semantic),
83 SdpLine::Attribute(Msid(msid)) => self.msid = Some(msid),
84 SdpLine::Attribute(RtpMap(rtp_map)) => self.rtp_map.push(rtp_map),
85 SdpLine::Attribute(PTime(p_time)) => self.p_time = Some(p_time),
86 SdpLine::Attribute(Ssrc(ssrc)) => self.ssrc.push(ssrc),
87 SdpLine::Attribute(BundleGroup(bundle_group)) => self.bundle_group = Some(bundle_group),
88 SdpLine::Attribute(SsrcGroup(ssrc_group)) => self.ssrc_group = Some(ssrc_group),
89 SdpLine::Attribute(Fingerprint(fingerprint)) => self.fingerprint = Some(fingerprint),
90 SdpLine::Attribute(Direction(direction)) => self.direction = Some(direction),
91
92 SdpLine::Attribute(Rtp(rtp)) => self.rtp = Some(rtp),
93 SdpLine::Attribute(Rtcp(rtcp)) => self.rtcp = Some(rtcp),
94 SdpLine::Attribute(Fmtp(fmtp)) => self.fmtp.push(fmtp),
95 SdpLine::Attribute(RtcpFb(rtcp_fb)) => self.rtcp_fb.push(rtcp_fb),
96 SdpLine::Attribute(RtcpOption(rtcp_option)) => self.rtcp_option.push(rtcp_option),
97 SdpLine::Attribute(Control(control)) => self.control = Some(control),
98 SdpLine::Attribute(SetupRole(setup_role)) => self.setup_role = Some(setup_role),
99 SdpLine::Attribute(Extmap(extmap)) => self.extmap.push(extmap),
100 SdpLine::Attribute(AttributeLine::BundleOnly) => self.bundle_only = true,
101 SdpLine::Attribute(attr) => self.attributes.push(attr),
102 SdpLine::Comment(_) => {}
103 }
104 }
105}
106
107impl<'a> From<Media<'a>> for MediaSection<'a> {
108 fn from(mline: Media<'a>) -> Self {
109 Self {
110 r#type: mline.r#type,
111 port: mline.port,
112 protocol: mline.protocol,
113 payloads: mline.payloads,
114 ..Default::default()
115 }
116 }
117}