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