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 EncoderParameters {
21 pub bit_rate: Option<u64>,
22 pub profile: Option<i32>,
23 pub level: Option<i32>,
24}
25
26impl EncoderParameters {
27 fn update(&mut self, other: &EncoderParameters) {
28 if other.bit_rate.is_some() {
29 self.bit_rate = other.bit_rate;
30 }
31 if other.profile.is_some() {
32 self.profile = other.profile;
33 }
34 if other.level.is_some() {
35 self.level = other.level;
36 }
37 }
38
39 fn update_with_option(&mut self, key: &str, value: &Variant) {
40 match key {
41 "bit_rate" => self.bit_rate = value.get_uint64(),
42 "profile" => self.profile = value.get_int32(),
43 "level" => self.level = value.get_int32(),
44 _ => {}
45 }
46 }
47}
48
49#[cfg(feature = "audio")]
50#[derive(Clone, Debug, Default)]
51pub struct AudioEncoderParameters {
52 pub audio: AudioParameters,
53 pub encoder: EncoderParameters,
54}
55
56#[cfg(feature = "audio")]
57impl CodecParameters for AudioEncoderParameters {
58 fn media_type() -> MediaType {
59 MediaType::Audio
60 }
61
62 fn codec_type() -> CodecType {
63 CodecType::Encoder
64 }
65}
66
67#[cfg(feature = "audio")]
68#[derive(Clone, Debug)]
69pub struct AudioEncoder {
70 pub audio: AudioParameters,
71 pub encoder: EncoderParameters,
72 pub frame_size: Option<u32>,
74 pub delay: Option<u32>,
75}
76
77#[cfg(feature = "audio")]
78#[deprecated = "Use 'AudioEncoder' instead"]
79pub type AudioEncoderConfiguration = AudioEncoder;
80
81#[cfg(feature = "audio")]
82impl CodecConfiguration for AudioEncoder {
83 type Parameters = AudioEncoderParameters;
84
85 fn from_parameters(parameters: &Self::Parameters) -> Result<Self> {
86 Ok(Self {
87 audio: parameters.audio.clone(),
88 encoder: parameters.encoder.clone(),
89 frame_size: None,
90 delay: None,
91 })
92 }
93
94 fn configure(&mut self, parameters: &Self::Parameters) -> Result<()> {
95 self.audio.update(¶meters.audio);
96 self.encoder.update(¶meters.encoder);
97 Ok(())
98 }
99
100 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
101 self.audio.update_with_option(key, value);
102 self.encoder.update_with_option(key, value);
103
104 match key {
105 "frame_size" => self.frame_size = value.get_uint32(),
106 "delay" => self.delay = value.get_uint32(),
107 _ => {}
108 }
109
110 Ok(())
111 }
112}
113
114#[cfg(feature = "video")]
115#[derive(Clone, Debug, Default)]
116pub struct VideoEncoderParameters {
117 pub video: VideoParameters,
118 pub encoder: EncoderParameters,
119}
120
121#[cfg(feature = "video")]
122impl CodecParameters for VideoEncoderParameters {
123 fn media_type() -> MediaType {
124 MediaType::Video
125 }
126
127 fn codec_type() -> CodecType {
128 CodecType::Encoder
129 }
130}
131
132#[cfg(feature = "video")]
133#[derive(Clone, Debug)]
134pub struct VideoEncoder {
135 pub video: VideoParameters,
136 pub encoder: EncoderParameters,
137}
138
139#[cfg(feature = "video")]
140#[deprecated = "Use 'VideoEncoder' instead"]
141pub type VideoEncoderConfiguration = VideoEncoder;
142
143#[cfg(feature = "video")]
144impl CodecConfiguration for VideoEncoder {
145 type Parameters = VideoEncoderParameters;
146
147 fn from_parameters(parameters: &Self::Parameters) -> Result<Self> {
148 Ok(Self {
149 video: parameters.video.clone(),
150 encoder: parameters.encoder.clone(),
151 })
152 }
153
154 fn configure(&mut self, parameters: &Self::Parameters) -> Result<()> {
155 self.video.update(¶meters.video);
156 self.encoder.update(¶meters.encoder);
157 Ok(())
158 }
159
160 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
161 self.video.update_with_option(key, value);
162 self.encoder.update_with_option(key, value);
163 Ok(())
164 }
165}
166
167pub trait Encoder<T: CodecConfiguration>: Codec<T> + Send + Sync {
168 fn send_frame(&mut self, config: &T, frame: &Frame) -> Result<()>;
169 fn receive_packet(&mut self, config: &T) -> Result<Packet<'static>> {
170 self.receive_packet_borrowed(config).map(|packet| packet.into_owned())
171 }
172 fn receive_packet_borrowed(&mut self, config: &T) -> Result<Packet<'_>>;
173 fn flush(&mut self, config: &T) -> Result<()>;
174}
175
176pub trait EncoderBuilder<T: CodecConfiguration>: CodecBuilder<T> {
177 fn new_encoder(&self, id: CodecID, parameters: &T::Parameters, options: Option<&Variant>) -> Result<Box<dyn Encoder<T>>>;
178}
179
180pub struct EncoderContext<T: CodecConfiguration> {
181 pub configurations: T,
182 encoder: Box<dyn Encoder<T>>,
183}
184
185#[cfg(feature = "audio")]
186static AUDIO_ENCODER_LIST: LazyCodecList<AudioEncoder> = LazyLock::new(|| {
187 RwLock::new(CodecList::<AudioEncoder> {
188 codecs: HashMap::new(),
189 })
190});
191
192#[cfg(feature = "video")]
193static VIDEO_ENCODER_LIST: LazyCodecList<VideoEncoder> = LazyLock::new(|| {
194 RwLock::new(CodecList::<VideoEncoder> {
195 codecs: HashMap::new(),
196 })
197});
198
199pub fn register_encoder<T: CodecConfiguration>(builder: Arc<dyn EncoderBuilder<T>>, default: bool) -> Result<()> {
200 match TypeId::of::<T>() {
201 #[cfg(feature = "audio")]
202 id if id == TypeId::of::<AudioEncoder>() => {
203 let builder = unsafe { mem::transmute::<Arc<dyn EncoderBuilder<T>>, Arc<dyn CodecBuilder<AudioEncoder>>>(builder) };
204 register_codec(&AUDIO_ENCODER_LIST, builder, default)
205 }
206 #[cfg(feature = "video")]
207 id if id == TypeId::of::<VideoEncoder>() => {
208 let builder = unsafe { mem::transmute::<Arc<dyn EncoderBuilder<T>>, Arc<dyn CodecBuilder<VideoEncoder>>>(builder) };
209 register_codec(&VIDEO_ENCODER_LIST, builder, default)
210 }
211 _ => Err(Error::Unsupported("codec parameters type".to_string())),
212 }
213}
214
215pub(crate) fn find_encoder<T: CodecConfiguration>(id: CodecID) -> Result<Arc<dyn EncoderBuilder<T>>> {
216 match TypeId::of::<T>() {
217 #[cfg(feature = "audio")]
218 type_id if type_id == TypeId::of::<AudioEncoder>() => {
219 let builder = find_codec(&AUDIO_ENCODER_LIST, id)?;
220 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
221 }
222 #[cfg(feature = "video")]
223 type_id if type_id == TypeId::of::<VideoEncoder>() => {
224 let builder = find_codec(&VIDEO_ENCODER_LIST, id)?;
225 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
226 }
227 _ => Err(Error::Unsupported("codec parameters type".to_string())),
228 }
229}
230
231pub(crate) fn find_encoder_by_name<T: CodecConfiguration>(name: &str) -> Result<Arc<dyn EncoderBuilder<T>>> {
232 match TypeId::of::<T>() {
233 #[cfg(feature = "audio")]
234 id if id == TypeId::of::<AudioEncoder>() => {
235 let builder = find_codec_by_name(&AUDIO_ENCODER_LIST, name)?;
236 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<AudioEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
237 }
238 #[cfg(feature = "video")]
239 id if id == TypeId::of::<VideoEncoder>() => {
240 let builder = find_codec_by_name(&VIDEO_ENCODER_LIST, name)?;
241 unsafe { Ok(mem::transmute::<Arc<dyn CodecBuilder<VideoEncoder>>, Arc<dyn EncoderBuilder<T>>>(builder)) }
242 }
243 _ => Err(Error::Unsupported("codec parameters type".to_string())),
244 }
245}
246
247impl<T: CodecConfiguration> EncoderContext<T> {
248 pub fn from_codec_id(id: CodecID, parameters: &T::Parameters, options: Option<&Variant>) -> Result<Self> {
249 let builder = find_encoder(id)?;
250 let encoder = builder.new_encoder(id, parameters, options)?;
251 let config = T::from_parameters(parameters)?;
252
253 Ok(Self {
254 configurations: config,
255 encoder,
256 })
257 }
258
259 pub fn from_codec_name(name: &str, parameters: &T::Parameters, options: Option<&Variant>) -> Result<Self> {
260 let builder = find_encoder_by_name(name)?;
261 let encoder = builder.new_encoder(builder.id(), parameters, options)?;
262 let config = T::from_parameters(parameters)?;
263
264 Ok(Self {
265 configurations: config,
266 encoder,
267 })
268 }
269
270 pub fn configure(&mut self, parameters: Option<&T::Parameters>, options: Option<&Variant>) -> Result<()> {
271 if let Some(params) = parameters {
272 self.configurations.configure(params)?;
273 }
274 self.encoder.configure(parameters, options)
275 }
276
277 pub fn set_option(&mut self, key: &str, value: &Variant) -> Result<()> {
278 self.encoder.set_option(key, value)
279 }
280
281 pub fn send_frame(&mut self, frame: &Frame) -> Result<()> {
282 self.encoder.send_frame(&self.configurations, frame)
283 }
284
285 pub fn receive_packet(&mut self) -> Result<Packet<'static>> {
286 self.encoder.receive_packet(&self.configurations)
287 }
288
289 pub fn receive_packet_borrowed(&mut self) -> Result<Packet<'_>> {
290 self.encoder.receive_packet_borrowed(&self.configurations)
291 }
292}