Skip to main content

media_codec_opus/
decoder.rs

1use std::{collections::VecDeque, os::raw::c_int, sync::Arc};
2
3use bytemuck;
4use ctor::ctor;
5use media_codec::{
6    decoder::{register_decoder, AudioDecoder, AudioDecoderParameters, Decoder, DecoderBuilder},
7    packet::Packet,
8    Codec, CodecBuilder, CodecID, CodecInformation, CodecParameters,
9};
10use media_core::{
11    audio::{AudioFrame, AudioFrameDescriptor, SampleFormat},
12    error::Error,
13    frame::SharedFrame,
14    frame_pool::FramePool,
15    invalid_param_error, unsupported_error,
16    variant::Variant,
17    Result,
18};
19
20use crate::{opus_error_string, opus_sys};
21
22struct OpusDecoder {
23    decoder: *mut opus_sys::OpusDecoder,
24    pending: VecDeque<SharedFrame<AudioFrame<'static>>>,
25    packet_loss: bool,
26    fec: bool,
27}
28
29unsafe impl Send for OpusDecoder {}
30unsafe impl Sync for OpusDecoder {}
31
32impl CodecInformation for OpusDecoder {
33    fn id(&self) -> CodecID {
34        CodecID::OPUS
35    }
36
37    fn name(&self) -> &'static str {
38        CODEC_NAME
39    }
40}
41
42impl Codec<AudioDecoder> for OpusDecoder {
43    fn configure(&mut self, _params: Option<&CodecParameters>, _options: Option<&Variant>) -> Result<()> {
44        Ok(())
45    }
46
47    fn set_option(&mut self, key: &str, value: &Variant) -> Result<()> {
48        let value = match value {
49            Variant::Bool(value) => *value as i32,
50            _ => value.get_int32().ok_or_else(|| invalid_param_error!(value))?,
51        };
52
53        match key {
54            "gain" => self.decoder_ctl(opus_sys::OPUS_SET_GAIN_REQUEST, value),
55            "packet_loss" => {
56                self.packet_loss = value != 0;
57                Ok(())
58            }
59            "fec" => {
60                self.fec = value != 0;
61                Ok(())
62            }
63            _ => Err(unsupported_error!(key)),
64        }
65    }
66}
67
68impl Decoder<AudioDecoder> for OpusDecoder {
69    fn send_packet(&mut self, config: &AudioDecoder, pool: Option<&Arc<FramePool<AudioFrame<'static>>>>, packet: &Packet) -> Result<()> {
70        let desc = self.create_descriptor(config)?;
71        let fec = self.fec && self.packet_loss;
72
73        if fec {
74            let mut frame = self.get_frame(pool, &desc)?;
75            self.decode(&desc, packet, frame.write().unwrap(), true)?;
76            self.pending.push_back(frame);
77            self.packet_loss = false;
78        }
79
80        if !packet.data().is_empty() {
81            let mut frame = self.get_frame(pool, &desc)?;
82            self.decode(&desc, packet, frame.write().unwrap(), false)?;
83            self.pending.push_back(frame);
84        }
85
86        Ok(())
87    }
88
89    fn receive_frame(
90        &mut self,
91        _config: &AudioDecoder,
92        _pool: Option<&Arc<FramePool<AudioFrame<'static>>>>,
93    ) -> Result<SharedFrame<AudioFrame<'static>>> {
94        self.pending.pop_front().ok_or(Error::Again("no frame available".into()))
95    }
96
97    fn flush(&mut self, _config: &AudioDecoder) -> Result<()> {
98        unsafe { opus_sys::opus_decoder_ctl(self.decoder, opus_sys::OPUS_RESET_STATE) };
99        Ok(())
100    }
101}
102
103impl Drop for OpusDecoder {
104    fn drop(&mut self) {
105        unsafe { opus_sys::opus_decoder_destroy(self.decoder) }
106    }
107}
108
109const DEFAULT_PACKET_PENDING_CAPACITY: usize = 2;
110
111impl OpusDecoder {
112    pub fn new(codec_id: CodecID, params: &AudioDecoderParameters, _options: Option<&Variant>) -> Result<Self> {
113        if codec_id != CodecID::OPUS {
114            return Err(unsupported_error!(codec_id));
115        }
116
117        let audio_params = &params.audio;
118        let sample_rate = audio_params.sample_rate.ok_or_else(|| invalid_param_error!(params))?.get() as opus_sys::opus_int32;
119        let channels = audio_params.channel_layout.as_ref().ok_or_else(|| invalid_param_error!(params))?.channels.get() as c_int;
120
121        let mut ret = 0;
122        let decoder = unsafe { opus_sys::opus_decoder_create(sample_rate, channels, &mut ret) };
123        if decoder.is_null() || ret != opus_sys::OPUS_OK {
124            return Err(Error::CreationFailed(opus_error_string(ret)));
125        }
126
127        Ok(OpusDecoder {
128            decoder,
129            pending: VecDeque::with_capacity(DEFAULT_PACKET_PENDING_CAPACITY),
130            packet_loss: false,
131            fec: false,
132        })
133    }
134
135    fn decoder_ctl(&mut self, key: i32, value: i32) -> Result<()> {
136        let ret = unsafe { opus_sys::opus_decoder_ctl(self.decoder, key, value) };
137
138        if ret != opus_sys::OPUS_OK {
139            return Err(Error::SetFailed(opus_error_string(ret)));
140        }
141
142        Ok(())
143    }
144
145    fn get_frame(&self, pool: Option<&Arc<FramePool<AudioFrame<'static>>>>, desc: &AudioFrameDescriptor) -> Result<SharedFrame<AudioFrame<'static>>> {
146        if let Some(pool) = pool {
147            pool.get_frame_with_descriptor(desc.clone())
148        } else {
149            Ok(SharedFrame::<AudioFrame<'static>>::new(AudioFrame::new_with_descriptor(desc.clone())?))
150        }
151    }
152
153    fn create_descriptor(&self, config: &AudioDecoder) -> Result<AudioFrameDescriptor> {
154        let audio_params = &config.audio;
155        let sample_rate = audio_params.sample_rate.ok_or_else(|| invalid_param_error!(config))?.get();
156        let sample_format = if audio_params.format.ok_or_else(|| invalid_param_error!(config))? == SampleFormat::F32 {
157            SampleFormat::F32
158        } else {
159            SampleFormat::S16
160        };
161        let channel_layout = audio_params.channel_layout.as_ref().ok_or_else(|| invalid_param_error!(config))?;
162        // Opus spec defines the maximum frame duration as 120ms
163        let max_samples = sample_rate * 120 / 1000;
164
165        AudioFrameDescriptor::try_from_channel_layout(sample_format, max_samples, sample_rate, channel_layout.clone())
166    }
167
168    fn decode(&mut self, desc: &AudioFrameDescriptor, packet: &Packet, frame: &mut AudioFrame, fec: bool) -> Result<()> {
169        let ret = if let Ok(mut guard) = frame.map_mut() {
170            let mut planes = guard.planes_mut().unwrap();
171            let packet_data = packet.data();
172            let frame_size = if fec {
173                unsafe { opus_sys::opus_packet_get_samples_per_frame(packet_data.as_ptr(), desc.sample_rate.get() as opus_sys::opus_int32) }
174            } else {
175                desc.samples.get() as c_int
176            };
177
178            if desc.format == SampleFormat::F32 {
179                let data = bytemuck::cast_slice_mut::<u8, f32>(planes.plane_data_mut(0).unwrap());
180                unsafe {
181                    opus_sys::opus_decode_float(
182                        self.decoder,
183                        packet_data.as_ptr(),
184                        packet_data.len() as opus_sys::opus_int32,
185                        data.as_mut_ptr(),
186                        frame_size,
187                        fec as c_int,
188                    )
189                }
190            } else {
191                let data = bytemuck::cast_slice_mut::<u8, i16>(planes.plane_data_mut(0).unwrap());
192                unsafe {
193                    opus_sys::opus_decode(
194                        self.decoder,
195                        packet_data.as_ptr(),
196                        packet_data.len() as opus_sys::opus_int32,
197                        data.as_mut_ptr(),
198                        frame_size,
199                        fec as c_int,
200                    )
201                }
202            }
203        } else {
204            return Err(Error::Invalid("not writable".into()));
205        };
206
207        let samples = if ret < 0 {
208            return Err(Error::Failed(opus_error_string(ret)));
209        } else {
210            ret as u32
211        };
212
213        frame.truncate(samples)?;
214
215        Ok(())
216    }
217}
218
219const CODEC_NAME: &str = "opus-dec";
220
221pub struct OpusDecoderBuilder;
222
223impl DecoderBuilder<AudioDecoder> for OpusDecoderBuilder {
224    fn new_decoder(&self, codec_id: CodecID, params: &CodecParameters, options: Option<&Variant>) -> Result<Box<dyn Decoder<AudioDecoder>>> {
225        Ok(Box::new(OpusDecoder::new(codec_id, &params.try_into()?, options)?))
226    }
227}
228
229impl CodecBuilder<AudioDecoder> for OpusDecoderBuilder {
230    fn ids(&self) -> &[CodecID] {
231        &[CodecID::OPUS]
232    }
233
234    fn name(&self) -> &'static str {
235        CODEC_NAME
236    }
237}
238
239#[ctor]
240pub fn initialize() {
241    register_decoder(Arc::new(OpusDecoderBuilder), false);
242}