mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-11 06:15:05 +00:00
encoders/ffmpeg/nvenc: Support reconfiguration during encoding
This commit is contained in:
parent
19689d1a11
commit
567620a6ad
5 changed files with 115 additions and 81 deletions
|
@ -107,19 +107,20 @@ 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)));
|
{
|
||||||
if (found != profiles.end()) {
|
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE)));
|
||||||
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
|
if (found != profiles.end()) {
|
||||||
|
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)));
|
||||||
{
|
if (found != levels.end()) {
|
||||||
auto found = levels.find(static_cast<level>(obs_data_get_int(settings, ST_KEY_LEVEL)));
|
av_opt_set(context->priv_data, "level", found->second.c_str(), 0);
|
||||||
if (found != levels.end()) {
|
} else {
|
||||||
av_opt_set(context->priv_data, "level", found->second.c_str(), 0);
|
av_opt_set(context->priv_data, "level", "auto", 0);
|
||||||
} else {
|
}
|
||||||
av_opt_set(context->priv_data, "level", "auto", 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -108,24 +108,26 @@ void nvenc_hevc_handler::update(obs_data_t* settings, const AVCodec* codec, AVCo
|
||||||
{
|
{
|
||||||
nvenc::update(settings, codec, context);
|
nvenc::update(settings, codec, context);
|
||||||
|
|
||||||
{ // HEVC Options
|
if (!context->internal) {
|
||||||
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE)));
|
{ // HEVC Options
|
||||||
if (found != profiles.end()) {
|
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE)));
|
||||||
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
|
if (found != profiles.end()) {
|
||||||
|
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
{
|
||||||
{
|
auto found = tiers.find(static_cast<tier>(obs_data_get_int(settings, ST_KEY_TIER)));
|
||||||
auto found = tiers.find(static_cast<tier>(obs_data_get_int(settings, ST_KEY_TIER)));
|
if (found != tiers.end()) {
|
||||||
if (found != tiers.end()) {
|
av_opt_set(context->priv_data, "tier", found->second.c_str(), 0);
|
||||||
av_opt_set(context->priv_data, "tier", 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()) {
|
av_opt_set(context->priv_data, "level", found->second.c_str(), 0);
|
||||||
av_opt_set(context->priv_data, "level", found->second.c_str(), 0);
|
} else {
|
||||||
} else {
|
av_opt_set(context->priv_data, "level", "auto", 0);
|
||||||
av_opt_set(context->priv_data, "level", "auto", 0);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()) {
|
||||||
av_opt_set(context->priv_data, "rc", rcopt->second.c_str(), AV_OPT_SEARCH_CHILDREN);
|
if (!context->internal) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_opt_set_int(context->priv_data, "cbr", 0, AV_OPT_SEARCH_CHILDREN);
|
if (!context->internal) {
|
||||||
|
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;
|
||||||
av_opt_set_int(context->priv_data, "cbr", 1, AV_OPT_SEARCH_CHILDREN);
|
if (!context->internal) {
|
||||||
|
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,30 +568,32 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two Pass
|
if (!context->internal) {
|
||||||
if (int tp = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_TWOPASS)); tp > -1) {
|
// Two Pass
|
||||||
av_opt_set_int(context->priv_data, "2pass", tp ? 1 : 0, AV_OPT_SEARCH_CHILDREN);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
// Look Ahead # of Frames
|
// Look Ahead # of Frames
|
||||||
int la = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_LOOKAHEAD));
|
int la = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_LOOKAHEAD));
|
||||||
if (!streamfx::util::is_tristate_default(la)) {
|
if (!streamfx::util::is_tristate_default(la)) {
|
||||||
av_opt_set_int(context->priv_data, "rc-lookahead", la, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_int(context->priv_data, "rc-lookahead", la, AV_OPT_SEARCH_CHILDREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adaptive I-Frames
|
// Adaptive I-Frames
|
||||||
if (int64_t adapt_i = obs_data_get_int(settings, ST_KEY_RATECONTROL_ADAPTIVEI);
|
if (int64_t adapt_i = obs_data_get_int(settings, ST_KEY_RATECONTROL_ADAPTIVEI);
|
||||||
!streamfx::util::is_tristate_default(adapt_i) && (la != 0)) {
|
!streamfx::util::is_tristate_default(adapt_i) && (la != 0)) {
|
||||||
// no-scenecut is inverted compared to our UI.
|
// no-scenecut is inverted compared to our UI.
|
||||||
av_opt_set_int(context->priv_data, "no-scenecut", 1 - adapt_i, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_int(context->priv_data, "no-scenecut", 1 - adapt_i, AV_OPT_SEARCH_CHILDREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adaptive B-Frames
|
// Adaptive B-Frames
|
||||||
constexpr std::string_view h264_encoder_name = "h264_nvenc";
|
constexpr std::string_view h264_encoder_name = "h264_nvenc";
|
||||||
if (h264_encoder_name == codec->name) {
|
if (h264_encoder_name == codec->name) {
|
||||||
if (int64_t adapt_b = obs_data_get_int(settings, ST_KEY_RATECONTROL_ADAPTIVEB);
|
if (int64_t adapt_b = obs_data_get_int(settings, ST_KEY_RATECONTROL_ADAPTIVEB);
|
||||||
!streamfx::util::is_tristate_default(adapt_b) && (la != 0)) {
|
!streamfx::util::is_tristate_default(adapt_b) && (la != 0)) {
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,38 +624,41 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
context->rc_buffer_size = 0;
|
context->rc_buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quality Limits
|
if (!context->internal) {
|
||||||
if (have_qp_limits) {
|
// Quality Limits
|
||||||
if (int qmin = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_MINIMUM)); qmin > -1)
|
if (have_qp_limits) {
|
||||||
context->qmin = qmin;
|
if (int qmin = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_MINIMUM)); qmin > -1)
|
||||||
if (int qmax = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_MAXIMUM)); qmax > -1)
|
context->qmin = qmin;
|
||||||
context->qmax = qmax;
|
if (int qmax = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_MAXIMUM)); qmax > -1)
|
||||||
} else {
|
context->qmax = qmax;
|
||||||
context->qmin = -1;
|
} else {
|
||||||
context->qmax = -1;
|
context->qmin = -1;
|
||||||
}
|
context->qmax = -1;
|
||||||
|
|
||||||
// Quality Target
|
|
||||||
if (have_quality) {
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
av_opt_set_double(context->priv_data, "cq", 0, AV_OPT_SEARCH_CHILDREN);
|
|
||||||
}
|
|
||||||
|
|
||||||
// QP Settings
|
// Quality Target
|
||||||
if (have_qp) {
|
if (have_quality) {
|
||||||
if (int64_t qp = obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_I); qp > -1)
|
if (double_t v = obs_data_get_double(settings, ST_KEY_RATECONTROL_LIMITS_QUALITY) / 100.0 * 51.0;
|
||||||
av_opt_set_int(context->priv_data, "init_qpI", static_cast<int>(qp), AV_OPT_SEARCH_CHILDREN);
|
v > 0) {
|
||||||
if (int64_t qp = obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_P); qp > -1)
|
av_opt_set_double(context->priv_data, "cq", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
av_opt_set_int(context->priv_data, "init_qpP", static_cast<int>(qp), AV_OPT_SEARCH_CHILDREN);
|
}
|
||||||
if (int64_t qp = obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_B); qp > -1)
|
} else {
|
||||||
av_opt_set_int(context->priv_data, "init_qpB", static_cast<int>(qp), AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_double(context->priv_data, "cq", 0, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// QP Settings
|
||||||
|
if (have_qp) {
|
||||||
|
if (int64_t qp = obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_I); qp > -1)
|
||||||
|
av_opt_set_int(context->priv_data, "init_qpI", static_cast<int>(qp), AV_OPT_SEARCH_CHILDREN);
|
||||||
|
if (int64_t qp = obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_P); qp > -1)
|
||||||
|
av_opt_set_int(context->priv_data, "init_qpP", static_cast<int>(qp), AV_OPT_SEARCH_CHILDREN);
|
||||||
|
if (int64_t qp = obs_data_get_int(settings, ST_KEY_RATECONTROL_QP_B); qp > -1)
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue