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