Skip to main content

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};