Skip to main content

active_call/media/track/
track_codec.rs

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