hyperspeed_broadcast/rtc/
codecs.rs1use std::num::{NonZeroU32, NonZeroU8};
2
3use mediasoup::router::RouterOptions;
4use mediasoup::rtp_parameters::{MimeTypeAudio, MimeTypeVideo, RtcpFeedback, RtpCodecCapability, RtpCodecParametersParameters};
5
6use super::routers::DataSource;
7
8pub struct VideoCodec {
9 pub mime_type: MimeTypeVideo,
10 pub clock_rate: u32,
11 pub parameters: RtpCodecParametersParameters,
12 pub rtcp_feedback: Vec<RtcpFeedback>
13}
14
15impl VideoCodec {
16 pub fn from(codec: &str) -> VideoCodec {
17 let mime_type = match codec {
18 "H264" => MimeTypeVideo::H264,
19 _ => unimplemented!()
20 };
21
22 let mut parameters = match mime_type {
23 MimeTypeVideo::H264 => RtpCodecParametersParameters::from([
24 ("packetization-mode", 1_u32.into()),
25 ("level-asymmetry-allowed", 1_u32.into())
26 ]),
27 _ => unreachable!()
28 };
29
30 parameters.insert("profile-level-id", "42e01f");
31
32 let clock_rate = match mime_type {
33 MimeTypeVideo::H264 => 90_000,
34 _ => unreachable!()
35 };
36
37 let rtcp_feedback = match mime_type {
38 MimeTypeVideo::H264 => vec! [
39 RtcpFeedback::Nack,
40 RtcpFeedback::NackPli,
41 RtcpFeedback::CcmFir,
42 RtcpFeedback::GoogRemb,
43 RtcpFeedback::TransportCc,
44 ],
45 _ => unreachable!()
46 };
47
48 VideoCodec {
49 mime_type,
50 clock_rate,
51 parameters,
52 rtcp_feedback
53 }
54 }
55}
56
57pub struct AudioCodec {
58 pub mime_type: MimeTypeAudio,
59 pub clock_rate: u32,
60 pub parameters: RtpCodecParametersParameters,
61 pub rtcp_feedback: Vec<RtcpFeedback>
62}
63
64impl AudioCodec {
65 pub fn from(codec: &str) -> AudioCodec {
66 let mime_type = match codec {
67 "OPUS" => MimeTypeAudio::Opus,
68 _ => unimplemented!()
69 };
70
71 let parameters = RtpCodecParametersParameters::default();
72 let rtcp_feedback = Vec::new();
73
74 let clock_rate = match mime_type {
75 MimeTypeAudio::Opus => 48_000,
76 _ => unreachable!()
77 };
78
79 AudioCodec {
80 mime_type,
81 clock_rate,
82 parameters,
83 rtcp_feedback
84 }
85 }
86}
87
88pub fn init_codecs(options: &mut RouterOptions, source: &DataSource) {
89 match source {
90 DataSource::Ftl(handshake) => {
91 if let Some(video) = &handshake.video {
92 let VideoCodec { mime_type, clock_rate, parameters, rtcp_feedback }
93 = VideoCodec::from(&video.codec);
94
95 options.media_codecs.push(
96 RtpCodecCapability::Video {
97 mime_type,
98 preferred_payload_type: None,
99 clock_rate: NonZeroU32::new(clock_rate).unwrap(),
100 parameters,
101 rtcp_feedback
102 }
103 );
104 }
105
106 if let Some(audio) = &handshake.audio {
107 let AudioCodec { mime_type, clock_rate, parameters, rtcp_feedback }
108 = AudioCodec::from(&audio.codec);
109
110 options.media_codecs.push(
111 RtpCodecCapability::Audio {
112 mime_type,
113 preferred_payload_type: None,
114 clock_rate: NonZeroU32::new(clock_rate).unwrap(),
115 channels: NonZeroU8::new(2).unwrap(),
116 parameters,
117 rtcp_feedback
118 }
119 );
120 }
121 }
122 }
123}