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}