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 ¶ms.media {
79 MediaParametersType::Audio(params) => params.clone(),
80 _ => return Err(invalid_param_error!(params)),
81 },
82 decoder: match ¶ms.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: (¶ms.media).try_into()?,
112 decoder: (¶ms.codec).try_into()?,
113 })
114 }
115
116 fn configure(&mut self, params: &CodecParameters) -> Result<()> {
117 let audio_params = (¶ms.media).try_into()?;
118 let decoder_params = (¶ms.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 ¶ms.media {
146 MediaParametersType::Video(params) => params.clone(),
147 _ => return Err(invalid_param_error!(params)),
148 },
149 decoder: match ¶ms.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 ¶ms.media {
180 MediaParametersType::Video(params) => params.clone(),
181 _ => return Err(invalid_param_error!(params)),
182 },
183 decoder: match ¶ms.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 = (¶ms.media).try_into()?;
193 let decoder_params = (¶ms.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 ¶ms.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}