Commit Graph
11 Commits
Author SHA1 Message Date
vangel76andClaude Opus 5.5 1e6f42eda2 #847: AV1 decode runs deblocking, CDEF and loop restoration in parallel row bands
Problem: the AV1 in-loop filters ran on one thread per frame (postfilter::apply
had an unused pool). On a single-tile stream they are a quarter to a third of a
frame, and since references are waited for as whole frames, that serial tail
sat on the critical path of every frame that references it.

Fix: the three filters run in bands of 64 luma rows on the decoder's existing
rayon pool, one join per filter per frame. CDEF and loop restoration write only
their own rows of a separate output. The loop filter's edges never touch the
same sample, and only a band's top horizontal edges reach into the band above:
each band refilters the vertical edges of a copy of the 8 rows above it, runs
those edges against the copy, and the samples they changed are written back.
With one thread the code path is the old one. Output stays bit-exact (1 vs 16
threads vs libdav1d; new 4:2:2 / 4:4:4 libaom fixtures). perf.rs gains a
low-delay 1080p and a single-tile 2160p fixture and the all-core stage
breakdown. 16 threads: 1080p GOP 1.16-1.30x, low delay 1.28x, 2160p 1.14x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 03:11:27 +02:00
Brandon ThomasandClaude Opus 5.5 7190fb9009 av1: never crash — no expect in the decoder, deny the panicking lints
- CDEF and inter-prediction filter rows: fixed-size views through `get()` + `first_chunk(_mut)`
  instead of slice + `try_into().expect()`.
- A missing reference frame predicts from the current frame instead of `expect`.
- Frame slots, output and in-flight queues, scalable-layer selection: no `expect`.
- `#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented,
  clippy::todo, clippy::unreachable)]` outside tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:35:48 -04:00
Brandon ThomasandClaude Opus 5.5 7ce0766744 M4.10: AV1 fixed-width MC passes, recycled planes, lean mode info, draft mode; media-stack draft test
Sub-pixel filter passes run over fixed block widths; frame / region planes are recycled
through a bounded pool (zeroed on reuse) instead of fresh calloc / munmap per frame; the
palette mode-info arrays (40 bytes per 4x4) exist only when screen content tools are allowed;
CDF adaptation is branch-free. Draft mode skips deblocking, CDEF and loop restoration of shown
frames that refresh no reference slot. Media-stack test: VP9 / HEVC / AV1 draft playback only
reaches draft requests, and an export afterwards is bit-exact with ffmpeg.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 08:02:43 -04:00
Brandon ThomasandClaude Opus 5.5 0e35e82e47 M9.7: AV1 tile, frame and post-filter threading
Tiles decode in parallel into private region buffers (Plane / MiInfo with a
frame-coordinate origin) that are merged afterwards; intra block copy frames
keep whole-frame buffers. Post-filter row bands run on a rayon pool (par.rs,
behind the `threads` feature, sequential on wasm32). Frames become jobs that
wait on the reference slots they read and run on frame worker threads, so
independent GOP layers decode concurrently; output stays in order and each
Picture carries the pts of its temporal unit (Decoder::decode_pts, flush,
flush_result). codecs::Av1Decoder passes pts through and drains on flush.

Oracle tests now compare 1 thread, many threads and libdav1d (bit-exact),
with new multi-tile fixtures and an ignored 1080p set. README records fps
before/after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 22:45:40 -04:00
Brandon ThomasandClaude Opus 5.5 31f8b3dadf M9.7: AV1 hot loops: vectorisable MC, CDEF, transforms; faster deblocking and entropy decoding
Bit-exact restructuring of the per-sample spec processes (all oracle and conformance
vectors still match libdav1d):
- Inter prediction: unscaled references use one filter phase per block, so the 8-tap
  filters run tap-outer over whole rows (no per-tap clamps inside the frame, identity
  phases copy, zero-tap rows skipped); scratch buffers are reused, not allocated.
- CDEF: padded 12x12 block with availability; blocks whose taps are all available run
  branch-free in i16 lanes; zero-strength blocks are skipped.
