feat(tools): vmaf-tune — QSV adapters (h264/hevc/av1)#367
Merged
Conversation
14 tasks
lusoris
pushed a commit
that referenced
this pull request
May 3, 2026
…s 17 adapters) Refactors `tools/vmaf-tune/src/vmaftune/encode.py` away from the Phase A hard-coded `libx264` `-c:v / -preset / -crf` argv. `run_encode` now looks up the codec adapter via `codec_adapters.get_adapter(req.encoder)` and asks it for the FFmpeg argv slice via `adapter.ffmpeg_codec_args(preset, quality)` plus an optional `adapter.extra_params()`. Adapters that don't yet expose `ffmpeg_codec_args` fall back silently to the legacy x264-CRF shape so partial in-flight adapter PRs stay drivable end-to-end. `parse_versions(stderr, encoder=...)` selects a per-codec version probe (libx264, libx265, libsvtav1, libvpx-vp9, libaom-av1, libvvenc, NVENC, QSV, AMF, VideoToolbox); unknown encoders return "unknown" rather than raising. The `EncodeRequest.crf` field is preserved unchanged for the SCHEMA_VERSION=1 row contract; a `quality` property mirrors it for adapter-side codec-agnostic vocabulary. Existing 13-test x264 suite still green; new 19-test multi-codec suite covers 9 representative codec shapes plus the unknown-codec / missing-method fallback paths. Unblocks 17 in-flight codec adapter PRs (#360 libaom, #362 libx265, #364 NVENC, #366 AMF, #367 QSV, #368 libvvenc, #370 libsvtav1, #373 VideoToolbox, plus follow-on waves) which can now drive end-to-end encodes without copying or mutating the harness. Ships ADR-0294 + research digest 0054, vmaf-tune.md "Codec adapter contract" section, rebase-notes #228 invariant, CHANGELOG entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds three Intel QSV codec adapters under tools/vmaf-tune/src/vmaftune/codec_adapters/ — h264_qsv, hevc_qsv, av1_qsv — backed by a shared private _qsv_common.py that pins the QSV preset vocabulary (veryslow…veryfast, x264-style names verbatim), the ICQ global_quality window (1..51), the preset identity check, the range validator, and an `ffmpeg -encoders` probe that fails fast when libmfx / VPL is not compiled in. Registry widens from libx264-only to four codecs; the search loop continues to route through the registry without branching on codec identity (per ADR-0237 contract). Hardware availability matrix documented in docs/usage/vmaf-tune.md: H.264 / HEVC on Intel iGPU 7th-gen+ (Kaby Lake or newer) or Arc / Battlemage; AV1 on 12th-gen+ iGPU only or Arc / Battlemage. Encode pipeline (encode.py) is still x264-CRF-tied — widening it to dispatch on adapter.quality_knob is a separate follow-up PR. The QSV adapter classes validate (preset, global_quality) correctly but the harness will not yet drive a QSV encode end-to-end until that lands. Sibling NVENC + AMF adapter PRs run in parallel; ADR-0281 documents the _<family>_common.py pattern they should follow. Six ADR-0108 deliverables shipped: 1. Research digest: docs/research/0054-vmaf-tune-qsv-adapters.md 2. Decision matrix: ADR-0281 §Alternatives considered 3. AGENTS.md invariant note: tools/vmaf-tune/AGENTS.md 4. Reproducer: `pytest tools/vmaf-tune/tests/` 5. CHANGELOG entry: lusoris-fork unreleased section 6. rebase-notes entry: docs/rebase-notes.md (no upstream impact) 50/50 tests pass (`pytest tools/vmaf-tune/tests/`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36e433d to
e430781
Compare
There was a problem hiding this comment.
Pull request overview
Adds Intel QSV codec-adapter scaffolding to tools/vmaf-tune so the codec registry can describe h264_qsv, hevc_qsv, and av1_qsv alongside libx264. This fits the Phase A vmaf-tune architecture by extending the adapter/registry layer and its docs/tests, while deferring the actual encode-pipeline wiring to a follow-up PR.
Changes:
- Adds three QSV adapter classes plus shared
_qsv_common.pyhelpers and registers them invmaftune.codec_adapters. - Expands tests to cover QSV adapter validation, registry lookups, and FFmpeg encoder probing.
- Adds ADR/research/user docs/rebase-note/changelog updates describing the new adapter family and its deferred runtime wiring.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
tools/vmaf-tune/tests/test_corpus.py |
Updates corpus smoke coverage for the widened codec registry. |
tools/vmaf-tune/tests/test_codec_adapter_qsv.py |
Adds focused unit tests for QSV adapters and probe helpers. |
tools/vmaf-tune/src/vmaftune/codec_adapters/hevc_qsv.py |
Adds HEVC QSV adapter dataclass. |
tools/vmaf-tune/src/vmaftune/codec_adapters/h264_qsv.py |
Adds H.264 QSV adapter dataclass. |
tools/vmaf-tune/src/vmaftune/codec_adapters/av1_qsv.py |
Adds AV1 QSV adapter dataclass. |
tools/vmaf-tune/src/vmaftune/codec_adapters/_qsv_common.py |
Adds shared QSV preset/range/probe helpers. |
tools/vmaf-tune/src/vmaftune/codec_adapters/__init__.py |
Registers/export QSV adapters in the codec registry. |
tools/vmaf-tune/AGENTS.md |
Documents repo-local invariants for QSV adapters and deferred encode wiring. |
docs/usage/vmaf-tune.md |
Documents QSV hardware encoders in user-facing usage docs. |
docs/research/0054-vmaf-tune-qsv-adapters.md |
Adds research digest for the QSV adapter design. |
docs/rebase-notes.md |
Records fork-local rebase notes for this addition. |
docs/adr/README.md |
Adds ADR index entry for ADR-0281. |
docs/adr/0281-vmaf-tune-qsv-adapters.md |
Adds the QSV adapter ADR. |
CHANGELOG.md |
Adds unreleased changelog entry for QSV adapters. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+226
to
+244
| - **`vmaf-tune` Intel QSV codec adapters — `h264_qsv`, `hevc_qsv`, | ||
| `av1_qsv` (ADR-0281).** Three thin frozen-dataclass adapters under | ||
| [`tools/vmaf-tune/src/vmaftune/codec_adapters/`](tools/vmaf-tune/src/vmaftune/codec_adapters/), | ||
| backed by a shared private `_qsv_common.py` that pins the QSV | ||
| preset vocabulary (`veryslow…veryfast`, x264-style names verbatim), | ||
| the ICQ `global_quality` window (`1..51`), the preset identity | ||
| check, the range validator, and an `ffmpeg -encoders` probe that | ||
| fails fast when libmfx / VPL is not compiled in. Registry widened | ||
| from libx264-only to four codecs; the search loop continues to | ||
| route through the registry without branching on codec identity. | ||
| Hardware availability matrix documented in | ||
| [`docs/usage/vmaf-tune.md`](docs/usage/vmaf-tune.md): H.264 / HEVC | ||
| on Intel iGPU 7th-gen+ (Kaby Lake or newer) or Arc / Battlemage; | ||
| AV1 on 12th-gen+ iGPU only or Arc / Battlemage. Encode pipeline | ||
| (`encode.py`) widening to dispatch on `adapter.quality_knob` | ||
| deferred to a follow-up PR — adapter classes are valid but inert | ||
| until that lands. Sibling NVENC + AMF adapter PRs run in parallel. | ||
| Companion research digest: | ||
| [`docs/research/0054-vmaf-tune-qsv-adapters.md`](docs/research/0054-vmaf-tune-qsv-adapters.md). |
| - Companion: [ADR-0235](0235-codec-collision-bucket.md) (codec | ||
| one-hot consumes the QSV bucket). | ||
| - Sibling PRs (parallel work): NVENC adapter ADR (forthcoming), | ||
| AMF adapter ADR (forthcoming). |
lusoris
pushed a commit
that referenced
this pull request
May 5, 2026
…s 17 adapters) Refactors `tools/vmaf-tune/src/vmaftune/encode.py` away from the Phase A hard-coded `libx264` `-c:v / -preset / -crf` argv. `run_encode` now looks up the codec adapter via `codec_adapters.get_adapter(req.encoder)` and asks it for the FFmpeg argv slice via `adapter.ffmpeg_codec_args(preset, quality)` plus an optional `adapter.extra_params()`. Adapters that don't yet expose `ffmpeg_codec_args` fall back silently to the legacy x264-CRF shape so partial in-flight adapter PRs stay drivable end-to-end. `parse_versions(stderr, encoder=...)` selects a per-codec version probe (libx264, libx265, libsvtav1, libvpx-vp9, libaom-av1, libvvenc, NVENC, QSV, AMF, VideoToolbox); unknown encoders return "unknown" rather than raising. The `EncodeRequest.crf` field is preserved unchanged for the SCHEMA_VERSION=1 row contract; a `quality` property mirrors it for adapter-side codec-agnostic vocabulary. Existing 13-test x264 suite still green; new 19-test multi-codec suite covers 9 representative codec shapes plus the unknown-codec / missing-method fallback paths. Unblocks 17 in-flight codec adapter PRs (#360 libaom, #362 libx265, #364 NVENC, #366 AMF, #367 QSV, #368 libvvenc, #370 libsvtav1, #373 VideoToolbox, plus follow-on waves) which can now drive end-to-end encodes without copying or mutating the harness. Ships ADR-0294 + research digest 0054, vmaf-tune.md "Codec adapter contract" section, rebase-notes #228 invariant, CHANGELOG entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lusoris
added a commit
that referenced
this pull request
May 5, 2026
…s 17 adapters) (#376) * feat(tools): vmaf-tune encode.py — codec-agnostic dispatcher (unblocks 17 adapters) Refactors `tools/vmaf-tune/src/vmaftune/encode.py` away from the Phase A hard-coded `libx264` `-c:v / -preset / -crf` argv. `run_encode` now looks up the codec adapter via `codec_adapters.get_adapter(req.encoder)` and asks it for the FFmpeg argv slice via `adapter.ffmpeg_codec_args(preset, quality)` plus an optional `adapter.extra_params()`. Adapters that don't yet expose `ffmpeg_codec_args` fall back silently to the legacy x264-CRF shape so partial in-flight adapter PRs stay drivable end-to-end. `parse_versions(stderr, encoder=...)` selects a per-codec version probe (libx264, libx265, libsvtav1, libvpx-vp9, libaom-av1, libvvenc, NVENC, QSV, AMF, VideoToolbox); unknown encoders return "unknown" rather than raising. The `EncodeRequest.crf` field is preserved unchanged for the SCHEMA_VERSION=1 row contract; a `quality` property mirrors it for adapter-side codec-agnostic vocabulary. Existing 13-test x264 suite still green; new 19-test multi-codec suite covers 9 representative codec shapes plus the unknown-codec / missing-method fallback paths. Unblocks 17 in-flight codec adapter PRs (#360 libaom, #362 libx265, #364 NVENC, #366 AMF, #367 QSV, #368 libvvenc, #370 libsvtav1, #373 VideoToolbox, plus follow-on waves) which can now drive end-to-end encodes without copying or mutating the harness. Ships ADR-0294 + research digest 0054, vmaf-tune.md "Codec adapter contract" section, rebase-notes #228 invariant, CHANGELOG entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(docs): renumber encode-multi-codec ADR 0294→0297 + research 0069→0070 --------- Co-authored-by: Lusoris <lusoris@pm.me> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
vmaf-tune—h264_qsv,hevc_qsv,av1_qsv— backed by a shared private_qsv_common.py(preset vocabulary, ICQglobal_qualitywindow, identity preset check, range validator, FFmpeg-encodersprobe).encode.py) widening to dispatch onadapter.quality_knobis deferred to a follow-up PR — adapter classes validate(preset, global_quality)correctly but the harness will not yet drive a QSV encode end-to-end until that lands. Sibling NVENC + AMF adapter PRs run in parallel.Test plan
pytest tools/vmaf-tune/tests/— 50/50 passruff check tools/vmaf-tune/— cleanblack --check/isort --check-onlyon touched files — cleanpre-commithooks pass on commit (clang-format, ruff, isort, black, semgrep, secrets, conventional-commit)Six ADR-0108 deliverables
docs/research/0066-vmaf-tune-qsv-adapters.mddocs/adr/0281-vmaf-tune-qsv-adapters.md§Alternatives considered (4 options weighed: 3-independent-files vs shared module vs unified parametric adapter; ICQ vs CQP vs VBR rate control)tools/vmaf-tune/AGENTS.md— pinned the registry-widening, the_qsv_common.pyshared-module exception, and the encode-pipeline gappytest tools/vmaf-tune/tests/docs/rebase-notes.md(zero upstream interaction;tools/vmaf-tune/is fork-introduced under ADR-0237)Project rule checklist
docs/usage/vmaf-tune.mdHardware encoders section)state.mdupdate — N/A (this PR opens neither a bug nor closes one)ffmpeg-patches/update — N/A (no libvmaf C-API surface touched)🤖 Generated with Claude Code