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}