rtp_engine/codec/
opus_codec.rs1use super::{AudioDecoder, AudioEncoder, CodecType};
7use crate::error::{Error, Result};
8
9pub struct OpusEncoder {
11 encoder: audiopus::coder::Encoder,
12 resample_buf: Vec<i16>,
13}
14
15impl OpusEncoder {
16 pub fn new() -> Result<Self> {
18 let encoder = audiopus::coder::Encoder::new(
19 audiopus::SampleRate::Hz48000,
20 audiopus::Channels::Mono,
21 audiopus::Application::Voip,
22 )
23 .map_err(|e| Error::codec(format!("Opus encoder init: {}", e)))?;
24
25 Ok(Self {
26 encoder,
27 resample_buf: Vec::with_capacity(960),
28 })
29 }
30}
31
32impl AudioEncoder for OpusEncoder {
33 fn encode(&mut self, pcm: &[i16], output: &mut Vec<u8>) -> usize {
34 self.resample_buf.clear();
36 for i in 0..pcm.len() {
37 let current = pcm[i] as f64;
38 let next = if i + 1 < pcm.len() {
39 pcm[i + 1] as f64
40 } else {
41 current
42 };
43 for j in 0..6 {
44 let t = j as f64 / 6.0;
45 self.resample_buf
46 .push((current + (next - current) * t) as i16);
47 }
48 }
49
50 let mut encoded = [0u8; 4000];
51 match self.encoder.encode(&self.resample_buf, &mut encoded) {
52 Ok(len) => {
53 output.extend_from_slice(&encoded[..len]);
54 pcm.len()
55 }
56 Err(e) => {
57 log::error!("Opus encode error: {}", e);
58 0
59 }
60 }
61 }
62
63 fn payload_type(&self) -> u8 {
64 111
65 }
66
67 fn codec_type(&self) -> CodecType {
68 CodecType::Opus
69 }
70}
71
72impl std::fmt::Debug for OpusEncoder {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 f.debug_struct("OpusEncoder")
75 .field("resample_buf_capacity", &self.resample_buf.capacity())
76 .finish()
77 }
78}
79
80pub struct OpusDecoder {
82 decoder: audiopus::coder::Decoder,
83}
84
85impl OpusDecoder {
86 pub fn new() -> Result<Self> {
88 let decoder =
89 audiopus::coder::Decoder::new(audiopus::SampleRate::Hz48000, audiopus::Channels::Mono)
90 .map_err(|e| Error::codec(format!("Opus decoder init: {}", e)))?;
91
92 Ok(Self { decoder })
93 }
94}
95
96impl AudioDecoder for OpusDecoder {
97 fn decode(&mut self, encoded: &[u8], output: &mut Vec<i16>) {
98 let mut decoded = [0i16; 5760]; let packet: audiopus::packet::Packet<'_> = match encoded.try_into() {
101 Ok(p) => p,
102 Err(e) => {
103 log::error!("Opus packet error: {}", e);
104 return;
105 }
106 };
107 let out_signals: audiopus::MutSignals<'_, _> = match (&mut decoded[..]).try_into() {
108 Ok(s) => s,
109 Err(e) => {
110 log::error!("Opus signals error: {}", e);
111 return;
112 }
113 };
114
115 match self.decoder.decode(Some(packet), out_signals, false) {
116 Ok(samples) => {
117 for i in (0..samples).step_by(6) {
119 output.push(decoded[i]);
120 }
121 }
122 Err(e) => {
123 log::error!("Opus decode error: {}", e);
124 }
125 }
126 }
127
128 fn codec_type(&self) -> CodecType {
129 CodecType::Opus
130 }
131}
132
133impl std::fmt::Debug for OpusDecoder {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 f.debug_struct("OpusDecoder").finish()
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_opus_encoder_creation() {
145 let encoder = OpusEncoder::new();
146 assert!(encoder.is_ok());
147 }
148
149 #[test]
150 fn test_opus_decoder_creation() {
151 let decoder = OpusDecoder::new();
152 assert!(decoder.is_ok());
153 }
154
155 #[test]
156 fn test_opus_roundtrip() {
157 let mut encoder = OpusEncoder::new().unwrap();
158 let mut decoder = OpusDecoder::new().unwrap();
159
160 let input: Vec<i16> = (0..160)
162 .map(|i| {
163 let t = i as f64 / 8000.0;
164 (f64::sin(2.0 * std::f64::consts::PI * 440.0 * t) * 16000.0) as i16
165 })
166 .collect();
167
168 let mut encoded = Vec::new();
169 let consumed = encoder.encode(&input, &mut encoded);
170 assert_eq!(consumed, 160);
171 assert!(!encoded.is_empty());
172
173 let mut decoded = Vec::new();
174 decoder.decode(&encoded, &mut decoded);
175 assert!(decoded.len() >= 100 && decoded.len() <= 200);
177 }
178}