mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-14 06:22:24 +00:00
craft-audio: Opus decoder (7/10) (#445)
* craft-audio: Opus decoder FilmCraft's `filmcraft-opus` decoder as `craft_audio::opus` behind `opus-decode`: SILK, hybrid and CELT, every frame size, PLC and FEC, multistream (`Decoder`) and single stream (`StreamDecoder`), 8-48 kHz output. - `TrackDecoder` decodes Opus; mono and stereo without an `OpusHead` (RTP, MPEG-TS) get a default one. Lost packets use Opus's own concealment. - The native read path takes Ogg Opus (pre-skip and end trimming per RFC 7845), and Opus in Matroska/WebM and MP4, where packet starts after a seek come from the packets' own lengths. The RFC 8251 conformance test runs all 36 vectors. `scripts/fetch-opus-vectors.sh` downloads them (SHA-256 checked) and the CI test job caches them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * craft-audio: review fixes, round 1 (#445) - CELT concealment keeps its pitch in its own field. It reused postfilter_period_old, which the next good frame's post-filter cross-fades from. - Matroska Opus seeks: a failed packet read no longer caches a wrong start; a one-byte packet is read as one byte. - A malformed OpusHead in Ogg is reported as malformed instead of falling back. - The libopus oracle tests skip through the testkit, so CRAFT_MEDIA_REQUIRE_ORACLES fails them. - Decoder::reset documents that it re-arms pre-skip trimming. - fetch-opus-vectors.sh retries its size probe. - CI: the vectors are fetched after ffmpeg is installed, and apt's timeout runs as root so a stalled apt-get is killed and frees the dpkg lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * craft-audio: review fixes, round 2 (#445) - CELT: the noise-based concealment sets skip_plc, as libopus does, so pitch-based concealment waits for two good frames in a row instead of extending history that holds noise. - SILK: decode_only_middle is per call, as in libopus. A lost or mono frame no longer reuses the mid-only flag from an earlier frame. - A damaged Opus packet is concealed at its own length (from its TOC and framing) rather than the previous packet's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
This commit is contained in:
34 files changed
+7863
-83
No files matched your search
+23
-10
@@ -3,9 +3,9 @@ name: Shared audio
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths: ["crates/audio/**", "crates/media/**", "crates/media-testkit/**", "Cargo.toml", "Cargo.lock", ".github/workflows/audio.yml"]
|
||||
paths: ["crates/audio/**", "crates/media/**", "crates/media-testkit/**", "scripts/fetch-opus-vectors.sh", "Cargo.toml", "Cargo.lock", ".github/workflows/audio.yml"]
|
||||
pull_request:
|
||||
paths: ["crates/audio/**", "crates/media/**", "crates/media-testkit/**", "Cargo.toml", "Cargo.lock", ".github/workflows/audio.yml"]
|
||||
paths: ["crates/audio/**", "crates/media/**", "crates/media-testkit/**", "scripts/fetch-opus-vectors.sh", "Cargo.toml", "Cargo.lock", ".github/workflows/audio.yml"]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
# Each feature on its own, so code that needs another feature fails here.
|
||||
- name: Clippy, each feature alone
|
||||
run: |
|
||||
for f in "" decode decode-native symphonia encode lossless-encode pcm-encode flac-encode peaks aac-decode aac-encode "aac-encode,rayon" serde; do
|
||||
for f in "" decode decode-native symphonia encode lossless-encode pcm-encode flac-encode peaks aac-decode aac-encode "aac-encode,rayon" opus-decode serde; do
|
||||
echo "::group::features: ${f:-none}"
|
||||
cargo clippy -p craft-audio --all-targets --locked --no-default-features ${f:+--features "$f"} -- -D warnings
|
||||
echo "::endgroup::"
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
- run: cargo test -p craft-audio --no-default-features --features decode-native --locked
|
||||
test:
|
||||
timeout-minutes: 20
|
||||
name: Audio tests with ffmpeg oracles
|
||||
name: Audio tests with ffmpeg oracles and the Opus conformance vectors
|
||||
# Pinned for the ffmpeg its apt ships (8.0), so the files the oracle tests write do not change
|
||||
# with the runner image.
|
||||
runs-on: ubuntu-26.04
|
||||
@@ -105,23 +105,36 @@ jobs:
|
||||
with:
|
||||
key: craft-audio-test
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Build tests while installing ffmpeg
|
||||
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: ${{ runner.temp }}/media-fixtures/opus/vectors
|
||||
# The archive's SHA-256 (scripts/fetch-opus-vectors.sh checks it).
|
||||
key: opus-testvectors-rfc8251-6b26a22f
|
||||
- name: Build tests while installing ffmpeg and fetching the Opus vectors
|
||||
run: |
|
||||
# The man-db index rebuild after dpkg is slow on hosted runners.
|
||||
sudo rm -f /var/lib/man-db/auto-update
|
||||
# A mirror can stall for most of the job's time limit, and the next try usually gets a good one.
|
||||
install_ffmpeg() {
|
||||
for attempt in 1 2 3; do
|
||||
timeout -k 10 180 sudo sh -c 'apt-get update -qq && apt-get install -y -qq --no-install-recommends ffmpeg' && return 0
|
||||
# timeout runs as root, so a stalled apt-get is killed too and frees the dpkg lock.
|
||||
sudo timeout -k 10 180 sh -c 'apt-get update -qq && apt-get install -y -qq --no-install-recommends ffmpeg' && return 0
|
||||
echo "apt: attempt $attempt failed with exit code $?"
|
||||
timeout -k 10 60 sudo dpkg --configure -a || true
|
||||
sudo timeout -k 10 60 dpkg --configure -a || true
|
||||
done
|
||||
return 1
|
||||
}
|
||||
install_ffmpeg > "$RUNNER_TEMP/apt.log" 2>&1 &
|
||||
apt=$!
|
||||
# The vectors are fetched after ffmpeg, so the two downloads do not slow each other.
|
||||
{
|
||||
install_ffmpeg > "$RUNNER_TEMP/apt.log" 2>&1 || exit 1
|
||||
scripts/fetch-opus-vectors.sh "$RUNNER_TEMP/media-fixtures/opus/vectors" > "$RUNNER_TEMP/vectors.log" 2>&1 || exit 2
|
||||
} &
|
||||
fetch=$!
|
||||
cargo test -p craft-audio --all-features --locked --no-run
|
||||
wait "$apt" || { cat "$RUNNER_TEMP/apt.log"; exit 1; }
|
||||
wait "$fetch" || case $? in
|
||||
1) cat "$RUNNER_TEMP/apt.log"; exit 1 ;;
|
||||
*) cat "$RUNNER_TEMP/vectors.log"; exit 1 ;;
|
||||
esac
|
||||
ffmpeg -hide_banner -version | sed -n 1p
|
||||
- run: cargo test -p craft-audio --all-features --locked
|
||||
env:
|
||||
|
||||
Reference in new issue
Block a user