1use crate::{media::AudioFrame, media::PcmBuf, media::Samples};
2use audio_codec::{
3 CodecType, Decoder, Encoder, Resampler, bytes_to_samples,
4 g722::{G722Decoder, G722Encoder},
5 pcma::{PcmaDecoder, PcmaEncoder},
6 pcmu::{PcmuDecoder, PcmuEncoder},
7 samples_to_bytes,
8};
9use std::collections::HashMap;
10
11use audio_codec::g729::{G729Decoder, G729Encoder};
12#[cfg(feature = "opus")]
13use audio_codec::opus::{OpusDecoder, OpusEncoder};
14
15pub struct TrackCodec {
16 pcmu_encoder: PcmuEncoder,
17 pcmu_decoder: PcmuDecoder,
18 pcma_encoder: PcmaEncoder,
19 pcma_decoder: PcmaDecoder,
20
21 g722_encoder: Option<Box<G722Encoder>>,
22 g722_decoder: Option<Box<G722Decoder>>,
23
24 g729_encoder: Option<Box<G729Encoder>>,
25 g729_decoder: Option<Box<G729Decoder>>,
26
27 #[cfg(feature = "opus")]
28 opus_encoder: Option<OpusEncoder>,
29 #[cfg(feature = "opus")]
30 opus_decoder: Option<OpusDecoder>,
31
32 resampler: Option<Resampler>,
33 resampler_in_rate: u32,
34 resampler_out_rate: u32,
35 pub payload_type_map: HashMap<u8, CodecType>,
36}
37
38impl Clone for TrackCodec {
39 fn clone(&self) -> Self {
40 let mut new = Self::new();
41 new.payload_type_map = self.payload_type_map.clone();
42 new
43 }
44}
45
46impl TrackCodec {
47 pub fn new() -> Self {
48 let mut payload_type_map = HashMap::new();
49 payload_type_map.insert(0, CodecType::PCMU);
50 payload_type_map.insert(8, CodecType::PCMA);
51 payload_type_map.insert(9, CodecType::G722);
52 payload_type_map.insert(18, CodecType::G729);
53 payload_type_map.insert(101, CodecType::TelephoneEvent);
54 #[cfg(feature = "opus")]
55 payload_type_map.insert(111, CodecType::Opus);
56
57 Self {
58 pcmu_encoder: PcmuEncoder::new(),
59 pcmu_decoder: PcmuDecoder::new(),
60 pcma_encoder: PcmaEncoder::new(),
61 pcma_decoder: PcmaDecoder::new(),
62 g722_encoder: None,
63 g722_decoder: None,
64 g729_encoder: None,
65 g729_decoder: None,
66 #[cfg(feature = "opus")]
67 opus_encoder: None,
68 #[cfg(feature = "opus")]
69 opus_decoder: None,
70 resampler: None,
71 resampler_in_rate: 0,
72 resampler_out_rate: 0,
73 payload_type_map,
74 }
75 }
76
77 pub fn set_payload_type(&mut self, pt: u8, codec: CodecType) {
78 self.payload_type_map.insert(pt, codec);
79 }
80
81 pub fn is_audio(payload_type: u8) -> bool {
82 match payload_type {
83 0 | 8 | 9 | 18 | 111 => true,
84 101 => false, pt if pt >= 96 && pt <= 127 => true,
86 _ => false,
87 }
88 }
89
90 pub fn decode(
91 &mut self,
92 payload_type: u8,
93 payload: &[u8],
94 target_sample_rate: u32,
95 ) -> (u32, u16, PcmBuf) {
96 let codec = self
97 .payload_type_map
98 .get(&payload_type)
99 .cloned()
100 .unwrap_or_else(|| match payload_type {
101 0 => CodecType::PCMU,
102 8 => CodecType::PCMA,
103 9 => CodecType::G722,
104 18 => CodecType::G729,
105 #[cfg(feature = "opus")]
106 111 => CodecType::Opus,
107 _ => CodecType::PCMU,
108 });
109
110 let pcm = match codec {
111 CodecType::PCMU => self.pcmu_decoder.decode(payload),
112 CodecType::PCMA => self.pcma_decoder.decode(payload),
113 CodecType::G722 => self
114 .g722_decoder
115 .get_or_insert_with(|| Box::new(G722Decoder::new()))
116 .decode(payload),
117 CodecType::G729 => self
118 .g729_decoder
119 .get_or_insert_with(|| Box::new(G729Decoder::new()))
120 .decode(payload),
121 #[cfg(feature = "opus")]
122 CodecType::Opus => self
123 .opus_decoder
124 .get_or_insert_with(OpusDecoder::new_default)
125 .decode(payload),
126 _ => bytes_to_samples(payload),
127 };
128
129 let (in_rate, channels) = match codec {
130 CodecType::PCMU => (8000, 1),
131 CodecType::PCMA => (8000, 1),
132 CodecType::G722 => (16000, 1),
133 CodecType::G729 => (8000, 1),
134 #[cfg(feature = "opus")]
135 CodecType::Opus => {
136 if pcm.len() >= 1920 {
137 (48000, 2)
138 } else {
139 (48000, 1)
140 }
141 }
142 _ => (8000, 1),
143 };
144
145 (
146 target_sample_rate,
147 channels,
148 self.resample(pcm, in_rate, target_sample_rate),
149 )
150 }
151
152 pub fn resample(&mut self, pcm: PcmBuf, in_rate: u32, out_rate: u32) -> PcmBuf {
153 if in_rate == out_rate {
154 return pcm;
155 }
156
157 if self.resampler.is_none()
158 || self.resampler_in_rate != in_rate
159 || self.resampler_out_rate != out_rate
160 {
161 self.resampler = Some(Resampler::new(in_rate as usize, out_rate as usize));
162 self.resampler_in_rate = in_rate;
163 self.resampler_out_rate = out_rate;
164 }
165 self.resampler.as_mut().unwrap().resample(&pcm)
166 }
167
168 pub fn encode(&mut self, payload_type: u8, frame: AudioFrame) -> (u8, Vec<u8>) {
169 match frame.samples {
170 Samples::PCM { samples: mut pcm } => {
171 let codec = self
172 .payload_type_map
173 .get(&payload_type)
174 .cloned()
175 .or_else(|| CodecType::try_from(payload_type).ok());
176
177 let target_samplerate = codec.map(|c| c.samplerate()).unwrap_or(8000);
178 if frame.sample_rate != target_samplerate {
179 if self.resampler.is_none()
180 || self.resampler_in_rate != frame.sample_rate
181 || self.resampler_out_rate != target_samplerate
182 {
183 self.resampler = Some(Resampler::new(
184 frame.sample_rate as usize,
185 target_samplerate as usize,
186 ));
187 self.resampler_in_rate = frame.sample_rate;
188 self.resampler_out_rate = target_samplerate;
189 }
190 pcm = self.resampler.as_mut().unwrap().resample(&pcm);
191 }
192
193 let payload = match codec {
194 Some(CodecType::PCMU) => self.pcmu_encoder.encode(&pcm),
195 Some(CodecType::PCMA) => self.pcma_encoder.encode(&pcm),
196 Some(CodecType::G722) => self
197 .g722_encoder
198 .get_or_insert_with(|| Box::new(G722Encoder::new()))
199 .encode(&pcm),
200 Some(CodecType::G729) => self
201 .g729_encoder
202 .get_or_insert_with(|| Box::new(G729Encoder::new()))
203 .encode(&pcm),
204 #[cfg(feature = "opus")]
205 Some(CodecType::Opus) => self
206 .opus_encoder
207 .get_or_insert_with(OpusEncoder::new_default)
208 .encode(&pcm),
209 _ => samples_to_bytes(&pcm),
210 };
211 (payload_type, payload)
212 }
213 Samples::RTP {
214 payload_type,
215 payload,
216 ..
217 } => (payload_type, payload),
218 _ => (payload_type, vec![]),
219 }
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226
227 #[cfg(feature = "opus")]
228 #[test]
229 fn test_encode_dynamic_opus_payload_type_uses_opus_encoder() {
230 let mut codec = TrackCodec::new();
231 codec.set_payload_type(96, CodecType::Opus);
232
233 let frame = AudioFrame {
234 samples: Samples::PCM {
235 samples: vec![0; 320],
237 },
238 sample_rate: 16000,
239 channels: 1,
240 ..Default::default()
241 };
242
243 let (pt, payload) = codec.encode(96, frame);
244 assert_eq!(pt, 96);
245 assert!(!payload.is_empty());
246 assert!(payload.len() < 640);
248 }
249}