media_codec/
decoder.rs

1use std::{
2    any::TypeId,
3    collections::HashMap,
4    mem,
5    sync::{Arc, LazyLock, RwLock},
6};
7
8#[cfg(feature = "audio")]
9use media_core::audio::AudioFrameDescriptor;
10#[cfg(feature = "video")]
11use media_core::video::VideoFrameDescriptor;
12use media_core::{
13    error::Error,
14    frame::{Frame, SharedFrame},
15    frame_pool::{FrameCreator, FramePool},
16    invalid_param_error,
17    variant::Variant,
18    MediaType, Result,
19};
20
21#[cfg(feature = "audio")]
22use crate::AudioParameters;
23#[cfg(feature = "video")]
24use crate::VideoParameters;
25use crate::{
26    find_codec, find_codec_by_name, packet::Packet, register_codec, Codec, CodecBuilder, CodecID, CodecList, CodecParameters, CodecParametersType,
27    CodecSpec, CodecType, LazyCodecList, MediaParametersType,
28};
29
30#[derive(Clone, Debug, Default)]
31pub struct DecoderParameters {
32    pub extra_data: Option<Vec<u8>>,
33    pub use_pool: Option<bool>,
34}
35
36impl DecoderParameters {
37    fn update(&mut self, other: &DecoderParameters) {
38        if let Some(ref extra_data) = other.extra_data {
39            self.extra_data = Some(extra_data.clone());
40        }
41    }
42
43    fn update_with_option(&mut self, key: &str, value: &Variant) {
44        #[allow(clippy::single_match)]
45        match key {
46            "extra_data" => self.extra_data = value.get_buffer(),
47            "use_pool" => self.use_pool = value.get_bool(),
48            _ => {}
49        }
50    }
51}
52
53impl TryFrom<&CodecParametersType> for DecoderParameters {
54    type Error = Error;
55
56    fn try_from(params: &CodecParametersType) -> Result<Self> {
57        match params {
58            CodecParametersType::Decoder(params) => Ok(params.clone()),
59            _ => Err(invalid_param_error!(params)),
60        }
61    }
62}
63
64#[cfg(feature = "audio")]
65#[derive(Clone, Debug, Default)]
66pub struct AudioDecoderParameters {
67    pub audio: AudioParameters,
68    pub decoder: DecoderParameters,
69}
70
71#[cfg(feature = "audio")]
72#[allow(unreachable_patterns)]
73impl TryFrom<&CodecParameters> for AudioDecoderParameters {
74    type Error = Error;
75
76    fn try_from(params: &CodecParameters) -> Result<Self> {
77        Ok(Self {
78            audio: match &params.media {
79                MediaParametersType::Audio(params) => params.clone(),
80                _ => return Err(invalid_param_error!(params)),
81            },
82            decoder: match &params.codec {
83                CodecParametersType::Decoder(params) => params.clone(),
84                _ => return Err(invalid_param_error!(params)),
85            },
86        })
87    }
88}
89
90#[cfg(feature = "audio")]
91#[derive(Clone, Debug)]
92pub struct AudioDecoder {
93    pub audio: AudioParameters,
94    pub decoder: DecoderParameters,
95}
96
97#[cfg(feature = "audio")]
98impl CodecSpec for AudioDecoder {
99    type FrameDescriptor = AudioFrameDescriptor;
100
101    fn media_type() -> MediaType {
102        MediaType::Audio
103    }
104
105    fn codec_type() -> CodecType {
106        CodecType::Decoder
107    }
108
109    fn from_parameters(params: &CodecParameters) -> Result<Self> {
110        Ok(Self {
111            audio: (&params.media).try_into()?,
112            decoder: (&params.codec).try_into()?,
113        })
114    }
115
116    fn configure(&mut self, params: &CodecParameters) -> Result<()> {
117        let audio_params = (&params.media).try_into()?;
118        let decoder_params = (&params.codec).try_into()?;
119        self.audio.update(&audio_params);
120        self.decoder.update(&decoder_params);
121        Ok(())
122    }
123
124    fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
125        self.audio.update_with_option(key, value);
126        self.decoder.update_with_option(key, value);
127        Ok(())
128    }
129}
130
131#[cfg(feature = "video")]
132#[derive(Clone, Debug, Default)]
133pub struct VideoDecoderParameters {
134    pub video: VideoParameters,
135    pub decoder: DecoderParameters,
136}
137
138#[cfg(feature = "video")]
139#[allow(unreachable_patterns)]
140impl TryFrom<&CodecParameters> for VideoDecoderParameters {
141    type Error = Error;
142
143    fn try_from(params: &CodecParameters) -> Result<Self> {
144        Ok(Self {
145            video: match &params.media {
146                MediaParametersType::Video(params) => params.clone(),
147                _ => return Err(invalid_param_error!(params)),
148            },
149            decoder: match &params.codec {
150                CodecParametersType::Decoder(params) => params.clone(),
151                _ => return Err(invalid_param_error!(params)),
152            },
153        })
154    }
155}
156
157#[cfg(feature = "video")]
158#[derive(Clone, Debug)]
159pub struct VideoDecoder {
160    pub video: VideoParameters,
161    pub decoder: DecoderParameters,
162}
163
164#[cfg(feature = "video")]
165impl CodecSpec for VideoDecoder {
166    type FrameDescriptor = VideoFrameDescriptor;
167
168    fn media_type() -> MediaType {
169        MediaType::Video
170    }
171
172    fn codec_type() -> CodecType {
173        CodecType::Decoder
174    }
175
176    #[allow(unreachable_patterns)]
177    fn from_parameters(params: &CodecParameters) -> Result<Self> {
178        Ok(Self {
179            video: match &params.media {
180                MediaParametersType::Video(params) => params.clone(),
181                _ => return Err(invalid_param_error!(params)),
182            },
183            decoder: match &params.codec {
184                CodecParametersType::Decoder(params) => params.clone(),
185                _ => return Err(invalid_param_error!(params)),
186            },
187        })
188    }
189
190    #[allow(unreachable_patterns)]
191    fn configure(&mut self, params: &CodecParameters) -> Result<()> {
192        let video_params = (&params.media).try_into()?;
193        let decoder_params = (&params.codec).try_into()?;
194        self.video.update(&video_params);
195        self.decoder.update(&decoder_params);
196        Ok(())
197    }
198
199    fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
200        self.video.update_with_option(key, value);
201        self.decoder.update_with_option(key, value);
202        Ok(())
203    }
204}
205
206pub trait Decoder<T: CodecSpec>: Codec<T> + Send + Sync {
207    fn init(&mut self, _config: &T) -> Result<()> {
208        Ok(())
209    }
210    fn send_packet(&mut self, config: &T, pool: Option<&Arc<FramePool<Frame<'static, T::FrameDescriptor>>>>, packet: Packet) -> Result<()>;
211    fn receive_frame(
212        &mut self,
213        config: &T,
214        pool: Option<&Arc<FramePool<Frame<'static, T::FrameDescriptor>>>>,
215    ) -> Result<SharedFrame<Frame<'static, T::FrameDescriptor>>>;
216    fn flush(&mut self, config: &T) -> Result<()>;
217}
218
219pub trait DecoderBuilder<T: CodecSpec>: CodecBuilder<T> {
220    fn new_decoder(&self, id: CodecID, params: &CodecParameters, options: Option<&Variant>) -> Result<Box<dyn Decoder<T>>>;
221}
222
223pub struct DecoderContext<T: CodecSpec> {
224    pub config: T,
225    decoder: Box<dyn Decoder<T>>,
226    pool: Option<Arc<FramePool<Frame<'static, T::FrameDescriptor>>>>,
227}
228
229#[cfg(feature = "audio")]
230static AUDIO_DECODER_LIST: LazyCodecList<AudioDecoder> = LazyLock::new(|| {
231    RwLock::new(CodecList::<AudioDecoder> {
232        codecs: HashMap::new(),
233    })
234});
235
236#[cfg(feature = "video")]
237static VIDEO_DECODER_LIST: LazyCodecList<VideoDecoder> = LazyLock::new(|| {
238    RwLock::new(CodecList::<VideoDecoder> {
239        codecs: HashMap::new(),
240    })
241});
242
243pub fn register_decoder<T: CodecSpec>(builder: Arc<dyn DecoderBuilder<T>>, default: bool) -> Result<()> {
244    match TypeId::of::<T>() {
245        #[cfg(feature = "audio")]
246        id if id == TypeId::of::<AudioDecoder>() => {
247            let builder = unsafe { mem::transmute::<Arc<dyn DecoderBuilder<T>>, Arc<dyn CodecBuilder<AudioDecoder>>>(builder) };
248            register_codec(&AUDIO_DECODER_LIST, builder, default)
249        }
250        #[cfg(feature = "video")]
251        id if id == TypeId::of::<VideoDecoder>() => {
252            let builder = unsafe { mem::transmute::<Arc<dyn DecoderBuilder<T>>, Arc<dyn CodecBuilder<VideoDecoder>>>(builder) };
253            register_codec(&VIDEO_DECODER_LIST, builder, default)
254        }
255        _ => Err(Error::Unsupported("codec parameters type".to_string())),
256    }
257}
258
259pub(crate) fn find_decoder<T: CodecSpec>(id: CodecID) -> Result<Arc<dyn DecoderBuilder<T>>> {
260    match TypeId::of::<T>() {
261        #[cfg(feature = "audio")]
262        type_id if type_id == TypeId::of::<AudioDecoder>() => {
263            let builder = find_codec(&AUDIO_DECODER_LIST, id)?;
264            unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioDecoder>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
265        }
266        #[cfg(feature = "video")]
267        type_id if type_id == TypeId::of::<VideoDecoder>() => {
268            let builder = find_codec(&VIDEO_DECODER_LIST, id)?;
269            unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoDecoder>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
270        }
271        _ => Err(Error::Unsupported("codec parameters type".to_string())),
272    }
273}
274
275pub(crate) fn find_decoder_by_name<T: CodecSpec>(name: &str) -> Result<Arc<dyn DecoderBuilder<T>>> {
276    match TypeId::of::<T>() {
277        #[cfg(feature = "audio")]
278        id if id == TypeId::of::<AudioDecoder>() => {
279            let builder = find_codec_by_name(&AUDIO_DECODER_LIST, name)?;
280            unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioDecoder>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
281        }
282        #[cfg(feature = "video")]
283        id if id == TypeId::of::<VideoDecoder>() => {
284            let builder = find_codec_by_name(&VIDEO_DECODER_LIST, name)?;
285            unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoDecoder>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
286        }
287        _ => Err(Error::Unsupported("codec parameters type".to_string())),
288    }
289}
290
291impl<T: CodecSpec> DecoderContext<T> {
292    fn new_with_builder(builder: Arc<dyn DecoderBuilder<T>>, params: &CodecParameters, options: Option<&Variant>) -> Result<Self> {
293        let decoder = builder.new_decoder(builder.id(), params, options)?;
294        let config = T::from_parameters(params)?;
295
296        let frame_pool = match &params.codec {
297            CodecParametersType::Decoder(decoder_params) => {
298                if decoder_params.use_pool.unwrap_or(false) {
299                    Some(FramePool::<Frame<'static, T::FrameDescriptor>>::new())
300                } else {
301                    None
302                }
303            }
304            _ => return Err(invalid_param_error!(params)),
305        };
306
307        Ok(Self {
308            config,
309            decoder,
310            pool: frame_pool,
311        })
312    }
313
314    pub fn from_codec_id(id: CodecID, params: &CodecParameters, options: Option<&Variant>) -> Result<Self> {
315        Self::new_with_builder(find_decoder(id)?, params, options)
316    }
317
318    pub fn from_codec_name(name: &str, params: &CodecParameters, options: Option<&Variant>) -> Result<Self> {
319        Self::new_with_builder(find_decoder_by_name(name)?, params, options)
320    }
321
322    pub fn with_frame_creator(mut self, creator: Box<dyn FrameCreator<T::FrameDescriptor>>) -> Self {
323        if let Some(pool) = self.pool.as_mut().and_then(Arc::get_mut) {
324            pool.configure(None, Some(creator));
325        }
326
327        self
328    }
329
330    pub fn codec_id(&self) -> CodecID {
331        self.decoder.id()
332    }
333
334    pub fn codec_name(&self) -> &'static str {
335        self.decoder.name()
336    }
337
338    pub fn configure(&mut self, params: Option<&CodecParameters>, options: Option<&Variant>) -> Result<()> {
339        if let Some(params) = params {
340            self.config.configure(params)?;
341        }
342        self.decoder.configure(params, options)
343    }
344
345    pub fn set_option(&mut self, key: &str, value: &Variant) -> Result<()> {
346        self.decoder.set_option(key, value)
347    }
348
349    pub fn send_packet(&mut self, packet: Packet) -> Result<()> {
350        self.decoder.send_packet(&self.config, self.pool.as_ref(), packet)
351    }
352
353    pub fn receive_frame(&mut self) -> Result<SharedFrame<Frame<'static, T::FrameDescriptor>>> {
354        self.decoder.receive_frame(&self.config, self.pool.as_ref())
355    }
356}