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