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, AudioDecoderConfiguration, AudioDecoderParameters, Decoder, DecoderBuilder},
8    packet::Packet,
9    CodecInfomation,
10};
11use media_core::{
12    audio::{AudioFrameDescriptor, SampleFormat},
13    error::Error,
14    frame::Frame,
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<Frame<'static>>,
25}
26
27unsafe impl Send for OpusDecoder {}
28unsafe impl Sync for OpusDecoder {}
29
30impl Codec<AudioDecoderConfiguration> for OpusDecoder {
31    fn configure(&mut self, _parameters: Option<&AudioDecoderParameters>, _options: Option<&Variant>) -> Result<()> {
32        Ok(())
33    }
34
35    fn set_option(&mut self, _key: &str, _value: &Variant) -> Result<()> {
36        Ok(())
37    }
38}
39
40impl Decoder<AudioDecoderConfiguration> for OpusDecoder {
41    fn send_packet(&mut self, config: &AudioDecoderConfiguration, packet: &Packet) -> Result<()> {
42        let audio_params = &config.audio;
43        let sample_rate = audio_params.sample_rate.ok_or(invalid_param_error!(config))?.get();
44        let sample_format = if audio_params.format.ok_or(invalid_param_error!(config))? == SampleFormat::F32 {
45            SampleFormat::F32
46        } else {
47            SampleFormat::S16
48        };
49        let channel_layout = audio_params.channel_layout.as_ref().ok_or(invalid_param_error!(config))?;
50        // Opus spec defines the maximum frame duration as 120ms
51        let max_samples = sample_rate * 120 / 1000;
52
53        let desc = AudioFrameDescriptor::try_from_channel_layout(sample_format, max_samples, sample_rate, channel_layout.clone())?;
54        let mut frame = Frame::audio_creator().create_with_descriptor(desc)?;
55
56        let ret = if let Ok(mut guard) = frame.map_mut() {
57            let mut planes = guard.planes_mut().unwrap();
58            let packet_data = packet.data();
59
60            if sample_format == SampleFormat::F32 {
61                let data = bytemuck::cast_slice_mut::<u8, f32>(planes.plane_data_mut(0).unwrap());
62                unsafe {
63                    opus_sys::opus_decode_float(
64                        self.decoder,
65                        packet_data.as_ptr(),
66                        packet_data.len() as i32,
67                        data.as_mut_ptr(),
68                        max_samples as i32,
69                        false as i32,
70                    )
71                }
72            } else {
73                let data = bytemuck::cast_slice_mut::<u8, i16>(planes.plane_data_mut(0).unwrap());
74                unsafe {
75                    opus_sys::opus_decode(
76                        self.decoder,
77                        packet_data.as_ptr(),
78                        packet_data.len() as i32,
79                        data.as_mut_ptr(),
80                        max_samples as i32,
81                        false as i32,
82                    )
83                }
84            }
85        } else {
86            return Err(Error::Invalid("not writable".to_string()));
87        };
88
89        let samples = if ret < 0 {
90            return Err(Error::Failed(opus_error_string(ret)));
91        } else {
92            ret as u32
93        };
94
95        frame.truncate(samples)?;
96
97        self.pending.push_back(frame);
98
99        Ok(())
100    }
101
102    fn receive_frame(&mut self, _config: &AudioDecoderConfiguration) -> Result<Frame<'static>> {
103        self.pending.pop_front().ok_or(Error::Again("no frame available".to_string()))
104    }
105
106    fn receive_frame_borrowed(&mut self, _config: &AudioDecoderConfiguration) -> Result<Frame<'_>> {
107        Err(Error::Unsupported("borrowed frame not supported".to_string()))
108    }
109
110    fn flush(&mut self, _config: &AudioDecoderConfiguration) -> Result<()> {
111        unsafe { opus_sys::opus_decoder_ctl(self.decoder, opus_sys::OPUS_RESET_STATE) };
112        Ok(())
113    }
114}
115
116impl Drop for OpusDecoder {
117    fn drop(&mut self) {
118        unsafe { opus_sys::opus_decoder_destroy(self.decoder) }
119    }
120}
121
122impl OpusDecoder {
123    pub fn new(codec_id: CodecID, parameters: &AudioDecoderParameters, _options: Option<&Variant>) -> Result<Self> {
124        if codec_id != CodecID::Opus {
125            return Err(unsupported_error!(codec_id));
126        }
127
128        let audio_params = &parameters.audio;
129        let sample_rate = audio_params.sample_rate.ok_or(invalid_param_error!(parameters))?.get() as opus_sys::opus_int32;
130        let channels = audio_params.channel_layout.as_ref().ok_or(invalid_param_error!(parameters))?.channels.get() as c_int;
131
132        let mut ret = 0;
133        let decoder = unsafe { opus_sys::opus_decoder_create(sample_rate, channels, &mut ret) };
134        if decoder.is_null() || ret != opus_sys::OPUS_OK {
135            return Err(Error::CreationFailed(opus_error_string(ret)));
136        }
137
138        Ok(OpusDecoder {
139            decoder,
140            pending: VecDeque::new(),
141        })
142    }
143}
144
145const CODEC_NAME: &str = "opus-dec";
146
147pub struct OpusDecoderBuilder;
148
149impl DecoderBuilder<AudioDecoderConfiguration> for OpusDecoderBuilder {
150    fn new_decoder(
151        &self,
152        codec_id: CodecID,
153        parameters: &AudioDecoderParameters,
154        options: Option<&Variant>,
155    ) -> Result<Box<dyn Decoder<AudioDecoderConfiguration>>> {
156        Ok(Box::new(OpusDecoder::new(codec_id, parameters, options)?))
157    }
158}
159
160impl CodecBuilder<AudioDecoderConfiguration> for OpusDecoderBuilder {
161    fn id(&self) -> CodecID {
162        CodecID::Opus
163    }
164
165    fn name(&self) -> &'static str {
166        CODEC_NAME
167    }
168}
169
170impl CodecInfomation for OpusDecoder {
171    fn id(&self) -> CodecID {
172        CodecID::Opus
173    }
174
175    fn name(&self) -> &'static str {
176        CODEC_NAME
177    }
178}
179
180#[ctor]
181fn initialize() {
182    register_decoder(Arc::new(OpusDecoderBuilder), false);
183}