mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-11 06:15:05 +00:00
encoders/ffmpeg/nvenc: Improve compatibility with FFmpeg
Replaces some very specific code with generic support for FFmpeg, which should last us much longer than the old way. Also improves the migration of settings, which wasn't quite working with the previous way.
This commit is contained in:
parent
378f2b3f0e
commit
03b16786e7
3 changed files with 201 additions and 96 deletions
|
@ -56,8 +56,8 @@ void nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec
|
||||||
{
|
{
|
||||||
nvenc::get_defaults(settings, codec, context);
|
nvenc::get_defaults(settings, codec, context);
|
||||||
|
|
||||||
obs_data_set_default_int(settings, ST_KEY_PROFILE, static_cast<int64_t>(profile::HIGH));
|
obs_data_set_default_string(settings, ST_KEY_PROFILE, "");
|
||||||
obs_data_set_default_int(settings, ST_KEY_LEVEL, static_cast<int64_t>(level::UNKNOWN));
|
obs_data_set_default_string(settings, ST_KEY_LEVEL, "auto");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nvenc_h264_handler::has_keyframe_support(ffmpeg_factory*)
|
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);
|
nvenc::update(settings, codec, context);
|
||||||
|
|
||||||
if (!context->internal) {
|
if (!context->internal) {
|
||||||
if (auto value = obs_data_get_int(settings, ST_KEY_PROFILE); value > -1) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_PROFILE); v && (strlen(v) > 0)) {
|
||||||
av_opt_set_int(context->priv_data, "profile", value, AV_OPT_SEARCH_CHILDREN);
|
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) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_LEVEL); v && (strlen(v) > 0)) {
|
||||||
av_opt_set_int(context->priv_data, "level", value, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set(context->priv_data, "level", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
} else {
|
|
||||||
av_opt_set(context->priv_data, "level", "auto", AV_OPT_SEARCH_CHILDREN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,19 +138,25 @@ 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),
|
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_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
obs_property_list_add_string(p, D_TRANSLATE(S_STATE_DEFAULT), "");
|
||||||
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "profile", p, S_CODEC_H264_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_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,
|
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_COMBO_FORMAT_STRING);
|
||||||
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,
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "level", [&p](const AVOption* opt) {
|
||||||
[](const AVOption* opt) {
|
if (opt->default_val.i64 == 0) {
|
||||||
if (opt->default_val.i64 == 0)
|
obs_property_list_add_string(p, D_TRANSLATE(S_STATE_AUTOMATIC), "auto");
|
||||||
return true;
|
} else {
|
||||||
return false;
|
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)
|
const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
nvenc::migrate(settings, version, codec, 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<int64_t, std::string> 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)
|
bool nvenc_h264_handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes)
|
||||||
|
|
|
@ -53,9 +53,9 @@ void nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec
|
||||||
{
|
{
|
||||||
nvenc::get_defaults(settings, codec, context);
|
nvenc::get_defaults(settings, codec, context);
|
||||||
|
|
||||||
obs_data_set_default_int(settings, ST_KEY_PROFILE, static_cast<int64_t>(profile::MAIN));
|
obs_data_set_default_string(settings, ST_KEY_PROFILE, "");
|
||||||
obs_data_set_default_int(settings, ST_KEY_TIER, static_cast<int64_t>(profile::MAIN));
|
obs_data_set_default_string(settings, ST_KEY_TIER, "");
|
||||||
obs_data_set_default_int(settings, ST_KEY_LEVEL, static_cast<int64_t>(level::UNKNOWN));
|
obs_data_set_default_string(settings, ST_KEY_LEVEL, "auto");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nvenc_hevc_handler::has_keyframe_support(ffmpeg_factory*)
|
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);
|
nvenc::update(settings, codec, context);
|
||||||
|
|
||||||
if (!context->internal) {
|
if (!context->internal) {
|
||||||
if (auto v = obs_data_get_int(settings, ST_KEY_PROFILE); v > -1) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_PROFILE); v && (strlen(v) > 0)) {
|
||||||
av_opt_set_int(context->priv_data, "profile", v, AV_OPT_SEARCH_CHILDREN);
|
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) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_TIER); v && (strlen(v) > 0)) {
|
||||||
av_opt_set_int(context->priv_data, "tier", v, AV_OPT_SEARCH_CHILDREN);
|
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) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_LEVEL); v && (strlen(v) > 0)) {
|
||||||
av_opt_set_int(context->priv_data, "level", v, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set(context->priv_data, "level", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
} else {
|
|
||||||
av_opt_set(context->priv_data, "level", "auto", AV_OPT_SEARCH_CHILDREN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,25 +141,35 @@ 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),
|
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);
|
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,
|
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);
|
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,
|
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_COMBO_FORMAT_STRING);
|
||||||
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,
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "level", [&p](const AVOption* opt) {
|
||||||
[](const AVOption* opt) {
|
if (opt->default_val.i64 == 0) {
|
||||||
if (opt->default_val.i64 == 0)
|
obs_property_list_add_string(p, D_TRANSLATE(S_STATE_AUTOMATIC), "auto");
|
||||||
return true;
|
} else {
|
||||||
return false;
|
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)
|
const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
nvenc::migrate(settings, version, codec, 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<int64_t, std::string> 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<int64_t, std::string> 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)
|
bool nvenc_hevc_handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes)
|
||||||
|
|
|
@ -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*)
|
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_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_LOOKAHEAD, -1);
|
||||||
obs_data_set_default_int(settings, ST_KEY_RATECONTROL_ADAPTIVEI, -1);
|
obs_data_set_default_int(settings, ST_KEY_RATECONTROL_ADAPTIVEI, -1);
|
||||||
obs_data_set_default_int(settings, ST_KEY_RATECONTROL_ADAPTIVEB, -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
|
static bool modified_ratecontrol(obs_properties_t* props, obs_property_t*, obs_data_t* settings) noexcept
|
||||||
{
|
{
|
||||||
// Decode the name into useful flags.
|
// 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 = false;
|
||||||
bool have_bitrate_range = false;
|
bool have_bitrate_range = false;
|
||||||
bool have_quality = false;
|
bool have_quality = false;
|
||||||
bool have_qp_limits = false;
|
bool have_qp_limits = false;
|
||||||
bool have_qp = false;
|
bool have_qp = false;
|
||||||
if (value == 2) {
|
if (value == std::string_view("cbr")) {
|
||||||
have_bitrate = true;
|
have_bitrate = true;
|
||||||
} else if (value == 1) {
|
} else if (value == std::string_view("vbr")) {
|
||||||
have_bitrate = true;
|
have_bitrate = true;
|
||||||
have_bitrate_range = true;
|
have_bitrate_range = true;
|
||||||
have_quality = true;
|
have_quality = true;
|
||||||
have_qp_limits = true;
|
have_qp_limits = true;
|
||||||
have_qp = true;
|
have_qp = true;
|
||||||
} else if (value == 0) {
|
} else if (value == std::string_view("constqp")) {
|
||||||
have_qp = true;
|
have_qp = true;
|
||||||
} else {
|
} else {
|
||||||
have_bitrate = true;
|
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,
|
auto p = obs_properties_add_list(props, ST_KEY_PRESET, D_TRANSLATE(ST_I18N_PRESET), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_STRING);
|
||||||
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "preset", p, ST_I18N_PRESET);
|
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")) {
|
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,
|
auto p = obs_properties_add_list(props, ST_KEY_TUNE, D_TRANSLATE(ST_I18N_TUNE), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_STRING);
|
||||||
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "tune", p, ST_I18N_TUNE);
|
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),
|
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);
|
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))
|
if (opt->default_val.i64 & (1 << 23))
|
||||||
return true;
|
return;
|
||||||
return false;
|
|
||||||
};
|
char buffer[1024];
|
||||||
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "rc", p, ST_I18N_RATECONTROL_MODE,
|
snprintf(buffer, sizeof(buffer), "%s.%s\0", ST_I18N_RATECONTROL_MODE, opt->name);
|
||||||
filter);
|
obs_property_list_add_string(p, D_TRANSLATE(buffer), opt->name);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) {
|
if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) {
|
||||||
auto p =
|
auto p =
|
||||||
obs_properties_add_list(grp, ST_KEY_RATECONTROL_MULTIPASS, D_TRANSLATE(ST_I18N_RATECONTROL_MULTIPASS),
|
obs_properties_add_list(grp, ST_KEY_RATECONTROL_MULTIPASS, D_TRANSLATE(ST_I18N_RATECONTROL_MULTIPASS),
|
||||||
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);
|
obs_property_list_add_string(p, D_TRANSLATE(S_STATE_DEFAULT), "");
|
||||||
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "multipass", p,
|
streamfx::ffmpeg::tools::avoption_list_add_entries(
|
||||||
ST_I18N_RATECONTROL_MULTIPASS);
|
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 {
|
} else {
|
||||||
auto p = streamfx::util::obs_properties_add_tristate(grp, ST_KEY_RATECONTROL_TWOPASS,
|
auto p = streamfx::util::obs_properties_add_tristate(grp, ST_KEY_RATECONTROL_TWOPASS,
|
||||||
D_TRANSLATE(ST_I18N_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,
|
auto p = obs_properties_add_list(grp, ST_KEY_OTHER_BFRAMEREFERENCEMODE,
|
||||||
D_TRANSLATE(ST_I18N_OTHER_BFRAMEREFERENCEMODE), OBS_COMBO_TYPE_LIST,
|
D_TRANSLATE(ST_I18N_OTHER_BFRAMEREFERENCEMODE), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_STRING);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
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,
|
streamfx::ffmpeg::tools::avoption_list_add_entries(
|
||||||
ST_I18N_OTHER_BFRAMEREFERENCEMODE);
|
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)
|
void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
if (!context->internal) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_PRESET);
|
||||||
auto value = obs_data_get_int(settings, ST_KEY_PRESET);
|
!context->internal && (v != nullptr) && (strlen(v) > 0)) {
|
||||||
if (value != -1) {
|
av_opt_set(context->priv_data, "preset", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Rate Control
|
{ // Rate Control
|
||||||
auto value = obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE);
|
auto v = obs_data_get_string(settings, ST_KEY_RATECONTROL_MODE);
|
||||||
auto name = streamfx::ffmpeg::tools::avoption_name_from_unit_value(context->priv_data, "rc", value);
|
if (!context->internal && (v != nullptr) && (strlen(v) > 0)) {
|
||||||
if (value != -1) {
|
av_opt_set(context->priv_data, "rc", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the name into useful flags.
|
// 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_quality = false;
|
||||||
bool have_qp_limits = false;
|
bool have_qp_limits = false;
|
||||||
bool have_qp = false;
|
bool have_qp = false;
|
||||||
if (is_cbr(name)) {
|
if (v && is_cbr(v)) {
|
||||||
have_bitrate = true;
|
have_bitrate = true;
|
||||||
|
|
||||||
if (!context->internal)
|
if (!context->internal)
|
||||||
|
@ -529,7 +538,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
|
|
||||||
// Support for OBS Studio
|
// Support for OBS Studio
|
||||||
obs_data_set_string(settings, "rate_control", "CBR");
|
obs_data_set_string(settings, "rate_control", "CBR");
|
||||||
} else if (is_vbr(name)) {
|
} else if (v && is_vbr(v)) {
|
||||||
have_bitrate = true;
|
have_bitrate = true;
|
||||||
have_bitrate_range = true;
|
have_bitrate_range = true;
|
||||||
have_quality = true;
|
have_quality = true;
|
||||||
|
@ -541,7 +550,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
|
|
||||||
// Support for OBS Studio
|
// Support for OBS Studio
|
||||||
obs_data_set_string(settings, "rate_control", "VBR");
|
obs_data_set_string(settings, "rate_control", "VBR");
|
||||||
} else if (is_cqp(name)) {
|
} else if (v && is_cqp(v)) {
|
||||||
have_qp = true;
|
have_qp = true;
|
||||||
|
|
||||||
if (!context->internal)
|
if (!context->internal)
|
||||||
|
@ -563,8 +572,9 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
if (!context->internal) {
|
if (!context->internal) {
|
||||||
if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) {
|
if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) {
|
||||||
// Multi-Pass
|
// Multi-Pass
|
||||||
if (int tp = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_MULTIPASS)); tp > -1) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_RATECONTROL_MULTIPASS);
|
||||||
av_opt_set_int(context->priv_data, "multipass", tp, AV_OPT_SEARCH_CHILDREN);
|
(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);
|
av_opt_set_int(context->priv_data, "2pass", 0, AV_OPT_SEARCH_CHILDREN);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
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) {
|
if (auto v = obs_data_get_string(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE);
|
||||||
av_opt_set_int(context->priv_data, "b_ref_mode", v, AV_OPT_SEARCH_CHILDREN);
|
(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) {
|
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)) {
|
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<int64_t, std::string> 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 (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) {
|
switch (v) {
|
||||||
case 0: // CQP
|
case 0: // CQP
|
||||||
|
obs_data_set_string(settings, ST_KEY_RATECONTROL_MODE, "constqp");
|
||||||
break;
|
break;
|
||||||
case 2: // VBR_HQ
|
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_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
|
case 1: // VBR
|
||||||
|
obs_data_set_string(settings, ST_KEY_RATECONTROL_MODE, "vbr");
|
||||||
break;
|
break;
|
||||||
case 5: // CBR_LD_HQ
|
case 5: // CBR_LD_HQ
|
||||||
obs_data_set_int(settings, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE, 1);
|
obs_data_set_int(settings, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE, 1);
|
||||||
case 4: // CBR_HQ
|
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_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
|
case 3: // CBR
|
||||||
|
obs_data_set_string(settings, ST_KEY_RATECONTROL_MODE, "cbr");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Target Quality
|
||||||
if (auto v = obs_data_get_double(settings, ST_KEY_RATECONTROL_LIMITS_QUALITY); v > 0) {
|
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.);
|
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<int64_t, std::string> 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
|
#undef COPY_UNSET
|
||||||
|
|
Loading…
Reference in a new issue