From 05adbc1cc258bcba4dabb65cba40722cd984e309 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 5 Jan 2023 01:43:24 -0600 Subject: [PATCH 1/2] Don't fail init if the preferred encoder is unavailable --- src/video.cpp | 94 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/src/video.cpp b/src/video.cpp index 8896216750b..e152b63e52c 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -1694,36 +1694,92 @@ bool validate_encoder(encoder_t &encoder) { } int init() { - BOOST_LOG(info) << "// Testing for available encoders, this may generate errors. You can safely ignore those errors. //"sv; + bool encoder_found = false; + if(!config::video.encoder.empty()) { + // If there is a specific encoder specified, use it if it passes validation + KITTY_WHILE_LOOP(auto pos = std::begin(encoders), pos != std::end(encoders), { + auto encoder = *pos; + + if(encoder.name == config::video.encoder) { + // Remove the encoder from the list entirely if it fails validation + if(!validate_encoder(encoder)) { + pos = encoders.erase(pos); + break; + } - KITTY_WHILE_LOOP(auto pos = std::begin(encoders), pos != std::end(encoders), { - if( - (!config::video.encoder.empty() && pos->name != config::video.encoder) || - !validate_encoder(*pos) || - (config::video.hevc_mode == 3 && !pos->hevc[encoder_t::DYNAMIC_RANGE])) { - pos = encoders.erase(pos); + // If we can't satisfy both the encoder and HDR requirement, prefer the encoder over HDR support + if(config::video.hevc_mode == 3 && !encoder.hevc[encoder_t::DYNAMIC_RANGE]) { + BOOST_LOG(warning) << "Encoder ["sv << config::video.encoder << "] does not support HDR on this system"sv; + config::video.hevc_mode = 0; + } - continue; + encoders.clear(); + encoders.emplace_back(encoder); + encoder_found = true; + break; + } + + pos++; + }); + + if(!encoder_found) { + BOOST_LOG(error) << "Couldn't find any working encoder matching ["sv << config::video.encoder << ']'; + config::video.encoder.clear(); } + } - break; - }) + BOOST_LOG(info) << "// Testing for available encoders, this may generate errors. You can safely ignore those errors. //"sv; - BOOST_LOG(info); - BOOST_LOG(info) << "// Ignore any errors mentioned above, they are not relevant. //"sv; - BOOST_LOG(info); + // If we haven't found an encoder yet but we want one with HDR support, search for that now. + if(!encoder_found && config::video.hevc_mode == 3) { + KITTY_WHILE_LOOP(auto pos = std::begin(encoders), pos != std::end(encoders), { + auto encoder = *pos; - if(encoders.empty()) { - if(config::video.encoder.empty()) { - BOOST_LOG(fatal) << "Couldn't find any encoder"sv; - } - else { - BOOST_LOG(fatal) << "Couldn't find any encoder matching ["sv << config::video.encoder << ']'; + // Remove the encoder from the list entirely if it fails validation + if(!validate_encoder(encoder)) { + pos = encoders.erase(pos); + continue; + } + + // Skip it if it doesn't support HDR + if(!encoder.hevc[encoder_t::DYNAMIC_RANGE]) { + pos++; + continue; + } + + encoders.clear(); + encoders.emplace_back(encoder); + encoder_found = true; + break; + }); + + if(!encoder_found) { + BOOST_LOG(error) << "Couldn't find any working HDR-capable encoder"sv; } + } + + // If no encoder was specified or the specified encoder was unusable, keep trying + // the remaining encoders until we find one that passes validation. + if(!encoder_found) { + KITTY_WHILE_LOOP(auto pos = std::begin(encoders), pos != std::end(encoders), { + if(!validate_encoder(*pos)) { + pos = encoders.erase(pos); + continue; + } + + break; + }); + } + if(encoders.empty()) { + BOOST_LOG(fatal) << "Couldn't find any working encoder"sv; return -1; } + BOOST_LOG(info); + BOOST_LOG(info) << "// Ignore any errors mentioned above, they are not relevant. //"sv; + BOOST_LOG(info); + auto &encoder = encoders.front(); BOOST_LOG(debug) << "------ h264 ------"sv; From 9fa6d82a4cc1bc43c53ef6de4c16eaab23447e11 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 5 Jan 2023 01:44:23 -0600 Subject: [PATCH 2/2] Scale rc_buffer_size for libx265 too --- src/video.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video.cpp b/src/video.cpp index e152b63e52c..020ab77c331 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -1029,9 +1029,11 @@ std::optional make_session(const encoder_t &encoder, const config_t & ctx->bit_rate = bitrate; ctx->rc_min_rate = bitrate; - if(!hardware && ctx->slices > 1) { + if(!hardware && (ctx->slices > 1 || config.videoFormat != 0)) { // Use a larger rc_buffer_size for software encoding when slices are enabled, // because libx264 can severely degrade quality if the buffer is too small. + // libx265 encounters this issue more frequently, so always scale the + // buffer by 1.5x for software HEVC encoding. ctx->rc_buffer_size = bitrate / ((config.framerate * 10) / 15); } else {