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