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 ¶ms.media {
75 MediaParametersType::Audio(params) => params.clone(),
76 _ => return Err(invalid_param_error!(params)),
77 },
78 decoder: match ¶ms.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: (¶ms.media).try_into()?,
110 decoder: (¶ms.codec).try_into()?,
111 })
112 }
113
114 fn configure(&mut self, params: &CodecParameters) -> Result<()> {
115 let audio_params = (¶ms.media).try_into()?;
116 let decoder_params = (¶ms.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 ¶ms.media {
144 MediaParametersType::Video(params) => params.clone(),
145 _ => return Err(invalid_param_error!(params)),
146 },
147 decoder: match ¶ms.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 ¶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: 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 ¶ms.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}