Learn/Remade with Rust

AV2 and AVIF Decode Fixes Keep remade_ffmpeg_rs Green

AV2 and AVIF decode in remade_ffmpeg_rs had three defects behind one red debug test: an empty packet abort, a GDF underflow, and ARM assembly.

Signed by M·
A short strip of 35mm film with four landscape frames on a sunlit oak desk beside a matte-black compact camera
What broke AV2 and AVIF decode in remade_ffmpeg_rs?

Three defects sat behind one red test. An empty AV2 packet aborted in debug, a GDF stripe underflowed in rusty_av2d, and rusty_av1d assembly could not build on ARM.

AV2 and AVIF decode in remade_ffmpeg_rs went red for one command and three different reasons. A debug cargo test died, and the first write-up treated two of the failures as the same bug. They are not. An empty AV2 packet aborted the process. A legal GDF frame underflowed a usize in rusty_av2d. AVIF assembly on ARM could not compile, because the published crate left out a header the .S files include.

The pipeline those codecs sit in is remade_ffmpeg_rs, the pure-Rust media stack. The catalog is Remade with Rust. This page is the 16 October 2026 fix, and the public note of what landed is Future Web News.

Trust is a picture that matches the reference in debug and in release. Security is a hostile packet that returns an error a test can catch. Incentive is a decode that still builds on the ARM laptop and on the x86_64 runner. NIST's Secure Software Development Framework wants memory-safe parsers on bytes a stranger sent. AV2 and AVIF decode is that parser.

What Broke AV2 and AVIF Decode

The red run was fuzz_robustness plus av2f_still, on a debug build. Debug is where Rust checks overflow and where debug_assertions turn a failed input check into process::abort. Release wraps the arithmetic and returns Err from the input check. A suite that is green only in release is a suite that lies about the build developers actually run.

Two notes in the tree had collapsed the story. They said av2_gdf.rs line 549 aborted with STATUS_STACK_BUFFER_OVERRUN. Line 549 is an ordinary panic, and a panic can be caught. The abort was a different line: validate_input! on a packet of length zero. Windows reports that abort as 0xc0000409. The compatibility note now describes the two behaviours apart, and so does this page.

The third break never reached a test binary. rusty_av1d 1.2.0 publishes assembly for ARM and leaves every *.h out of the crate. The ARM sources include src/arm/asm-offsets.h. Any target that turns the asm feature on, and is Apple Silicon, Linux arm64, or Windows ARM64, fails at compile time. That is an AV2 and AVIF decode problem even though the missing header lives only on the AV1 side. AVIF is an AV1 intra frame.

Where remade_ffmpeg_rs AV2 Failed The Suite

remade_ffmpeg_rs AV2 is rff-codec-av2 in front of rusty_av2d 0.2.8. The same underflow is in every published rusty_av2d through 0.2.11. AVIF is rff-codec-avif in front of rusty_av1d 1.2.0 and rusty_av1e 0.8.0. Each engine failed in its own way.

An Empty Packet Aborted remade_ffmpeg_rs AV2

The fuzzer's truncate mutation can hand the decoder a packet with no bytes. rff-codec-av2 used to pass that slice straight through. rusty_av2d requires sz > 0 and sz <= usize::MAX / 2. On a failed check, validate_input! calls debug_abort() when debug assertions are on. An abort is not a panic. catch_unwind does not contain it. The process ends, and the rest of the suite never runs.

The existing random-bytes test added one to every length, so it never sent zero bytes. The empty packet had no test of its own. AVIF already rejected that shape for rusty_av1d. AV2 and AVIF decode did not share the guard.

The First GDF Stripe Underflowed Before Any Pixel

rusty_av2d computes the GDF stripe base as origin + (i_min - 1) * stride + (j_min - 1), in usize. On the first stripe of every GDF frame, valid input included, i_min - 1 or j_min - 1 steps below zero. Debug overflow checks panic. Release wraps, and the wrapped address is the one the C reference reaches with a negative offset.

av2f_still is the still-image check for that path. In release it is byte-identical to the reference, 4 of 4. The av2f container codes are ours. They are not an AOM assignment, so those files read back here. The pixels, on a release build, match the reference anyway. A debug build of the published crate panicked on the same legal frame.

rusty_av1d Assembly Omitted The ARM Header

