The qsv-decode-encode-split record told HDR-on-QSV users to set QsvPreferNativeDecoder OFF "to keep GPU tonemap". Measured on the Intel host, vpp_qsv=tonemap=1 is a silent no-op on pre-Gen11 graphics, so following that advice did not preserve GPU tonemapping -- it disabled tonemapping entirely and shipped untonemapped HDR. Prose correction only; the decision itself (the QsvPreferNativeDecoder toggle) is unchanged and stays active. The software-tonemap half of the bullet was always accurate and stands. Decisions-Edit: yes
4.8 KiB
key, title, status, since, supersedes, superseded-by, rule, signals, mechanics
| key | title | status | since | supersedes | superseded-by | rule | signals | mechanics |
|---|---|---|---|---|---|---|---|---|
| ffmpeg.qsv-decode-encode-split | 2026-07-20 (#498) — QSV decode is split from QSV encode via a single `QsvPreferNativeDecoder` bool | active | 2026-07-20 | none | none | QSV decode is decoupled from QSV encode via a single `FFmpegProfile.QsvPreferNativeDecoder` bool (default ON, Linux-only), so a QSV encode profile can decode with the more tolerant native VA-API decoder instead of the QSV decoder, mirroring Jellyfin's hybrid decode/encode toggle instead of a general decode-family enum. | QSV, native VA-API decode, Dolby Vision passthrough, hybrid decode/encode, HDR tonemap fallback · paths: `FFmpegProfile.QsvPreferNativeDecoder`, `QsvPipelineBuilder.SetTonemap`, `QsvPipelineBuilder` · issues: #498, #505 | `docs/superpowers/specs/2026-07-20-qsv-native-decode-design.md`; migration `HasDefaultValue(true)` on the nullable `bool?` column; `QsvPipelineBuilder` decoder-mode branch |
FFmpegProfile.HardwareAcceleration picked one pipeline builder for both decode and encode, so an
Intel QSV profile decoded with the QSV decoder — which is materially less tolerant of imperfect H.264 than
FFmpeg's native VA-API decoder and cannot carry Dolby Vision metadata. Jellyfin, on identical hardware,
avoids this by decoding with VA-API and encoding with QSV; that combination was not expressible in
ErsatzTV. Full design: docs/superpowers/specs/2026-07-20-qsv-native-decode-design.md.
-
Chosen: a single, QSV-scoped
FFmpegProfile.QsvPreferNativeDecoderboolean, mirroring Jellyfin's "Prefer OS native DXVA or VA-API hardware decoders" checkbox exactly — Jellyfin itself deliberately collapses this to one default-on toggle rather than a decode-family picker, and copying the reference tool's granularity avoids over-building past a problem it has already solved. -
Default ON. Native VA-API decode is strictly more tolerant of imperfect streams than the QSV decoder wrapper, and Dolby Vision passthrough requires it — so the working configuration is the default for a reliability fix. Existing QSV profiles adopt the hybrid on upgrade via the migration's
HasDefaultValue(true)(SQLiteINTEGER/MySQLtinyint, nullable withDEFAULT 1— the column isbool?so an explicitfalsepersists, whileNULL/absent reads as ON via!= false; a non-nullablebool+ store default would make EF silently drop a create-with-false), no opt-in required. -
Rejected: a general
DecodeHardwareAccelerationenum column decoupling decode and encode hardware families entirely. More configurable than Jellyfin's own control, but nothing in the codebase or the reported failure needs that generality yet —FFmpegStatealready separatesDecoderHardwareAccelerationMode/EncoderHardwareAccelerationModeinternally (used today for the software-decode-plus-hardware-encode error-loop fallback), so the seam to grow into a real enum exists if a second asymmetric-decode case ever shows up on another hardware family. Deferred rather than built now, on YAGNI grounds. -
Contained to the QSV builder. The flag does not touch
PipelineBuilderFactory's single-builder dispatch per profile, and does not repurpose the existing decode/encode-mode fields into a general cross-family selector — that repurposing is exactly the rejected enum option, just introduced through the back door. -
Accepted trade-off — HDR tonemapping runs in software on the native path. With native decode ON the decoder mode is
Vaapi, soQsvPipelineBuilder.SetTonemap(which only selectsTonemapQsvFilterforDecoderHardwareAccelerationMode == Qsv) falls to the softwarezscale/tonemapchain for HDR content. Output is correct but costs CPU on the realtime path. Accepted for now because software tonemap is correct-but-slower while an unvalidated GPU-tonemap graph could be worse (needs the Intel host to verify). Optimizing the native path is tracked in #505.Corrected 2026-07-26 (#505): the escape-hatch half of this bullet was wrong, and wrong in the dangerous direction. It claimed HDR-on-QSV users could set the flag OFF to keep GPU tonemap — but
vpp_qsv=tonemap=1is a silent no-op on pre-Gen11 Intel graphics, so turning the flag off did not preserve GPU tonemapping, it disabled tonemapping altogether and shipped untonemapped HDR. The software-tonemap half stands (that path was always correct). Do not offer the flag as an HDR work-around. Seeffmpeg.qsv-hdr-tonemap-openclfor the measurements and the OpenCL route that replaced it;TonemapQsvFilterno longer exists. -
Native decode is Linux-only. Guarded with
!OperatingSystem.IsWindows()in the QSV builder — FFmpeg has novaapihwaccel on Windows (and Windows QSV capabilities are over-reported), so on Windows a QSV profile keeps QSV decode regardless of the flag.