[Feature] Register NVMTL_NVENCVT decoders in VTDecoderXPCService (green H.264 in Safari on Ada and Blackwell)
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- macos, objective-c
- Domain
- backend
Research direction
Start in plugin/NVMTLDevice.m at nvmtl_nvdec_in_decode_service() around line 471 and read the dispatch block alongside the existing decoder registrations. Add the gated nvmtl_nvencvt_register() call there, then check the build or existing tests for that target. Done when the NVENCVT decoder is registered in VTDecoderXPCService under the existing whitelist and opt-out users remain unaffected.
Written by the indexing model from the issue text.
Description
What should it do, and why does it matter to you?
Register the opt-in NVMTL_NVENCVT codec library in VTDecoderXPCService too.
Concretely: add a nvmtl_nvencvt_register() call to the dispatch block in nvmtl_nvdec_in_decode_service() (plugin/NVMTLDevice.m:471), next to the two built-in registrations. It stays gated by the existing NVMTL_NVENCVT whitelist, so nothing changes for users who have not opted in.
Without it, Safari (and other sandboxed Apple clients that delegate decoding) can only reach the driver's built-in H.264 decoder, which produces an entirely green picture on both Ada and Blackwell. Chrome is fine because it decodes in its own GPU process, where the rating-1100 decoder is registered.
Why this happens
nvmtl_decode_is_delegated()documents that Safari's WebKit GPU process, QuickTime and Preview delegate decoding toVTDecoderXPCService; in-process registration fails under their sandbox.- GH #175 added
nvmtl_nvdec_in_decode_service()to register the built-in decoders at load in that one process. Its comment says the XPC service "holds the bundle's mappings but never creates a Metal device". It callsnvmtl_nvdec_register()andnvmtl_nvdec_hevc_register()only. nvmtl_nvencvt_register()has exactly one call site,NVMTLDevice.m:718, inside Metal device initialisation. I checked both thev2.7.2tag and currentmain: they are identical in this respect. So the external library that registers the rating-1100 decoders is never registered inVTDecoderXPCService.- The built-in decoders hand out buffers with hard-coded attributes. On Blackwell, the third-party replacement (
arrebel/nvcodec-blackwellv1.2.0,src/vtdec.c) puts it plainly: "What the decoder hands out, built the way the shipped plugin builds it: four keys, the pixel format as a CFNumber ('420v'), an empty IOSurface dictionary" — it never readsVTDecoderSessionGetDestinationPixelBufferAttributes. By contrastmickys/nvenc'sset_output()invt/nvencvt_dec.cinspects the client's destination attributes, optionally builds its own pool and exposesNVDEC_NOOWNPOOL/NVDEC_OWNATTRS/NVDEC_NOMETALfor exactly this variability.
A Safari session's attributes therefore do not match what the built-in decoder produces; VideoToolbox converts or transfers the picture and the chroma plane comes out empty (NV12 with UV=0 renders green). This is the most likely mechanism — I could not dump decoded planes from inside the sandboxed XPC service.
Measurements
VTCopyVideoDecoderListon 2.7.2 / RTX 4070 Ti SUPER with mickys/nvenc v0.9.5 shows twoavc1entries:com.nvmtl.videodecoder.avc.nvdec.avc1(rating 1000, hardware) andorg.nvenc.videodecoder.avc.avc1(rating 1100, hardware).lsofonVTDecoderXPCServiceshows it mapsNVMTLDriver,libnvdec_h264_t2d.dylibandlibnvencvt.dylib;com.apple.WebKit.GPUmaps none of them.- Setting
NVMTL_NO_NVDEC=1removes the rating-1000 decoder from the XPC service and Safari falls back toAppleH264SW. That is the current workaround, but it gives up hardware decoding entirely — and on Blackwell it also disables the third-party replacement decoder, whose installer deliberately strips that very switch because it depends on the registration.
Scope: Ada and Blackwell
| Ada (RTX 4070 Ti SUPER) | Blackwell (RTX 5060 Ti / 5070 Ti) | |
|---|---|---|
| rating 1000 in the XPC service | built-in libnvdec_h264_t2d.dylib |
built-in / replaced libnvdec_h264.dylib |
| rating 1100 | mickys/nvenc libnvencvt.dylib |
nvcodec-blackwell libnvencvt.dylib |
| H.264 in Safari | green | green |
The two generations use completely different decoder binaries, so a chroma bug in one library does not explain both. The common factor is the XPC path, where only the rating-1000 decoder is reachable. This also fits #472 (green 1080p H.264 in Safari and Edge on an RTX 5060 Ti) and #414 (QuickTime still on AppleH264SW in the XPC service).
Suggested change
// in nvmtl_nvdec_in_decode_service(), inside the dispatch_async block
nvmtl_nvdec_register();
nvmtl_nvdec_hevc_register();
nvmtl_nvencvt_register(); // gated by NVMTL_NVENCVT; registers rating 1100 above ours
With the external decoders present in the XPC service, Safari should pick the rating-1100 decoder and get correct colour with hardware decoding on both generations, without needing NVMTL_NO_NVDEC=1.
Related
#472 (green video, RTX 5060 Ti), #414 (QuickTime H.264 falls back to AppleH264SW), #349 (delegate decoding to VTDecoderXPCService), #65 (hard-coded Blackwell video layout).
Environment
macOS 26.7.2, NullMoth 2.7.2, RTX 4070 Ti SUPER (AD103-A), mickys/nvenc v0.9.5, Safari 27.2 / Chrome 156. Blackwell observations are from #472 and the nvcodec-blackwell v1.2.0 README (RTX 5070 Ti, driver 2.7.1). I have no information about other generations.
- Dominant language
- Rust
- Stars
- 2.5k
- Forks
- 233
- Avg merge
- 3d 14h
- Merged PRs (30d)
- 14
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from nullmoth/nvidia-macos-driver
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
nullmoth/nvidia-macos-driver#141 · 1 comment ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
nullmoth/nvidia-macos-driver#28 ·
Maintainers usually reply within 2 days
-
bug
Difficulty 5/5 Over a week Newbie friendliness 25/100
nullmoth/nvidia-macos-driver#520 ·
Maintainers usually reply within 2 days
-
bug
Difficulty 5/5 Over a week Newbie friendliness 25/100
nullmoth/nvidia-macos-driver#518 ·
Maintainers usually reply within 2 days
-
Difficulty 1/5 Under an hour Newbie friendliness 35/100
nullmoth/nvidia-macos-driver#517 ·
Maintainers usually reply within 2 days
All issues in nullmoth/nvidia-macos-driver
Similar issues
-
An EXE started from the shell with MAXALLOC FFFFh leaves a 0-paragraph free block after its ownOpenbug low-priority
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
dividebysandwich/rust-dos#629 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
eliasstravik/herdr-projects#758 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement needs:sonnet ready-for-agent
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day