oddity_sdp_protocol/
codec.rs

1use std::fmt::Write;
2
3use base64::engine::Engine;
4
5pub use super::{fmt::FMT_RTP_PAYLOAD_DYNAMIC, Tag};
6
7pub trait MediaAttributes {
8    fn media_attributes(&self) -> Vec<Tag>;
9}
10
11pub enum CodecInfo<'params> {
12    H264(H264CodecParameters<'params>),
13}
14
15impl<'params> CodecInfo<'params> {
16    pub fn h264(
17        sps: &'params [u8],
18        pps: &'params [&'params [u8]],
19        packetization_mode: usize,
20    ) -> Self {
21        Self::H264(H264CodecParameters {
22            sps,
23            pps,
24            packetization_mode,
25        })
26    }
27}
28
29pub struct H264CodecParameters<'params> {
30    sps: &'params [u8],
31    pps: &'params [&'params [u8]],
32    packetization_mode: usize,
33}
34
35impl MediaAttributes for CodecInfo<'_> {
36    fn media_attributes(&self) -> Vec<Tag> {
37        match self {
38            CodecInfo::H264(params) => vec![
39                h264_rtpmap(),
40                h264_fmtp(params.packetization_mode, params.sps, params.pps),
41            ],
42        }
43    }
44}
45
46fn h264_rtpmap() -> Tag {
47    Tag::Value(
48        "rtpmap".to_string(),
49        format!("{} H264/90000", FMT_RTP_PAYLOAD_DYNAMIC),
50    )
51}
52
53fn h264_fmtp(packetization_mode: usize, sps: &[u8], pps: &[&[u8]]) -> Tag {
54    let profile_level_id_bytes = &sps[1..4];
55    let profile_level_id = profile_level_id_bytes
56        .iter()
57        .fold(String::new(), |mut output, b| {
58            let _ = write!(output, "{b:02X}");
59            output
60        });
61
62    let mut parameter_sets = Vec::with_capacity(1 + pps.len());
63    parameter_sets.push(base64::engine::general_purpose::STANDARD.encode(sps));
64    parameter_sets.extend(
65        pps.iter()
66            .map(|pps| base64::engine::general_purpose::STANDARD.encode(pps)),
67    );
68    let sprop_parameter_sets = parameter_sets.join(",");
69
70    Tag::Value(
71        "fmtp".to_string(),
72        format!(
73            "{} packetization-mode={}; profile-level-id={}; sprop-parameter-sets={}",
74            FMT_RTP_PAYLOAD_DYNAMIC, packetization_mode, profile_level_id, sprop_parameter_sets,
75        ),
76    )
77}