oxideav_codec/lib.rs
1//! Codec traits and registry.
2//!
3//! Format crates implement `Decoder` / `Encoder` and register themselves by
4//! building `DecoderFactory` / `EncoderFactory` values. The central `oxideav`
5//! aggregator pulls everything together into a single `Registry`.
6
7pub mod registry;
8
9use oxideav_core::{CodecId, CodecParameters, ExecutionContext, Frame, Packet, Result};
10
11/// A packet-to-frame decoder.
12pub trait Decoder: Send {
13 fn codec_id(&self) -> &CodecId;
14
15 /// Feed one compressed packet. May or may not produce a frame immediately —
16 /// call `receive_frame` in a loop afterwards.
17 fn send_packet(&mut self, packet: &Packet) -> Result<()>;
18
19 /// Pull the next decoded frame, if any. Returns `Error::NeedMore` when the
20 /// decoder needs another packet.
21 fn receive_frame(&mut self) -> Result<Frame>;
22
23 /// Signal end-of-stream. After this, `receive_frame` will drain buffered
24 /// frames and eventually return `Error::Eof`.
25 fn flush(&mut self) -> Result<()>;
26
27 /// Discard all carry-over state so the decoder can resume from a new
28 /// bitstream position without producing stale output. Called by the
29 /// player after a container seek.
30 ///
31 /// Unlike [`flush`](Self::flush) (which signals end-of-stream and
32 /// drains buffered frames), `reset` is expected to:
33 /// * drop every buffered input packet and pending output frame;
34 /// * zero any per-stream filter / predictor / overlap memory so the
35 /// next `send_packet` decodes as if it were the first;
36 /// * leave the codec id and stream parameters untouched.
37 ///
38 /// The default is a conservative "drain-then-forget": call
39 /// [`flush`](Self::flush) and ignore any remaining frames. Stateful
40 /// codecs (LPC predictors, backward-adaptive gain, IMDCT overlap,
41 /// reference pictures, …) should override this to wipe their
42 /// internal state explicitly — otherwise the first ~N output
43 /// samples after a seek will be glitchy until the state re-adapts.
44 fn reset(&mut self) -> Result<()> {
45 self.flush()?;
46 // Drain any remaining output frames so the next send_packet
47 // starts clean. NeedMore / Eof both mean "no more frames"; any
48 // other error is surfaced so the caller can see why.
49 use oxideav_core::Error;
50 loop {
51 match self.receive_frame() {
52 Ok(_) => {}
53 Err(Error::NeedMore) | Err(Error::Eof) => return Ok(()),
54 Err(e) => return Err(e),
55 }
56 }
57 }
58
59 /// Advisory: announce the runtime environment (today: a thread budget
60 /// for codec-internal parallelism). Called at most once, before the
61 /// first `send_packet`. Default no-op; codecs that want to run
62 /// slice-/GOP-/tile-parallel override this to capture the budget.
63 /// Ignoring the hint is always safe — callers must still work with
64 /// a decoder that runs serial.
65 fn set_execution_context(&mut self, _ctx: &ExecutionContext) {}
66}
67
68/// A frame-to-packet encoder.
69pub trait Encoder: Send {
70 fn codec_id(&self) -> &CodecId;
71
72 /// Parameters describing this encoder's output stream (to feed into a muxer).
73 fn output_params(&self) -> &CodecParameters;
74
75 fn send_frame(&mut self, frame: &Frame) -> Result<()>;
76
77 fn receive_packet(&mut self) -> Result<Packet>;
78
79 fn flush(&mut self) -> Result<()>;
80
81 /// Advisory: announce the runtime environment. Same semantics as
82 /// [`Decoder::set_execution_context`].
83 fn set_execution_context(&mut self, _ctx: &ExecutionContext) {}
84}
85
86/// Factory that builds a decoder for a given codec parameter set.
87pub type DecoderFactory = fn(params: &CodecParameters) -> Result<Box<dyn Decoder>>;
88
89/// Factory that builds an encoder for a given codec parameter set.
90pub type EncoderFactory = fn(params: &CodecParameters) -> Result<Box<dyn Encoder>>;
91
92pub use registry::{CodecImplementation, CodecRegistry};