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}