encoders/ffmpeg/nvenc: Support reconfiguration during encoding

This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2021-12-03 07:20:31 +01:00
parent 19689d1a11
commit 567620a6ad
5 changed files with 115 additions and 81 deletions

View File

@ -107,13 +107,13 @@ 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) {
{ {
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE))); auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE)));
if (found != profiles.end()) { if (found != profiles.end()) {
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0); av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
} }
} }
{ {
auto found = levels.find(static_cast<level>(obs_data_get_int(settings, ST_KEY_LEVEL))); auto found = levels.find(static_cast<level>(obs_data_get_int(settings, ST_KEY_LEVEL)));
if (found != levels.end()) { if (found != levels.end()) {
@ -123,6 +123,7 @@ void nvenc_h264_handler::update(obs_data_t* settings, const AVCodec* codec, AVCo
} }
} }
} }
}
void nvenc_h264_handler::override_update(ffmpeg_instance* instance, obs_data_t* settings) void nvenc_h264_handler::override_update(ffmpeg_instance* instance, obs_data_t* settings)
{ {
@ -183,3 +184,11 @@ void streamfx::encoder::ffmpeg::handler::nvenc_h264_handler::migrate(obs_data_t*
{ {
nvenc::migrate(settings, version, codec, context); nvenc::migrate(settings, version, codec, context);
} }
bool nvenc_h264_handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes)
{
threads = false;
gpu = false;
keyframes = false;
return true;
}

View File

@ -54,6 +54,8 @@ namespace streamfx::encoder::ffmpeg::handler {
virtual bool has_pixel_format_support(ffmpeg_factory* instance); virtual bool has_pixel_format_support(ffmpeg_factory* instance);
virtual bool supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes);
public /*settings*/: public /*settings*/:
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
bool hw_encode); bool hw_encode);

View File

@ -108,6 +108,7 @@ 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) {
{ // HEVC Options { // HEVC Options
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE))); auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE)));
if (found != profiles.end()) { if (found != profiles.end()) {
@ -129,6 +130,7 @@ void nvenc_hevc_handler::update(obs_data_t* settings, const AVCodec* codec, AVCo
} }
} }
} }
}
void nvenc_hevc_handler::override_update(ffmpeg_instance* instance, obs_data_t* settings) void nvenc_hevc_handler::override_update(ffmpeg_instance* instance, obs_data_t* settings)
{ {
@ -200,3 +202,11 @@ void streamfx::encoder::ffmpeg::handler::nvenc_hevc_handler::migrate(obs_data_t*
{ {
nvenc::migrate(settings, version, codec, context); nvenc::migrate(settings, version, codec, context);
} }
bool nvenc_hevc_handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes)
{
threads = false;
gpu = false;
keyframes = false;
return true;
}

View File

@ -54,6 +54,8 @@ namespace streamfx::encoder::ffmpeg::handler {
virtual bool has_pixel_format_support(ffmpeg_factory* instance); virtual bool has_pixel_format_support(ffmpeg_factory* instance);
virtual bool supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes);
public /*settings*/: public /*settings*/:
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
bool hw_encode); bool hw_encode);

View File

