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