From 93a7ddaf6309146c56fabfc086b6d6061265f5e7 Mon Sep 17 00:00:00 2001 From: "Lars R. Damerow" Date: Sun, 9 Aug 2026 09:19:49 -0700 Subject: [PATCH 1/2] feat(video): record 10-bit encoder probe results for each codec Adds two arrays that store the probe results for h264, hevc, and av1's 10-bit 4:2:0 and 4:4:4 encoding support. The naming scheme for the arrays follows the codebase's use of "dynamic_range" to indicate 10-bit, even though these results can be used for SDR and HDR encoding. --- src/video.cpp | 16 ++++++++++++++++ src/video.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/src/video.cpp b/src/video.cpp index 3bc41638591..4904fa03618 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -1445,6 +1445,8 @@ namespace video { int active_av1_mode; ///< AV1 mode selected by the most recent encoder probe. bool last_encoder_probe_supported_ref_frames_invalidation = false; ///< Whether the last probe found reference-frame invalidation support. std::array last_encoder_probe_supported_yuv444_for_codec = {}; ///< YUV444 support discovered for each probed codec. + std::array last_encoder_probe_supported_dynamic_range_for_codec = {}; ///< 10-bit 4:2:0 support discovered for each probed codec. + std::array last_encoder_probe_supported_dynamic_range_yuv444_for_codec = {}; ///< 10-bit YUV444 support discovered for each probed codec. /** * @brief Recreate a display capture object after a capture failure. @@ -3253,6 +3255,8 @@ namespace video { active_hevc_mode = config::video.hevc_mode; active_av1_mode = config::video.av1_mode; last_encoder_probe_supported_ref_frames_invalidation = false; + last_encoder_probe_supported_dynamic_range_for_codec = {}; + last_encoder_probe_supported_dynamic_range_yuv444_for_codec = {}; auto adjust_encoder_constraints_hevc = [&](encoder_t *encoder) { // If we can't satisfy both the encoder and codec requirement, prefer the encoder over codec support @@ -3409,6 +3413,18 @@ namespace video { encoder.hevc[encoder_t::YUV444]; last_encoder_probe_supported_yuv444_for_codec[2] = encoder.av1[encoder_t::PASSED] && encoder.av1[encoder_t::YUV444]; + last_encoder_probe_supported_dynamic_range_for_codec[0] = encoder.h264[encoder_t::PASSED] && + encoder.h264[encoder_t::DYNAMIC_RANGE]; + last_encoder_probe_supported_dynamic_range_for_codec[1] = encoder.hevc[encoder_t::PASSED] && + encoder.hevc[encoder_t::DYNAMIC_RANGE]; + last_encoder_probe_supported_dynamic_range_for_codec[2] = encoder.av1[encoder_t::PASSED] && + encoder.av1[encoder_t::DYNAMIC_RANGE]; + last_encoder_probe_supported_dynamic_range_yuv444_for_codec[0] = encoder.h264[encoder_t::PASSED] && + encoder.h264[encoder_t::DYNAMIC_RANGE_YUV444]; + last_encoder_probe_supported_dynamic_range_yuv444_for_codec[1] = encoder.hevc[encoder_t::PASSED] && + encoder.hevc[encoder_t::DYNAMIC_RANGE_YUV444]; + last_encoder_probe_supported_dynamic_range_yuv444_for_codec[2] = encoder.av1[encoder_t::PASSED] && + encoder.av1[encoder_t::DYNAMIC_RANGE_YUV444]; BOOST_LOG(debug) << "------ h264 ------"sv; for (int x = 0; x < encoder_t::MAX_FLAGS; ++x) { diff --git a/src/video.h b/src/video.h index 63f3cf55cbf..e138a5001fd 100644 --- a/src/video.h +++ b/src/video.h @@ -682,6 +682,8 @@ namespace video { extern int active_av1_mode; extern bool last_encoder_probe_supported_ref_frames_invalidation; extern std::array last_encoder_probe_supported_yuv444_for_codec; // 0 - H.264, 1 - HEVC, 2 - AV1 + extern std::array last_encoder_probe_supported_dynamic_range_for_codec; // 0 - H.264, 1 - HEVC, 2 - AV1 + extern std::array last_encoder_probe_supported_dynamic_range_yuv444_for_codec; // 0 - H.264, 1 - HEVC, 2 - AV1 /** * @brief Resolve a client-requested dynamic range against probed encoder capabilities. From 41bc33e4be5df5d304eae6d696ea9bd868ef3584 Mon Sep 17 00:00:00 2001 From: "Lars R. Damerow" Date: Tue, 18 Aug 2026 17:53:36 -0700 Subject: [PATCH 2/2] fix(nvhttp): differentiate 8-bit and 10-bit 444 advertisement With this change, 8-bit and 10-bit 444 encoder advertisement will correctly reflect the results of the encoder probes. Before it, the code used the probe result for 8-bit 444 encoding to decide whether or not to advertise 10-bit 444 encoding, but not all hardware can do both. (Mostly it seems like older Intel Media Engines and older VA-API versions make up that category.) In those cases, the code would still offer the 10-bit 444 advertisement, but if the client selected it, it wouldn't have worked. --- src/nvhttp.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 8e33cad8aae..7ee1a2a88af 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1175,10 +1175,10 @@ namespace nvhttp { codec_mode_flags |= SCM_HEVC_REXT8_444; } } - if (video::active_hevc_mode == 3 || video::active_hevc_mode == 5) { + if ((video::active_hevc_mode == 3 || video::active_hevc_mode == 5) && video::last_encoder_probe_supported_dynamic_range_for_codec[1]) { codec_mode_flags |= SCM_HEVC_MAIN10; } - if ((video::active_hevc_mode == 4 || video::active_hevc_mode == 5) && video::last_encoder_probe_supported_yuv444_for_codec[1]) { + if ((video::active_hevc_mode == 4 || video::active_hevc_mode == 5) && video::last_encoder_probe_supported_dynamic_range_yuv444_for_codec[1]) { codec_mode_flags |= SCM_HEVC_REXT10_444; } @@ -1188,10 +1188,10 @@ namespace nvhttp { codec_mode_flags |= SCM_AV1_HIGH8_444; } } - if (video::active_av1_mode == 3 || video::active_av1_mode == 5) { + if ((video::active_av1_mode == 3 || video::active_av1_mode == 5) && video::last_encoder_probe_supported_dynamic_range_for_codec[2]) { codec_mode_flags |= SCM_AV1_MAIN10; } - if ((video::active_av1_mode == 4 || video::active_av1_mode == 5) && video::last_encoder_probe_supported_yuv444_for_codec[2]) { + if ((video::active_av1_mode == 4 || video::active_av1_mode == 5) && video::last_encoder_probe_supported_dynamic_range_yuv444_for_codec[2]) { codec_mode_flags |= SCM_AV1_HIGH10_444; } return codec_mode_flags;