use std::collections::HashMap;
use rff_core::{
CodecId, Dictionary, Error, Frame, MediaType, Packet, PixelFormat, Result, SampleFormat,
};
#[derive(Debug, Clone, Default)]
pub struct CodecParams {
pub codec_id: CodecId,
pub width: u32,
pub height: u32,
pub pixel_format: Option<PixelFormat>,
pub sample_rate: u32,
pub channels: u16,
pub sample_format: Option<SampleFormat>,
pub extradata: Vec<u8>,
}
pub trait Decoder: Send {
fn configure(&mut self, _params: &CodecParams) -> Result<()> {
Ok(())
}
fn send_packet(&mut self, packet: &Packet) -> Result<()>;
fn receive_frame(&mut self) -> Result<Frame>;
fn flush(&mut self) {}
}
pub trait Encoder: Send {
fn configure(&mut self, _options: &Dictionary) -> Result<()> {
Ok(())
}
fn accepted_sample_rates(&self) -> Option<Vec<u32>> {
None
}
fn accepted_pixel_formats(&self) -> Option<Vec<PixelFormat>> {
None
}
fn send_frame(&mut self, frame: &Frame) -> Result<()>;
fn receive_packet(&mut self) -> Result<Packet>;
fn flush(&mut self) {}
}
pub type DecoderFactory = fn() -> Box<dyn Decoder>;
pub type EncoderFactory = fn() -> Box<dyn Encoder>;
pub struct Codec {
pub id: CodecId,
pub name: &'static str,
pub long_name: &'static str,
pub media_type: MediaType,
pub decoder: Option<DecoderFactory>,
pub encoder: Option<EncoderFactory>,
}
impl Codec {
pub fn can_decode(&self) -> bool {
self.decoder.is_some()
}
pub fn can_encode(&self) -> bool {
self.encoder.is_some()
}
}
#[derive(Default)]
pub struct CodecRegistry {
by_id: HashMap<CodecId, Codec>,
by_name: HashMap<&'static str, CodecId>,
}
impl CodecRegistry {
pub fn new() -> CodecRegistry {
CodecRegistry::default()
}
pub fn register(&mut self, codec: Codec) {
self.by_name.insert(codec.name, codec.id);
self.by_id.insert(codec.id, codec);
}
pub fn find_decoder(&self, id: CodecId) -> Result<Box<dyn Decoder>> {
self.by_id
.get(&id)
.and_then(|c| c.decoder)
.map(|factory| factory())
.ok_or(Error::DecoderNotFound(id))
}
pub fn find_encoder(&self, id: CodecId) -> Result<Box<dyn Encoder>> {
self.by_id
.get(&id)
.and_then(|c| c.encoder)
.map(|factory| factory())
.ok_or(Error::EncoderNotFound(id))
}
pub fn by_name(&self, name: &str) -> Option<&Codec> {
self.by_name.get(name).and_then(|id| self.by_id.get(id))
}
pub fn by_id(&self, id: CodecId) -> Option<&Codec> {
self.by_id.get(&id)
}
pub fn iter(&self) -> impl Iterator<Item = &Codec> {
self.by_id.values()
}
pub fn len(&self) -> usize {
self.by_id.len()
}
pub fn is_empty(&self) -> bool {
self.by_id.is_empty()
}
}