rff-codec-avif wants the fast kernels. The published rusty_av1d 1.2.0 package can take an asm feature, and its aarch64 and ARM .S files, including refmvs and film grain, include src/arm/asm-offsets.h. The packaged crate excludes every header. The assembler stops. rusty_av1e does not include that header, so its assembly still builds.

IETF RFC 6381 is how a container names the codec it carries. AVIF names AV1. A decode that builds only on x86_64 is a decode that drops the machines people open those images on. The pure-Rust kernels were already in the crate. The feature flag was what forced the broken assembly onto ARM.

How AV2 and AVIF Decode Ships After The Fix

The 16 October change keeps the three fixes separate, because the defects were separate. Measured on Windows, debug, --locked: rff-codec-av2 unit tests 5 of 5, av2f_still 4 of 4 and byte-identical to the reference, fuzz_robustness 2 of 2 with exit code 0. The same fuzz target had been exiting 0xc0000409.

The importance of Remade with Rust is why these engines are in the tree at all. Rebuilding the foundation is the longer argument. A file that never leaves the house is the EFF's privacy point applied to a picture: AV2 and AVIF decode runs where the file already is.

remade_ffmpeg_rs AV2 Rejects An Empty Packet

send_packet now returns Error::InvalidData when the packet is empty or larger than usize::MAX / 2, before rusty_av2d is called. The check is compiled in every build, not only in debug. The new test empty_packet_is_an_error_not_an_abort sends a zero-length packet and expects that error. The decoder stays usable afterward: receive_frame returns an error instead of aborting the process.

That is the same boundary the AVIF adapter already kept for rusty_av1d. Hostile input fails closed. Why a distributed cloud needs memory-safe Rust is the reason a fuzzer has to be able to finish.

Debug AV2 Borrows The Release Wrap

The real GDF repair is add before subtract, so the index never goes through a negative usize. That repair is not in a published rusty_av2d yet. Until it is, the workspace sets overflow-checks = false for the rusty_av2d package in the dev profile only. Debug then wraps the way release already wrapped, which is the address the reference uses. Delete that profile block when the upstream crate ships the arithmetic fix. A downstream debug build that does not carry the override will panic on the first stripe again.

The picture does not change. av2f_still remains byte-identical. What changes is that a developer can run the suite without the process dying on a legal frame.

ARM Keeps AV2 and AVIF Decode On Rust Kernels

rff-codec-avif enables rusty_av1d's asm feature only when the target is x86_64. ARM uses the pure-Rust kernels until a rusty_av1d release contains asm-offsets.h. rusty_av1e keeps asm and threading on every non-wasm target, because that crate does not include the missing header. wasm32 stays on the base build, with no assembly and no thread pool.

x86_64 still gets the NASM kernels. ARM still gets a decoder. AV2 and AVIF decode is the still image beside rusty_png and rusty_jpeg, the moving picture beside rusty_h264, and the media floor under Starfire and Comet. The mesh those streams join is the Disco Party.

FAQ

Short answers already in this article.

Why did an empty AV2 packet abort remade_ffmpeg_rs?

rusty_av2d calls abort on a failed input check when debug assertions are on. An empty packet tripped that check. catch_unwind cannot contain an abort, so the fuzz run died with Windows status 0xc0000409.

How does remade_ffmpeg_rs AV2 treat an empty packet now?

rff-codec-av2 returns InvalidData for an empty or oversized packet before rusty_av2d sees it, in every build. A new test sends zero bytes. The older random-bytes test had added one to every length, so it never did.

What is the GDF underflow in rusty_av2d 0.2.11?

The stripe base is origin plus (i_min minus 1) times stride plus (j_min minus 1), in usize. The first stripe of every GDF frame underflows. Release wraps to the reference address. Debug used to panic.

Did the AV2 and AVIF decode fix rewrite the GDF math?

The add-before-subtract fix is not published yet. This workspace turns overflow checks off for rusty_av2d in the dev profile, so debug matches the release wrap. av2f_still stayed byte-identical to the reference, 4 of 4.

Why is AVIF assembly limited to x86_64?

Published rusty_av1d 1.2.0 omits every header, and its ARM assembly includes asm-offsets.h. rff-codec-avif enables the asm feature on x86_64 only. ARM uses the pure-Rust kernels. rusty_av1e keeps assembly.