av_codec/
encoder.rs

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
13/// Used to interact with an encoder.
14pub trait Encoder: Send {
15    /// Returns the extra data added by an encoder to a codec.
16    fn get_extradata(&self) -> Option<Vec<u8>>;
17    /// Sends to the encoder a frame to be encoded.
18    fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
19    /// Returns an encoded packet.
20    fn receive_packet(&mut self) -> Result<Packet>;
21    /// Tells encoder to clear its internal state.
22    fn flush(&mut self) -> Result<()>;
23
24    /// Configures the encoder.
25    fn configure(&mut self) -> Result<()>;
26    /// Sets an encoder option.
27    fn set_option(&mut self, key: &str, val: Value) -> Result<()>;
28    // fn get_option(&mut self, key: &str) -> Option<Value>;
29    //
30    /// Sets the parameters associated to a determined codec.
31    fn set_params(&mut self, params: &CodecParams) -> Result<()>;
32    /// Gets the parameters associated to a determined codec.
33    fn get_params(&self) -> Result<CodecParams>;
34}
35
36/// Auxiliary structure to encapsulate an encoder object and
37/// its additional data.
38pub struct Context<E: Encoder> {
39    enc: E,
40    // TODO: Queue up packets/frames
41    // TODO: Store here more information
42    // TODO: Have a resource pool
43    // format: Format
44}
45
46impl<E: Encoder> Context<E> {
47    // TODO: More constructors
48    /// Retrieves a codec descriptor from a codec list through its name,
49    /// creates the relative encoder, and encapsulates it into a new `Context`.
50    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    /// Configures the encoder.
60    pub fn configure(&mut self) -> Result<()> {
61        self.enc.configure()
62    }
63
64    /// Sets the parameters associated to a determined codec.
65    pub fn set_params(&mut self, params: &CodecParams) -> Result<()> {
66        self.enc.set_params(params)
67    }
68
69    /// Gets the parameters associated to a determined codec.
70    pub fn get_params(&self) -> Result<CodecParams> {
71        self.enc.get_params()
72    }
73
74    /// Sets an encoder option.
75    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
76    where
77        V: Into<Value<'a>>,
78    {
79        // TODO: support more options
80        self.enc.set_option(key, val.into())
81    }
82
83    /// Returns the extra data added by an encoder to a codec.
84    pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
85        self.enc.get_extradata()
86    }
87    /// Sends to the encoder a frame to be encoded.
88    pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
89        self.enc.send_frame(frame)
90    }
91    /// Returns an encoded packet.
92    // TODO: Return an Event?
93    pub fn receive_packet(&mut self) -> Result<Packet> {
94        self.enc.receive_packet()
95    }
96
97    /// Tells encoder to clear its internal state.
98    pub fn flush(&mut self) -> Result<()> {
99        self.enc.flush()
100    }
101
102    /// Returns the underlying encoder.
103    pub fn encoder(&self) -> &E {
104        &self.enc
105    }
106}
107
108/// Codec descriptor.
109///
110/// Contains information on a codec and its own encoder.
111#[derive(Debug)]
112pub struct Descr {
113    /// The codec name.
114    pub codec: &'static str,
115    /// The extended codec name.
116    pub name: &'static str,
117    /// The codec description.
118    pub desc: &'static str,
119    /// The codec MIME.
120    pub mime: &'static str,
121    // TODO more fields regarding capabilities
122}
123
124/// Used to get the descriptor of a codec and create its own encoder.
125pub trait Descriptor {
126    /// The specific type of the encoder.
127    type OutputEncoder: Encoder;
128
129    /// Creates a new encoder for the requested codec.
130    fn create(&self) -> Self::OutputEncoder;
131    /// Returns the codec descriptor.
132    fn describe(&self) -> &Descr;
133}
134
135/// A list of codec descriptors.
136pub 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    // TODO more lookup functions
150    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}