ui/nvenc: Improve and fix some options and logging

Some of the options shown to the user were never actually being applied, which resulted in encoding that looked worse than it could have. With this these options are now applied and users may experience a sudden increase or decrease in quality if they had these options changed.

In addition to that, some options now use a triple state field, which allows them to also have a default/middle state instead of being On or Off.

Furthermore, log output is now read from the actual AVCodecContext, which contains the actual values used in the encoding, instead of relying on the OBS settings to be the actual values.
This commit is contained in:
Michael Fabian 'Xaymar' Dirks
2019-11-16 21:44:03 +01:00
parent 2a75d5fabd
commit e4474c29c4
5 changed files with 174 additions and 229 deletions
+8 -8
View File
@@ -117,11 +117,11 @@ NVENC.RateControl.Mode.CBR_LD_HQ="Low Delay High Quality Constant Bitrate"
NVENC.RateControl.Mode.CBR_LD_HQ.Description="Constant Bitrate optimized for lowest encoding latency."
NVENC.RateControl.LookAhead="Look Ahead"
NVENC.RateControl.LookAhead.Description="Look ahead this many frames while encoding to better distribute bitrate.\nImproves quality slightly at the cost of some GPU time.\nSet to 0 to disable."
NVENC.RateControl.AdaptiveI="Enable adaptive I-Frame insertion"
NVENC.RateControl.AdaptiveI="Adaptive I-Frames"
NVENC.RateControl.AdaptiveI.Description="Enables adaptive I-Frame insertion.\nOnly has an effect when look ahead is set to a value other than 0."
NVENC.RateControl.AdaptiveB="Enable adaptive B-Frame insertion"
NVENC.RateControl.AdaptiveB="Adaptive B-Frames"
NVENC.RateControl.AdaptiveB.Description="Enables adaptive B-Frame insertion.\nOnly has an effect when look ahead is set to a value other than 0."
NVENC.RateControl.TwoPass="Enable Two Pass"
NVENC.RateControl.TwoPass="Two Pass"
NVENC.RateControl.TwoPass.Description="Enable a secondary pass for encoding, which can help with quality and bitrate stability.\nImproves quality slightly at the cost of some GPU time.\nNvidia Turing hardware might actually see a quality degrade from this."
NVENC.RateControl.Bitrate="Bitrate Limits"
NVENC.RateControl.Bitrate.Target="Target Bitrate"
@@ -147,11 +147,11 @@ NVENC.RateControl.QP.B.Description="Quantization parameter for B-Frames.\nSmalle
NVENC.RateControl.QP.B.Initial="Initial B-Frame QP"
NVENC.RateControl.QP.B.Initial.Description="Initial B-Frame quantization parameter.\nSet to -1 to use the automatically detected value instead."
NVENC.AQ="Adaptive Quantization"
NVENC.AQ.Spatial="Enable Spatial Adaptive Quantization"
NVENC.AQ.Spatial="Spatial Adaptive Quantization"
NVENC.AQ.Spatial.Description="Enable spatial adaptive quantization, also sometimes referred to as Psychovisual Adaptive Quantization."
NVENC.AQ.Strength="Spatial AQ Strength"
NVENC.AQ.Strength.Description="Strength of the spatial adaptive quantization.\nValues closer to 15 mean more aggressive, while values closer to 1 mean more relaxed."
NVENC.AQ.Temporal="Enable Temporal Adaptive Quantization"
NVENC.AQ.Temporal="Temporal Adaptive Quantization"
NVENC.AQ.Temporal.Description="Enable temporal adaptive quantization."
NVENC.Other="Other Options"
NVENC.Other.BFrames="Maximum B-Frames"
@@ -159,9 +159,9 @@ NVENC.Other.BFrames.Description="Maximum number of B-Frames to insert into the e
NVENC.Other.BFrameReferenceMode="B-Frame Reference Mode"
NVENC.Other.BFrameReferenceMode.Each="Each B-Frame will be used for references"
NVENC.Other.BFrameReferenceMode.Middle="Only (# of B-Frames)/2 will be used for references"
NVENC.Other.ZeroLatency="Enable Zero Latency"
NVENC.Other.ZeroLatency="Zero Latency"
NVENC.Other.ZeroLatency.Description="Enable zero latency operation, which ensures that there is no reordering delay."
NVENC.Other.WeightedPrediction="Enable Weighted Prediction"
NVENC.Other.WeightedPrediction="Weighted Prediction"
NVENC.Other.WeightedPrediction.Description="Enable weighted prediction for encoding.\nCan't be used with B-Frames."
NVENC.Other.NonReferencePFrames="Enable non-reference P-Frames"
NVENC.Other.NonReferencePFrames="Non-reference P-Frames"
NVENC.Other.NonReferencePFrames.Description="Enable the automatic insertion of non-reference P-Frames."
+16 -33
View File
@@ -22,6 +22,7 @@
#include "nvenc_h264_handler.hpp"
#include "codecs/h264.hpp"
#include "encoder.hpp"
#include "ffmpeg/tools.hpp"
#include "nvenc_shared.hpp"
#include "plugin.hpp"
#include "strings.hpp"
@@ -35,30 +36,7 @@ extern "C" {
#pragma warning(pop)
}
/* Missing Options:
Seem to be covered by initQP_* instead.
- [obs-ffmpeg-encoder] Option 'cq' with help 'Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control' of type 'Float' with default value '0.000000', minimum '0.000000' and maximum '51.000000'.
- [obs-ffmpeg-encoder] Option 'qp' with help 'Constant quantization parameter rate control method' of type 'Int' with default value '-1', minimum '-1.000000' and maximum '51.000000'.
Not sure what there are useful for.
[obs-ffmpeg-encoder] Option 'aud' with help 'Use access unit delimiters' of type 'Bool' with default value 'false', minimum '0.000000' and maximum '1.000000'.
[obs-ffmpeg-encoder] Option 'surfaces' with help 'Number of concurrent surfaces' of type 'Int' with default value '0', minimum '0.000000' and maximum '64.000000'.
[obs-ffmpeg-encoder] Option 'delay' with help 'Delay frame output by the given amount of frames' of type 'Int' with default value '2147483647', minimum '0.000000' and maximum '2147483647.000000'.
Should probably add this.
[obs-ffmpeg-encoder] Option 'gpu' with unit (gpu) with help 'Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.' of type 'Int' with default value '-1', minimum '-2.000000' and maximum '2147483647.000000'.
[obs-ffmpeg-encoder] [gpu] Constant 'any' and help text 'Pick the first device available' with value '-1'.
[obs-ffmpeg-encoder] [gpu] Constant 'list' and help text 'List the available devices' with value '-2'.
Useless except for strict_gop maybe?
[obs-ffmpeg-encoder] Option 'forced-idr' with help 'If forcing keyframes, force them as IDR frames.' of type 'Bool' with default value 'false', minimum '-1.000000' and maximum '1.000000'.
[obs-ffmpeg-encoder] Option 'strict_gop' with help 'Set 1 to minimize GOP-to-GOP rate fluctuations' of type 'Bool' with default value 'false', minimum '0.000000' and maximum '1.000000'.
[obs-ffmpeg-encoder] Option 'bluray-compat' with help 'Bluray compatibility workarounds' of type 'Bool' with default value 'false', minimum '0.000000' and maximum '1.000000'.
*/
using namespace obsffmpeg::codecs::h264;
using namespace obsffmpeg::nvenc;
std::map<profile, std::string> profiles{
{profile::BASELINE, "baseline"},
@@ -143,16 +121,21 @@ void obsffmpeg::ui::nvenc_h264_handler::log_options(obs_data_t* settings, const
{
nvenc::log_options(settings, codec, context);
profile cfg_profile = static_cast<profile>(obs_data_get_int(settings, P_H264_PROFILE));
level cfg_level = static_cast<level>(obs_data_get_int(settings, P_H264_LEVEL));
auto found1 = profiles.find(cfg_profile);
if (found1 != profiles.end())
PLOG_INFO("[%s] H.264 Profile: %s", codec->name, found1->second.c_str());
auto found2 = levels.find(cfg_level);
if (found2 != levels.end())
PLOG_INFO("[%s] H.264 Level: %s", codec->name, found2->second.c_str());
PLOG_INFO("[%s] H.265/HEVC:", codec->name);
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
profile val = static_cast<profile>(v);
auto index = profiles.find(val);
if (index != profiles.end())
return index->second;
return std::string("<Unknown>");
});
ffmpeg::tools::print_av_option_string(context, "level", " Level", [](int64_t v) {
level val = static_cast<level>(v);
auto index = levels.find(val);
if (index != levels.end())
return index->second;
return std::string("<Unknown>");
});
}
void obsffmpeg::ui::nvenc_h264_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
+23 -37
View File
@@ -22,6 +22,7 @@
#include "nvenc_hevc_handler.hpp"
#include "codecs/hevc.hpp"
#include "encoder.hpp"
#include "ffmpeg/tools.hpp"
#include "nvenc_shared.hpp"
#include "plugin.hpp"
#include "strings.hpp"
@@ -35,28 +36,6 @@ extern "C" {
#pragma warning(pop)
}
/* Missing Options:
Seem to be covered by initQP_* instead.
- [obs-ffmpeg-encoder] Option 'cq' with help 'Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control' of type 'Float' with default value '0.000000', minimum '0.000000' and maximum '51.000000'.
- [obs-ffmpeg-encoder] Option 'qp' with help 'Constant quantization parameter rate control method' of type 'Int' with default value '-1', minimum '-1.000000' and maximum '51.000000'.
Not sure what there are useful for.
[obs-ffmpeg-encoder] Option 'aud' with help 'Use access unit delimiters' of type 'Bool' with default value 'false', minimum '0.000000' and maximum '1.000000'.
[obs-ffmpeg-encoder] Option 'surfaces' with help 'Number of concurrent surfaces' of type 'Int' with default value '0', minimum '0.000000' and maximum '64.000000'.
[obs-ffmpeg-encoder] Option 'delay' with help 'Delay frame output by the given amount of frames' of type 'Int' with default value '2147483647', minimum '0.000000' and maximum '2147483647.000000'.
Should probably add this.
[obs-ffmpeg-encoder] Option 'gpu' with unit (gpu) with help 'Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.' of type 'Int' with default value '-1', minimum '-2.000000' and maximum '2147483647.000000'.
[obs-ffmpeg-encoder] [gpu] Constant 'any' and help text 'Pick the first device available' with value '-1'.
[obs-ffmpeg-encoder] [gpu] Constant 'list' and help text 'List the available devices' with value '-2'.
Useless except for strict_gop maybe?
[obs-ffmpeg-encoder] Option 'forced-idr' with help 'If forcing keyframes, force them as IDR frames.' of type 'Bool' with default value 'false', minimum '-1.000000' and maximum '1.000000'.
[obs-ffmpeg-encoder] Option 'strict_gop' with help 'Set 1 to minimize GOP-to-GOP rate fluctuations' of type 'Bool' with default value 'false', minimum '0.000000' and maximum '1.000000'.
[obs-ffmpeg-encoder] Option 'bluray-compat' with help 'Bluray compatibility workarounds' of type 'Bool' with default value 'false', minimum '0.000000' and maximum '1.000000'.
*/
using namespace obsffmpeg::codecs::hevc;
std::map<profile, std::string> profiles{
@@ -150,21 +129,28 @@ void obsffmpeg::ui::nvenc_hevc_handler::log_options(obs_data_t* settings, const
{
nvenc::log_options(settings, codec, context);
profile cfg_profile = static_cast<profile>(obs_data_get_int(settings, P_HEVC_PROFILE));
tier cfg_tier = static_cast<tier>(obs_data_get_int(settings, P_HEVC_TIER));
level cfg_level = static_cast<level>(obs_data_get_int(settings, P_HEVC_LEVEL));
auto found1 = profiles.find(cfg_profile);
if (found1 != profiles.end())
PLOG_INFO("[%s] H.265 Profile: %s", codec->name, found1->second.c_str());
auto found2 = levels.find(cfg_level);
if (found2 != levels.end())
PLOG_INFO("[%s] H.265 Level: %s", codec->name, found2->second.c_str());
auto found3 = tiers.find(cfg_tier);
if (found3 != tiers.end())
PLOG_INFO("[%s] H.265 Tier: %s", codec->name, found3->second.c_str());
PLOG_INFO("[%s] H.265/HEVC:", codec->name);
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
profile val = static_cast<profile>(v);
auto index = profiles.find(val);
if (index != profiles.end())
return index->second;
return std::string("<Unknown>");
});
ffmpeg::tools::print_av_option_string(context, "level", " Level", [](int64_t v) {
level val = static_cast<level>(v);
auto index = levels.find(val);
if (index != levels.end())
return index->second;
return std::string("<Unknown>");
});
ffmpeg::tools::print_av_option_string(context, "tier", " Tier", [](int64_t v) {
tier val = static_cast<tier>(v);
auto index = tiers.find(val);
if (index != tiers.end())
return index->second;
return std::string("<Unknown>");
});
}
void obsffmpeg::ui::nvenc_hevc_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
+118 -148
View File
@@ -23,6 +23,7 @@
#include <algorithm>
#include "codecs/hevc.hpp"
#include "encoder.hpp"
#include "ffmpeg/tools.hpp"
#include "plugin.hpp"
#include "strings.hpp"
#include "utility.hpp"
@@ -170,8 +171,8 @@ void obsffmpeg::nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCode
obs_data_set_default_int(settings, ST_RATECONTROL_MODE, static_cast<int64_t>(ratecontrolmode::CBR_HQ));
obs_data_set_default_int(settings, ST_RATECONTROL_TWOPASS, -1);
obs_data_set_default_int(settings, ST_RATECONTROL_LOOKAHEAD, 0);
obs_data_set_default_bool(settings, ST_RATECONTROL_ADAPTIVEI, true);
obs_data_set_default_bool(settings, ST_RATECONTROL_ADAPTIVEB, true);
obs_data_set_default_int(settings, ST_RATECONTROL_ADAPTIVEI, -1);
obs_data_set_default_int(settings, ST_RATECONTROL_ADAPTIVEB, -1);
obs_data_set_default_int(settings, ST_RATECONTROL_BITRATE_TARGET, 6000);
obs_data_set_default_int(settings, ST_RATECONTROL_BITRATE_MAXIMUM, 6000);
@@ -188,15 +189,15 @@ void obsffmpeg::nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCode
obs_data_set_default_int(settings, ST_RATECONTROL_QP_B, 21);
obs_data_set_default_int(settings, ST_RATECONTROL_QP_B_INITIAL, -1);
obs_data_set_default_bool(settings, ST_AQ_SPATIAL, true);
obs_data_set_default_int(settings, ST_AQ_SPATIAL, -1);
obs_data_set_default_int(settings, ST_AQ_STRENGTH, 8);
obs_data_set_default_bool(settings, ST_AQ_TEMPORAL, true);
obs_data_set_default_int(settings, ST_AQ_TEMPORAL, -1);
obs_data_set_default_int(settings, ST_OTHER_BFRAMES, 2);
obs_data_set_default_int(settings, ST_OTHER_BFRAME_REFERENCEMODE, static_cast<int64_t>(b_ref_mode::DISABLED));
obs_data_set_default_bool(settings, ST_OTHER_ZEROLATENCY, false);
obs_data_set_default_bool(settings, ST_OTHER_WEIGHTED_PREDICTION, false);
obs_data_set_default_bool(settings, ST_OTHER_NONREFERENCE_PFRAMES, false);
obs_data_set_default_int(settings, ST_OTHER_ZEROLATENCY, -1);
obs_data_set_default_int(settings, ST_OTHER_WEIGHTED_PREDICTION, -1);
obs_data_set_default_int(settings, ST_OTHER_NONREFERENCE_PFRAMES, -1);
}
static bool modified_ratecontrol(obs_properties_t* props, obs_property_t*, obs_data_t* settings)
@@ -259,7 +260,7 @@ static bool modified_quality(obs_properties_t* props, obs_property_t*, obs_data_
static bool modified_aq(obs_properties_t* props, obs_property_t*, obs_data_t* settings)
{
bool spatial_aq = obs_data_get_bool(settings, ST_AQ_SPATIAL);
bool spatial_aq = obs_data_get_int(settings, ST_AQ_SPATIAL) == 1;
obs_property_set_visible(obs_properties_get(props, ST_AQ_STRENGTH), spatial_aq);
return true;
}
@@ -298,12 +299,9 @@ void obsffmpeg::nvenc::get_properties_post(obs_properties_t* props, const AVCode
}
{
auto p = obs_properties_add_list(grp, ST_RATECONTROL_TWOPASS, TRANSLATE(ST_RATECONTROL_TWOPASS),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_TWOPASS,
TRANSLATE(ST_RATECONTROL_TWOPASS));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_TWOPASS)));
obs_property_list_add_int(p, TRANSLATE(S_STATE_DEFAULT), -1);
obs_property_list_add_int(p, TRANSLATE(S_STATE_DISABLED), 0);
obs_property_list_add_int(p, TRANSLATE(S_STATE_ENABLED), 1);
}
{
@@ -313,13 +311,13 @@ void obsffmpeg::nvenc::get_properties_post(obs_properties_t* props, const AVCode
obs_property_int_set_suffix(p, " frames");
}
{
auto p =
obs_properties_add_bool(grp, ST_RATECONTROL_ADAPTIVEI, TRANSLATE(ST_RATECONTROL_ADAPTIVEI));
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEI,
TRANSLATE(ST_RATECONTROL_ADAPTIVEI));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_ADAPTIVEI)));
}
if (strcmp(codec->name, "h264_nvenc") == 0) {
auto p =
obs_properties_add_bool(grp, ST_RATECONTROL_ADAPTIVEB, TRANSLATE(ST_RATECONTROL_ADAPTIVEB));
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEB,
TRANSLATE(ST_RATECONTROL_ADAPTIVEB));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_ADAPTIVEB)));
}
}
@@ -435,7 +433,7 @@ void obsffmpeg::nvenc::get_properties_post(obs_properties_t* props, const AVCode
}
{
auto p = obs_properties_add_bool(grp, ST_AQ_SPATIAL, TRANSLATE(ST_AQ_SPATIAL));
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_AQ_SPATIAL, TRANSLATE(ST_AQ_SPATIAL));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_AQ_SPATIAL)));
obs_property_set_modified_callback(p, modified_aq);
}
@@ -445,7 +443,7 @@ void obsffmpeg::nvenc::get_properties_post(obs_properties_t* props, const AVCode
obs_property_set_long_description(p, TRANSLATE(DESC(ST_AQ_STRENGTH)));
}
{
auto p = obs_properties_add_bool(grp, ST_AQ_TEMPORAL, TRANSLATE(ST_AQ_TEMPORAL));
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_AQ_TEMPORAL, TRANSLATE(ST_AQ_TEMPORAL));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_AQ_TEMPORAL)));
}
}
@@ -476,18 +474,19 @@ void obsffmpeg::nvenc::get_properties_post(obs_properties_t* props, const AVCode
}
{
auto p = obs_properties_add_bool(grp, ST_OTHER_ZEROLATENCY, TRANSLATE(ST_OTHER_ZEROLATENCY));
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_ZEROLATENCY,
TRANSLATE(ST_OTHER_ZEROLATENCY));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_ZEROLATENCY)));
}
{
auto p = obs_properties_add_bool(grp, ST_OTHER_WEIGHTED_PREDICTION,
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_WEIGHTED_PREDICTION,
TRANSLATE(ST_OTHER_WEIGHTED_PREDICTION));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_WEIGHTED_PREDICTION)));
}
{
auto p = obs_properties_add_bool(grp, ST_OTHER_NONREFERENCE_PFRAMES,
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_NONREFERENCE_PFRAMES,
TRANSLATE(ST_OTHER_NONREFERENCE_PFRAMES));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_NONREFERENCE_PFRAMES)));
}
@@ -555,6 +554,7 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
av_opt_set(context->priv_data, "rc", rcopt->second.c_str(), 0);
}
av_opt_set_int(context->priv_data, "cbr", 0, 0);
switch (rc) {
case ratecontrolmode::CQP:
have_qp = true;
@@ -580,14 +580,18 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
}
int la = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_LOOKAHEAD));
av_opt_set_int(context->priv_data, "lookahead", la, 0);
av_opt_set_int(context->priv_data, "rc-lookahead", la, 0);
if (la > 0) {
bool adapt_i = obs_data_get_bool(settings, ST_RATECONTROL_ADAPTIVEI);
av_opt_set_int(context->priv_data, "no-scenecut", !adapt_i ? 1 : 0, 0);
int64_t adapt_i = obs_data_get_int(settings, ST_RATECONTROL_ADAPTIVEI);
if (!is_tristate_default(adapt_i)) {
av_opt_set_int(context->priv_data, "no-scenecut", adapt_i, AV_OPT_SEARCH_CHILDREN);
}
if (strcmp(codec->name, "h264_nvenc")) {
bool adapt_b = obs_data_get_bool(settings, ST_RATECONTROL_ADAPTIVEB);
av_opt_set_int(context->priv_data, "b_adapt", adapt_b ? 1 : 0, 0);
int64_t adapt_b = obs_data_get_int(settings, ST_RATECONTROL_ADAPTIVEB);
if (!is_tristate_default(adapt_b)) {
av_opt_set_int(context->priv_data, "b_adapt", adapt_b, AV_OPT_SEARCH_CHILDREN);
}
}
}
@@ -636,37 +640,42 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
}
{ // AQ
bool saq = obs_data_get_bool(settings, ST_AQ_SPATIAL);
bool taq = obs_data_get_bool(settings, ST_AQ_TEMPORAL);
int64_t saq = obs_data_get_int(settings, ST_AQ_SPATIAL);
int64_t taq = obs_data_get_int(settings, ST_AQ_TEMPORAL);
if (strcmp(codec->name, "h264_nvenc")) {
av_opt_set_int(context->priv_data, "spatial-aq", saq ? 1 : 0, 0);
av_opt_set_int(context->priv_data, "temporal-aq", taq ? 1 : 0, 0);
if (strcmp(codec->name, "h264_nvenc") == 0) {
if (!is_tristate_default(saq))
av_opt_set_int(context->priv_data, "spatial-aq", saq, 0);
if (!is_tristate_default(taq))
av_opt_set_int(context->priv_data, "temporal-aq", taq, 0);
} else {
av_opt_set_int(context->priv_data, "spatial_aq", saq ? 1 : 0, 0);
av_opt_set_int(context->priv_data, "temporal_aq", taq ? 1 : 0, 0);
if (!is_tristate_default(saq))
av_opt_set_int(context->priv_data, "spatial_aq", saq, 0);
if (!is_tristate_default(taq))
av_opt_set_int(context->priv_data, "temporal_aq", taq, 0);
}
if (saq) {
if (is_tristate_enabled(saq))
av_opt_set_int(context->priv_data, "aq-strength",
static_cast<int>(obs_data_get_int(settings, ST_AQ_STRENGTH)), 0);
}
}
{ // Other
bool zl = obs_data_get_bool(settings, ST_OTHER_ZEROLATENCY);
bool wp = obs_data_get_bool(settings, ST_OTHER_WEIGHTED_PREDICTION);
bool nrp = obs_data_get_bool(settings, ST_OTHER_NONREFERENCE_PFRAMES);
int64_t zl = obs_data_get_int(settings, ST_OTHER_ZEROLATENCY);
int64_t wp = obs_data_get_int(settings, ST_OTHER_WEIGHTED_PREDICTION);
int64_t nrp = obs_data_get_int(settings, ST_OTHER_NONREFERENCE_PFRAMES);
context->max_b_frames = static_cast<int>(obs_data_get_int(settings, ST_OTHER_BFRAMES));
av_opt_set_int(context->priv_data, "zerolatency", zl ? 1 : 0, 0);
av_opt_set_int(context->priv_data, "nonref_p", nrp ? 1 : 0, 0);
if (!is_tristate_default(zl))
av_opt_set_int(context->priv_data, "zerolatency", zl, 0);
if (!is_tristate_default(nrp))
av_opt_set_int(context->priv_data, "nonref_p", nrp, 0);
if ((context->max_b_frames != 0) && wp) {
PLOG_WARNING(
"Automatically disabled weighted prediction due to being incompatible with B-Frames.");
} else {
av_opt_set_int(context->priv_data, "weighted_pred", wp ? 1 : 0, 0);
if ((context->max_b_frames != 0) && is_tristate_enabled(wp)) {
PLOG_WARNING("[%s] Weighted Prediction disabled because of B-Frames being used.", codec->name);
av_opt_set_int(context->priv_data, "weighted_pred", 0, 0);
} else if (!is_tristate_default(wp)) {
av_opt_set_int(context->priv_data, "weighted_pred", wp, 0);
}
{
@@ -679,112 +688,73 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
}
}
void obsffmpeg::nvenc::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
void obsffmpeg::nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecContext* context)
{
preset cfg_preset = static_cast<preset>(obs_data_get_int(settings, ST_PRESET));
PLOG_INFO("[%s] Nvidia NVENC:", codec->name);
ffmpeg::tools::print_av_option_string(context, "preset", " Preset", [](int64_t v) {
preset val = static_cast<preset>(v);
std::string name = "<Unknown>";
auto index = preset_to_opt.find(val);
if (index != preset_to_opt.end())
name = index->second;
return name;
});
ffmpeg::tools::print_av_option_string(context, "rc", " Rate Control", [](int64_t v) {
ratecontrolmode val = static_cast<ratecontrolmode>(v);
std::string name = "<Unknown>";
auto index = ratecontrolmode_to_opt.find(val);
if (index != ratecontrolmode_to_opt.end())
name = index->second;
return name;
});
ffmpeg::tools::print_av_option_bool(context, "2pass", " Two Pass");
ffmpeg::tools::print_av_option_int(context, "rc-lookahead", " Look-Ahead", "Frames");
ffmpeg::tools::print_av_option_bool(context, "no-scenecut", " Adaptive I-Frames");
if (strcmp(codec->name, "h264_nvenc") == 0)
ffmpeg::tools::print_av_option_bool(context, "b_adapt", " Adaptive B-Frames");
auto found1 = preset_to_opt.find(cfg_preset);
if (found1 != preset_to_opt.end())
PLOG_INFO("[%s] Preset: %s", codec->name, found1->second.c_str());
PLOG_INFO("[%s] Bitrate:", codec->name);
ffmpeg::tools::print_av_option_int(context, "bitrate", " Target", "bits/sec");
ffmpeg::tools::print_av_option_int(context, "rc_max_rate", " Maximum", "bits/sec");
ffmpeg::tools::print_av_option_int(context, "rc_buffer_size", " Buffer", "bits");
PLOG_INFO("[%s] Quality:", codec->name);
ffmpeg::tools::print_av_option_int(context, "qmin", " Minimum", "");
ffmpeg::tools::print_av_option_int(context, "cq", " Target", "");
ffmpeg::tools::print_av_option_int(context, "qmax", " Maximum", "");
PLOG_INFO("[%s] Quantization Parameters:", codec->name);
ffmpeg::tools::print_av_option_int(context, "init_qpI", " I-Frame", "");
ffmpeg::tools::print_av_option_int(context, "init_qpP", " P-Frame", "");
ffmpeg::tools::print_av_option_int(context, "init_qpB", " B-Frame", "");
ratecontrolmode cfg_rc_mode = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_RATECONTROL_MODE));
int64_t cfg_rc_2pass = obs_data_get_int(settings, ST_RATECONTROL_TWOPASS);
int64_t cfg_rc_lahead = obs_data_get_int(settings, ST_RATECONTROL_LOOKAHEAD);
bool cfg_rc_adapti = obs_data_get_bool(settings, ST_RATECONTROL_ADAPTIVEI);
bool cfg_rc_adaptb = obs_data_get_bool(settings, ST_RATECONTROL_ADAPTIVEB);
ffmpeg::tools::print_av_option_int(context, "max_b_frames", " B-Frames", "Frames");
ffmpeg::tools::print_av_option_string(context, "b_ref_mode", " Reference Mode", [](int64_t v) {
b_ref_mode val = static_cast<b_ref_mode>(v);
std::string name = "<Unknown>";
auto index = b_ref_mode_to_opt.find(val);
if (index != b_ref_mode_to_opt.end())
name = index->second;
return name;
});
auto found2 = ratecontrolmode_to_opt.find(cfg_rc_mode);
if (found2 != ratecontrolmode_to_opt.end())
PLOG_INFO("[%s] Rate Control: %s", codec->name, found2->second.c_str());
PLOG_INFO("[%s] Two Pass: %s", codec->name,
cfg_rc_2pass == 1 ? "Enabled" : (cfg_rc_2pass == 0 ? "Disabled" : "Default"));
PLOG_INFO("[%s] Lookahead: %" PRId64 " Frames", codec->name, cfg_rc_lahead);
if (cfg_rc_adapti && cfg_rc_lahead > 0)
PLOG_INFO("[%s] Adaptive I-Frames Enabled", codec->name);
if (cfg_rc_adaptb && cfg_rc_lahead > 0)
PLOG_INFO("[%s] Adaptive B-Frames Enabled", codec->name);
int64_t cfg_rc_bitrate = obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET);
int64_t cfg_rc_max_bitrate = obs_data_get_int(settings, ST_RATECONTROL_BITRATE_MAXIMUM);
int64_t cfg_rc_bufsize = obs_data_get_int(settings, S_RATECONTROL_BUFFERSIZE);
bool cfg_rc_quality = obs_data_get_bool(settings, ST_RATECONTROL_QUALITY);
int64_t cfg_rc_quality_min = obs_data_get_int(settings, ST_RATECONTROL_QUALITY_MINIMUM);
int64_t cfg_rc_quality_max = obs_data_get_int(settings, ST_RATECONTROL_QUALITY_MAXIMUM);
double_t cfg_rc_quality_tgt = obs_data_get_double(settings, ST_RATECONTROL_QUALITY_TARGET) / 100.0 * 51.0;
int64_t cfg_rc_qp_i = obs_data_get_int(settings, ST_RATECONTROL_QP_I);
int64_t cfg_rc_qp_p = obs_data_get_int(settings, ST_RATECONTROL_QP_P);
int64_t cfg_rc_qp_b = obs_data_get_int(settings, ST_RATECONTROL_QP_B);
int64_t cfg_rc_qp_i_init = obs_data_get_int(settings, ST_RATECONTROL_QP_I_INITIAL);
int64_t cfg_rc_qp_p_init = obs_data_get_int(settings, ST_RATECONTROL_QP_P_INITIAL);
int64_t cfg_rc_qp_b_init = obs_data_get_int(settings, ST_RATECONTROL_QP_B_INITIAL);
{
bool have_bitrate = false;
bool have_bitrate_max = false;
bool have_quality = false;
bool have_qp = false;
bool have_qp_init = false;
switch (cfg_rc_mode) {
case ratecontrolmode::CQP:
have_qp = true;
break;
case ratecontrolmode::CBR:
case ratecontrolmode::CBR_HQ:
case ratecontrolmode::CBR_LD_HQ:
have_bitrate = true;
av_opt_set_int(context->priv_data, "cbr", 1, 0);
break;
case ratecontrolmode::VBR:
case ratecontrolmode::VBR_HQ:
have_bitrate_max = true;
have_bitrate = true;
have_quality = true;
have_qp_init = true;
break;
PLOG_INFO("[%s] Adaptive Quantization:", codec->name);
if (strcmp(codec->name, "h264_nvenc") == 0) {
ffmpeg::tools::print_av_option_bool(context, "spatial-aq", " Spatial AQ");
ffmpeg::tools::print_av_option_int(context, "aq-strength", " Strength", "");
ffmpeg::tools::print_av_option_bool(context, "temporal-aq", " Temporal AQ");
} else {
ffmpeg::tools::print_av_option_bool(context, "spatial_aq", " Spatial AQ");
ffmpeg::tools::print_av_option_int(context, "aq-strength", " Strength", "");
ffmpeg::tools::print_av_option_bool(context, "temporal_aq", " Temporal AQ");
}
PLOG_INFO("[%s] Buffer Size: %" PRId64, codec->name, cfg_rc_bufsize);
if (have_bitrate)
PLOG_INFO("[%s] Bitrate Target: %" PRId64, codec->name, cfg_rc_bitrate);
if (have_bitrate_max)
PLOG_INFO("[%s] Bitrate Maximum: %" PRId64, codec->name, cfg_rc_max_bitrate);
if (have_quality && cfg_rc_quality) {
PLOG_INFO("[%s] Quality Limits:", codec->name);
PLOG_INFO("[%s] Minimum: %" PRId64, codec->name, cfg_rc_quality_min);
PLOG_INFO("[%s] Maximum: %" PRId64, codec->name, cfg_rc_quality_max);
PLOG_INFO("[%s] Target: %f", codec->name, cfg_rc_quality_tgt);
}
if (have_qp)
PLOG_INFO("[%s] QP Values: %" PRId64 "/%" PRId64 "/%" PRId64, codec->name, cfg_rc_qp_i,
cfg_rc_qp_p, cfg_rc_qp_b);
if (have_qp_init)
PLOG_INFO("[%s] Initial QP Values: %" PRId64 "/%" PRId64 "/%" PRId64, codec->name,
cfg_rc_qp_i_init, cfg_rc_qp_p_init, cfg_rc_qp_b_init);
}
bool cfg_aq_spatial = obs_data_get_bool(settings, ST_AQ_SPATIAL);
int64_t cfg_aq_strength = obs_data_get_int(settings, ST_AQ_STRENGTH);
bool cfg_aq_temporal = obs_data_get_bool(settings, ST_AQ_TEMPORAL);
if (cfg_aq_spatial)
PLOG_INFO("[%s] Spatial AQ Enabled: Strength %" PRId64, codec->name, cfg_aq_strength);
if (cfg_aq_temporal)
PLOG_INFO("[%s] Temporal AQ Enabled", codec->name);
int64_t cfg_bf = obs_data_get_int(settings, ST_OTHER_BFRAMES);
b_ref_mode cfg_bf_mode = static_cast<b_ref_mode>(obs_data_get_int(settings, ST_OTHER_BFRAME_REFERENCEMODE));
bool cfg_zerolatency = obs_data_get_bool(settings, ST_OTHER_ZEROLATENCY);
bool cfg_weightp = obs_data_get_bool(settings, ST_OTHER_WEIGHTED_PREDICTION);
bool cfg_nonrefp = obs_data_get_bool(settings, ST_OTHER_NONREFERENCE_PFRAMES);
PLOG_INFO("[%s] B-Frames: %" PRId64, codec->name, cfg_bf);
auto found3 = b_ref_mode_to_opt.find(cfg_bf_mode);
if (found3 != b_ref_mode_to_opt.end())
PLOG_INFO("[%s] Reference Mode: %s", codec->name, found3->second.c_str());
if (cfg_zerolatency)
PLOG_INFO("[%s] Zero Latency Enabled", codec->name);
if (cfg_weightp)
PLOG_INFO("[%s] Weighted Prediction Enabled", codec->name);
if (cfg_nonrefp)
PLOG_INFO("[%s] Non-Ref P-Frames Enabled", codec->name);
PLOG_INFO("[%s] Other:", codec->name);
ffmpeg::tools::print_av_option_bool(context, "zerolatency", " Zero Latency");
ffmpeg::tools::print_av_option_bool(context, "weighted_pred", " Weighted Prediction");
ffmpeg::tools::print_av_option_bool(context, "nonref_p", " Non-reference P-Frames");
ffmpeg::tools::print_av_option_bool(context, "strict_gop", " Strict GOP");
ffmpeg::tools::print_av_option_bool(context, "aud", " Access Unit Delimiters");
ffmpeg::tools::print_av_option_bool(context, "bluray-compat", " Bluray Compatibility");
if (strcmp(codec->name, "h264_nvenc") == 0)
ffmpeg::tools::print_av_option_bool(context, "a53cc", " A53 Closed Captions");
ffmpeg::tools::print_av_option_int(context, "dpb_size", " DPB Size", "");
}
+6
View File
@@ -48,6 +48,8 @@ namespace obsffmpeg {
LOW_LATENCY_HIGH_QUALITY,
LOSSLESS,
LOSSLESS_HIGH_PERFORMANCE,
// Append things before this.
INVALID = -1,
};
enum class ratecontrolmode : int64_t {
@@ -57,12 +59,16 @@ namespace obsffmpeg {
CBR,
CBR_HQ,
CBR_LD_HQ,
// Append things before this.
INVALID = -1,
};
enum class b_ref_mode : int64_t {
DISABLED,
EACH,
MIDDLE,
// Append things before this.
INVALID = -1,
};
extern std::map<preset, std::string> presets;