Skip to content

fix: keep hardware encoders for sources whose first frame has an odd size - #324

Merged
devopvoid merged 3 commits into
mainfrom
test/nvenc-lifecycle
Oct 4, 2026
Merged

devopvoid merged 3 commits into
mainfrom
test/nvenc-lifecycle

Conversation

@devopvoid

@devopvoid devopvoid commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

WebRTC asks a source for the encoder's requested_resolution_alignment only after the encoder has been set up, so the first frame of a window capture or a camera with an odd size reaches InitEncode as it is. NvencVideoEncoder, MFVideoEncoder and VaapiH264Encoder refused it with WEBRTC_VIDEO_CODEC_ERR_PARAMETER, and the fallback encoder then left the whole session to OpenH264 (Hardware encoder failed to initialize (-4), switching to software).

All three encoders now take the even size below an odd one and drop the last row and column of such frames, which needs no copy. The input type and the encoded size follow the even size.

Tests (HardwareVideoEncoderIntegrationTest), each requiring a hardware encoder where webrtc.test.hardwareEncoder is set:

  • hardwareEncodesOddSize: 641x361. This failed before the NVENC change.
  • hardwareEncodes1080p
  • hardwareFollowsResolutionChange: 320x240 to 640x480 and back.
  • hardwareFollowsBitrateCap: the encoder is reconfigured in place and keeps sending; the cap is lifted again.
  • hardwareRestartsCleanly: 15 calls one after the other, so a leaked session would run the GPU out of them.
  • hardwareEncodesSeveralStreams: four calls at once.

NVENC was run on an NVIDIA GeForce RTX 3080 on Windows: all 11 tests of the class pass, also under -Xcheck:jni (no FATAL ERROR).

The Media Foundation change is compiled but has not been run with a Media Foundation encoder. The only H.264 one on the machine it was written on is a leftover AMD driver component that fails to start without the GPU (hr=0x8007000E), so with NVENC out of the way even an even-size call fell back to OpenH264. hardwareEncodesOddSize covers it on a machine where Media Foundation is the first hardware encoder, for example an AMD or Intel GPU on Windows; it would be good to run it on one before merging. CI runners have no GPU, so they skip it.

The VA-API change was neither compiled nor run on the machine it was written on (Windows, no Linux toolchain, no VA-API device). It is the change made to NVENC, which was built and tested, and the macroblock counts, the cropping in the sequence parameters and the encoded size follow the even size. CI compiles it on the Linux builds. hardwareEncodesOddSize covers it on a machine where VA-API is the first hardware encoder (an Intel or AMD GPU on Linux); please run it on one before merging.

WebRTC asks a source for the encoder's requested_resolution_alignment only
after the encoder has been set up, so the first frame of a window capture or
a camera with an odd size reaches InitEncode as it is. NvencVideoEncoder
refused it with WEBRTC_VIDEO_CODEC_ERR_PARAMETER, and the fallback encoder
then left the whole session to OpenH264.

The encoder now takes the even size below an odd one and drops the last row
and column of such frames, which needs no copy.

New tests send 1080p, an odd 641x361, a change of resolution, a bitrate cap
that is lifted again, fifteen calls one after the other (a leaked session
would run the GPU out of them) and four calls at once, and require NVENC for
all of them. The odd size failed before the change.

Run on an NVIDIA GeForce RTX 3080 on Windows, also with -Xcheck:jni.
The same as for NVENC: WebRTC asks a source for the encoder's
requested_resolution_alignment only after the encoder has been set up, so an
odd first frame reached MFVideoEncoder::InitEncode, which refused it with
WEBRTC_VIDEO_CODEC_ERR_PARAMETER, and the fallback encoder left the whole
session to OpenH264.

The encoder now takes the even size below an odd one and drops the last row
and column of such frames, which needs no copy. The input type and the
encoded size follow the even size.

Compiled, and the NVENC path next to it is unchanged (all tests of
HardwareVideoEncoderIntegrationTest pass), but not run with a Media Foundation
encoder: the only H.264 one on the machine it was written on is a leftover AMD
driver component that cannot start without the GPU. hardwareEncodesOddSize
covers it wherever Media Foundation is the first hardware encoder.
@devopvoid devopvoid changed the title fix: keep NVENC for sources whose first frame has an odd size fix: keep hardware encoders for sources whose first frame has an odd size Oct 4, 2026
The same as for NVENC and Media Foundation: WebRTC asks a source for the
encoder's requested_resolution_alignment only after the encoder has been set
up, so an odd first frame reached VaapiH264Encoder::InitEncode, which refused
it with WEBRTC_VIDEO_CODEC_ERR_PARAMETER, and the fallback encoder left the
whole session to OpenH264.

The encoder now takes the even size below an odd one and drops the last row
and column of such frames, which needs no copy. The macroblock counts, the
cropping in the sequence parameters and the encoded size follow the even
size, which the cropping (in units of two samples) needs anyway.

Neither compiled nor run: this machine is Windows without a Linux toolchain or
WSL, and has no VA-API device. The change is the one made to NVENC, which was
built and tested, and CI compiles this file on the Linux builds.
hardwareEncodesOddSize covers it on a machine where VA-API is the first
hardware encoder.
@devopvoid
devopvoid merged commit a6a4234 into main Oct 4, 2026
22 checks passed
@devopvoid
devopvoid deleted the test/nvenc-lifecycle branch October 4, 2026 18:29
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.

1 participant