media_codec_opus/
decoder.rs

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