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    /// Set CRF quality.
211    #[must_use]
212    pub fn with_crf(mut self, crf: f32) -> Self {
213        self.bitrate = BitrateMode::Crf(crf);
214        self
215    }
216
217    /// Set target bitrate.
218    #[must_use]
219    pub fn with_bitrate(mut self, bitrate: u64) -> Self {
220        self.bitrate = BitrateMode::Cbr(bitrate);
221        self
222    }
223
224    /// Set encoder preset.
225    #[must_use]
226    pub fn with_preset(mut self, preset: EncoderPreset) -> Self {
227        self.preset = preset;
228        self
229    }
230}
231
232/// Bitrate control mode.
233#[derive(Clone, Debug)]
234pub enum BitrateMode {
235    /// Constant bitrate (bits/sec).
236    Cbr(u64),
237    /// Variable bitrate with target and maximum.
238    Vbr {
239        /// Target bitrate.
240        target: u64,
241        /// Maximum bitrate.
242        max: u64,
243    },
244    /// Constant quality (CRF value, lower = better).
245    Crf(f32),
246    /// Lossless encoding.
247    Lossless,
248}
249
250/// Encoder preset (speed vs quality tradeoff).
251#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
252pub enum EncoderPreset {
253    /// Fastest encoding, lowest quality.
254    Ultrafast,
255    /// Very fast encoding.
256    Superfast,
257    /// Fast encoding.
258    Veryfast,
259    /// Faster than medium.
260    Faster,
261    /// Fast encoding.
262    Fast,
263    /// Balanced speed and quality.
264    #[default]
265    Medium,
266    /// Slower, better quality.
267    Slow,
268    /// Even slower, better quality.
269    Slower,
270    /// Very slow, high quality.
271    Veryslow,
272    /// Maximum quality, slowest.
273    Placebo,
274}
275
276impl EncoderPreset {
277    /// Get speed value (0-10, 0 = slowest).
278    #[must_use]
279    pub fn speed(&self) -> u8 {
280        match self {
281            Self::Ultrafast => 10,
282            Self::Superfast => 9,
283            Self::Veryfast => 8,
284            Self::Faster => 7,
285            Self::Fast => 6,
286            Self::Medium => 5,
287            Self::Slow => 4,
288            Self::Slower => 3,
289            Self::Veryslow => 2,
290            Self::Placebo => 0,
291        }
292    }
293}
294
295#[cfg(test)]
296mod tests {
297    use super::*;
298
299    #[test]
300    fn test_encoder_config_builder() {
301        let config = EncoderConfig::av1(1920, 1080)
302            .with_crf(24.0)
303            .with_preset(EncoderPreset::Slow);
304
305        assert_eq!(config.width, 1920);
306        assert_eq!(config.height, 1080);
307        assert_eq!(config.preset, EncoderPreset::Slow);
308        assert!(
309            matches!(config.bitrate, BitrateMode::Crf(crf) if (crf - 24.0).abs() < f32::EPSILON)
310        );
311    }
312
313    #[test]
314    fn test_preset_speed() {
315        assert_eq!(EncoderPreset::Ultrafast.speed(), 10);
316        assert_eq!(EncoderPreset::Medium.speed(), 5);
317        assert_eq!(EncoderPreset::Placebo.speed(), 0);
318    }
319}