diff --git a/source/encoders/handlers/nvenc_h264_handler.cpp b/source/encoders/handlers/nvenc_h264_handler.cpp index 3eeedecd..d395c418 100644 --- a/source/encoders/handlers/nvenc_h264_handler.cpp +++ b/source/encoders/handlers/nvenc_h264_handler.cpp @@ -56,8 +56,8 @@ void nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec { nvenc::get_defaults(settings, codec, context); - obs_data_set_default_int(settings, ST_KEY_PROFILE, static_cast(profile::HIGH)); - obs_data_set_default_int(settings, ST_KEY_LEVEL, static_cast(level::UNKNOWN)); + obs_data_set_default_string(settings, ST_KEY_PROFILE, ""); + obs_data_set_default_string(settings, ST_KEY_LEVEL, "auto"); } bool nvenc_h264_handler::has_keyframe_support(ffmpeg_factory*) @@ -94,13 +94,11 @@ void nvenc_h264_handler::update(obs_data_t* settings, const AVCodec* codec, AVCo nvenc::update(settings, codec, context); if (!context->internal) { - if (auto value = obs_data_get_int(settings, ST_KEY_PROFILE); value > -1) { - av_opt_set_int(context->priv_data, "profile", value, AV_OPT_SEARCH_CHILDREN); + if (auto v = obs_data_get_string(settings, ST_KEY_PROFILE); v && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "profile", v, AV_OPT_SEARCH_CHILDREN); } - if (auto value = obs_data_get_int(settings, ST_KEY_LEVEL); value > -1) { - av_opt_set_int(context->priv_data, "level", value, AV_OPT_SEARCH_CHILDREN); - } else { - av_opt_set(context->priv_data, "level", "auto", AV_OPT_SEARCH_CHILDREN); + if (auto v = obs_data_get_string(settings, ST_KEY_LEVEL); v && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "level", v, AV_OPT_SEARCH_CHILDREN); } } } @@ -140,20 +138,26 @@ void nvenc_h264_handler::get_encoder_properties(obs_properties_t* props, const A { auto p = obs_properties_add_list(grp, ST_KEY_PROFILE, D_TRANSLATE(S_CODEC_H264_PROFILE), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1); - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "profile", p, S_CODEC_H264_PROFILE); + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_list_add_string(p, D_TRANSLATE(S_STATE_DEFAULT), ""); + streamfx::ffmpeg::tools::avoption_list_add_entries( + context->priv_data, "profile", [&p](const AVOption* opt) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", S_CODEC_H264_PROFILE, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } { auto p = obs_properties_add_list(grp, ST_KEY_LEVEL, D_TRANSLATE(S_CODEC_H264_LEVEL), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), 0); - streamfx::ffmpeg::tools::avoption_list_add_entries_unnamed(context->priv_data, "level", p, - [](const AVOption* opt) { - if (opt->default_val.i64 == 0) - return true; - return false; - }); + OBS_COMBO_FORMAT_STRING); + + streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "level", [&p](const AVOption* opt) { + if (opt->default_val.i64 == 0) { + obs_property_list_add_string(p, D_TRANSLATE(S_STATE_AUTOMATIC), "auto"); + } else { + obs_property_list_add_string(p, opt->name, opt->name); + } + }); } } @@ -173,6 +177,24 @@ void streamfx::encoder::ffmpeg::handler::nvenc_h264_handler::migrate(obs_data_t* const AVCodec* codec, AVCodecContext* context) { nvenc::migrate(settings, version, codec, context); + + if (version < STREAMFX_MAKE_VERSION(0, 11, 1, 0)) { + // Profile + if (auto v = obs_data_get_int(settings, ST_KEY_PROFILE); v != -1) { + if (!obs_data_has_user_value(settings, ST_KEY_PROFILE)) + v = 3; + + std::map preset{ + {0, "baseline"}, {1, "baseline"}, {2, "main"}, {3, "high"}, {4, "high444p"}, + }; + if (auto k = preset.find(v); k != preset.end()) { + obs_data_set_string(settings, ST_KEY_PROFILE, k->second.data()); + } + } + + // Level + obs_data_set_string(settings, ST_KEY_LEVEL, "auto"); + } } bool nvenc_h264_handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes) diff --git a/source/encoders/handlers/nvenc_hevc_handler.cpp b/source/encoders/handlers/nvenc_hevc_handler.cpp index 5c3cb7ba..7c8915cd 100644 --- a/source/encoders/handlers/nvenc_hevc_handler.cpp +++ b/source/encoders/handlers/nvenc_hevc_handler.cpp @@ -53,9 +53,9 @@ void nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec { nvenc::get_defaults(settings, codec, context); - obs_data_set_default_int(settings, ST_KEY_PROFILE, static_cast(profile::MAIN)); - obs_data_set_default_int(settings, ST_KEY_TIER, static_cast(profile::MAIN)); - obs_data_set_default_int(settings, ST_KEY_LEVEL, static_cast(level::UNKNOWN)); + obs_data_set_default_string(settings, ST_KEY_PROFILE, ""); + obs_data_set_default_string(settings, ST_KEY_TIER, ""); + obs_data_set_default_string(settings, ST_KEY_LEVEL, "auto"); } bool nvenc_hevc_handler::has_keyframe_support(ffmpeg_factory*) @@ -92,16 +92,14 @@ void nvenc_hevc_handler::update(obs_data_t* settings, const AVCodec* codec, AVCo nvenc::update(settings, codec, context); if (!context->internal) { - if (auto v = obs_data_get_int(settings, ST_KEY_PROFILE); v > -1) { - av_opt_set_int(context->priv_data, "profile", v, AV_OPT_SEARCH_CHILDREN); + if (auto v = obs_data_get_string(settings, ST_KEY_PROFILE); v && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "profile", v, AV_OPT_SEARCH_CHILDREN); } - if (auto v = obs_data_get_int(settings, ST_KEY_TIER); v > -1) { - av_opt_set_int(context->priv_data, "tier", v, AV_OPT_SEARCH_CHILDREN); + if (auto v = obs_data_get_string(settings, ST_KEY_TIER); v && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "tier", v, AV_OPT_SEARCH_CHILDREN); } - if (auto v = obs_data_get_int(settings, ST_KEY_LEVEL); v > -1) { - av_opt_set_int(context->priv_data, "level", v, AV_OPT_SEARCH_CHILDREN); - } else { - av_opt_set(context->priv_data, "level", "auto", AV_OPT_SEARCH_CHILDREN); + if (auto v = obs_data_get_string(settings, ST_KEY_LEVEL); v && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "level", v, AV_OPT_SEARCH_CHILDREN); } } } @@ -143,26 +141,36 @@ void nvenc_hevc_handler::get_encoder_properties(obs_properties_t* props, const A { auto p = obs_properties_add_list(grp, ST_KEY_PROFILE, D_TRANSLATE(S_CODEC_HEVC_PROFILE), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1); - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "profile", p, S_CODEC_HEVC_PROFILE); + streamfx::ffmpeg::tools::avoption_list_add_entries( + context->priv_data, "profile", [&p](const AVOption* opt) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", S_CODEC_HEVC_PROFILE, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } { auto p = obs_properties_add_list(grp, ST_KEY_TIER, D_TRANSLATE(S_CODEC_HEVC_TIER), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); + OBS_COMBO_FORMAT_STRING); obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1); - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "tier", p, S_CODEC_HEVC_TIER); + streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "tier", [&p](const AVOption* opt) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", S_CODEC_HEVC_TIER, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } { auto p = obs_properties_add_list(grp, ST_KEY_LEVEL, D_TRANSLATE(S_CODEC_HEVC_LEVEL), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), 0); - streamfx::ffmpeg::tools::avoption_list_add_entries_unnamed(context->priv_data, "level", p, - [](const AVOption* opt) { - if (opt->default_val.i64 == 0) - return true; - return false; - }); + OBS_COMBO_FORMAT_STRING); + + streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "level", [&p](const AVOption* opt) { + if (opt->default_val.i64 == 0) { + obs_property_list_add_string(p, D_TRANSLATE(S_STATE_AUTOMATIC), "auto"); + } else { + obs_property_list_add_string(p, opt->name, opt->name); + } + }); } } @@ -182,6 +190,40 @@ void streamfx::encoder::ffmpeg::handler::nvenc_hevc_handler::migrate(obs_data_t* const AVCodec* codec, AVCodecContext* context) { nvenc::migrate(settings, version, codec, context); + + if (version < STREAMFX_MAKE_VERSION(0, 11, 1, 0)) { + // Profile + if (auto v = obs_data_get_int(settings, ST_KEY_PROFILE); v != -1) { + if (!obs_data_has_user_value(settings, ST_KEY_PROFILE)) + v = 0; + + std::map preset{ + {0, "main"}, + {1, "main10"}, + {2, "rext"}, + }; + if (auto k = preset.find(v); k != preset.end()) { + obs_data_set_string(settings, ST_KEY_PROFILE, k->second.data()); + } + } + + // Tier + if (auto v = obs_data_get_int(settings, ST_KEY_TIER); v != -1) { + if (!obs_data_has_user_value(settings, ST_KEY_TIER)) + v = 0; + + std::map preset{ + {0, "main"}, + {1, "high"}, + }; + if (auto k = preset.find(v); k != preset.end()) { + obs_data_set_string(settings, ST_KEY_TIER, k->second.data()); + } + } + + // Level + obs_data_set_string(settings, ST_KEY_LEVEL, "auto"); + } } bool nvenc_hevc_handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes) diff --git a/source/encoders/handlers/nvenc_shared.cpp b/source/encoders/handlers/nvenc_shared.cpp index 4426ac8f..2f6de97b 100644 --- a/source/encoders/handlers/nvenc_shared.cpp +++ b/source/encoders/handlers/nvenc_shared.cpp @@ -162,10 +162,12 @@ void nvenc::override_update(ffmpeg_instance* instance, obs_data_t*) void nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*) { - obs_data_set_default_int(settings, ST_KEY_PRESET, -1); + obs_data_set_default_string(settings, ST_KEY_PRESET, "default"); + obs_data_set_default_string(settings, ST_I18N_TUNE, "hq"); - obs_data_set_default_int(settings, ST_KEY_RATECONTROL_MODE, -1); + obs_data_set_default_string(settings, ST_KEY_RATECONTROL_MODE, "cbr"); obs_data_set_default_int(settings, ST_KEY_RATECONTROL_TWOPASS, -1); + obs_data_set_default_int(settings, ST_KEY_RATECONTROL_MULTIPASS, -1); obs_data_set_default_int(settings, ST_KEY_RATECONTROL_LOOKAHEAD, -1); obs_data_set_default_int(settings, ST_KEY_RATECONTROL_ADAPTIVEI, -1); obs_data_set_default_int(settings, ST_KEY_RATECONTROL_ADAPTIVEB, -1); @@ -200,21 +202,21 @@ void nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*) static bool modified_ratecontrol(obs_properties_t* props, obs_property_t*, obs_data_t* settings) noexcept { // Decode the name into useful flags. - auto value = obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE); + auto value = obs_data_get_string(settings, ST_KEY_RATECONTROL_MODE); bool have_bitrate = false; bool have_bitrate_range = false; bool have_quality = false; bool have_qp_limits = false; bool have_qp = false; - if (value == 2) { + if (value == std::string_view("cbr")) { have_bitrate = true; - } else if (value == 1) { + } else if (value == std::string_view("vbr")) { have_bitrate = true; have_bitrate_range = true; have_quality = true; have_qp_limits = true; have_qp = true; - } else if (value == 0) { + } else if (value == std::string_view("constqp")) { have_qp = true; } else { have_bitrate = true; @@ -251,14 +253,22 @@ void nvenc::get_properties_pre(obs_properties_t* props, const AVCodec*, const AV { { auto p = obs_properties_add_list(props, ST_KEY_PRESET, D_TRANSLATE(ST_I18N_PRESET), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "preset", p, ST_I18N_PRESET); + OBS_COMBO_FORMAT_STRING); + streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "preset", [&p](const AVOption* opt) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", ST_I18N_PRESET, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "tune")) { auto p = obs_properties_add_list(props, ST_KEY_TUNE, D_TRANSLATE(ST_I18N_TUNE), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "tune", p, ST_I18N_TUNE); + OBS_COMBO_FORMAT_STRING); + streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "tune", [&p](const AVOption* opt) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", ST_I18N_TUNE, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } } @@ -274,24 +284,31 @@ void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec, c { auto p = obs_properties_add_list(grp, ST_KEY_RATECONTROL_MODE, D_TRANSLATE(ST_I18N_RATECONTROL_MODE), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); obs_property_set_modified_callback(p, modified_ratecontrol); - auto filter = [](const AVOption* opt) { + obs_property_list_add_string(p, D_TRANSLATE(S_STATE_DEFAULT), ""); + streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "rc", [&p](const AVOption* opt) { + // Ignore options that are "deprecated" but not flagged as such. if (opt->default_val.i64 & (1 << 23)) - return true; - return false; - }; - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "rc", p, ST_I18N_RATECONTROL_MODE, - filter); + return; + + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", ST_I18N_RATECONTROL_MODE, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) { auto p = obs_properties_add_list(grp, ST_KEY_RATECONTROL_MULTIPASS, D_TRANSLATE(ST_I18N_RATECONTROL_MULTIPASS), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1); - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "multipass", p, - ST_I18N_RATECONTROL_MULTIPASS); + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_list_add_string(p, D_TRANSLATE(S_STATE_DEFAULT), ""); + streamfx::ffmpeg::tools::avoption_list_add_entries( + context->priv_data, "multipass", [&p](const AVOption* opt) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", ST_I18N_RATECONTROL_MULTIPASS, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } else { auto p = streamfx::util::obs_properties_add_tristate(grp, ST_KEY_RATECONTROL_TWOPASS, D_TRANSLATE(ST_I18N_RATECONTROL_TWOPASS)); @@ -419,10 +436,14 @@ void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec, c { auto p = obs_properties_add_list(grp, ST_KEY_OTHER_BFRAMEREFERENCEMODE, D_TRANSLATE(ST_I18N_OTHER_BFRAMEREFERENCEMODE), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1); - streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "b_ref_mode", p, - ST_I18N_OTHER_BFRAMEREFERENCEMODE); + OBS_COMBO_FORMAT_STRING); + obs_property_list_add_string(p, D_TRANSLATE(S_STATE_DEFAULT), ""); + streamfx::ffmpeg::tools::avoption_list_add_entries( + context->priv_data, "b_ref_mode", [&p](const AVOption* opt) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%s.%s\0", ST_I18N_OTHER_BFRAMEREFERENCEMODE, opt->name); + obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name); + }); } { @@ -492,27 +513,15 @@ void nvenc::get_runtime_properties(obs_properties_t* props, const AVCodec*, AVCo void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) { - if (!context->internal) { - auto value = obs_data_get_int(settings, ST_KEY_PRESET); - if (value != -1) { - auto name = streamfx::ffmpeg::tools::avoption_name_from_unit_value(context->priv_data, "preset", value); - if (name) { - av_opt_set(context->priv_data, "preset", name, AV_OPT_SEARCH_CHILDREN); - } else { - av_opt_set_int(context->priv_data, "preset", value, AV_OPT_SEARCH_CHILDREN); - } - } + if (auto v = obs_data_get_string(settings, ST_KEY_PRESET); + !context->internal && (v != nullptr) && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "preset", v, AV_OPT_SEARCH_CHILDREN); } { // Rate Control - auto value = obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE); - auto name = streamfx::ffmpeg::tools::avoption_name_from_unit_value(context->priv_data, "rc", value); - if (value != -1) { - if (name && !context->internal) { - av_opt_set(context->priv_data, "rc", name, AV_OPT_SEARCH_CHILDREN); - } else { - av_opt_set_int(context->priv_data, "rc", value, AV_OPT_SEARCH_CHILDREN); - } + auto v = obs_data_get_string(settings, ST_KEY_RATECONTROL_MODE); + if (!context->internal && (v != nullptr) && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "rc", v, AV_OPT_SEARCH_CHILDREN); } // Decode the name into useful flags. @@ -521,7 +530,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c bool have_quality = false; bool have_qp_limits = false; bool have_qp = false; - if (is_cbr(name)) { + if (v && is_cbr(v)) { have_bitrate = true; if (!context->internal) @@ -529,7 +538,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c // Support for OBS Studio obs_data_set_string(settings, "rate_control", "CBR"); - } else if (is_vbr(name)) { + } else if (v && is_vbr(v)) { have_bitrate = true; have_bitrate_range = true; have_quality = true; @@ -541,7 +550,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c // Support for OBS Studio obs_data_set_string(settings, "rate_control", "VBR"); - } else if (is_cqp(name)) { + } else if (v && is_cqp(v)) { have_qp = true; if (!context->internal) @@ -563,8 +572,9 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c if (!context->internal) { if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) { // Multi-Pass - if (int tp = static_cast(obs_data_get_int(settings, ST_KEY_RATECONTROL_MULTIPASS)); tp > -1) { - av_opt_set_int(context->priv_data, "multipass", tp, AV_OPT_SEARCH_CHILDREN); + if (auto v = obs_data_get_string(settings, ST_KEY_RATECONTROL_MULTIPASS); + (v != nullptr) && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "multipass", v, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(context->priv_data, "2pass", 0, AV_OPT_SEARCH_CHILDREN); } } else { @@ -707,8 +717,9 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c av_opt_set_int(context->priv_data, "weighted_pred", wp, AV_OPT_SEARCH_CHILDREN); } - if (auto v = obs_data_get_int(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE); v > -1) { - av_opt_set_int(context->priv_data, "b_ref_mode", v, AV_OPT_SEARCH_CHILDREN); + if (auto v = obs_data_get_string(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE); + (v != nullptr) && (strlen(v) > 0)) { + av_opt_set(context->priv_data, "b_ref_mode", v, AV_OPT_SEARCH_CHILDREN); } if (auto v = obs_data_get_int(settings, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE); v > -1) { @@ -810,29 +821,59 @@ void streamfx::encoder::ffmpeg::handler::nvenc::migrate(obs_data_t* settings, ui } if (version < STREAMFX_MAKE_VERSION(0, 11, 1, 0)) { + // Preset + if (auto v = obs_data_get_int(settings, ST_KEY_PRESET); v != -1) { + std::map preset{ + {0, "default"}, {1, "slow"}, {2, "medium"}, {3, "fast"}, {4, "hp"}, {5, "hq"}, + {6, "bd"}, {7, "ll"}, {8, "llhq"}, {9, "llhp"}, {10, "lossless"}, {11, "losslesshp"}, + }; + if (auto k = preset.find(v); k != preset.end()) { + obs_data_set_string(settings, ST_KEY_PRESET, k->second.data()); + } + } + + // Rate Control Mode if (auto v = obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE); v != -1) { + if (!obs_data_has_user_value(settings, ST_KEY_RATECONTROL_MODE)) + v = 4; + switch (v) { case 0: // CQP + obs_data_set_string(settings, ST_KEY_RATECONTROL_MODE, "constqp"); break; case 2: // VBR_HQ - obs_data_set_int(settings, ST_KEY_RATECONTROL_MODE, 1); obs_data_set_int(settings, ST_KEY_RATECONTROL_TWOPASS, 1); - obs_data_set_int(settings, ST_KEY_RATECONTROL_MULTIPASS, 1); + obs_data_set_string(settings, ST_KEY_RATECONTROL_MULTIPASS, "qres"); case 1: // VBR + obs_data_set_string(settings, ST_KEY_RATECONTROL_MODE, "vbr"); break; case 5: // CBR_LD_HQ obs_data_set_int(settings, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE, 1); case 4: // CBR_HQ - obs_data_set_int(settings, ST_KEY_RATECONTROL_MODE, 2); obs_data_set_int(settings, ST_KEY_RATECONTROL_TWOPASS, 1); - obs_data_set_int(settings, ST_KEY_RATECONTROL_MULTIPASS, 1); + obs_data_set_string(settings, ST_KEY_RATECONTROL_MULTIPASS, "qres"); case 3: // CBR + obs_data_set_string(settings, ST_KEY_RATECONTROL_MODE, "cbr"); break; } } + + // Target Quality if (auto v = obs_data_get_double(settings, ST_KEY_RATECONTROL_LIMITS_QUALITY); v > 0) { obs_data_set_double(settings, ST_KEY_RATECONTROL_LIMITS_QUALITY, (v / 100.) * 51.); } + + // B-Frame Reference Modes + if (auto v = obs_data_get_int(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE); v != -1) { + std::map preset{ + {0, "default"}, + {1, "each"}, + {2, "middle"}, + }; + if (auto k = preset.find(v); k != preset.end()) { + obs_data_set_string(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE, k->second.data()); + } + } } #undef COPY_UNSET