1use std::{
2 any::TypeId,
3 collections::HashMap,
4 mem,
5 sync::{Arc, LazyLock, RwLock},
6};
7
8use media_core::{error::Error, frame::Frame, variant::Variant, MediaType, Result};
9
10#[cfg(feature = "audio")]
11use crate::AudioParameters;
12#[cfg(feature = "video")]
13use crate::VideoParameters;
14use crate::{
15 find_codec, find_codec_by_name, packet::Packet, register_codec, Codec, CodecBuilder, CodecConfiguration, CodecID, CodecList, CodecParameters,
16 CodecType, LazyCodecList,
17};
18
19#[derive(Clone, Debug, Default)]
20pub struct DecoderParameters {
21 pub extra_data: Option<Vec<u8>>,
22}
23
24impl DecoderParameters {
25 fn update(&mut self, other: &DecoderParameters) {
26 if let Some(ref extra_data) = other.extra_data {
27 self.extra_data = Some(extra_data.clone());
28 }
29 }
30
31 fn update_with_option(&mut self, key: &str, value: &Variant) {
32 #[allow(clippy::single_match)]
33 match key {
34 "extra_data" => self.extra_data = value.get_buffer(),
35 _ => {}
36 }
37 }
38}
39
40#[cfg(feature = "audio")]
41#[derive(Clone, Debug, Default)]
42pub struct AudioDecoderParameters {
43 pub audio: AudioParameters,
44 pub decoder: DecoderParameters,
45}
46
47#[cfg(feature = "audio")]
48impl CodecParameters for AudioDecoderParameters {
49 fn media_type() -> MediaType {
50 MediaType::Audio
51 }
52
53 fn codec_type() -> CodecType {
54 CodecType::Decoder
55 }
56}
57
58#[cfg(feature = "audio")]
59#[derive(Clone, Debug)]
60pub struct AudioDecoderConfiguration {
61 pub audio: AudioParameters,
62 pub decoder: DecoderParameters,
63}
64
65#[cfg(feature = "audio")]
66impl CodecConfiguration for AudioDecoderConfiguration {
67 type Parameters = AudioDecoderParameters;
68
69 fn from_parameters(parameters: &Self::Parameters) -> Result<Self> {
70 Ok(Self {
71 audio: parameters.audio.clone(),
72 decoder: parameters.decoder.clone(),
73 })
74 }
75
76 fn configure(&mut self, parameters: &Self::Parameters) -> Result<()> {
77 self.audio.update(¶meters.audio);
78 self.decoder.update(¶meters.decoder);
79 Ok(())
80 }
81
82 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
83 self.audio.update_with_option(key, value);
84 self.decoder.update_with_option(key, value);
85 Ok(())
86 }
87}
88
89#[cfg(feature = "video")]
90#[derive(Clone, Debug, Default)]
91pub struct VideoDecoderParameters {
92 pub video: VideoParameters,
93 pub decoder: DecoderParameters,
94}
95
96#[cfg(feature = "video")]
97impl CodecParameters for VideoDecoderParameters {
98 fn media_type() -> MediaType {
99 MediaType::Video
100 }
101
102 fn codec_type() -> CodecType {
103 CodecType::Decoder
104 }
105}
106
107#[cfg(feature = "video")]
108#[derive(Clone, Debug)]
109pub struct VideoDecoderConfiguration {
110 pub video: VideoParameters,
111 pub decoder: DecoderParameters,
112}
113
114#[cfg(feature = "video")]
115impl CodecConfiguration for VideoDecoderConfiguration {
116 type Parameters = VideoDecoderParameters;
117
118 fn from_parameters(parameters: &Self::Parameters) -> Result<Self> {
119 Ok(Self {
120 video: parameters.video.clone(),
121 decoder: parameters.decoder.clone(),
122 })
123 }
124
125 fn configure(&mut self, parameters: &Self::Parameters) -> Result<()> {
126 self.video.update(¶meters.video);
127 self.decoder.update(¶meters.decoder);
128 Ok(())
129 }
130
131 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
132 self.video.update_with_option(key, value);
133 self.decoder.update_with_option(key, value);
134 Ok(())
135 }
136}
137
138pub trait Decoder<T: CodecConfiguration>: Codec<T> + Send + Sync {
139 fn send_packet(&mut self, config: &T, packet: &Packet) -> Result<()>;
140 fn receive_frame(&mut self, config: &T) -> Result<Frame<'static>> {
141 self.receive_frame_borrowed(config).map(|frame| frame.into_owned())
142 }
143 fn receive_frame_borrowed(&mut self, config: &T) -> Result<Frame<'_>>;
144 fn flush(&mut self, config: &T) -> Result<()>;
145}
146
147pub trait DecoderBuilder<T: CodecConfiguration>: CodecBuilder<T> {
148 fn new_decoder(&self, id: CodecID, parameters: &T::Parameters, options: Option<&Variant>) -> Result<Box<dyn Decoder<T>>>;
149}
150
151pub struct DecoderContext<T: CodecConfiguration> {
152 pub configurations: T,
153 decoder: Box<dyn Decoder<T>>,
154}
155
156#[cfg(feature = "audio")]
157static AUDIO_DECODER_LIST: LazyCodecList<AudioDecoderConfiguration> = LazyLock::new(|| {
158 RwLock::new(CodecList::<AudioDecoderConfiguration> {
159 codecs: HashMap::new(),
160 })
161});
162
163#[cfg(feature = "video")]
164static VIDEO_DECODER_LIST: LazyCodecList<VideoDecoderConfiguration> = LazyLock::new(|| {
165 RwLock::new(CodecList::<VideoDecoderConfiguration> {
166 codecs: HashMap::new(),
167 })
168});
169
170pub fn register_decoder<T: CodecConfiguration>(builder: Arc<dyn DecoderBuilder<T>>, default: bool) -> Result<()> {
171 match TypeId::of::<T>() {
172 #[cfg(feature = "audio")]
173 id if id == TypeId::of::<AudioDecoderConfiguration>() => {
174 let builder = unsafe { mem::transmute::<Arc<dyn DecoderBuilder<T>>, Arc<dyn CodecBuilder<AudioDecoderConfiguration>>>(builder) };
175 register_codec(&AUDIO_DECODER_LIST, builder, default)
176 }
177 #[cfg(feature = "video")]
178 id if id == TypeId::of::<VideoDecoderConfiguration>() => {
179 let builder = unsafe { mem::transmute::<Arc<dyn DecoderBuilder<T>>, Arc<dyn CodecBuilder<VideoDecoderConfiguration>>>(builder) };
180 register_codec(&VIDEO_DECODER_LIST, builder, default)
181 }
182 _ => Err(Error::Unsupported("codec parameters type".to_string())),
183 }
184}
185
186pub(crate) fn find_decoder<T: CodecConfiguration>(id: CodecID) -> Result<Arc<dyn DecoderBuilder<T>>> {
187 match TypeId::of::<T>() {
188 #[cfg(feature = "audio")]
189 type_id if type_id == TypeId::of::<AudioDecoderConfiguration>() => {
190 let builder = find_codec(&AUDIO_DECODER_LIST, id)?;
191 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioDecoderConfiguration>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
192 }
193 #[cfg(feature = "video")]
194 type_id if type_id == TypeId::of::<VideoDecoderConfiguration>() => {
195 let builder = find_codec(&VIDEO_DECODER_LIST, id)?;
196 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoDecoderConfiguration>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
197 }
198 _ => Err(Error::Unsupported("codec parameters type".to_string())),
199 }
200}
201
202pub(crate) fn find_decoder_by_name<T: CodecConfiguration>(name: &str) -> Result<Arc<dyn DecoderBuilder<T>>> {
203 match TypeId::of::<T>() {
204 #[cfg(feature = "audio")]
205 id if id == TypeId::of::<AudioDecoderConfiguration>() => {
206 let builder = find_codec_by_name(&AUDIO_DECODER_LIST, name)?;
207 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioDecoderConfiguration>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
208 }
209 #[cfg(feature = "video")]
210 id if id == TypeId::of::<VideoDecoderConfiguration>() => {
211 let builder = find_codec_by_name(&VIDEO_DECODER_LIST, name)?;
212 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoDecoderConfiguration>>, Arc<dyn DecoderBuilder<T>>>(builder)) }
213 }
214 _ => Err(Error::Unsupported("codec parameters type".to_string())),
215 }
216}
217
218impl<T: CodecConfiguration> DecoderContext<T> {
219 pub fn from_codec_id(id: CodecID, parameters: &T::Parameters, options: Option<&Variant>) -> Result<Self> {
220 let builder = find_decoder(id)?;
221 let decoder = builder.new_decoder(id, parameters, options)?;
222 let config = T::from_parameters(parameters)?;
223
224 Ok(Self {
225 configurations: config,
226 decoder,
227 })
228 }
229
230 pub fn from_codec_name(name: &str, parameters: &T::Parameters, options: Option<&Variant>) -> Result<Self> {
231 let builder = find_decoder_by_name(name)?;
232 let decoder = builder.new_decoder(builder.id(), parameters, options)?;
233 let config = T::from_parameters(parameters)?;
234
235 Ok(Self {
236 configurations: config,
237 decoder,
238 })
239 }
240
241 pub fn codec_id(&self) -> CodecID {
242 self.decoder.id()
243 }
244
245 pub fn codec_name(&self) -> &'static str {
246 self.decoder.name()
247 }
248
249 pub fn configure(&mut self, parameters: Option<&T::Parameters>, options: Option<&Variant>) -> Result<()> {
250 if let Some(params) = parameters {
251 self.configurations.configure(params)?;
252 }
253 self.decoder.configure(parameters, options)
254 }
255
256 pub fn set_option(&mut self, key: &str, value: &Variant) -> Result<()> {
257 self.decoder.set_option(key, value)
258 }
259
260 pub fn send_packet(&mut self, packet: &Packet) -> Result<()> {
261 self.decoder.send_packet(&self.configurations, packet)
262 }
263
264 pub fn receive_frame(&mut self) -> Result<Frame<'static>> {
265 self.decoder.receive_frame(&self.configurations)
266 }
267
268 pub fn receive_frame_borrowed(&mut self) -> Result<Frame<'_>> {
269 self.decoder.receive_frame_borrowed(&self.configurations)
270 }
271}