media_codec/
decoder.rs

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