Commit Graph
26 Commits
Author SHA1 Message Date
aiongg fb8a8653c0 Integration: #3280 drop throwaway bench_dec.rs example 2026-10-31 02:10:10 +00:00
aiongg 079dcdf767 Merge PR #3280: Opus decoder: cap concealment and FEC length at 120 ms 2026-10-31 02:10:05 +00:00
aiongg 6edc81b603 Merge PR #3277: Opus decoder: faster SILK output resampler 2026-10-31 02:10:04 +00:00
aiongg 753524efec Merge PR #3275: Opus decoder: de-emphasis for both channels in one loop 2026-10-31 02:10:03 +00:00
aiongg 3653874359 Merge PR #3273: Opus decoder: build the PVQ V(n,k) table once 2026-10-31 02:10:02 +00:00
aiongg 38f379e92f Merge PR #3272: Opus decoder: radix-2/3/4 FFT kernels in the CELT IMDCT 2026-10-31 02:10:01 +00:00
Dylan M. Taylor 78d77b72d3 Refactor opus for strict Clippy checks 2026-10-28 04:36:48 +00:00
vangel76 e85bb00330 Merge remote-tracking branch 'upstream/main' into s1/opus-deemph 2026-10-27 19:46:21 +01:00
aiongg 8fd1124075 refactor(opus): convert mod.rs files to <module>.rs 2026-10-26 18:15:16 +00:00
vangel76andClaude Sonnet 5.5 014b5e5659 Opus decoder: cap concealment and FEC length at 120 ms
StreamDecoder::conceal(n) and decode_fec(.., n, ..) resized the output
by n * channels for any caller-supplied n that was a multiple of 2.5 ms,
so a huge n (for example from a corrupt container timestamp) allocated
without limit. Both now reject n above 120 ms, the longest Opus packet,
with InvalidArgument before any output is reserved. Internal callers
(packet-loss concealment of the last packet's duration, multistream) never
exceed that. A test covers the boundary and oversized values.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:00:23 +01:00
vangel76andClaude Sonnet 5.5 87b8e22dca Opus decoder: eight partial sums in the SILK resampler dot product
The ~35-tap dot product accumulated strictly sequentially, one 4-cycle
float add after another. It now uses eight independent partial sums over
8-wide chunks, which the compiler vectorises. The resampler filter is
non-normative, so the output moves only at f32 rounding level: max abs
diff 1.5e-7 (about 141 dB SNR) against the previous code, and the SNR
against libopus is unchanged to 0.1 dB (50.3 / 51.5 / 51.7 dB on voip
speech streams).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:57:34 +01:00
vangel76andClaude Sonnet 5.5 eb352ec8ff Opus decoder: SILK resampler without per-sample divisions
The SILK output resampler computed j / period, j % period and a 64-bit
cycle*fin*period/fout division for every output sample, and bounds-checked
every tap. The phase and cycle are now tracked incrementally (the cycle
step fin*period/fout is exact), and when the tap window lies inside the
history, which is always the case after the first call, the dot product
runs over one contiguous slice. The accumulation order is unchanged, so
the output is byte-identical.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:56:41 +01:00
vangel76andClaude Sonnet 5.5 08f1a87207 Opus decoder: use as_chunks_mut in stereo de-emphasis (clippy)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:55:48 +01:00
vangel76andClaude Sonnet 5.5 c4dc64d1a8 Opus decoder: de-emphasis for both channels in one loop
At 48 kHz output the CELT de-emphasis filter ran one channel at a time
through a scratch Vec and then copied into the interleaved output. Stereo
now runs both IIR chains in one loop and writes straight into the output,
so the two independent dependency chains hide each other's add/multiply
latency; mono at 48 kHz writes directly too. The arithmetic and its order
are unchanged, the output is byte-identical.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:55:11 +01:00
vangel76andClaude Sonnet 5.5 12e3202620 Opus decoder: build the PVQ V(n,k) table once
decode_pulses rebuilt an O(n*k) table of saturating u64 adds for every
coded band partition, about a quarter of CELT decode time. The table is
now built once per process (n <= 176, k <= 128, u32 saturated, 91 KB) and
decoding reads only the O(n+k) entries it needs. Every coded (n, k) has
V(n, k) < 2^32 and only entries <= V(n, k) are read, so the integer
arithmetic is unchanged. The unused pvq_v scratch Vec in BandCtx is gone.

Output is byte-identical on all test inputs; a test checks the table
against rate::pvq_v.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:54:08 +01:00
vangel76andClaude Sonnet 5.5 bf7ac4200c Opus decoder: radix-2/3/4 FFT kernels in the CELT IMDCT
The mixed-radix FFT multiplied every butterfly input by every DFT root
(16 complex multiplies for radix 4) and took a modulo per twiddle index.
Radix 2, 3 and 4 now use dedicated butterflies (radix 4 with the +-j
rotations as swaps, radix 3 with one real constant); radix 5, which
occurs at most once per transform, keeps the generic form with its roots
looked up once. The modulo is dropped, the index never reaches n.

The output moves at f32 rounding level (max abs diff 2.7e-7 against the
previous code on 90 s of music and speech). The previous implementation
is kept under cfg(test) and a test compares it with the new one for all
CELT FFT sizes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:52:20 +01:00
aiongg 0a881266c8 CI: xtask ci in the dev profile, one test binary per crate, nextest (#2860)
* Tests: one integration-test binary per crate

Each crate with several tests/*.rs files keeps them as modules of tests/it/,
so cargo links one test executable per crate instead of one per file. Files
that change process-wide state or time a workload stay binaries of their own.

* Profiles: line tables for workspace crates, no debug info for dependencies

* Windows ARM64: nightly and on release pushes instead of every push to main

* xtask ci: clippy and tests in the dev profile

The release profile's thin LTO and single codegen unit made linking the test
binaries take most of the gate. The codec and audio crates stay at opt-level 3
in the dev profile, so their tests run at release speed.

* xtask ci: nextest, doctests, no examples, one wasm check

Tests run with cargo nextest when it is installed (cargo test otherwise) and
build with --lib --bins --tests, so examples aren't linked; doctests run
separately. The wasm check keeps going past the first failing crate. VP8
fixture generation locks across processes, since nextest runs each test in
its own.

* VP9 synthetic fixtures: write aside and rename

A test in another process could read a fixture ffmpeg was still writing.

* Fuzz tests: a third of each sweep by default, all of it with FILMCRAFT_FUZZ_ITERS

Every seed, mutation kind and thread count still runs. Header bytes each get
one overwrite value and two bit flips in rotation, so every value and bit
index still occurs across the region. FILMCRAFT_FUZZ_ITERS=N runs the whole
sweep plus N random rounds per seed, as before.

* Platform fallback tests: one failure point per hybrid path

The failure-anywhere test injected a failure at four points around every
restart point; the hybrid's paths differ only in the first GOP, around the
second and last restart points, at the end and never. The replay test needs
the first two GOPs.

* Export tests: shorter ranges with the same checks

The bitrate test measures 0.5–1.5 s, where each preset reaches its own
target (on 0–3 s the simple demo left two presets at the same rate). The
every-preset test exports three frames per preset.

* Audio tests: effects in parallel, a table-driven FFT for the Opus quality metric

The extreme-settings test keeps both settings and the 40 s tail for every
effect, one thread each. The Opus quality metric's FFT builds its twiddles
once and allocates nothing per transform (same algorithm and summation order).

* CI: dev-profile gate with nextest

xtask ci no longer builds with --release, so the release-profile overrides
go; nextest is installed for the test step.

* CI: apt packages through the cached install-apt-packages action

* Review fixes: fuzz tests with a panic hook in their own binaries, loud fixture lock

The fuzz tests of av1, h264, hevc, mpeg2v, vp8 and vp9 count panics through
a process-wide hook, so a panic in another test of the same process would
fail them; they are binaries of their own again. The VP8 fixture lock fails
the test instead of skipping it silently, and the full-sweep doc comments say
how many truncation points the full run samples.

* Fuzz tests: rotate the default subset per run (FILMCRAFT_FUZZ_SEED replays one)

* platform tests: decode-switch tests in their own binaries, one NVENC lock
2026-10-23 13:34:16 -04:00
Earl Co 71d5f52b4d security(opus): validate direct multistream headers (#2905) 2026-10-23 10:53:00 -04:00
Brandon Thomas 28563e8030 Merge pull request #16 from storytold/pr/never-crash-codecs-small
Codecs: never crash (ac3, audio-dsp, opus, mpeg2v, prores, dnx)
2026-10-04 16:16:55 -04:00
Brandon ThomasandClaude Opus 5.5 3a392ae8da Clippy 1.99: fix new lints so cargo xtask ci is green again
Rust/clippy 1.99 added `chunks_exact_to_as_chunks` and tightened
`needless_late_init` and `drain_collect`, failing `clippy -D warnings`
on main.

- `chunks_exact(N)` / `chunks_exact_mut(N)` with a constant N become
  `as_chunks::<N>()` / `as_chunks_mut::<N>()` (fixed-size arrays, so
  several byte reads drop their per-element indexing). relink's
  fingerprint uses the `(chunks, remainder)` split; its hash output is
  unchanged.
- Late-initialised `let`s in ac3 bit allocation and opus CELT
  bands/rate become `let x = if/match …`.
- `dpb.drain(..).collect()` becomes `std::mem::take(&mut dpb)`.

No behaviour change; `cargo xtask ci` passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 15:55:23 -04:00
Brandon ThomasandClaude Opus 5.5 46b286edaf Codecs: never crash — ac3, audio-dsp, opus, mpeg2v, prores, dnx
- ac3: LFE channel taken without `expect`.
- audio-dsp: the channel matrix match is exhaustive (no `unreachable!`); an unknown internal
  parameter reads as 0 (debug-asserted) instead of `panic!`.
- opus: dual-stereo bands and SILK frames take the optional buffer / range decoder with `if let`.
- mpeg2v: 64-bit peek through `get()` + `first_chunk`; the literal VLC table parser no longer
  panics (debug-asserted).
- prores, dnx: IDCT rows through `as_chunks`; ProRes block store and alpha slices without
  unwrap/expect; DNx header timecode through `get()`.
- dnx: `Encoder::new` returns `Result` instead of panicking on a raster the profile can't code
  (e.g. 0x0), with a regression test; missing CID table is an error.
- Each crate denies unwrap/expect/panic/unimplemented/todo/unreachable outside tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:43:19 -04:00
Brandon ThomasandClaude Opus 5.5 8780d5ffa2 T1: shared ffmpeg/ffprobe discovery in filmcraft-testkit
New dev-dependency-only crate crates/testkit (L0, no FilmCraft deps):
FILMCRAFT_FFMPEG/FILMCRAFT_FFPROBE, then PATH (incl. .exe), then known
dirs; SKIPPED lines and FILMCRAFT_REQUIRE_ORACLES=1 to make skips fail;
require_ffmpeg!/require_ffprobe!/require_oracles!; fixtures_dir() under
<workspace>/target/fixtures with per-thread temp names and atomic
generation. Oracle helpers in aac, opus, h264, hevc, h264enc, isobmff,
matroska, prores and export migrated (codecs left on its local lookup).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:10:59 -04:00
Brandon ThomasandClaude Opus 5.5 20f29623b5 M9.13: Opus robustness + output-rate oracle tests
Multistream packet-loss concealment conceals the last packet duration on
every stream (conceal(dur)) so all streams stay in step. New robustness
tests: random garbage over every TOC config at all output rates, multistream
garbage, truncated/bit-flipped conformance packets interleaved with losses;
none panic and all output is finite. New oracle test decodes at 8/12/16/24 kHz
against libopus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:27:10 -04:00
Brandon ThomasandClaude Opus 5.5 c03de12b31 M9.13: Opus decoder — LS fractional-delay SILK resampler, ffmpeg/libopus oracle tests, vector diagnostics
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 22:57:09 -04:00
Brandon ThomasandClaude Opus 5.5 a2fa4c0a69 M9.13: Opus decoder — SILK, hybrid, redundancy/transitions, OpusHead, multistream; all RFC 8251 vectors range-exact
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 22:50:02 -04:00
Brandon ThomasandClaude Opus 5.5 ed47db6861 M9.13: Opus decoder (WIP: range decoder, packet parsing, CELT core, SILK tables)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 22:21:51 -04:00