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 ¶ms.media {
83 MediaParametersType::Audio(params) => params.clone(),
84 _ => return Err(invalid_param_error!(params)),
85 },
86 decoder: match ¶ms.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: (¶ms.media).try_into()?,
116 decoder: (¶ms.codec).try_into()?,
117 })
118 }
119
120 fn configure(&mut self, params: &CodecParameters) -> Result<()> {
121 let audio_params = (¶ms.media).try_into()?;
122 let decoder_params = (¶ms.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 ¶ms.media {
150 MediaParametersType::Video(params) => params.clone(),
151 _ => return Err(invalid_param_error!(params)),
152 },
153 decoder: match ¶ms.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 ¶ms.media {
184 MediaParametersType::Video(params) => params.clone(),
185 _ => return Err(invalid_param_error!(params)),
186 },
187 decoder: match ¶ms.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 = (¶ms.media).try_into()?;
197 let decoder_params = (¶ms.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 ¶ms.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}