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 buffer::BufferPool,
14 error::Error,
15 frame::{Frame, SharedFrame},
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 EncoderParameters {
32 pub bit_rate: Option<u64>,
33 pub profile: Option<i32>,
34 pub level: Option<i32>,
35 pub use_pool: Option<bool>,
36}
37
38impl EncoderParameters {
39 fn update(&mut self, other: &EncoderParameters) {
40 if other.bit_rate.is_some() {
41 self.bit_rate = other.bit_rate;
42 }
43 if other.profile.is_some() {
44 self.profile = other.profile;
45 }
46 if other.level.is_some() {
47 self.level = other.level;
48 }
49 }
50
51 fn update_with_option(&mut self, key: &str, value: &Variant) {
52 match key {
53 "bit_rate" => self.bit_rate = value.get_uint64(),
54 "profile" => self.profile = value.get_int32(),
55 "level" => self.level = value.get_int32(),
56 _ => {}
57 }
58 }
59}
60
61impl TryFrom<&CodecParametersType> for EncoderParameters {
62 type Error = Error;
63
64 fn try_from(params: &CodecParametersType) -> Result<Self> {
65 match params {
66 CodecParametersType::Encoder(params) => Ok(params.clone()),
67 _ => Err(invalid_param_error!(params)),
68 }
69 }
70}
71
72#[cfg(feature = "audio")]
73#[derive(Clone, Debug, Default)]
74pub struct AudioEncoderParameters {
75 pub audio: AudioParameters,
76 pub encoder: EncoderParameters,
77}
78
79#[cfg(feature = "audio")]
80#[allow(unreachable_patterns)]
81impl TryFrom<&CodecParameters> for AudioEncoderParameters {
82 type Error = Error;
83
84 fn try_from(params: &CodecParameters) -> Result<Self> {
85 Ok(Self {
86 audio: match ¶ms.media {
87 MediaParametersType::Audio(params) => params.clone(),
88 _ => return Err(invalid_param_error!(params)),
89 },
90 encoder: match ¶ms.codec {
91 CodecParametersType::Encoder(params) => params.clone(),
92 _ => return Err(invalid_param_error!(params)),
93 },
94 })
95 }
96}
97
98#[cfg(feature = "audio")]
99#[derive(Clone, Debug)]
100pub struct AudioEncoder {
101 pub audio: AudioParameters,
102 pub encoder: EncoderParameters,
103 pub frame_size: Option<u32>,
105 pub delay: Option<u32>,
106}
107
108#[cfg(feature = "audio")]
109impl CodecSpec for AudioEncoder {
110 type FrameDescriptor = AudioFrameDescriptor;
111
112 fn media_type() -> MediaType {
113 MediaType::Audio
114 }
115
116 fn codec_type() -> CodecType {
117 CodecType::Encoder
118 }
119
120 fn from_parameters(params: &CodecParameters) -> Result<Self> {
121 Ok(Self {
122 audio: (¶ms.media).try_into()?,
123 encoder: (¶ms.codec).try_into()?,
124 frame_size: None,
125 delay: None,
126 })
127 }
128
129 fn configure(&mut self, params: &CodecParameters) -> Result<()> {
130 let audio_params = (¶ms.media).try_into()?;
131 let encoder_params = (¶ms.codec).try_into()?;
132 self.audio.update(&audio_params);
133 self.encoder.update(&encoder_params);
134 Ok(())
135 }
136
137 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
138 self.audio.update_with_option(key, value);
139 self.encoder.update_with_option(key, value);
140
141 match key {
142 "frame_size" => self.frame_size = value.get_uint32(),
143 "delay" => self.delay = value.get_uint32(),
144 _ => {}
145 }
146
147 Ok(())
148 }
149}
150
151#[cfg(feature = "video")]
152#[derive(Clone, Debug, Default)]
153pub struct VideoEncoderParameters {
154 pub video: VideoParameters,
155 pub encoder: EncoderParameters,
156}
157
158#[cfg(feature = "video")]
159#[allow(unreachable_patterns)]
160impl TryFrom<&CodecParameters> for VideoEncoderParameters {
161 type Error = Error;
162
163 #[allow(unreachable_patterns)]
164 fn try_from(params: &CodecParameters) -> Result<Self> {
165 Ok(Self {
166 video: match ¶ms.media {
167 MediaParametersType::Video(params) => params.clone(),
168 _ => return Err(invalid_param_error!(params)),
169 },
170 encoder: match ¶ms.codec {
171 CodecParametersType::Encoder(params) => params.clone(),
172 _ => return Err(invalid_param_error!(params)),
173 },
174 })
175 }
176}
177
178#[cfg(feature = "video")]
179#[derive(Clone, Debug)]
180pub struct VideoEncoder {
181 pub video: VideoParameters,
182 pub encoder: EncoderParameters,
183}
184
185#[cfg(feature = "video")]
186impl CodecSpec for VideoEncoder {
187 type FrameDescriptor = VideoFrameDescriptor;
188
189 fn media_type() -> MediaType {
190 MediaType::Video
191 }
192
193 fn codec_type() -> CodecType {
194 CodecType::Encoder
195 }
196
197 #[allow(unreachable_patterns)]
198 fn from_parameters(params: &CodecParameters) -> Result<Self> {
199 Ok(Self {
200 video: match ¶ms.media {
201 MediaParametersType::Video(params) => params.clone(),
202 _ => return Err(invalid_param_error!(params)),
203 },
204 encoder: match ¶ms.codec {
205 CodecParametersType::Encoder(params) => params.clone(),
206 _ => return Err(invalid_param_error!(params)),
207 },
208 })
209 }
210
211 #[allow(unreachable_patterns)]
212 fn configure(&mut self, params: &CodecParameters) -> Result<()> {
213 let video_params = (¶ms.media).try_into()?;
214 let encoder_params = (¶ms.codec).try_into()?;
215 self.video.update(&video_params);
216 self.encoder.update(&encoder_params);
217 Ok(())
218 }
219
220 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
221 self.video.update_with_option(key, value);
222 self.encoder.update_with_option(key, value);
223 Ok(())
224 }
225}
226
227pub trait Encoder<T: CodecSpec>: Codec<T> + Send + Sync {
228 fn init(&mut self, _config: &T) -> Result<()> {
229 Ok(())
230 }
231 fn send_frame(&mut self, config: &T, pool: Option<&Arc<BufferPool>>, frame: SharedFrame<Frame<'static, T::FrameDescriptor>>) -> Result<()>;
232 fn receive_packet(&mut self, config: &T, pool: Option<&Arc<BufferPool>>) -> Result<Packet<'static>>;
233 fn flush(&mut self, config: &T) -> Result<()>;
234}
235
236pub trait EncoderBuilder<T: CodecSpec>: CodecBuilder<T> {
237 fn new_encoder(&self, id: CodecID, params: &CodecParameters, options: Option<&Variant>) -> Result<Box<dyn Encoder<T>>>;
238}
239
240pub struct EncoderContext<T: CodecSpec> {
241 pub config: T,
242 encoder: Box<dyn Encoder<T>>,
243 pool: Option<Arc<BufferPool>>,
244}
245
246#[cfg(feature = "audio")]
247static AUDIO_ENCODER_LIST: LazyCodecList<AudioEncoder> = LazyLock::new(|| {
248 RwLock::new(CodecList::<AudioEncoder> {
249 codecs: HashMap::new(),
250 })
251});
252
253#[cfg(feature = "video")]
254static VIDEO_ENCODER_LIST: LazyCodecList<VideoEncoder> = LazyLock::new(|| {
255 RwLock::new(CodecList::<VideoEncoder> {
256 codecs: HashMap::new(),
257 })
258});
259
260pub fn register_encoder<T: CodecSpec>(builder: Arc<dyn EncoderBuilder<T>>, default: bool) -> Result<()> {
261 match TypeId::of::<T>() {
262 #[cfg(feature = "audio")]
263 id if id == TypeId::of::<AudioEncoder>() => {
264 let builder = unsafe { mem::transmute::<Arc<dyn EncoderBuilder<T>>, Arc<dyn CodecBuilder<AudioEncoder>>>(builder) };
265 register_codec(&AUDIO_ENCODER_LIST, builder, default)
266 }
267 #[cfg(feature = "video")]
268 id if id == TypeId::of::<VideoEncoder>() => {
269 let builder = unsafe { mem::transmute::<Arc<dyn EncoderBuilder<T>>, Arc<dyn CodecBuilder<VideoEncoder>>>(builder) };
270 register_codec(&VIDEO_ENCODER_LIST, builder, default)
271 }
272 _ => Err(Error::Unsupported("codec parameters type".to_string())),
273 }
274}
275
276pub(crate) fn find_encoder<T: CodecSpec>(id: CodecID) -> Result<Arc<dyn EncoderBuilder<T>>> {
277 match TypeId::of::<T>() {
278 #[cfg(feature = "audio")]
279 type_id if type_id == TypeId::of::<AudioEncoder>() => {
280 let builder = find_codec(&AUDIO_ENCODER_LIST, id)?;
281 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
282 }
283 #[cfg(feature = "video")]
284 type_id if type_id == TypeId::of::<VideoEncoder>() => {
285 let builder = find_codec(&VIDEO_ENCODER_LIST, id)?;
286 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
287 }
288 _ => Err(Error::Unsupported("codec parameters type".to_string())),
289 }
290}
291
292pub(crate) fn find_encoder_by_name<T: CodecSpec>(name: &str) -> Result<Arc<dyn EncoderBuilder<T>>> {
293 match TypeId::of::<T>() {
294 #[cfg(feature = "audio")]
295 id if id == TypeId::of::<AudioEncoder>() => {
296 let builder = find_codec_by_name(&AUDIO_ENCODER_LIST, name)?;
297 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
298 }
299 #[cfg(feature = "video")]
300 id if id == TypeId::of::<VideoEncoder>() => {
301 let builder = find_codec_by_name(&VIDEO_ENCODER_LIST, name)?;
302 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
303 }
304 _ => Err(Error::Unsupported("codec parameters type".to_string())),
305 }
306}
307
308impl<T: CodecSpec> EncoderContext<T> {
309 pub fn from_codec_id(id: CodecID, params: &CodecParameters, options: Option<&Variant>) -> Result<Self> {
310 let builder = find_encoder(id)?;
311 let encoder = builder.new_encoder(id, params, options)?;
312 let config = T::from_parameters(params)?;
313
314 let buffer_pool = match ¶ms.codec {
315 CodecParametersType::Encoder(encoder_params) => {
316 if encoder_params.use_pool.unwrap_or(false) {
317 Some(BufferPool::new(0))
318 } else {
319 None
320 }
321 }
322 _ => return Err(invalid_param_error!(params)),
323 };
324
325 Ok(Self {
326 config,
327 encoder,
328 pool: buffer_pool,
329 })
330 }
331
332 pub fn from_codec_name(name: &str, params: &CodecParameters, options: Option<&Variant>) -> Result<Self> {
333 let builder = find_encoder_by_name(name)?;
334 let encoder = builder.new_encoder(builder.id(), params, options)?;
335 let config = T::from_parameters(params)?;
336
337 Ok(Self {
338 config,
339 encoder,
340 pool: None,
341 })
342 }
343
344 pub fn configure(&mut self, params: Option<&CodecParameters>, options: Option<&Variant>) -> Result<()> {
345 if let Some(params) = params {
346 self.config.configure(params)?;
347 }
348 self.encoder.configure(params, options)
349 }
350
351 pub fn set_option(&mut self, key: &str, value: &Variant) -> Result<()> {
352 self.encoder.set_option(key, value)
353 }
354
355 pub fn send_frame(&mut self, frame: SharedFrame<Frame<'static, T::FrameDescriptor>>) -> Result<()> {
356 self.encoder.send_frame(&self.config, self.pool.as_ref(), frame)
357 }
358
359 pub fn receive_packet(&mut self) -> Result<Packet<'static>> {
360 self.encoder.receive_packet(&self.config, self.pool.as_ref())
361 }
362}