Feature request: expose NV_ENC_INITIALIZE_PARAMS::splitEncodeMode in PyNvVideoCodec

Hello,

I would like to request exposing NVENC split-frame encoding control through the public PyNvVideoCodec Encoder API.

PyNvVideoCodec 2.2.0 already contains everything required internally:

  • the bundled Video Codec SDK header defines NV_ENC_SPLIT_ENCODE_MODE;
  • NV_ENC_INITIALIZE_PARAMS already contains splitEncodeMode;
  • PyNvVideoCodec already fills NV_ENC_INITIALIZE_PARAMS;
  • an encoder option parser already exists;
  • Python kwargs / JSON options are already converted into a std::map.

However, splitEncodeMode is not exposed through CreateEncoder() or JSON configuration. The structure remains zero-initialized, which selects NV_ENC_SPLIT_AUTO_MODE, and applications cannot force or disable split-frame encoding.

I added a local implementation by modifying only:

src/PyNvVideoCodec/src/NvEncoderClInterface.cpp

The patch parses one new option before encoder initialization:

auto split_encode_mode = FindAttribute(options, "split_encode_mode");

if (!split_encode_mode.empty()) {
    if (split_encode_mode == "NV_ENC_SPLIT_AUTO_MODE") {
        params.splitEncodeMode = NV_ENC_SPLIT_AUTO_MODE;
    }
    else if (split_encode_mode == "NV_ENC_SPLIT_AUTO_FORCED_MODE") {
        params.splitEncodeMode = NV_ENC_SPLIT_AUTO_FORCED_MODE;
    }
    else if (split_encode_mode == "NV_ENC_SPLIT_TWO_FORCED_MODE") {
        params.splitEncodeMode = NV_ENC_SPLIT_TWO_FORCED_MODE;
    }
    else if (split_encode_mode == "NV_ENC_SPLIT_THREE_FORCED_MODE") {
        params.splitEncodeMode = NV_ENC_SPLIT_THREE_FORCED_MODE;
    }
    else if (split_encode_mode == "NV_ENC_SPLIT_FOUR_FORCED_MODE") {
#if CHECK_API_VERSION(13, 0)
        params.splitEncodeMode = NV_ENC_SPLIT_FOUR_FORCED_MODE;
#else
        throw invalid_argument(
            "NV_ENC_SPLIT_FOUR_FORCED_MODE requires NVENC API 13.0 or newer.");
#endif
    }
    else if (split_encode_mode == "NV_ENC_SPLIT_DISABLE_MODE") {
        params.splitEncodeMode = NV_ENC_SPLIT_DISABLE_MODE;
    }
    else {
        throw invalid_argument(
            "Invalid split_encode_mode: " + split_encode_mode);
    }
}

Accepted values in the local implementation are:

split_encode_mode="NV_ENC_SPLIT_AUTO_MODE"
split_encode_mode="NV_ENC_SPLIT_AUTO_FORCED_MODE"
split_encode_mode="NV_ENC_SPLIT_TWO_FORCED_MODE"
split_encode_mode="NV_ENC_SPLIT_THREE_FORCED_MODE"
split_encode_mode="NV_ENC_SPLIT_FOUR_FORCED_MODE"
split_encode_mode="NV_ENC_SPLIT_DISABLE_MODE"

Example:

encoder = nvc.CreateEncoder(
    width,
    height,
    "NV12",
    False,
    # other encoder options...
    split_encode_mode="NV_ENC_SPLIT_THREE_FORCED_MODE",
)

No NVENC implementation changes were required. The patch only maps the existing Python/JSON option to NV_ENC_INITIALIZE_PARAMS::splitEncodeMode.

Test environment

  • Windows 11 Pro, build 26200
  • NVIDIA GeForce RTX 5090
  • NVIDIA driver 610.88, WDDM
  • Python 3.12.10
  • PyNvVideoCodec 2.2.0
  • FFmpeg 8.1.1
  • Input: HEVC Main, NV12/yuv420p, 7680x2160, 60 FPS, 10,000 frames

Full details are attached in environment_and_input.log.

Minimal PyNvVideoCodec benchmark

The test uses only:

SimpleDecoder native NV12 device output
-> CreateEncoder HEVC NVENC
-> encoded packets discarded

There is no PyTorch, CuPy, SBS conversion, muxing, audio, or output-file I/O. Each configuration was run twice.

Configuration Total FPS Encode/frame Encode-call FPS
Official NVIDIA 2.2.0 wheel, option omitted (implicit AUTO) 165.17 3.126 ms 319.96
Locally rebuilt 2.2.0, forced 3-strip 191.80 2.288 ms 437.11

Observed improvement from forcing 3-strip:

  • encode-call throughput: +36.6%
  • encode time per frame: -26.8%
  • end-to-end NVDEC → NVENC throughput: +16.1%
  • wall time: -13.9%

Encode-call rate was highly repeatable:

Implicit AUTO:
- 319.92 FPS
- 320.00 FPS

THREE_FORCED:
- 437.03 FPS
- 437.18 FPS

See PyNvVideoCodec_split_test.log and test_pynv_nvdec_nvenc_split.py inside the attached scripts ZIP.

FFmpeg control test

I also tested the same GPU and the same 7680x2160 input with FFmpeg. All relevant encoder parameters were fixed, and only split_encode_mode was changed.

split_encode_mode Throughput Relative to disabled
disabled 143.13 FPS 1.00x
2 274.14 FPS 1.91x
3 331.62 FPS 2.32x

See ffmpeg_hevc_nvenc_split_tests.log and run_ffmpeg_split_tests.cmd inside the attached scripts ZIP for the exact commands.

The FFmpeg and PyNvVideoCodec timing architectures are different, so their absolute FPS values should not be compared directly. However, both tests clearly show that explicit split-frame control has a large performance impact on this workload.

Why this matters

AUTO is a reasonable default, but it is not always optimal in high-throughput GPU pipelines where NVDEC, CUDA inference, image processing, and NVENC run concurrently.

In my full pipeline, AUTO performance was close to the explicitly forced two-strip result. This does not prove the effective strip count selected by the driver, but it shows that AUTO did not provide the same throughput as forced three-strip encoding. Without a public splitEncodeMode option, an application cannot make this behavior deterministic.

This is especially relevant for large HEVC and AV1 frames on GPUs containing multiple NVENC engines.

Requested API addition

Please expose splitEncodeMode through CreateEncoder and JSON configuration, for example:

split_encode_mode="auto"
split_encode_mode="auto_forced"
split_encode_mode="2"
split_encode_mode="3"
split_encode_mode="4"
split_encode_mode="disabled"

Using the exact NVENC enum names would also be acceptable.

Attachments

  • environment_and_input.log
  • ffmpeg_hevc_nvenc_split_tests.log
  • PyNvVideoCodec_split_test.log
  • split_encode_repro_scripts.zip (contains run_ffmpeg_split_tests.cmd and test_pynv_nvdec_nvenc_split.py)

Thank you

environment_and_input.log (6.7 KB)
ffmpeg_hevc_nvenc_split_tests.log (6.2 KB)
PyNvVideoCodec_split_test.log (6.4 KB)
split_encode_repro_scripts.zip (3.0 KB)