1#![cfg_attr(not(feature = "std"), no_std)]
2
3pub use error::CodecError;
4
5pub mod error;
6pub mod g722;
7pub mod g729;
8#[cfg(feature = "opus")]
9pub mod opus;
10pub mod pcma;
11pub mod pcmu;
12pub mod resampler;
13pub mod telephone_event;
14
15#[cfg(feature = "std")]
16pub use resampler::{Resampler, resample};
17
18pub type Sample = i16;
19
20#[cfg(feature = "std")]
21pub type PcmBuf = Vec<Sample>;
22
23#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
24pub enum CodecType {
25 PCMU,
26 PCMA,
27 G722,
28 G729,
29 #[cfg(feature = "opus")]
30 Opus,
31 TelephoneEvent,
32}
33
34pub trait Decoder: Send + Sync {
41 fn decode_into(&mut self, data: &[u8], out: &mut [Sample]) -> Result<usize, CodecError>;
46
47 fn max_decode_samples(&self, n_bytes: usize) -> usize;
50
51 fn sample_rate(&self) -> u32;
53
54 fn channels(&self) -> u16;
56
57 #[cfg(feature = "std")]
59 fn decode(&mut self, data: &[u8]) -> PcmBuf {
60 let max = self.max_decode_samples(data.len());
61 let mut buf = vec![0i16; max];
62 match self.decode_into(data, &mut buf) {
63 Ok(n) => {
64 buf.truncate(n);
65 buf
66 }
67 Err(_) => Vec::new(),
68 }
69 }
70}
71
72pub trait Encoder: Send + Sync {
79 fn encode_into(&mut self, samples: &[Sample], out: &mut [u8]) -> Result<usize, CodecError>;
84
85 fn max_encode_bytes(&self, n_samples: usize) -> usize;
88
89 fn sample_rate(&self) -> u32;
91
92 fn channels(&self) -> u16;
94
95 #[cfg(feature = "std")]
97 fn encode(&mut self, samples: &[Sample]) -> Vec<u8> {
98 let max = self.max_encode_bytes(samples.len());
99 let mut buf = vec![0u8; max];
100 match self.encode_into(samples, &mut buf) {
101 Ok(n) => {
102 buf.truncate(n);
103 buf
104 }
105 Err(_) => Vec::new(),
106 }
107 }
108}
109
110#[cfg(feature = "std")]
111pub fn create_decoder(codec: CodecType) -> Box<dyn Decoder> {
112 match codec {
113 CodecType::PCMU => Box::new(pcmu::PcmuDecoder::new()),
114 CodecType::PCMA => Box::new(pcma::PcmaDecoder::new()),
115 CodecType::G722 => Box::new(g722::G722Decoder::new()),
116 CodecType::G729 => Box::new(g729::G729Decoder::new()),
117 #[cfg(feature = "opus")]
118 CodecType::Opus => Box::new(opus::OpusDecoder::new_default()),
119 CodecType::TelephoneEvent => Box::new(telephone_event::TelephoneEventDecoder::new()),
120 }
121}
122
123#[cfg(feature = "std")]
124pub fn create_encoder(codec: CodecType) -> Box<dyn Encoder> {
125 match codec {
126 CodecType::PCMU => Box::new(pcmu::PcmuEncoder::new()),
127 CodecType::PCMA => Box::new(pcma::PcmaEncoder::new()),
128 CodecType::G722 => Box::new(g722::G722Encoder::new()),
129 CodecType::G729 => Box::new(g729::G729Encoder::new()),
130 #[cfg(feature = "opus")]
131 CodecType::Opus => Box::new(opus::OpusEncoder::new_default()),
132 CodecType::TelephoneEvent => Box::new(telephone_event::TelephoneEventEncoder::new()),
133 }
134}
135
136#[cfg(all(feature = "std", feature = "opus"))]
137pub fn create_opus_encoder(
138 sample_rate: u32,
139 channels: u16,
140 application: opus::OpusApplication,
141) -> Box<dyn Encoder> {
142 Box::new(opus::OpusEncoder::new_with_application(
143 sample_rate,
144 channels,
145 application,
146 ))
147}
148
149#[cfg(all(feature = "std", feature = "opus"))]
150pub fn create_opus_decoder(sample_rate: u32, channels: u16) -> Box<dyn Decoder> {
151 Box::new(opus::OpusDecoder::new(sample_rate, channels))
152}
153
154impl CodecType {
155 pub fn mime_type(&self) -> &str {
156 match self {
157 CodecType::PCMU => "audio/PCMU",
158 CodecType::PCMA => "audio/PCMA",
159 CodecType::G722 => "audio/G722",
160 CodecType::G729 => "audio/G729",
161 #[cfg(feature = "opus")]
162 CodecType::Opus => "audio/opus",
163 CodecType::TelephoneEvent => "audio/telephone-event",
164 }
165 }
166 pub fn rtpmap(&self) -> &str {
167 match self {
168 CodecType::PCMU => "PCMU/8000",
169 CodecType::PCMA => "PCMA/8000",
170 CodecType::G722 => "G722/8000",
171 CodecType::G729 => "G729/8000",
172 #[cfg(feature = "opus")]
173 CodecType::Opus => "opus/48000/2",
174 CodecType::TelephoneEvent => "telephone-event/8000",
175 }
176 }
177 pub fn fmtp(&self) -> Option<&str> {
178 match self {
179 CodecType::PCMU => None,
180 CodecType::PCMA => None,
181 CodecType::G722 => None,
182 CodecType::G729 => None,
183 #[cfg(feature = "opus")]
184 CodecType::Opus => Some("minptime=10;useinbandfec=1;stereo=1;sprop-stereo=1"),
185 CodecType::TelephoneEvent => Some("0-16"),
186 }
187 }
188
189 pub fn clock_rate(&self) -> u32 {
190 match self {
191 CodecType::PCMU => 8000,
192 CodecType::PCMA => 8000,
193 CodecType::G722 => 8000,
194 CodecType::G729 => 8000,
195 #[cfg(feature = "opus")]
196 CodecType::Opus => 48000,
197 CodecType::TelephoneEvent => 8000,
198 }
199 }
200
201 pub fn channels(&self) -> u16 {
202 match self {
203 #[cfg(feature = "opus")]
204 CodecType::Opus => 2,
205 _ => 1,
206 }
207 }
208
209 pub fn payload_type(&self) -> u8 {
210 match self {
211 CodecType::PCMU => 0,
212 CodecType::PCMA => 8,
213 CodecType::G722 => 9,
214 CodecType::G729 => 18,
215 #[cfg(feature = "opus")]
216 CodecType::Opus => 111,
217 CodecType::TelephoneEvent => 101,
218 }
219 }
220 pub fn samplerate(&self) -> u32 {
221 match self {
222 CodecType::PCMU => 8000,
223 CodecType::PCMA => 8000,
224 CodecType::G722 => 16000,
225 CodecType::G729 => 8000,
226 #[cfg(feature = "opus")]
227 CodecType::Opus => 48000,
228 CodecType::TelephoneEvent => 8000,
229 }
230 }
231 pub fn is_audio(&self) -> bool {
232 match self {
233 CodecType::PCMU | CodecType::PCMA | CodecType::G722 => true,
234 CodecType::G729 => true,
235 #[cfg(feature = "opus")]
236 CodecType::Opus => true,
237 _ => false,
238 }
239 }
240
241 pub fn is_dynamic(&self) -> bool {
242 match self {
243 #[cfg(feature = "opus")]
244 CodecType::Opus => true,
245 CodecType::TelephoneEvent => true,
246 _ => false,
247 }
248 }
249}
250
251impl TryFrom<u8> for CodecType {
252 type Error = CodecError;
253
254 fn try_from(value: u8) -> Result<Self, Self::Error> {
255 match value {
256 0 => Ok(CodecType::PCMU),
257 8 => Ok(CodecType::PCMA),
258 9 => Ok(CodecType::G722),
259 18 => Ok(CodecType::G729), 101 => Ok(CodecType::TelephoneEvent),
262 #[cfg(feature = "opus")]
263 111 => Ok(CodecType::Opus), _ => Err(CodecError::InvalidCodecType),
265 }
266 }
267}
268
269impl TryFrom<&str> for CodecType {
270 type Error = CodecError;
271
272 fn try_from(name: &str) -> Result<Self, Self::Error> {
273 let b = name.as_bytes();
274 if b.eq_ignore_ascii_case(b"pcmu") || b.eq_ignore_ascii_case(b"ulaw") {
275 Ok(CodecType::PCMU)
276 } else if b.eq_ignore_ascii_case(b"pcma") || b.eq_ignore_ascii_case(b"alaw") {
277 Ok(CodecType::PCMA)
278 } else if b.eq_ignore_ascii_case(b"g722") {
279 Ok(CodecType::G722)
280 } else if b.eq_ignore_ascii_case(b"g729") {
281 Ok(CodecType::G729)
282 } else if cfg!(feature = "opus") && b.eq_ignore_ascii_case(b"opus") {
283 #[cfg(feature = "opus")]
284 {
285 Ok(CodecType::Opus)
286 }
287 #[cfg(not(feature = "opus"))]
288 {
289 Err(CodecError::InvalidCodecName)
290 }
291 } else if b.eq_ignore_ascii_case(b"telephone-event") {
292 Ok(CodecType::TelephoneEvent)
293 } else {
294 Err(CodecError::InvalidCodecName)
295 }
296 }
297}
298
299pub fn samples_to_bytes_into(samples: &[Sample], out: &mut [u8]) -> Result<usize, CodecError> {
308 let needed = core::mem::size_of_val(samples);
309 if out.len() < needed {
310 return Err(CodecError::BufferTooSmall);
311 }
312 #[cfg(target_endian = "little")]
313 {
314 let dst = unsafe {
317 core::slice::from_raw_parts_mut(out.as_mut_ptr() as *mut Sample, samples.len())
318 };
319 dst.copy_from_slice(samples);
320 }
321 #[cfg(target_endian = "big")]
322 {
323 for (i, s) in samples.iter().enumerate() {
324 let b = s.to_le_bytes();
325 out[2 * i] = b[0];
326 out[2 * i + 1] = b[1];
327 }
328 }
329 Ok(needed)
330}
331
332pub fn bytes_to_samples_into(u8_data: &[u8], out: &mut [Sample]) -> Result<usize, CodecError> {
337 let n = u8_data.len() / core::mem::size_of::<Sample>();
338 if out.len() < n {
339 return Err(CodecError::BufferTooSmall);
340 }
341 #[cfg(target_endian = "little")]
342 {
343 let src =
345 unsafe { core::slice::from_raw_parts(u8_data.as_ptr() as *const Sample, n) };
346 out[..n].copy_from_slice(src);
347 }
348 #[cfg(target_endian = "big")]
349 {
350 for (i, chunk) in u8_data.chunks_exact(2).enumerate() {
351 out[i] = (chunk[0] as i16) | ((chunk[1] as i16) << 8);
352 }
353 }
354 Ok(n)
355}
356
357#[cfg(feature = "std")]
358pub fn samples_to_bytes(samples: &[Sample]) -> Vec<u8> {
359 let mut out = vec![0u8; core::mem::size_of_val(samples)];
360 let _ = samples_to_bytes_into(samples, &mut out);
361 out
362}
363
364#[cfg(feature = "std")]
365pub fn bytes_to_samples(u8_data: &[u8]) -> PcmBuf {
366 let n = u8_data.len() / core::mem::size_of::<Sample>();
367 let mut out = vec![0i16; n];
368 let _ = bytes_to_samples_into(u8_data, &mut out);
369 out
370}