1use std::sync::Arc;
2
3#[cfg(feature = "audio")]
4use media_core::audio::AudioFrameDescriptor;
5#[cfg(feature = "video")]
6use media_core::video::VideoFrameDescriptor;
7use media_core::{
8 buffer::BufferPool,
9 error::Error,
10 frame::{Frame, SharedFrame},
11 invalid_param_error,
12 variant::Variant,
13 MediaType, Result,
14};
15
16#[cfg(feature = "audio")]
17use crate::AudioParameters;
18#[cfg(feature = "video")]
19use crate::VideoParameters;
20use crate::{packet::Packet, Codec, CodecBuilder, CodecID, CodecParameters, CodecParametersType, CodecSpec, CodecType, MediaParametersType};
21
22#[derive(Clone, Debug, Default)]
23pub struct EncoderParameters {
24 pub bit_rate: Option<u64>,
25 pub profile: Option<i32>,
26 pub level: Option<i32>,
27 pub use_pool: Option<bool>,
28}
29
30impl EncoderParameters {
31 fn update(&mut self, other: &EncoderParameters) {
32 if other.bit_rate.is_some() {
33 self.bit_rate = other.bit_rate;
34 }
35 if other.profile.is_some() {
36 self.profile = other.profile;
37 }
38 if other.level.is_some() {
39 self.level = other.level;
40 }
41 }
42
43 fn update_with_option(&mut self, key: &str, value: &Variant) {
44 match key {
45 "bit_rate" => self.bit_rate = value.get_uint64(),
46 "profile" => self.profile = value.get_int32(),
47 "level" => self.level = value.get_int32(),
48 _ => {}
49 }
50 }
51}
52
53impl TryFrom<&CodecParametersType> for EncoderParameters {
54 type Error = Error;
55
56 fn try_from(params: &CodecParametersType) -> Result<Self> {
57 #[allow(unreachable_patterns)]
58 match params {
59 CodecParametersType::Encoder(params) => Ok(params.clone()),
60 _ => Err(invalid_param_error!(params)),
61 }
62 }
63}
64
65#[cfg(feature = "audio")]
66#[derive(Clone, Debug, Default)]
67pub struct AudioEncoderParameters {
68 pub audio: AudioParameters,
69 pub encoder: EncoderParameters,
70}
71
72#[cfg(feature = "audio")]
73#[allow(unreachable_patterns)]
74impl TryFrom<&CodecParameters> for AudioEncoderParameters {
75 type Error = Error;
76
77 fn try_from(params: &CodecParameters) -> Result<Self> {
78 Ok(Self {
79 audio: match ¶ms.media {
80 MediaParametersType::Audio(params) => params.clone(),
81 _ => return Err(invalid_param_error!(params)),
82 },
83 encoder: match ¶ms.codec {
84 CodecParametersType::Encoder(params) => params.clone(),
85 _ => return Err(invalid_param_error!(params)),
86 },
87 })
88 }
89}
90
91#[cfg(feature = "audio")]
92#[derive(Clone, Debug)]
93pub struct AudioEncoder {
94 pub audio: AudioParameters,
95 pub encoder: EncoderParameters,
96 pub frame_size: Option<u32>,
98 pub delay: Option<u32>,
99}
100
101#[cfg(feature = "audio")]
102impl CodecSpec for AudioEncoder {
103 type FrameDescriptor = AudioFrameDescriptor;
104
105 fn media_type() -> MediaType {
106 MediaType::Audio
107 }
108
109 fn codec_type() -> CodecType {
110 CodecType::Encoder
111 }
112
113 fn from_parameters(params: &CodecParameters) -> Result<Self> {
114 Ok(Self {
115 audio: (¶ms.media).try_into()?,
116 encoder: (¶ms.codec).try_into()?,
117 frame_size: None,
118 delay: None,
119 })
120 }
121
122 fn configure(&mut self, params: &CodecParameters) -> Result<()> {
123 let audio_params = (¶ms.media).try_into()?;
124 let encoder_params = (¶ms.codec).try_into()?;
125 self.audio.update(&audio_params);
126 self.encoder.update(&encoder_params);
127 Ok(())
128 }
129
130 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
131 self.audio.update_with_option(key, value);
132 self.encoder.update_with_option(key, value);
133
134 match key {
135 "frame_size" => self.frame_size = value.get_uint32(),
136 "delay" => self.delay = value.get_uint32(),
137 _ => {}
138 }
139
140 Ok(())
141 }
142}
143
144#[cfg(feature = "video")]
145#[derive(Clone, Debug, Default)]
146pub struct VideoEncoderParameters {
147 pub video: VideoParameters,
148 pub encoder: EncoderParameters,
149}
150
151#[cfg(feature = "video")]
152#[allow(unreachable_patterns)]
153impl TryFrom<&CodecParameters> for VideoEncoderParameters {
154 type Error = Error;
155
156 #[allow(unreachable_patterns)]
157 fn try_from(params: &CodecParameters) -> Result<Self> {
158 Ok(Self {
159 video: match ¶ms.media {
160 MediaParametersType::Video(params) => params.clone(),
161 _ => return Err(invalid_param_error!(params)),
162 },
163 encoder: match ¶ms.codec {
164 CodecParametersType::Encoder(params) => params.clone(),
165 _ => return Err(invalid_param_error!(params)),
166 },
167 })
168 }
169}
170
171#[cfg(feature = "video")]
172#[derive(Clone, Debug)]
173pub struct VideoEncoder {
174 pub video: VideoParameters,
175 pub encoder: EncoderParameters,
176}
177
178#[cfg(feature = "video")]
179impl CodecSpec for VideoEncoder {
180 type FrameDescriptor = VideoFrameDescriptor;
181
182 fn media_type() -> MediaType {
183 MediaType::Video
184 }
185
186 fn codec_type() -> CodecType {
187 CodecType::Encoder
188 }
189
190 #[allow(unreachable_patterns)]
191 fn from_parameters(params: &CodecParameters) -> Result<Self> {
192 Ok(Self {
193 video: match ¶ms.media {
194 MediaParametersType::Video(params) => params.clone(),
195 _ => return Err(invalid_param_error!(params)),
196 },
197 encoder: match ¶ms.codec {
198 CodecParametersType::Encoder(params) => params.clone(),
199 _ => return Err(invalid_param_error!(params)),
200 },
201 })
202 }
203
204 #[allow(unreachable_patterns)]
205 fn configure(&mut self, params: &CodecParameters) -> Result<()> {
206 let video_params = (¶ms.media).try_into()?;
207 let encoder_params = (¶ms.codec).try_into()?;
208 self.video.update(&video_params);
209 self.encoder.update(&encoder_params);
210 Ok(())
211 }
212
213 fn configure_with_option(&mut self, key: &str, value: &Variant) -> Result<()> {
214 self.video.update_with_option(key, value);
215 self.encoder.update_with_option(key, value);
216 Ok(())
217 }
218}
219
220pub trait Encoder<T: CodecSpec>: Codec<T> + Send + Sync {
221 fn init(&mut self, _config: &T) -> Result<()> {
222 Ok(())
223 }
224 fn send_frame(&mut self, config: &T, pool: Option<&Arc<BufferPool>>, frame: SharedFrame<Frame<'static, T::FrameDescriptor>>) -> Result<()>;
225 fn receive_packet(&mut self, config: &T, pool: Option<&Arc<BufferPool>>) -> Result<Packet<'static>>;
226 fn flush(&mut self, config: &T) -> Result<()>;
227}
228
229pub trait EncoderBuilder<T: CodecSpec>: CodecBuilder<T> {
230 fn new_encoder(&self, id: CodecID, params: &CodecParameters, options: Option<&Variant>) -> Result<Box<dyn Encoder<T>>>;
231}