- Inverse transforms: generic over lanes, 4 or 8 rows/columns at a time in 32-bit
  arithmetic (exact up to 10-bit per the spec's intermediate range); all-zero rows skipped;
  only the used dequant area is cleared.
- Deblocking: early exits before strength lookup; per-length sample filters; the wide
  filters as sliding-window sums.
- Symbol decoder: a 64-bit window of inverted bits instead of bit-at-a-time refills.
- Coefficient contexts from a zero-padded level buffer (no bounds checks); mode info
  stored with row fills; reconstruction on row slices.

Single-threaded 1080p (thread CPU): GOP 20.7 -> ~52 fps, high-quality GOP 9.6 -> ~20 fps,
4x2-tile GOP 22 -> ~48 fps, 10-bit GOP 17 -> ~44 fps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:48:22 -04:00
Brandon ThomasandClaude Opus 5.5 fef248a527 M9.7: AV1 decode statistics (per-stage busy time) and perf test with stage breakdown
Decoder::stats() reports frames, tiles and the busy time of setup, tile decoding,
deblocking, CDEF, superres, loop restoration and output. The ignored perf test
measures single-threaded throughput with the thread CPU clock (robust to machine
load), prints ms/frame per stage, and the all-cores wall-clock rate next to the
load average. Adds high-quality and 4x2-tile 1080p fixtures. Decoder::with_threads
and flush() are added as the API the threaded decoder will use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:07:55 -04:00
Brandon ThomasandClaude Opus 5.5 05e6976854 M9.7: AV1 film grain synthesis; superres and film-grain oracle fixtures
Film grain (7.18.3) on output pictures, bit-exact against libdav1d on the libaom
23-film_grain-50 vectors (8/10-bit) and an SVT film-grain stream; super-resolution now
oracle-tested (SVT superres denominator 12) and bit-exact.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:52:26 -04:00
Brandon ThomasandClaude Opus 5.5 753b673e6a M9.7: AV1 inter prediction, MV prediction, motion field, intra block copy, scalable output
Inter mode info syntax, spatial/temporal MV candidate stacks, motion field estimation and MV
storage, scaled references, sub-pixel filters, global/local warp, OBMC, wedge/diffwtd/inter-intra
masks, distance weights; intra block copy; one output frame per temporal unit with spatial
layers. Bit-exact against libdav1d on SVT-AV1 GOPs and the libaom size/quantizer/cdfupdate/mv/
mfmv/svc/monochrome/intrabc vectors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:47:36 -04:00
Brandon ThomasandClaude Opus 5.5 35a2d2a861 M9.7: AV1 import from MP4 (av01/av1C) and Matroska/WebM (V_AV1)
Av1Decoder in filmcraft-codecs: feeds the av1C configuration OBUs before the
first sample (and after every reset), converts pictures to 8/16-bit planar
YUV with the stream's colour description, and reports random-access points
from the first frame header of each temporal unit (shown key frame) so GOP
seeking ignores bogus container sync flags. Matroska V_AV1 tracks map to an
av01 sample entry; MP4 labels show the AV1 profile.

All-intra 8-bit MP4 and 10-bit WebM files seek sample-exactly against
libdav1d. Inter frames still return "unsupported" until inter prediction
lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:18:49 -04:00
Brandon ThomasandClaude Opus 5.5 be1ce4943e M9.7: AV1 loop filter, CDEF, super-resolution upscaling, loop restoration
Loop filter (7.14: all filter sizes, deltas, segment/ref/mode adjustments),
CDEF (7.15), superres upscaling (7.16) and loop restoration (7.17: Wiener,
self-guided, switchable, stripe handling) in decode_frame_wrapup.

All-intra libsvtav1 fixtures with every in-loop filter (64/128 superblocks,
edge filter on/off, 8/10-bit) and libaom's av1-1-b8-02-allintra conformance
vector (39 frames, downloaded on first use) are bit-exact against libdav1d.
Frames coded slightly larger than the sequence maximum are accepted, like
other decoders do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:16:44 -04:00
Brandon ThomasandClaude Opus 5.5 1813bbaca2 M9.7: AV1 headers, symbol decoder, CDFs, intra decoding, transforms, intra prediction
New L0 crate filmcraft-av1 from the AV1 Bitstream & Decoding Process
Specification v1.0.0 with Errata 1 (tables extracted from the spec's Markdown
source by tools/extract_tables.py).

Stages: OBU parsing, sequence and uncompressed frame headers (all fields),
reference state (set_frame_refs, load_previous, reference update,
show_existing_frame), symbol decoder with CDF adaptation and
init/load/save/frame-end CDF handling, tiles, intra frame mode info
(partitions, segment ids, delta q/lf, CDEF index, modes, angle deltas, CfL,
palette, filter intra, tx size), coefficient decoding, dequantisation,
inverse transforms (DCT 4-64, ADST, identity, WHT), intra prediction (all
modes, edge filter/upsampling, recursive filter, CfL, palette), LR syntax.

All-intra libsvtav1 streams with in-loop filters disabled decode bit-exactly
against libdav1d (8/10-bit, 128x128..1280x720, odd sizes, presets 2-8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:00:03 -04:00