Skip to main content

oximedia_codec/
traits.rs

1//! Codec traits for video encoding and decoding.
2
3use crate::{CodecResult, VideoFrame};
4use oximedia_core::{CodecId, PixelFormat, Rational};
5
6/// Video decoder trait.
7///
8/// Implements a push-pull decoding model:
9/// 1. Send compressed packets with [`send_packet`](VideoDecoder::send_packet)
10/// 2. Receive decoded frames with [`receive_frame`](VideoDecoder::receive_frame)
11///
12/// # Example
13///
14/// ```ignore
15/// while let Some(packet) = demuxer.read_packet()? {
16///     decoder.send_packet(&packet)?;
17///     while let Some(frame) = decoder.receive_frame()? {
18///         process_frame(frame);
19///     }
20/// }
21/// decoder.flush()?;
22/// while let Some(frame) = decoder.receive_frame()? {
23///     process_frame(frame);
24/// }
25/// ```
26pub trait VideoDecoder: Send {
27    /// Get codec identifier.
28    fn codec(&self) -> CodecId;
29
30    /// Send a compressed packet to the decoder.
31    ///
32    /// # Errors
33    ///
34    /// Returns error if the packet is invalid or decoder is in error state.
35    fn send_packet(&mut self, data: &[u8], pts: i64) -> CodecResult<()>;
36
37    /// Receive a decoded frame.
38    ///
39    /// Returns `Ok(None)` if more data is needed.
40    ///
41    /// # Errors
42    ///
43    /// Returns error if decoding fails.
44    fn receive_frame(&mut self) -> CodecResult<Option<VideoFrame>>;
45
46    /// Flush the decoder.
47    ///
48    /// Call this after all packets have been sent to retrieve remaining frames.
49    ///
50    /// # Errors
51    ///
52    /// Returns error if flush fails.
53    fn flush(&mut self) -> CodecResult<()>;
54
55    /// Reset the decoder state.
56    fn reset(&mut self);
57
58    /// Get decoder output format.
59    fn output_format(&self) -> Option<PixelFormat>;
60
61    /// Get decoded frame dimensions.
62    fn dimensions(&self) -> Option<(u32, u32)>;
63}
64
65/// Video encoder trait.
66///
67/// Implements a push-pull encoding model:
68/// 1. Send raw frames with [`send_frame`](VideoEncoder::send_frame)
69/// 2. Receive compressed packets with [`receive_packet`](VideoEncoder::receive_packet)
70pub trait VideoEncoder: Send {
71    /// Get codec identifier.
72    fn codec(&self) -> CodecId;
73
74    /// Send a raw frame to the encoder.
75    ///
76    /// # Errors
77    ///
78    /// Returns error if the frame format is invalid.
79    fn send_frame(&mut self, frame: &VideoFrame) -> CodecResult<()>;
80
81    /// Receive an encoded packet.
82    ///
83    /// Returns `Ok(None)` if more frames are needed.
84    ///
85    /// # Errors
86    ///
87    /// Returns error if encoding fails.
88    fn receive_packet(&mut self) -> CodecResult<Option<EncodedPacket>>;
89
90    /// Flush the encoder.
91    ///
92    /// Call this after all frames have been sent to retrieve remaining packets.
93    ///
94    /// # Errors
95    ///
96    /// Returns error if flush fails.
97    fn flush(&mut self) -> CodecResult<()>;
98
99    /// Get encoder configuration.
100    fn config(&self) -> &EncoderConfig;
101}
102
103/// Encoded packet output from encoder.
104#[derive(Clone, Debug)]
105pub struct EncodedPacket {
106    /// Compressed data.
107    pub data: Vec<u8>,
108    /// Presentation timestamp.
109    pub pts: i64,
110    /// Decode timestamp.
111    pub dts: i64,
112    /// Is keyframe.
113    pub keyframe: bool,
114    /// Duration in timebase units.
115    pub duration: Option<i64>,
116}
117
118/// Decoder configuration.
119#[derive(Clone, Debug)]
120pub struct DecoderConfig {
121    /// Codec to decode.
122    pub codec: CodecId,
123    /// Extra data (codec-specific).
124    pub extradata: Option<Vec<u8>>,
125    /// Number of decoder threads (0 = auto).
126    pub threads: usize,
127    /// Enable low-latency mode.
128    pub low_latency: bool,
129}
130
131impl Default for DecoderConfig {
132    fn default() -> Self {
133        Self {
134            codec: CodecId::Av1,
135            extradata: None,
136            threads: 0,
137            low_latency: false,
138        }
139    }
140}
141
142/// Encoder configuration.
143#[derive(Clone, Debug)]
144pub struct EncoderConfig {
145    /// Target codec.
146    pub codec: CodecId,
147    /// Frame width.
148    pub width: u32,
149    /// Frame height.
150    pub height: u32,
151    /// Input pixel format.
152    pub pixel_format: PixelFormat,
153    /// Frame rate.
154    pub framerate: Rational,
155    /// Bitrate mode.
156    pub bitrate: BitrateMode,
157    /// Encoder preset.
158    pub preset: EncoderPreset,
159    /// Profile (codec-specific).
160    pub profile: Option<String>,
161    /// Keyframe interval.
162    pub keyint: u32,
163    /// Number of encoder threads (0 = auto).
164    pub threads: usize,
165    /// Timebase for output packets.
166    pub timebase: Rational,
167}
168
169impl Default for EncoderConfig {
170    fn default() -> Self {
171        Self {
172            codec: CodecId::Av1,
173            width: 1920,
174            height: 1080,
175            pixel_format: PixelFormat::Yuv420p,
176            framerate: Rational::new(30, 1),
177            bitrate: BitrateMode::Crf(28.0),
178            preset: EncoderPreset::Medium,
179            profile: None,
180            keyint: 250,
181            threads: 0,
182            timebase: Rational::new(1, 1000),
183        }
184    }
185}
186
187impl EncoderConfig {
188    /// Create AV1 encoder config.
189    #[must_use]
190    pub fn av1(width: u32, height: u32) -> Self {
191        Self {
192            codec: CodecId::Av1,
193            width,
194            height,
195            ..Default::default()
196        }
197    }
198
199    /// Create VP9 encoder config.
200    #[must_use]
201    pub fn vp9(width: u32, height: u32) -> Self {
202        Self {
203            codec: CodecId::Vp9,
204            width,
205            height,
206            ..Default::default()
207        }
208    }
209
210    /// Create VP8 encoder config.
211    #[must_use]
212    pub fn vp8(width: u32, height: u32) -> Self {
213        Self {
214            codec: CodecId::Vp8,
215            width,
216            height,
217            ..Default::default()
218        }
219    }
220
221    /// Set CRF quality.
222    #[must_use]
223    pub fn with_crf(mut self, crf: f32) -> Self {
224        self.bitrate = BitrateMode::Crf(crf);
225        self
226    }
227
228    /// Set target bitrate.
229    #[must_use]
230    pub fn with_bitrate(mut self, bitrate: u64) -> Self {
231        self.bitrate = BitrateMode::Cbr(bitrate);
232        self
233    }
234
235    /// Set encoder preset.
236    #[must_use]
237    pub fn with_preset(mut self, preset: EncoderPreset) -> Self {
238        self.preset = preset;
239        self
240    }
241}
242
243/// Bitrate control mode.
244#[derive(Clone, Debug)]
245pub enum BitrateMode {
246    /// Constant bitrate (bits/sec).
247    Cbr(u64),
248    /// Variable bitrate with target and maximum.
249    Vbr {
250        /// Target bitrate.
251        target: u64,
252        /// Maximum bitrate.
253        max: u64,
254    },
255    /// Constant quality (CRF value, lower = better).
256    Crf(f32),
257    /// Lossless encoding.
258    Lossless,
259}
260
261/// Encoder preset (speed vs quality tradeoff).
262#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
263pub enum EncoderPreset {
264    /// Fastest encoding, lowest quality.
265    Ultrafast,
266    /// Very fast encoding.
267    Superfast,
268    /// Fast encoding.
269    Veryfast,
270    /// Faster than medium.
271    Faster,
272    /// Fast encoding.
273    Fast,
274    /// Balanced speed and quality.
275    #[default]
276    Medium,
277    /// Slower, better quality.
278    Slow,
279    /// Even slower, better quality.
280    Slower,
281    /// Very slow, high quality.
282    Veryslow,
283    /// Maximum quality, slowest.
284    Placebo,
285}
286
287impl EncoderPreset {
288    /// Get speed value (0-10, 0 = slowest).
289    #[must_use]
290    pub fn speed(&self) -> u8 {
291        match self {
292            Self::Ultrafast => 10,
293            Self::Superfast => 9,
294            Self::Veryfast => 8,
295            Self::Faster => 7,
296            Self::Fast => 6,
297            Self::Medium => 5,
298            Self::Slow => 4,
299            Self::Slower => 3,
300            Self::Veryslow => 2,
301            Self::Placebo => 0,
302        }
303    }
304}
305
306#[cfg(test)]
307mod tests {
308    use super::*;
309
310    #[test]
311    fn test_encoder_config_builder() {
312        let config = EncoderConfig::av1(1920, 1080)
313            .with_crf(24.0)
314            .with_preset(EncoderPreset::Slow);
315
316        assert_eq!(config.width, 1920);
317        assert_eq!(config.height, 1080);
318        assert_eq!(config.preset, EncoderPreset::Slow);
319        assert!(
320            matches!(config.bitrate, BitrateMode::Crf(crf) if (crf - 24.0).abs() < f32::EPSILON)
321        );
322    }
323
324    #[test]
325    fn test_preset_speed() {
326        assert_eq!(EncoderPreset::Ultrafast.speed(), 10);
327        assert_eq!(EncoderPreset::Medium.speed(), 5);
328        assert_eq!(EncoderPreset::Placebo.speed(), 0);
329    }
330}