Summary
GPU-direct AV1 (GpuVideoEncoderConfig::codec == "av1", NVIDIA AV1 Encoder MFT)
binds, starts, and runs at the correct cadence, but emits near-empty access
units: ~54 bytes per sample at 1920x1080@60 against H.264's ~12,483 on the same
build and the same rig. The muxed stream is ~18.4 kbit/s against a configured
6 Mbps — 0.3% of its bitrate — so nothing usable arrives at the destination.
H.264 and HEVC pass the identical 1080p60 gate on the same build. As of this
change, AV1 ships REFUSED, not broken: StreamStartAdmission refuses the
start with the new code codec-not-deliverable and an honest operator sentence,
rather than silently streaming 18 kbit/s or silently downgrading the codec.
Evidence
Per-event output drain, instrumented on the async MFT loop:
av1 output drain: events=1260 samples=1260 mean=1.00 max-per-event=1
Identical to H.264's shape — the encoder is neither stalling nor queueing. The
codecs differ only in payload size:
| codec |
samples in a 30 s 1080p60 run |
bytes/sample |
received bitrate |
| h264 |
~1,260 |
~12,483 |
~6 Mbps (gate PASS, 60.0 fps) |
| hevc |
~1,260 |
(comparable) |
~6 Mbps (gate PASS, 60.0 fps) |
| av1 |
1,260 |
~54 (≈49 after a normal 5,892-byte keyframe) |
~18.4 kbit/s, 66 KiB total |
The first output chunk is normal — [gpu-encode] first output chunk size=5892 keyframe=1 — and the 320x180 / 12-frame unit round-trip
(MediaFoundationGpuVideoEncoderTest.DirectSharedTextureAv1RoundTrip) passes.
Only the full-resolution, full-rate stream is empty. Reproduced on three
consecutive runs with no other process holding the GPU encoder.
Three hypotheses, ELIMINATED
These were the expensive part of the investigation. Do not repeat them.
- Deep encoder pipeline (lookahead / alt-ref buffering more than 30 s).
ELIMINATED — low-latency mode is accepted by the AV1 MFT (av1 b-frames off via low-latency-mode, the same ladder HEVC uses) and the rate was unchanged.
- FFmpeg's
obu demuxer mis-handling a live pipe. ELIMINATED — a 10 s
1080p60 av1_nvenc OBU stream was piped through the sender's exact flags:
600 frames in / 600 frames out, 1.15 MB in / 1.18 MB out. The muxer is fine.
- Our async MFT loop reading only one output per HaveOutput event.
ELIMINATED — instrumented (see the drain counts above): mean=1.00,
max-per-event=1, identical to H.264. Commit 6cedb9b7 (drain every ready
output per event) is defensive correctness and a no-op here.
What is left is the encoder itself producing empty access units at this
resolution/rate — a vendor/driver-level investigation.
Reproduce
node scripts/validate-gpu-encode.mjs --seconds 30 --codec av1
Today this PASSES by observing the refusal (stream start REFUSED code=codec-not-deliverable, and no path=gpu-direct codec=av1). To see the
defect itself, clear admission.codecKnownNotDeliverable in
RtmpOutputSenderAdapter::startFfmpegProcess and re-run: the gate then fails on
received bitrate/fps.
This gate is what flips the refusal back off once the payload defect is
understood.
Rig
- NVIDIA GeForce RTX 4090, driver 616.92
- Windows SDK 10.0.26100
- Windows 11,
COREVIDEO_WITH_MF_ENCODER=ON Release core
Where it is refused
native/src/modules/StreamStartAdmission.h — codecKnownNotDeliverable /
notDeliverableDetail -> result code codec-not-deliverable
native/src/modules/RtmpOutputSenderAdapter.cpp — the one named predicate
(requestedVideoCodec == "av1"), with an obvious home for a future rig-specific
override
native/src/modules/OutputDestinationSupervisorPolicy.h — the code is TERMINAL
(a configuration refusal; retrying re-decides identically forever)
native-shell/.../TransportStatusFormatter.cs — the operator sentence and the
compact "Codec refused" readout
- Spec:
docs/superpowers/specs/2026-09-20-gpu-direct-hevc-av1-stream-design.md
Summary
GPU-direct AV1 (
GpuVideoEncoderConfig::codec == "av1", NVIDIA AV1 Encoder MFT)binds, starts, and runs at the correct cadence, but emits near-empty access
units: ~54 bytes per sample at 1920x1080@60 against H.264's ~12,483 on the same
build and the same rig. The muxed stream is ~18.4 kbit/s against a configured
6 Mbps — 0.3% of its bitrate — so nothing usable arrives at the destination.
H.264 and HEVC pass the identical 1080p60 gate on the same build. As of this
change, AV1 ships REFUSED, not broken:
StreamStartAdmissionrefuses thestart with the new code
codec-not-deliverableand an honest operator sentence,rather than silently streaming 18 kbit/s or silently downgrading the codec.
Evidence
Per-event output drain, instrumented on the async MFT loop:
Identical to H.264's shape — the encoder is neither stalling nor queueing. The
codecs differ only in payload size:
The first output chunk is normal —
[gpu-encode] first output chunk size=5892 keyframe=1— and the 320x180 / 12-frame unit round-trip(
MediaFoundationGpuVideoEncoderTest.DirectSharedTextureAv1RoundTrip) passes.Only the full-resolution, full-rate stream is empty. Reproduced on three
consecutive runs with no other process holding the GPU encoder.
Three hypotheses, ELIMINATED
These were the expensive part of the investigation. Do not repeat them.
ELIMINATED — low-latency mode is accepted by the AV1 MFT (
av1 b-frames off via low-latency-mode, the same ladder HEVC uses) and the rate was unchanged.obudemuxer mis-handling a live pipe. ELIMINATED — a 10 s1080p60
av1_nvencOBU stream was piped through the sender's exact flags:600 frames in / 600 frames out, 1.15 MB in / 1.18 MB out. The muxer is fine.
ELIMINATED — instrumented (see the drain counts above):
mean=1.00,max-per-event=1, identical to H.264. Commit6cedb9b7(drain every readyoutput per event) is defensive correctness and a no-op here.
What is left is the encoder itself producing empty access units at this
resolution/rate — a vendor/driver-level investigation.
Reproduce
Today this PASSES by observing the refusal (
stream start REFUSED code=codec-not-deliverable, and nopath=gpu-direct codec=av1). To see thedefect itself, clear
admission.codecKnownNotDeliverableinRtmpOutputSenderAdapter::startFfmpegProcessand re-run: the gate then fails onreceived bitrate/fps.
This gate is what flips the refusal back off once the payload defect is
understood.
Rig
COREVIDEO_WITH_MF_ENCODER=ONRelease coreWhere it is refused
native/src/modules/StreamStartAdmission.h—codecKnownNotDeliverable/notDeliverableDetail-> result codecodec-not-deliverablenative/src/modules/RtmpOutputSenderAdapter.cpp— the one named predicate(
requestedVideoCodec == "av1"), with an obvious home for a future rig-specificoverride
native/src/modules/OutputDestinationSupervisorPolicy.h— the code is TERMINAL(a configuration refusal; retrying re-decides identically forever)
native-shell/.../TransportStatusFormatter.cs— the operator sentence and thecompact "Codec refused" readout
docs/superpowers/specs/2026-09-20-gpu-direct-hevc-av1-stream-design.md