@ -510,7 +510,7 @@ 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) {
preset c_preset = static_cast<preset>(obs_data_get_int(settings, ST_KEY_PRESET)); preset c_preset = static_cast<preset>(obs_data_get_int(settings, ST_KEY_PRESET));
auto found = preset_to_opt.find(c_preset); auto found = preset_to_opt.find(c_preset);
if (found != preset_to_opt.end()) { if (found != preset_to_opt.end()) {
@ -530,7 +530,9 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
ratecontrolmode rc = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE)); ratecontrolmode rc = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE));
auto rcopt = ratecontrolmode_to_opt.find(rc); auto rcopt = ratecontrolmode_to_opt.find(rc);
if (rcopt != ratecontrolmode_to_opt.end()) { if (rcopt != ratecontrolmode_to_opt.end()) {
if (!context->internal) {
av_opt_set(context->priv_data, "rc", rcopt->second.c_str(), AV_OPT_SEARCH_CHILDREN); av_opt_set(context->priv_data, "rc", rcopt->second.c_str(), AV_OPT_SEARCH_CHILDREN);
}
} else { } else {
have_bitrate = true; have_bitrate = true;
have_bitrate_range = true; have_bitrate_range = true;
@ -539,7 +541,9 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
have_qp = true; have_qp = true;
} }
if (!context->internal) {
av_opt_set_int(context->priv_data, "cbr", 0, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(context->priv_data, "cbr", 0, AV_OPT_SEARCH_CHILDREN);
}
switch (rc) { switch (rc) {
case ratecontrolmode::CQP: case ratecontrolmode::CQP:
have_qp = true; have_qp = true;
@ -550,7 +554,9 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
case ratecontrolmode::CBR_LD_HQ: case ratecontrolmode::CBR_LD_HQ:
have_bitrate = true; have_bitrate = true;
have_qp_limits = true; have_qp_limits = true;
if (!context->internal) {
av_opt_set_int(context->priv_data, "cbr", 1, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(context->priv_data, "cbr", 1, AV_OPT_SEARCH_CHILDREN);
}
break; break;
case ratecontrolmode::VBR: case ratecontrolmode::VBR:
case ratecontrolmode::VBR_HQ: case ratecontrolmode::VBR_HQ:
@ -562,6 +568,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
break; break;
} }
if (!context->internal) {
// Two Pass // Two Pass
if (int tp = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_TWOPASS)); tp > -1) { if (int tp = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_TWOPASS)); tp > -1) {
av_opt_set_int(context->priv_data, "2pass", tp ? 1 : 0, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(context->priv_data, "2pass", tp ? 1 : 0, AV_OPT_SEARCH_CHILDREN);
@ -588,6 +595,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
av_opt_set_int(context->priv_data, "b_adapt", adapt_b, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(context->priv_data, "b_adapt", adapt_b, AV_OPT_SEARCH_CHILDREN);
} }
} }
}
if (have_bitrate) { if (have_bitrate) {
int64_t v = obs_data_get_int(settings, ST_KEY_RATECONTROL_LIMITS_BITRATE_TARGET); int64_t v = obs_data_get_int(settings, ST_KEY_RATECONTROL_LIMITS_BITRATE_TARGET);
@ -616,6 +624,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
context->rc_buffer_size = 0; context->rc_buffer_size = 0;
} }
if (!context->internal) {
// Quality Limits // Quality Limits
if (have_qp_limits) { if (have_qp_limits) {
if (int qmin = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_MINIMUM)); qmin > -1) if (int qmin = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_MINIMUM)); qmin > -1)
@ -629,7 +638,8 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
// Quality Target // Quality Target
if (have_quality) { if (have_quality) {
if (double_t v = obs_data_get_double(settings, ST_KEY_RATECONTROL_LIMITS_QUALITY) / 100.0 * 51.0; v > 0) { if (double_t v = obs_data_get_double(settings, ST_KEY_RATECONTROL_LIMITS_QUALITY) / 100.0 * 51.0;
v > 0) {
av_opt_set_double(context->priv_data, "cq", v, AV_OPT_SEARCH_CHILDREN); av_opt_set_double(context->priv_data, "cq", v, AV_OPT_SEARCH_CHILDREN);
} }
} else { } else {
@ -646,8 +656,9 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
av_opt_set_int(context->priv_data, "init_qpB", static_cast<int>(qp), AV_OPT_SEARCH_CHILDREN); av_opt_set_int(context->priv_data, "init_qpB", static_cast<int>(qp), AV_OPT_SEARCH_CHILDREN);
} }
} }
}
{ // AQ if (!context->internal) { // AQ
int64_t saq = obs_data_get_int(settings, ST_KEY_AQ_SPATIAL); int64_t saq = obs_data_get_int(settings, ST_KEY_AQ_SPATIAL);
int64_t taq = obs_data_get_int(settings, ST_KEY_AQ_TEMPORAL); int64_t taq = obs_data_get_int(settings, ST_KEY_AQ_TEMPORAL);
@ -667,7 +678,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
av_opt_set_int(context->priv_data, "aq-strength", static_cast<int>(aqs), AV_OPT_SEARCH_CHILDREN); av_opt_set_int(context->priv_data, "aq-strength", static_cast<int>(aqs), AV_OPT_SEARCH_CHILDREN);
} }
{ // Other if (!context->internal) { // Other
if (int64_t bf = obs_data_get_int(settings, ST_KEY_OTHER_BFRAMES); bf > -1) if (int64_t bf = obs_data_get_int(settings, ST_KEY_OTHER_BFRAMES); bf > -1)
context->max_b_frames = static_cast<int>(bf); context->max_b_frames = static_cast<int>(bf);