# rusty_av2f
[](https://github.com/remade-with-rust)
[](https://www.mata.network)
[](https://crates.io/crates/rusty_av2f)
[](https://docs.rs/rusty_av2f)
[](LICENSE)
A pure-Rust **still-image container for AV2** — one coded picture stored as an
item in an ISOBMFF/HEIF file, in the shape AVIF uses for AV1. Zero dependencies,
no C, no FFI, no `unsafe`.
- **Writer** — emits the minimum HEIF structure for a single image item
(`ftyp` / `meta` / `iloc` / `ipco` with `ispe`+`pixi`+`av2C` / `mdat`), 250
bytes of overhead over the coded payload.
- **Reader** — parses that structure back and hands you the AV2 bitstream
**byte for byte**; the container is lossless by construction.
- **Fails rather than guesses** — unbounded box sizes are rejected, every parsed
length is `checked_add`, and the tests feed it every truncation prefix plus
several thousand byte mutations.
- **100% safe Rust**, and the whole crate is four small modules — the format
surface is deliberately small enough to audit in one sitting.
> ### ⚠️ Not an AOM standard, and not interoperable
>
> AV2F's four-character codes are **chosen by this crate**, not specified by
> anyone. Files it writes are readable by it and by nothing else. Read
> [the next section](#read-this-before-you-use-it) before producing files you
> intend to keep.
---
## Read this before you use it
AVIF exists because AOM published a specification that fixes its brand (`avif`),
its item type (`av01`) and its configuration record (`av1C`). **There is no
equivalent document for AV2** — none that we have found. Every four-character
code below is therefore *chosen*, not *specified*:
| Major brand | `avif` | `av2f` |
| Item type | `av01` | `av02` |
| Config box | `av1C` | `av2C` |
| Extension | `.avif` | `.av2f` |
They live in [`src/fourcc.rs`](src/fourcc.rs) and nowhere else — a unit test
(`every_fourcc_comes_from_the_fourcc_module`) enforces that nothing in the reader
or writer hard-codes one. Adopting a real specification later is an edit to one
file.
Consequences, stated plainly:
- **No browser, phone, or image viewer will open these files.** A conforming
HEIF reader can walk the box structure — we write the standard `mif1`/`miaf`
compatible brands — but will not recognise the codec.
- **The format may change without a compatibility story.** If AOM publishes
something different, this crate follows it and files written by earlier
versions stop being readable. There is no migration promise.
- **The `av2C` record's layout is ours too** — deliberately plain (a version
byte, then one field per byte) rather than bit-packed, because it exists to be
replaced. Unlike `av1C`, it is not a mirror of the codec's sequence header.
What it is genuinely good for: pipeline plumbing, storing AV2 stills next to AVIF
stills for size comparisons, and having the container work already done when a
specification does arrive.
## Usage
```rust
use rusty_av2f::{encode, decode, Params, Config};
// `payload` is an AV2 still-picture bitstream — e.g. an IVF frame's payload.
let params = Params { width: 432, height: 240, config: Config::default() };
let file = encode(¶ms, payload)?;
let img = decode(&file)?;
assert_eq!(img.payload, payload); // the container is lossless
assert_eq!((img.width, img.height), (432, 240));
```
Sniff a file without parsing it, in the shape format probes conventionally use
(0–100):
```rust
if rusty_av2f::probe(&bytes) == 100 { /* it's ours */ }
```
## Header forms: both supported
AV2 can code a still picture two ways: with the ordinary frame headers, or with
the compact form signalled by `single_picture_header_flag` (AV2's rename of AV1's
`reduced_still_picture_header`). The compact form is the natural choice for an
image format — it is what AVIF uses — and **both forms encode and decode here**.
(Versions before 0.2.0 accepted only the full form because
[`rusty_av2d`](https://crates.io/crates/rusty_av2d) could not yet decode the
compact one bit-exactly. That landed in `rusty_av2d` 0.2.5, verified
byte-identical against AOM's reference decoder, and the restriction is gone —
`Config::full_still_picture_header` is now informational.)
Produce a payload with AOM's reference encoder — either form:
```sh
avmenc --codec=av2 --limit=1 --ivf --end-usage=q --qp=140 -o still.ivf source.y4m
# add --full-still-picture-hdr for the full-header form
```
and hand `encode` the IVF frame's payload.
## What's in the file
The minimum HEIF structure for a single image item — the same skeleton AVIF uses,
so the layout is familiar in a hex dump:
```
ftyp major brand av2f, compatible av2f/mif1/miaf
meta
hdlr 'pict'
pitm item 1
iinf one infe, item type av02
iprp
ipco ispe (dimensions), pixi (bit depth per channel), av2C (config)
ipma binds all three to item 1
iloc offset + length of the payload in mdat
mdat the AV2 bitstream, byte for byte
```
A real 320×480 photograph encoded at qp 140 lands at **6,980 bytes**, of which
250 are container overhead. (The same picture as lossless PNG is 285,948 bytes —
not a like-for-like comparison, since one is lossy and one is not, but it is what
a real file looks like.)
## Robustness
The parser is written to fail rather than guess, and is tested that way:
- Box sizes of 0 ("to end of file") and 1 ("64-bit size follows") are
**rejected** — neither appears in what this crate writes, and accepting them
would mean trusting a length the parser cannot bound.
- `truncation_never_panics` feeds every prefix of a valid file.
- `corrupt_bytes_never_panic` feeds several thousand single-byte mutations.
- All arithmetic on parsed lengths is checked. A bounds test written as
`off + len > buf.len()` is itself an overflow bug, so the code uses
`checked_add`.
## Status
**Experimental — 0.x, and the format is provisional.** Published so it can be
depended on normally, not because the codes are settled. Treat any version bump
as potentially format-breaking until an AOM specification exists.
Verified end to end: a real AV2 still round-trips byte-identically through the
container, and the decoded pixels are **byte-identical to AOM's `avmdec`**.
Note that the container is only as useful as the decoder behind it — `rusty_av2d`
is a research preview with known gaps, so validate your own content rather than
assuming coverage.
## Part of Remade With Rust
`rusty_av2f` is the still-image container of
**[remade_ffmpeg_rs](https://github.com/Remade-With-Rust/remade_ffmpeg_rs)** — a
ground-up, permissively-licensed Rust rebuild of FFmpeg, where it is wired in as
the `av2f` format. Sister project:
**[FFAI](https://github.com/Remade-With-Rust/FFAI)** — media for an AI-first
world. More at **[github.com/remade-with-rust](https://github.com/remade-with-rust)**.
Closest sibling: [`rusty_av2d`](https://crates.io/crates/rusty_av2d), the pure-Rust
AV2 decoder that reads what this crate wraps. Other codec crates:
[`rusty_h264`](https://crates.io/crates/rusty_h264),
[`rusty_vp9`](https://crates.io/crates/rusty_vp9),
[`rusty_aac`](https://crates.io/crates/rusty_aac),
[`rusty_mp3`](https://crates.io/crates/rusty_mp3), and the
[rusty-av1-toolkit](https://github.com/Remade-With-Rust/rusty-av1-toolkit) forks.
## About Mata Network
[Mata Network](https://www.mata.network) builds sovereign, self-hostable
infrastructure. **Remade With Rust** is our open-source home for the
permissively-licensed building blocks that work depends on.
## License
MIT. See [LICENSE](LICENSE). (Original code — unlike `rusty_av2d`, which is
BSD-2-Clause because it carries a fork lineage.)