From 2c2d42ebaf6bd8187bcaa9aed331c5979159659d Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Wed, 24 Jul 2019 20:48:51 +0200 Subject: [PATCH] encoder: Support Key-Frame options in all encoders --- source/encoder.cpp | 71 ++++++++++++++++++++++++++++++++++++++ source/ui/nvenc_shared.cpp | 66 ----------------------------------- 2 files changed, 71 insertions(+), 66 deletions(-) diff --git a/source/encoder.cpp b/source/encoder.cpp index a9f052e..aecb2d4 100644 --- a/source/encoder.cpp +++ b/source/encoder.cpp @@ -27,6 +27,7 @@ #include "ffmpeg/tools.hpp" #include "plugin.hpp" #include "utility.hpp" +#include "strings.hpp" extern "C" { #include @@ -298,6 +299,12 @@ const char* obsffmpeg::encoder_factory::get_name() void obsffmpeg::encoder_factory::get_defaults(obs_data_t* settings) { + if (!this->avcodec_ptr->capabilities & AV_CODEC_CAP_INTRA_ONLY) { + obs_data_set_default_int(settings, G_KEYFRAMES_INTERVALTYPE, 0); + obs_data_set_default_double(settings, G_KEYFRAMES_INTERVAL_SECONDS, 2.0); + obs_data_set_default_int(settings, G_KEYFRAMES_INTERVAL_FRAMES, 300); + } + { // Handler auto ptr = obsffmpeg::find_codec_handler(this->avcodec_ptr->name); if (ptr) { @@ -314,6 +321,14 @@ void obsffmpeg::encoder_factory::get_defaults(obs_data_t* settings) } } +static bool modified_keyframes(obs_properties_t* props, obs_property_t*, obs_data_t* settings) +{ + bool is_seconds = obs_data_get_int(settings, G_KEYFRAMES_INTERVALTYPE) == 0; + obs_property_set_visible(obs_properties_get(props, G_KEYFRAMES_INTERVAL_FRAMES), !is_seconds); + obs_property_set_visible(obs_properties_get(props, G_KEYFRAMES_INTERVAL_SECONDS), is_seconds); + return true; +} + void obsffmpeg::encoder_factory::get_properties(obs_properties_t* props) { { // Handler @@ -323,6 +338,39 @@ void obsffmpeg::encoder_factory::get_properties(obs_properties_t* props) } } + if ((this->avcodec_ptr->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0) { + // Key-Frame Options + obs_properties_t* grp = props; + if (!obsffmpeg::are_property_groups_broken()) { + grp = obs_properties_create(); + obs_properties_add_group(props, G_KEYFRAMES, TRANSLATE(G_KEYFRAMES), OBS_GROUP_NORMAL, grp); + } + + { + auto p = + obs_properties_add_list(grp, G_KEYFRAMES_INTERVALTYPE, TRANSLATE(G_KEYFRAMES_INTERVALTYPE), + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_property_set_long_description(p, TRANSLATE(DESC(G_KEYFRAMES_INTERVALTYPE))); + obs_property_set_modified_callback(p, modified_keyframes); + obs_property_list_add_int(p, TRANSLATE(G_KEYFRAMES_INTERVALTYPE_(Seconds)), 0); + obs_property_list_add_int(p, TRANSLATE(G_KEYFRAMES_INTERVALTYPE_(Frames)), 1); + } + { + auto p = + obs_properties_add_float(grp, G_KEYFRAMES_INTERVAL_SECONDS, TRANSLATE(G_KEYFRAMES_INTERVAL), + 0.00, std::numeric_limits::max(), 0.01); + obs_property_set_long_description(p, TRANSLATE(DESC(G_KEYFRAMES_INTERVAL))); + obs_property_float_set_suffix(p, " seconds"); + } + { + auto p = + obs_properties_add_int(grp, G_KEYFRAMES_INTERVAL_FRAMES, TRANSLATE(G_KEYFRAMES_INTERVAL), 0, + std::numeric_limits::max(), 1); + obs_property_set_long_description(p, TRANSLATE(DESC(G_KEYFRAMES_INTERVAL))); + obs_property_int_set_suffix(p, " frames"); + } + } + { obs_properties_t* grp = props; if (!obsffmpeg::are_property_groups_broken()) { @@ -575,6 +623,11 @@ void obsffmpeg::encoder::get_properties(obs_properties_t* props) } } + obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES), false); + obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES_INTERVALTYPE), false); + obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES_INTERVAL_SECONDS), false); + obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES_INTERVAL_FRAMES), false); + obs_property_set_enabled(obs_properties_get(props, P_FFMPEG_COLORFORMAT), false); obs_property_set_enabled(obs_properties_get(props, P_FFMPEG_THREADS), false); obs_property_set_enabled(obs_properties_get(props, P_FFMPEG_STANDARDCOMPLIANCE), false); @@ -589,6 +642,24 @@ bool obsffmpeg::encoder::update(obs_data_t* settings) } } + { // Key Frames + obs_video_info ovi; + if (!obs_get_video_info(&ovi)) { + throw std::runtime_error("no video info"); + } + + int64_t kf_type = obs_data_get_int(settings, G_KEYFRAMES_INTERVALTYPE); + bool is_seconds = (kf_type == 0); + + if (is_seconds) { + context->gop_size = static_cast(obs_data_get_double(settings, G_KEYFRAMES_INTERVAL_SECONDS) + * (ovi.fps_num / ovi.fps_den)); + } else { + context->gop_size = static_cast(obs_data_get_int(settings, G_KEYFRAMES_INTERVAL_FRAMES)); + } + context->keyint_min = context->gop_size; + } + { // FFmpeg // Apply custom options. av_opt_set_from_string(this->context->priv_data, obs_data_get_string(settings, P_FFMPEG_CUSTOMSETTINGS), diff --git a/source/ui/nvenc_shared.cpp b/source/ui/nvenc_shared.cpp index f5de676..507400e 100644 --- a/source/ui/nvenc_shared.cpp +++ b/source/ui/nvenc_shared.cpp @@ -154,10 +154,6 @@ void obsffmpeg::nvenc::get_defaults(obs_data_t* settings, AVCodec*, AVCodecConte obs_data_set_default_int(settings, P_RATECONTROL_QP_B, 21); obs_data_set_default_int(settings, P_RATECONTROL_QP_B_INITIAL, -1); - obs_data_set_default_int(settings, G_KEYFRAMES_INTERVALTYPE, 0); - obs_data_set_default_double(settings, G_KEYFRAMES_INTERVAL_SECONDS, 2.0); - obs_data_set_default_int(settings, G_KEYFRAMES_INTERVAL_FRAMES, 300); - obs_data_set_default_bool(settings, P_AQ_SPATIAL, true); obs_data_set_default_int(settings, P_AQ_STRENGTH, 8); obs_data_set_default_bool(settings, P_AQ_TEMPORAL, true); @@ -225,14 +221,6 @@ static bool modified_quality(obs_properties_t* props, obs_property_t*, obs_data_ return true; } -static bool modified_keyframes(obs_properties_t* props, obs_property_t*, obs_data_t* settings) -{ - bool is_seconds = obs_data_get_int(settings, G_KEYFRAMES_INTERVALTYPE) == 0; - obs_property_set_visible(obs_properties_get(props, G_KEYFRAMES_INTERVAL_FRAMES), !is_seconds); - obs_property_set_visible(obs_properties_get(props, G_KEYFRAMES_INTERVAL_SECONDS), is_seconds); - return true; -} - static bool modified_aq(obs_properties_t* props, obs_property_t*, obs_data_t* settings) { bool spatial_aq = obs_data_get_bool(settings, P_AQ_SPATIAL); @@ -395,38 +383,6 @@ void obsffmpeg::nvenc::get_properties_post(obs_properties_t* props, AVCodec* cod } } - { - obs_properties_t* grp = props; - if (!obsffmpeg::are_property_groups_broken()) { - grp = obs_properties_create(); - obs_properties_add_group(props, G_KEYFRAMES, TRANSLATE(G_KEYFRAMES), OBS_GROUP_NORMAL, grp); - } - - { - auto p = - obs_properties_add_list(grp, G_KEYFRAMES_INTERVALTYPE, TRANSLATE(G_KEYFRAMES_INTERVALTYPE), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_set_long_description(p, TRANSLATE(DESC(G_KEYFRAMES_INTERVALTYPE))); - obs_property_set_modified_callback(p, modified_keyframes); - obs_property_list_add_int(p, TRANSLATE(G_KEYFRAMES_INTERVALTYPE_(Seconds)), 0); - obs_property_list_add_int(p, TRANSLATE(G_KEYFRAMES_INTERVALTYPE_(Frames)), 1); - } - { - auto p = - obs_properties_add_float(grp, G_KEYFRAMES_INTERVAL_SECONDS, TRANSLATE(G_KEYFRAMES_INTERVAL), - 0.00, std::numeric_limits::max(), 0.01); - obs_property_set_long_description(p, TRANSLATE(DESC(G_KEYFRAMES_INTERVAL))); - obs_property_float_set_suffix(p, " seconds"); - } - { - auto p = - obs_properties_add_int(grp, G_KEYFRAMES_INTERVAL_FRAMES, TRANSLATE(G_KEYFRAMES_INTERVAL), 0, - std::numeric_limits::max(), 1); - obs_property_set_long_description(p, TRANSLATE(DESC(G_KEYFRAMES_INTERVAL))); - obs_property_int_set_suffix(p, " frames"); - } - } - { obs_properties_t* grp = props; if (!obsffmpeg::are_property_groups_broken()) { @@ -516,10 +472,6 @@ void obsffmpeg::nvenc::get_runtime_properties(obs_properties_t* props, AVCodec*, obs_property_set_enabled(obs_properties_get(props, P_RATECONTROL_QP_P_INITIAL), false); obs_property_set_enabled(obs_properties_get(props, P_RATECONTROL_QP_B), false); obs_property_set_enabled(obs_properties_get(props, P_RATECONTROL_QP_B_INITIAL), false); - obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES), false); - obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES_INTERVALTYPE), false); - obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES_INTERVAL_SECONDS), false); - obs_property_set_enabled(obs_properties_get(props, G_KEYFRAMES_INTERVAL_FRAMES), false); obs_property_set_enabled(obs_properties_get(props, P_AQ), false); obs_property_set_enabled(obs_properties_get(props, P_AQ_SPATIAL), false); obs_property_set_enabled(obs_properties_get(props, P_AQ_STRENGTH), false); @@ -632,24 +584,6 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, AVCodec* codec, AVCodecConte } } - { // Key Frames - obs_video_info ovi; - if (!obs_get_video_info(&ovi)) { - throw std::runtime_error("no video info"); - } - - int64_t kf_type = obs_data_get_int(settings, G_KEYFRAMES_INTERVALTYPE); - bool is_seconds = (kf_type == 0); - - if (is_seconds) { - context->gop_size = static_cast(obs_data_get_double(settings, G_KEYFRAMES_INTERVAL_SECONDS) - * (ovi.fps_num / ovi.fps_den)); - } else { - context->gop_size = static_cast(obs_data_get_int(settings, G_KEYFRAMES_INTERVAL_FRAMES)); - } - context->keyint_min = context->gop_size; - } - { // AQ bool saq = obs_data_get_bool(settings, P_AQ_SPATIAL); bool taq = obs_data_get_bool(settings, P_AQ_TEMPORAL);