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