use std::collections::HashMap;
use av_data::frame::ArcFrame;
use av_data::packet::Packet;
use crate::common::CodecList;
use crate::error::*;
pub trait Decoder: Send + Sync {
fn set_extradata(&mut self, extra: &[u8]);
fn send_packet(&mut self, pkt: &Packet) -> Result<()>;
fn receive_frame(&mut self) -> Result<ArcFrame>;
fn configure(&mut self) -> Result<()>;
fn flush(&mut self) -> Result<()>;
}
#[derive(Debug)]
pub struct Descr {
pub codec: &'static str,
pub name: &'static str,
pub desc: &'static str,
pub mime: &'static str,
}
pub struct Context<D: Decoder> {
dec: D,
}
impl<D: Decoder> Context<D> {
pub fn by_name<T: Descriptor<OutputDecoder = D> + ?Sized>(
codecs: &Codecs<T>,
name: &str,
) -> Option<Self> {
codecs.by_name(name).map(|builder| Context {
dec: builder.create(),
})
}
pub fn set_extradata(&mut self, extra: &[u8]) {
self.dec.set_extradata(extra);
}
pub fn send_packet(&mut self, pkt: &Packet) -> Result<()> {
self.dec.send_packet(pkt)
}
pub fn receive_frame(&mut self) -> Result<ArcFrame> {
self.dec.receive_frame()
}
pub fn configure(&mut self) -> Result<()> {
self.dec.configure()
}
pub fn flush(&mut self) -> Result<()> {
self.dec.flush()
}
pub fn decoder(&self) -> &D {
&self.dec
}
}
pub trait Descriptor {
type OutputDecoder: Decoder;
fn create(&self) -> Self::OutputDecoder;
fn describe(&self) -> &Descr;
}
pub struct Codecs<T: 'static + Descriptor + ?Sized> {
list: HashMap<&'static str, Vec<&'static T>>,
}
impl<T: Descriptor + ?Sized> CodecList for Codecs<T> {
type D = T;
fn new() -> Self {
Self {
list: HashMap::new(),
}
}
fn by_name(&self, name: &str) -> Option<&'static Self::D> {
self.list.get(name).map(|descs| descs[0])
}
fn append(&mut self, desc: &'static Self::D) {
let codec_name = desc.describe().codec;
self.list.entry(codec_name).or_default().push(desc);
}
}
#[cfg(test)]
mod test {
use super::*;
mod dummy {
use super::super::*;
pub struct Dec {
state: usize,
}
pub struct Des {
descr: Descr,
}
impl Descriptor for Des {
type OutputDecoder = Dec;
fn create(&self) -> Self::OutputDecoder {
Dec { state: 0 }
}
fn describe(&self) -> &Descr {
&self.descr
}
}
impl Decoder for Dec {
fn configure(&mut self) -> Result<()> {
Ok(())
}
fn set_extradata(&mut self, extra: &[u8]) {
if extra.len() > 4 {
self.state = 42;
} else {
self.state = 12;
}
}
fn send_packet(&mut self, _packet: &Packet) -> Result<()> {
self.state += 1;
Ok(())
}
fn receive_frame(&mut self) -> Result<ArcFrame> {
unimplemented!()
}
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
pub const DUMMY_DESCR: &Des = &Des {
descr: Descr {
codec: "dummy",
name: "dummy",
desc: "Dummy decoder",
mime: "x-application/dummy",
},
};
}
use self::dummy::DUMMY_DESCR;
#[test]
fn lookup() {
let codecs = Codecs::from_list(&[DUMMY_DESCR]);
let _dec = codecs.by_name("dummy").unwrap();
}
}