Skip to content

feat(tools): vmaf-tune — QSV adapters (h264/hevc/av1)#367

Merged
lusoris merged 2 commits intomasterfrom
feat/vmaf-tune-codec-adapter-qsv
May 5, 2026
Merged

feat(tools): vmaf-tune — QSV adapters (h264/hevc/av1)#367
lusoris merged 2 commits intomasterfrom
feat/vmaf-tune-codec-adapter-qsv

Conversation

@lusoris
Copy link
Copy Markdown
Owner

@lusoris lusoris commented May 3, 2026

Summary

  • Adds three Intel QSV codec adapters to vmaf-tuneh264_qsv, hevc_qsv, av1_qsv — backed by a shared private _qsv_common.py (preset vocabulary, ICQ global_quality window, identity preset check, range validator, FFmpeg -encoders probe).
  • 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).
  • Encode pipeline (encode.py) widening to dispatch on adapter.quality_knob is 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 pass
  • ruff check tools/vmaf-tune/ — clean
  • black --check / isort --check-only on touched files — clean
  • pre-commit hooks pass on commit (clang-format, ruff, isort, black, semgrep, secrets, conventional-commit)

Six ADR-0108 deliverables

  • (1) Research digest: docs/research/0066-vmaf-tune-qsv-adapters.md
  • (2) Decision matrix: docs/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)
  • (3) AGENTS.md invariant note: tools/vmaf-tune/AGENTS.md — pinned the registry-widening, the _qsv_common.py shared-module exception, and the encode-pipeline gap
  • (4) Reproducer / smoke-test command: pytest tools/vmaf-tune/tests/
  • (5) CHANGELOG fragment: lusoris-fork unreleased section
  • (6) Rebase note: docs/rebase-notes.md (zero upstream interaction; tools/vmaf-tune/ is fork-introduced under ADR-0237)

Project rule checklist

  • CLAUDE §12 r10 — user-discoverable surface ships docs (docs/usage/vmaf-tune.md Hardware encoders section)
  • CLAUDE §12 r12 — touched files lint-clean (no NOLINTs)
  • CLAUDE §12 r13 — state.md update — N/A (this PR opens neither a bug nor closes one)
  • CLAUDE §12 r14 — ffmpeg-patches/ update — N/A (no libvmaf C-API surface touched)

🤖 Generated with Claude Code

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>
@lusoris lusoris marked this pull request as ready for review May 5, 2026 09:29
Copilot AI review requested due to automatic review settings May 5, 2026 09:29
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>
@lusoris lusoris force-pushed the feat/vmaf-tune-codec-adapter-qsv branch from 36e433d to e430781 Compare May 5, 2026 09:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py helpers and registers them in vmaftune.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 thread CHANGELOG.md
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 lusoris merged commit a278e71 into master May 5, 2026
54 checks passed
@lusoris lusoris deleted the feat/vmaf-tune-codec-adapter-qsv branch May 5, 2026 09:54
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants