rusty_av2d 0.3.0: A Faster Rust AV2 Decoder
rusty_av2d 0.3.0 is a Rust AV2 decoder, 2.7 to 3.8 times faster than 0.2.13 on two clips, byte-identical to AVM, and not a claim against libavm.

How fast is the Rust AV2 decoder in rusty_av2d 0.3.0?
rusty_av2d 0.3.0 decodes two 432 by 240 clips 2.7 to 3.8 times faster than rusty_av2d 0.2.13, with byte-identical output. The README says not to treat that number as a win over the C reference decoder libavm yet.
Related reading
Companion brief
rusty_av2d: Pure-Rust AV2 Video DecodePure-Rust AV2 video decoder, no C/FFI. Byte-identical to the AVM reference decoder across a 69-clip conformance corpus. Built for developers shipping onto MATA.NETWORK.
rusty_av2d 0.3.0 is the Rust AV2 decoder Remade with Rust ships beside the C reference. The crate README measures it at 2.7 to 3.8 times the speed of rusty_av2d 0.2.13 on two small clips, and the output still matches the Alliance for Open Media reference decoder byte for byte. This note is that measurement, what produced it, and the limit the same README puts on the number.
The catalog page is rusty_av2d. The search page for the C path is the pure Rust alternative for AVM reference decoder paths. AV1 stays on rusty-av1-toolkit.
What the Rust AV2 decoder replaces
AV2 is the successor to AV1, and it is still being written. The README's claim is direct: every AV2 decoder available today, apart from this crate, is the C reference called libavm. The Rust AV2 decoder is an independent implementation. It does not shell out to that library. It builds with cargo alone: no nasm, no C toolchain, Rust 1.79 or newer. The crates.io line is rusty_av2d 0.3.
A fork that left the C sources behind
The lineage is public. rusty_av2d is a fork of rav1d, the pure-Rust AV1 decoder, which is a port of dav1d. The AV1 scaffold was retargeted to AV2 by inverting the AVM reference, brick by brick, against a symbol-level oracle. The fork had inherited dav1d's C sources, about 37,600 lines, and none of that C was compiled. It has been deleted, along with the old assembly. The license stays BSD-2-Clause.
The safe Rust API mirrors dav1d-rs. You send one temporal unit, drain the pictures it produced, then finish the stream so frames that wait on a later picture can come out. A C ABI is on by default and reuses dav1d symbol names, which collide with rav1d if both decoders are linked. Turning default features off drops that ABI and leaves the safe Rust API in place. That is how remade_ffmpeg_rs links an AV1 decoder and this Rust AV2 decoder in one binary. The field note is remade_ffmpeg_rs.
Sixty-nine clips, every byte
Correctness is the gate the speedup had to keep. Sixty-nine clips are decoded and compared byte for byte with AOM's avmdec. A single bit in a single pixel fails the build. One hundred twenty-nine unit and integration tests run beside them. The corpus covers intra and inter tools, temporal interpolated prediction, transforms, deblocking, CDEF, loop restoration, CCSO, GDF, film grain, 64 and 128 pixel superblocks, odd dimensions, 8-bit and 10-bit, and 4:2:0, 4:2:2, and 4:4:4. Eleven clips turn off exactly one sequence tool, so the gate is checked in both directions. There are no official AV2 conformance vectors. Correct here means bit-exact against AVM as of this commit. The bitstream can still change under the crate.
How the Rust AV2 decoder got faster
The README is plain that the original goal was provable correctness, and that speed came second. Version 0.3.0 is the first large step on speed, and it keeps the bytes. A Rust AV2 decoder that only looked faster would have failed the same gate.
Two clips on one core
Both clips are 432 by 240, one thread, Windows 11, x86-64. Times are the fastest of ten runs per binary, pinned to one core at high priority, the two binaries alternating, with an MD5 check on every run. Process start is included in the time. The newer binary won all ten pairs on both clips. A same-binary control pair differed by under 1 percent. Instruction counts are callgrind totals on Linux for the same decodes, and those counts do not vary from run to run.
| Clip | 0.2.13 | 0.3.0 | Wall clock | Instructions | | --- | --- | --- | --- | --- | | v432_16f_q128, 16 frames | 903 ms | 233 ms | 3.84 times | 6.83G to 2.95G, 2.31 times fewer | | v432_8f_sb128cdef, 8 frames | 253 ms | 95 ms | 2.66 times | 1.69G to 0.82G, 2.06 times fewer |
Both clips are ones 0.2.13 already decoded correctly, so the two versions do the same work. On real avmenc streams, 0.2.13's output was wrong, tracked as issue 14, so there is no like-for-like timing on those files.
Kernels, copies, and one allocator line
The README names the changes behind that table. AVX2 and NEON motion-compensation kernels now cover every fixed-filter 8-tap sample. Before 0.3.0 they covered 12.8 percent. Reference frames are shared across a reference switch, where they used to be copied. Loop restoration reads a prefetched window, where it used to fetch each tap through a clamping accessor. Scratch buffers are reused, where they used to be zeroed on each call. Diagnostic probes and corrupt-stream guards no longer sit on the hot path. The kernels are dispatched at runtime, checked against a scalar twin, and RUSTY_AV2D_NOSIMD=1 turns them off.
A second number belongs next to the table, because it is larger than the kernels that remain. The Rust AV2 decoder allocates heavily, on the order of 190 sites, many of them per transform unit. On a system heap that cost dominates the profile. Installing rusty_alloc in the binary measured 1.38 times end to end, still byte-identical, from one line. The bundled CLI does this. The library does not, because a library must not pick the global allocator for every caller. The field note is rusty_alloc. The README calls that allocator line the single largest speedup still available, larger than fully vectorizing every remaining kernel.
What this Rust AV2 decoder still leaves open
The crate is a research preview. The README says to read the limits before depending on it, especially if bitstream stability or decode speed is the reason you came.
The C reference is still ahead on purpose
Motion compensation is the vectorized part. The in-loop filters, GDF, loop restoration, and CDEF, are still scalar, and they now lead the profile. The README says not to benchmark this Rust AV2 decoder against libavm and expect a fair fight yet. Threading is under-tested: the correctness gate is single-threaded, and multi-threaded output has only been spot-checked. There is no encoder in this crate. Stills in an AV2-shaped container live next door in rusty_av2f.
Corrupt input is fuzzed with bit flips, truncation, and header mutation. The most recent 1000-case run produced zero panics and zero hangs. That is a sample, not a proof. Two modules are panic-free under a clippy deny of indexing and slicing. The rest of the decode path is not yet.
Where the pipeline actually runs
Embed rusty_av2d 0.3 from crates.io, set the allocator in your binary, and keep the C ABI off if rav1d shares the link. remade_ffmpeg_rs already uses the crate as the rff-codec-av2 backend, so a media pipeline on mata.network can decode AV2 with libavm off the hot path. The map is Media on Vision. The program thesis is The Importance of Remade With Rust. The repo pin is the rusty_av2d landing.
The speedup is real on the clips the project published, against its own previous Rust AV2 decoder, with the picture held still. The C reference remains the clock the README refuses to claim. That is the honest shape of this Rust AV2 decoder at version 0.3.0.
FAQ
Quick answers for builders evaluating this technology.
What does the Rust AV2 decoder replace?
The README says every other AV2 decoder available today is libavm, the C reference. rusty_av2d is an independent Rust implementation. It builds with cargo alone, with no nasm and no C toolchain, and it does not shell out to libavm.
Which clips show the 2.7 to 3.8 times speedup?
Two clips at 432 by 240, one thread. v432_16f_q128 fell from 903 ms to 233 ms, 3.84 times. v432_8f_sb128cdef fell from 253 ms to 95 ms, 2.66 times. Times are the fastest of ten pinned runs, and the picture matched.
Does rusty_alloc change the Rust AV2 decoder speed?
On a system heap the allocator dominates the profile. Installing rusty_alloc in the binary measured 1.38 times end to end, still byte-identical. The library does not set that allocator. The caller does, in one line.
Is the Rust AV2 decoder faster than libavm?
The published speedup is against rusty_av2d 0.2.13, not against libavm. Motion compensation is vectorized. GDF, loop restoration, and CDEF are still scalar and now lead the profile. The README says a comparison with libavm is not a fair fight yet.
Where should a builder read the rusty_av2d 0.3.0 speed note?
The crate README on GitHub, then the rusty_av2d field note, the remade_ffmpeg_rs page that links it as rff-codec-av2, and mata.network for the mesh that runs that pipeline.