1use std::collections::HashMap;
2use std::convert::Into;
3
4use av_data::frame::ArcFrame;
5use av_data::packet::Packet;
6use av_data::params::CodecParams;
7use av_data::value::Value;
8
9use crate::common::CodecList;
10
11use crate::error::*;
12
13pub trait Encoder: Send {
15 fn get_extradata(&self) -> Option<Vec<u8>>;
17 fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
19 fn receive_packet(&mut self) -> Result<Packet>;
21 fn flush(&mut self) -> Result<()>;
23
24 fn configure(&mut self) -> Result<()>;
26 fn set_option(&mut self, key: &str, val: Value) -> Result<()>;
28 fn set_params(&mut self, params: &CodecParams) -> Result<()>;
32 fn get_params(&self) -> Result<CodecParams>;
34}
35
36pub struct Context<E: Encoder> {
39 enc: E,
40 }
45
46impl<E: Encoder> Context<E> {
47 pub fn by_name<T: Descriptor<OutputEncoder = E> + ?Sized>(
51 codecs: &Codecs<T>,
52 name: &str,
53 ) -> Option<Self> {
54 codecs.by_name(name).map(|builder| Context {
55 enc: builder.create(),
56 })
57 }
58
59 pub fn configure(&mut self) -> Result<()> {
61 self.enc.configure()
62 }
63
64 pub fn set_params(&mut self, params: &CodecParams) -> Result<()> {
66 self.enc.set_params(params)
67 }
68
69 pub fn get_params(&self) -> Result<CodecParams> {
71 self.enc.get_params()
72 }
73
74 pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
76 where
77 V: Into<Value<'a>>,
78 {
79 self.enc.set_option(key, val.into())
81 }
82
83 pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
85 self.enc.get_extradata()
86 }
87 pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
89 self.enc.send_frame(frame)
90 }
91 pub fn receive_packet(&mut self) -> Result<Packet> {
94 self.enc.receive_packet()
95 }
96
97 pub fn flush(&mut self) -> Result<()> {
99 self.enc.flush()
100 }
101
102 pub fn encoder(&self) -> &E {
104 &self.enc
105 }
106}
107
108#[derive(Debug)]
112pub struct Descr {
113 pub codec: &'static str,
115 pub name: &'static str,
117 pub desc: &'static str,
119 pub mime: &'static str,
121 }
123
124pub trait Descriptor {
126 type OutputEncoder: Encoder;
128
129 fn create(&self) -> Self::OutputEncoder;
131 fn describe(&self) -> &Descr;
133}
134
135pub struct Codecs<T: 'static + Descriptor + ?Sized> {
137 list: HashMap<&'static str, Vec<&'static T>>,
138}
139
140impl<T: Descriptor + ?Sized> CodecList for Codecs<T> {
141 type D = T;
142
143 fn new() -> Self {
144 Self {
145 list: HashMap::new(),
146 }
147 }
148
149 fn by_name(&self, name: &str) -> Option<&'static Self::D> {
151 self.list.get(name).map(|descs| descs[0])
152 }
153
154 fn append(&mut self, desc: &'static Self::D) {
155 let codec_name = desc.describe().codec;
156
157 self.list.entry(codec_name).or_default().push(desc);
158 }
159}
160
161#[cfg(test)]
162mod test {
163 use super::*;
164
165 mod dummy {
166 use super::super::*;
167 use av_data::pixel::Formaton;
168 use std::sync::Arc;
169
170 pub struct Enc {
171 state: usize,
172 w: Option<usize>,
173 h: Option<usize>,
174 format: Option<Arc<Formaton>>,
175 }
176
177 pub struct Des {
178 descr: Descr,
179 }
180
181 impl Descriptor for Des {
182 type OutputEncoder = Enc;
183
184 fn create(&self) -> Self::OutputEncoder {
185 Enc {
186 state: 0,
187 w: None,
188 h: None,
189 format: None,
190 }
191 }
192
193 fn describe(&self) -> &Descr {
194 &self.descr
195 }
196 }
197
198 impl Encoder for Enc {
199 fn configure(&mut self) -> Result<()> {
200 if self.h.is_some() && self.w.is_some() && self.format.is_some() {
201 Ok(())
202 } else {
203 Err(Error::ConfigurationIncomplete)
204 }
205 }
206 fn get_extradata(&self) -> Option<Vec<u8>> {
207 Some(vec![self.state as u8; 1])
208 }
209 fn send_frame(&mut self, _frame: &ArcFrame) -> Result<()> {
210 self.state += 1;
211 Ok(())
212 }
213 fn receive_packet(&mut self) -> Result<Packet> {
214 let mut p = Packet::with_capacity(1);
215
216 p.data.push(self.state as u8);
217
218 Ok(p)
219 }
220 fn set_option(&mut self, key: &str, val: Value) -> Result<()> {
221 match (key, val) {
222 ("w", Value::U64(v)) => self.w = Some(v as usize),
223 ("h", Value::U64(v)) => self.h = Some(v as usize),
224 ("format", Value::Formaton(f)) => self.format = Some(f),
225 _ => return Err(Error::Unsupported(format!("{} key", key))),
226 }
227
228 Ok(())
229 }
230
231 fn set_params(&mut self, params: &CodecParams) -> Result<()> {
232 use av_data::params::*;
233
234 if let Some(MediaKind::Video(ref info)) = params.kind {
235 self.w = Some(info.width);
236 self.h = Some(info.height);
237 self.format = info.format.clone();
238 }
239 Ok(())
240 }
241
242 fn get_params(&self) -> Result<CodecParams> {
243 use av_data::params::*;
244
245 if self.w.is_none() || self.w.is_none() || self.format.is_none() {
246 return Err(Error::ConfigurationIncomplete);
247 }
248
249 Ok(CodecParams {
250 kind: Some(MediaKind::Video(VideoInfo {
251 height: self.w.unwrap(),
252 width: self.h.unwrap(),
253 format: self.format.clone(),
254 })),
255 codec_id: Some("dummy".to_owned()),
256 extradata: self.get_extradata(),
257 bit_rate: 0,
258 convergence_window: 0,
259 delay: 0,
260 })
261 }
262
263 fn flush(&mut self) -> Result<()> {
264 Ok(())
265 }
266 }
267
268 pub const DUMMY_DESCR: &Des = &Des {
269 descr: Descr {
270 codec: "dummy",
271 name: "dummy",
272 desc: "Dummy encoder",
273 mime: "x-application/dummy",
274 },
275 };
276 }
277
278 use self::dummy::DUMMY_DESCR;
279
280 #[test]
281 fn lookup() {
282 let codecs = Codecs::from_list(&[DUMMY_DESCR]);
283
284 let _enc = codecs.by_name("dummy");
285 }
286}