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