1use std::{
2 collections::HashMap,
3 marker::PhantomData,
4 sync::{Arc, LazyLock, RwLock},
5};
6
7pub use media_codec_types::decoder::*;
8use media_codec_types::{
9 packet::{Packet, PacketProperties},
10 CodecID, CodecParameters, CodecParametersType, CodecSpec,
11};
12use media_core::{
13 frame::{Frame, SharedFrame},
14 frame_pool::{FrameCreator, FramePool},
15 invalid_param_error,
16 rational::Rational64,
17 variant::Variant,
18 Result,
19};
20
21use crate::codec::{find_codec, find_codec_by_name, register_codec, CodecList, LazyCodecList};
22
23pub trait DecoderSpec: CodecSpec {
24 fn register(builder: Arc<dyn DecoderBuilder<Self>>, default: bool) -> Result<()>;
25 fn find(id: CodecID) -> Result<Arc<dyn DecoderBuilder<Self>>>;
26 fn find_by_name(name: &str) -> Result<Arc<dyn DecoderBuilder<Self>>>;
27}
28
29pub struct DecoderContext<T: DecoderSpec> {
30 pub config: T,
31 pub time_base: Option<Rational64>,
32 decoder: Box<dyn Decoder<T>>,
33 pool: Option<Arc<FramePool<Frame<'static, T::FrameDescriptor>>>>,
34 last_pkt_props: Option<PacketProperties>,
35}
36
37#[cfg(feature = "audio")]
38static AUDIO_DECODER_LIST: LazyCodecList<AudioDecoder, dyn DecoderBuilder<AudioDecoder>> = LazyLock::new(|| {
39 RwLock::new(CodecList::<AudioDecoder, dyn DecoderBuilder<AudioDecoder>> {
40 codecs: HashMap::new(),
41 _marker: PhantomData,
42 })
43});
44
45#[cfg(feature = "audio")]
46impl DecoderSpec for AudioDecoder {
47 fn register(builder: Arc<dyn DecoderBuilder<Self>>, default: bool) -> Result<()> {
48 register_codec(&AUDIO_DECODER_LIST, builder, default)
49 }
50
51 fn find(id: CodecID) -> Result<Arc<dyn DecoderBuilder<Self>>> {
52 find_codec(&AUDIO_DECODER_LIST, id)
53 }
54
55 fn find_by_name(name: &str) -> Result<Arc<dyn DecoderBuilder<Self>>> {
56 find_codec_by_name(&AUDIO_DECODER_LIST, name)
57 }
58}
59
60#[cfg(feature = "video")]
61static VIDEO_DECODER_LIST: LazyCodecList<VideoDecoder, dyn DecoderBuilder<VideoDecoder>> = LazyLock::new(|| {
62 RwLock::new(CodecList::<VideoDecoder, dyn DecoderBuilder<VideoDecoder>> {
63 codecs: HashMap::new(),
64 _marker: PhantomData,
65 })
66});
67
68#[cfg(feature = "video")]
69impl DecoderSpec for VideoDecoder {
70 fn register(builder: Arc<dyn DecoderBuilder<Self>>, default: bool) -> Result<()> {
71 register_codec(&VIDEO_DECODER_LIST, builder, default)
72 }
73
74 fn find(id: CodecID) -> Result<Arc<dyn DecoderBuilder<Self>>> {
75 find_codec(&VIDEO_DECODER_LIST, id)
76 }
77
78 fn find_by_name(name: &str) -> Result<Arc<dyn DecoderBuilder<Self>>> {
79 find_codec_by_name(&VIDEO_DECODER_LIST, name)
80 }
81}
82
83pub fn register_decoder<T: DecoderSpec>(builder: Arc<dyn DecoderBuilder<T>>, default: bool) -> Result<()> {
84 T::register(builder, default)
85}
86
87pub(crate) fn find_decoder<T: DecoderSpec>(id: CodecID) -> Result<Arc<dyn DecoderBuilder<T>>> {
88 T::find(id)
89}
90
91pub(crate) fn find_decoder_by_name<T: DecoderSpec>(name: &str) -> Result<Arc<dyn DecoderBuilder<T>>> {
92 T::find_by_name(name)
93}
94
95impl<T: DecoderSpec> DecoderContext<T> {
96 pub fn new(codec_id: CodecID, codec_name: Option<&str>, params: &CodecParameters, options: Option<&Variant>) -> Result<Self> {
97 let builder = if let Some(codec_name) = codec_name {
98 find_decoder_by_name(codec_name)?
99 } else {
100 find_decoder(codec_id)?
101 };
102
103 let decoder = builder.new_decoder(codec_id, params, options)?;
104
105 Self::new_with_decoder(decoder, params)
106 }
107
108 pub fn new_with_decoder(decoder: Box<dyn Decoder<T>>, params: &CodecParameters) -> Result<Self> {
109 let config = T::from_parameters(params)?;
110
111 #[allow(unreachable_patterns)]
112 let frame_pool = match ¶ms.codec {
113 CodecParametersType::Decoder(decoder_params) => {
114 if decoder_params.use_pool.unwrap_or(false) {
115 Some(FramePool::<Frame<'static, T::FrameDescriptor>>::new())
116 } else {
117 None
118 }
119 }
120 _ => return Err(invalid_param_error!(params)),
121 };
122
123 Ok(Self {
124 config,
125 decoder,
126 pool: frame_pool,
127 time_base: None,
128 last_pkt_props: None,
129 })
130 }
131
132 pub fn with_frame_creator(mut self, creator: Box<dyn FrameCreator<T::FrameDescriptor>>) -> Self {
133 if let Some(pool) = self.pool.as_mut().and_then(Arc::get_mut) {
134 pool.configure(None, Some(creator));
135 }
136
137 self
138 }
139
140 pub fn codec_id(&self) -> CodecID {
141 self.decoder.id()
142 }
143
144 pub fn codec_name(&self) -> &'static str {
145 self.decoder.name()
146 }
147
148 pub fn configure(&mut self, params: Option<&CodecParameters>, options: Option<&Variant>) -> Result<()> {
149 if let Some(params) = params {
150 self.config.configure(params)?;
151 }
152 self.decoder.configure(params, options)
153 }
154
155 pub fn set_option(&mut self, key: &str, value: &Variant) -> Result<()> {
156 self.decoder.set_option(key, value)
157 }
158
159 pub fn send_packet(&mut self, packet: &Packet) -> Result<()> {
160 self.decoder.send_packet(&self.config, self.pool.as_ref(), packet)?;
161 self.last_pkt_props = Some(PacketProperties::from_packet(packet));
162
163 Ok(())
164 }
165
166 pub fn receive_frame(&mut self) -> Result<SharedFrame<Frame<'static, T::FrameDescriptor>>> {
167 let mut shared_frame = self.decoder.receive_frame(&self.config, self.pool.as_ref())?;
168
169 let frame = shared_frame.write();
170 if let Some(frame) = frame {
171 if let Some(pkt_props) = &self.last_pkt_props {
172 frame.pts = frame.pts.or(pkt_props.pts);
173 frame.dts = frame.dts.or(pkt_props.dts);
174 frame.duration = frame.duration.or(pkt_props.duration);
175 }
176
177 frame.time_base = frame.time_base.or(self.time_base);
178 }
179
180 Ok(shared_frame)
181 }
182
183 pub fn flush(&mut self) -> Result<()> {
184 self.decoder.flush(&self.config)
185 }
186}