oxideav-codec
Codec traits + registry for the
oxideav pure-Rust media
framework. Every per-format codec crate (MP3, AAC, H.264, GIF, …)
implements Decoder and/or Encoder and registers itself via a
CodecImplementation; the aggregator builds one CodecRegistry with
the union of every enabled feature.
Decoder—send_packet→receive_frame, plusflush(EOS drain) andreset(state wipe after seek, added in 0.0.4).Encoder—send_frame→receive_packet, plusflush.CodecCapabilities— per-impl flags (lossless, intra-only, accepted pixel formats, supported sample rates, priority) so registries can pick the right implementation for a given request.CodecRegistry— factory lookup byCodecId, with fallback when the first-choice implementation refuses the input.
Zero C dependencies. Zero FFI.
Usage
[]
= "0.0"
Using a codec directly (standalone, no container, no pipeline)
OxideAV's codecs are designed to be usable on their own. If you already
have raw encoded packets (from disk, the network, or another parser),
you only need three crates: oxideav-core for the Packet / Frame
types, oxideav-codec for the Decoder / Encoder traits + registry,
and the specific codec crate you want.
Example — decoding G.711 µ-law:
[]
= "0.0"
= "0.0"
= "0.0"
use CodecRegistry;
use ;
// 1. Register the codec with a registry (one-time setup).
let mut reg = new;
register;
// 2. Describe the stream — here 8 kHz mono µ-law.
let mut params = audio;
params.sample_rate = Some;
params.channels = Some;
// 3. Build a decoder.
let mut dec = reg.make_decoder?;
// 4. Feed packets + pull frames in a loop.
let pkt = new;
dec.send_packet?;
match dec.receive_frame?
# Ok::
The packet → frame loop
send_packet / receive_frame is a two-step state machine. Most
codecs accept exactly one packet per frame (a 1:1 mapping), so the
pattern is:
for pkt in stream_of_packets
Some codecs buffer internally (e.g. a video codec waiting for reference
frames). In that case receive_frame returns Error::NeedMore until
the decoder has enough input; keep sending packets until you get a
frame, and keep pulling frames after each send (a single packet may
produce multiple frames for some codecs). The canonical loop:
loop
Signalling end-of-stream
When you've sent every packet and want to flush any still-buffered output:
dec.flush?;
while let Ok = dec.receive_frame
Resetting after a seek
If you reposition the input mid-stream (seek), call reset() instead
of flush(). reset drops buffered packets and wipes codec-internal
state (LPC memory, IMDCT overlap, reference pictures) so the first
frame after the seek decodes cleanly rather than glitching:
// After repositioning your byte stream:
dec.reset?;
// ...resume feeding packets from the new position...
Encoding is symmetric
The Encoder trait mirrors Decoder — build via
reg.make_encoder(¶ms), feed raw Frames with send_frame, pull
encoded Packets with receive_packet. See each codec's README for
per-format parameter requirements (sample rate, channel count,
bitrate, pixel format, etc.).
Extending the registry
Codec crates expose a single register(reg) function that pushes their
implementation(s) into the registry. The registry supports multiple
implementations per codec id with priority + capability fallback, so
you can register a fast-but-lossy impl and a slow-but-accurate one and
have the registry pick based on CodecPreferences:
License
MIT — see LICENSE.