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