Skip to main content

rff_codec/
lib.rs

1//! `rff-codec` — the codec abstraction layer (FFmpeg's `libavcodec` core,
2//! minus the codecs themselves).
3//!
4//! It defines:
5//! * the [`Decoder`] and [`Encoder`] traits, using the same *send / receive*
6//!   shape as modern FFmpeg (`avcodec_send_packet` / `avcodec_receive_frame`),
7//! * a [`Codec`] descriptor that advertises a codec's identity and which
8//!   directions (decode/encode) it supports,
9//! * a [`CodecRegistry`] that individual codec crates register into.
10//!
11//! Concrete codecs live in their own crates (`rff-codec-h264`, ...) and are
12//! pulled together by the `rff` facade.
13
14use std::collections::HashMap;
15
16use rff_core::{
17    CodecId, Dictionary, Error, Frame, MediaType, Packet, PixelFormat, Result, SampleFormat,
18};
19
20/// Stream parameters handed to a decoder before the first packet. Self-describing
21/// codecs (AV1, PNG, ...) can ignore these; raw/parametric codecs (PCM, and
22/// codecs that carry config out of band like H.264 SPS/PPS) need them.
23#[derive(Debug, Clone, Default)]
24pub struct CodecParams {
25    pub codec_id: CodecId,
26    // Video
27    pub width: u32,
28    pub height: u32,
29    pub pixel_format: Option<PixelFormat>,
30    // Audio
31    pub sample_rate: u32,
32    pub channels: u16,
33    pub sample_format: Option<SampleFormat>,
34    /// Codec-private init data (SPS/PPS, OpusHead, ...).
35    pub extradata: Vec<u8>,
36}
37
38/// Decodes compressed [`Packet`]s into raw [`Frame`]s.
39///
40/// Drive it the FFmpeg way: feed packets with [`send_packet`](Decoder::send_packet),
41/// then pull frames with [`receive_frame`](Decoder::receive_frame) until it
42/// returns [`Error::Again`] (needs more input) or [`Error::Eof`].
43pub trait Decoder: Send {
44    /// Receive the stream's parameters before decoding begins. Default: ignore
45    /// them (the bitstream is self-describing). Called once, after construction.
46    fn configure(&mut self, _params: &CodecParams) -> Result<()> {
47        Ok(())
48    }
49
50    /// Submit one compressed packet for decoding.
51    fn send_packet(&mut self, packet: &Packet) -> Result<()>;
52
53    /// Retrieve the next decoded frame, if one is ready.
54    ///
55    /// Returns [`Error::Again`] when more packets are needed, or [`Error::Eof`]
56    /// once fully drained.
57    fn receive_frame(&mut self) -> Result<Frame>;
58
59    /// Signal end-of-input so buffered frames can be flushed out via
60    /// subsequent `receive_frame` calls. Default: no buffering.
61    fn flush(&mut self) {}
62}
63
64/// Encodes raw [`Frame`]s into compressed [`Packet`]s. Mirror of [`Decoder`].
65pub trait Encoder: Send {
66    /// Receive output options before encoding begins — rate control and tuning:
67    /// `crf`/`qp` (quality), `preset` (speed/quality trade-off), `b` (bitrate),
68    /// `pass` (1 or 2). Default: ignore them. Called once, after construction.
69    fn configure(&mut self, _options: &Dictionary) -> Result<()> {
70        Ok(())
71    }
72
73    /// The input sample rates this encoder accepts, or `None` for "any rate".
74    /// The transcode pipeline resamples audio to the nearest accepted rate
75    /// before feeding frames (mirrors FFmpeg's automatic `aresample`).
76    fn accepted_sample_rates(&self) -> Option<Vec<u32>> {
77        None
78    }
79
80    /// The pixel formats this encoder accepts, most-preferred first, or `None`
81    /// for "any format". The transcode pipeline converts video to the first
82    /// accepted format before feeding frames (FFmpeg's automatic `scale`).
83    ///
84    /// Declaring this lets decoders emit whatever layout is cheapest for them —
85    /// a JPEG decoder can hand out planar Y'CbCr instead of converting to RGB —
86    /// without breaking encoders that need something else. An encoder that
87    /// leaves this `None` must genuinely handle every format it is given.
88    fn accepted_pixel_formats(&self) -> Option<Vec<PixelFormat>> {
89        None
90    }
91
92    /// Submit one raw frame for encoding.
93    fn send_frame(&mut self, frame: &Frame) -> Result<()>;
94
95    /// Retrieve the next encoded packet, if one is ready.
96    fn receive_packet(&mut self) -> Result<Packet>;
97
98    /// Signal end-of-input to drain buffered packets.
99    fn flush(&mut self) {}
100}
101
102/// Factory function producing a fresh decoder instance.
103pub type DecoderFactory = fn() -> Box<dyn Decoder>;
104/// Factory function producing a fresh encoder instance.
105pub type EncoderFactory = fn() -> Box<dyn Encoder>;
106
107/// Static description of a codec and the implementations available for it.
108pub struct Codec {
109    pub id: CodecId,
110    /// Short name as used on the command line (`h264`, `opus`, ...).
111    pub name: &'static str,
112    /// Human-readable description (shown by `ffmpeg -codecs`).
113    pub long_name: &'static str,
114    pub media_type: MediaType,
115    /// Present if this codec can decode.
116    pub decoder: Option<DecoderFactory>,
117    /// Present if this codec can encode.
118    pub encoder: Option<EncoderFactory>,
119}
120
121impl Codec {
122    pub fn can_decode(&self) -> bool {
123        self.decoder.is_some()
124    }
125    pub fn can_encode(&self) -> bool {
126        self.encoder.is_some()
127    }
128}
129
130/// Holds every codec known to a running engine. Codec crates call
131/// [`register`](CodecRegistry::register) to add themselves.
132#[derive(Default)]
133pub struct CodecRegistry {
134    by_id: HashMap<CodecId, Codec>,
135    by_name: HashMap<&'static str, CodecId>,
136}
137
138impl CodecRegistry {
139    pub fn new() -> CodecRegistry {
140        CodecRegistry::default()
141    }
142
143    /// Register a codec. A later registration for the same [`CodecId`] replaces
144    /// the earlier one (lets downstreams override a built-in).
145    pub fn register(&mut self, codec: Codec) {
146        self.by_name.insert(codec.name, codec.id);
147        self.by_id.insert(codec.id, codec);
148    }
149
150    /// Instantiate a decoder for `id`, or [`Error::DecoderNotFound`].
151    pub fn find_decoder(&self, id: CodecId) -> Result<Box<dyn Decoder>> {
152        self.by_id
153            .get(&id)
154            .and_then(|c| c.decoder)
155            .map(|factory| factory())
156            .ok_or(Error::DecoderNotFound(id))
157    }
158
159    /// Instantiate an encoder for `id`, or [`Error::EncoderNotFound`].
160    pub fn find_encoder(&self, id: CodecId) -> Result<Box<dyn Encoder>> {
161        self.by_id
162            .get(&id)
163            .and_then(|c| c.encoder)
164            .map(|factory| factory())
165            .ok_or(Error::EncoderNotFound(id))
166    }
167
168    /// Look up a codec descriptor by its canonical name.
169    pub fn by_name(&self, name: &str) -> Option<&Codec> {
170        self.by_name.get(name).and_then(|id| self.by_id.get(id))
171    }
172
173    /// Look up a codec descriptor by id.
174    pub fn by_id(&self, id: CodecId) -> Option<&Codec> {
175        self.by_id.get(&id)
176    }
177
178    /// Iterate all registered codecs (order unspecified).
179    pub fn iter(&self) -> impl Iterator<Item = &Codec> {
180        self.by_id.values()
181    }
182
183    pub fn len(&self) -> usize {
184        self.by_id.len()
185    }
186
187    pub fn is_empty(&self) -> bool {
188        self.by_id.is_empty()
189    }
190}