mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-28 18:41:14 +00:00
encoders/ffmpeg/nvenc: Ensure compatibility with more than just FFmpeg 4.2
When FFmpeg Encoders was originally written, FFmpeg 4.2 was still new and OBS Studio did not seem to want to update to anything newer for a while. This led to code being fine-tuned for FFmpeg 4.2, which stops working the moment OBS Studio upgrades FFmpeg. This removes the dependency on FFmpeg 4.2 hopefully, and allows using newer FFmpeg versions - or perhaps even older versions. Additionally the nonsensical behavior of the Target Quality slider was fixed. It is now from 0 to 51, instead of from 0 to 100, and as such matches FFmpeg exactly.
This commit is contained in:
parent
7f6047f43f
commit
36aec3be54
5 changed files with 277 additions and 318 deletions
|
@ -166,27 +166,40 @@ Encoder.FFmpeg.AMF.Other.AccessUnitDelimiter="Access Unit Delimiter"
|
||||||
|
|
||||||
# Encoder/FFmpeg/NVENC
|
# Encoder/FFmpeg/NVENC
|
||||||
Encoder.FFmpeg.NVENC.Preset="Preset"
|
Encoder.FFmpeg.NVENC.Preset="Preset"
|
||||||
Encoder.FFmpeg.NVENC.Preset.Default="Default"
|
Encoder.FFmpeg.NVENC.Preset.default="Default"
|
||||||
Encoder.FFmpeg.NVENC.Preset.Slow="Slow"
|
Encoder.FFmpeg.NVENC.Preset.slow="Slow"
|
||||||
Encoder.FFmpeg.NVENC.Preset.Medium="Medium"
|
Encoder.FFmpeg.NVENC.Preset.medium="Medium"
|
||||||
Encoder.FFmpeg.NVENC.Preset.Fast="Fast"
|
Encoder.FFmpeg.NVENC.Preset.fast="Fast"
|
||||||
Encoder.FFmpeg.NVENC.Preset.HighPerformance="High Performance"
|
Encoder.FFmpeg.NVENC.Preset.hp="High Performance"
|
||||||
Encoder.FFmpeg.NVENC.Preset.HighQuality="High Quality"
|
Encoder.FFmpeg.NVENC.Preset.hq="High Quality"
|
||||||
Encoder.FFmpeg.NVENC.Preset.BluRayDisc="BluRay Disc"
|
Encoder.FFmpeg.NVENC.Preset.bd="BluRay Disc"
|
||||||
Encoder.FFmpeg.NVENC.Preset.LowLatency="Low Latency"
|
Encoder.FFmpeg.NVENC.Preset.ll="Low Latency"
|
||||||
Encoder.FFmpeg.NVENC.Preset.LowLatencyHighPerformance="Low Latency High Performance"
|
Encoder.FFmpeg.NVENC.Preset.llhq="Low Latency High Quality"
|
||||||
Encoder.FFmpeg.NVENC.Preset.LowLatencyHighQuality="Low Latency High Quality"
|
Encoder.FFmpeg.NVENC.Preset.llhp="Low Latency High Performance"
|
||||||
Encoder.FFmpeg.NVENC.Preset.Lossless="Lossless"
|
Encoder.FFmpeg.NVENC.Preset.lossless="Lossless"
|
||||||
Encoder.FFmpeg.NVENC.Preset.LosslessHighPerformance="Lossless High Performance"
|
Encoder.FFmpeg.NVENC.Preset.losslesshp="Lossless High Performance"
|
||||||
|
Encoder.FFmpeg.NVENC.Preset.p1="Fastest (P1)"
|
||||||
|
Encoder.FFmpeg.NVENC.Preset.p2="Faster (P2)"
|
||||||
|
Encoder.FFmpeg.NVENC.Preset.p3="Fast (P3)"
|
||||||
|
Encoder.FFmpeg.NVENC.Preset.p4="Medium (P4)"
|
||||||
|
Encoder.FFmpeg.NVENC.Preset.p5="Slow (P5)"
|
||||||
|
Encoder.FFmpeg.NVENC.Preset.p6="Slower (P6)"
|
||||||
|
Encoder.FFmpeg.NVENC.Preset.p7="Slowest (P7)"
|
||||||
|
Encoder.FFmpeg.NVENC.Tune="Tune"
|
||||||
|
Encoder.FFmpeg.NVENC.Tune.hq="High Quality"
|
||||||
|
Encoder.FFmpeg.NVENC.Tune.ll="Low Latency"
|
||||||
|
Encoder.FFmpeg.NVENC.Tune.ull="Ultra Low Latency"
|
||||||
|
Encoder.FFmpeg.NVENC.Tune.lossless="Lossless"
|
||||||
Encoder.FFmpeg.NVENC.RateControl="Rate Control Options"
|
Encoder.FFmpeg.NVENC.RateControl="Rate Control Options"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.Mode="Mode"
|
Encoder.FFmpeg.NVENC.RateControl.Mode="Mode"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.Mode.CQP="Constant Quantization Parameter"
|
Encoder.FFmpeg.NVENC.RateControl.Mode.constqp="Constant Quantization Parameter"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.Mode.VBR="Variable Bitrate"
|
Encoder.FFmpeg.NVENC.RateControl.Mode.vbr="Variable Bitrate"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.Mode.VBR_HQ="High Quality Variable Bitrate"
|
Encoder.FFmpeg.NVENC.RateControl.Mode.cbr="Constant Bitrate"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.Mode.CBR="Constant Bitrate"
|
|
||||||
Encoder.FFmpeg.NVENC.RateControl.Mode.CBR_HQ="High Quality Constant Bitrate"
|
|
||||||
Encoder.FFmpeg.NVENC.RateControl.Mode.CBR_LD_HQ="Low Delay High Quality Constant Bitrate"
|
|
||||||
Encoder.FFmpeg.NVENC.RateControl.TwoPass="Two Pass"
|
Encoder.FFmpeg.NVENC.RateControl.TwoPass="Two Pass"
|
||||||
|
Encoder.FFmpeg.NVENC.RateControl.MultiPass="Multi-Pass"
|
||||||
|
Encoder.FFmpeg.NVENC.RateControl.MultiPass.disabled="Single Pass"
|
||||||
|
Encoder.FFmpeg.NVENC.RateControl.MultiPass.qres="Two Pass at Quarter Resolution"
|
||||||
|
Encoder.FFmpeg.NVENC.RateControl.MultiPass.fullres="Two Pass at Full Resolution"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.LookAhead="Look Ahead"
|
Encoder.FFmpeg.NVENC.RateControl.LookAhead="Look Ahead"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.AdaptiveI="Adaptive I-Frames"
|
Encoder.FFmpeg.NVENC.RateControl.AdaptiveI="Adaptive I-Frames"
|
||||||
Encoder.FFmpeg.NVENC.RateControl.AdaptiveB="Adaptive B-Frames"
|
Encoder.FFmpeg.NVENC.RateControl.AdaptiveB="Adaptive B-Frames"
|
||||||
|
@ -208,12 +221,14 @@ Encoder.FFmpeg.NVENC.AQ.Temporal="Temporal Adaptive Quantization"
|
||||||
Encoder.FFmpeg.NVENC.Other="Other Options"
|
Encoder.FFmpeg.NVENC.Other="Other Options"
|
||||||
Encoder.FFmpeg.NVENC.Other.BFrames="Maximum B-Frames"
|
Encoder.FFmpeg.NVENC.Other.BFrames="Maximum B-Frames"
|
||||||
Encoder.FFmpeg.NVENC.Other.BFrameReferenceMode="B-Frame Reference Mode"
|
Encoder.FFmpeg.NVENC.Other.BFrameReferenceMode="B-Frame Reference Mode"
|
||||||
Encoder.FFmpeg.NVENC.Other.BFrameReferenceMode.Middle="Use only middle B-Frames as reference"
|
Encoder.FFmpeg.NVENC.Other.BFrameReferenceMode.disabled="No B-Frames will be used as Reference"
|
||||||
Encoder.FFmpeg.NVENC.Other.BFrameReferenceMode.Each="Use all B-Frames as reference"
|
Encoder.FFmpeg.NVENC.Other.BFrameReferenceMode.middle="Only B-Frames/2 will be used as Reference"
|
||||||
|
Encoder.FFmpeg.NVENC.Other.BFrameReferenceMode.each="Each B-Frame will be used as Reference"
|
||||||
Encoder.FFmpeg.NVENC.Other.ZeroLatency="Zero Latency"
|
Encoder.FFmpeg.NVENC.Other.ZeroLatency="Zero Latency"
|
||||||
Encoder.FFmpeg.NVENC.Other.WeightedPrediction="Weighted Prediction"
|
Encoder.FFmpeg.NVENC.Other.WeightedPrediction="Weighted Prediction"
|
||||||
Encoder.FFmpeg.NVENC.Other.NonReferencePFrames="Non-reference P-Frames"
|
Encoder.FFmpeg.NVENC.Other.NonReferencePFrames="Non-reference P-Frames"
|
||||||
Encoder.FFmpeg.NVENC.Other.ReferenceFrames="Reference Frames"
|
Encoder.FFmpeg.NVENC.Other.ReferenceFrames="Reference Frames"
|
||||||
|
Encoder.FFmpeg.NVENC.Other.LowDelayKeyFrameScale="Low Delay Key-Frame Scale"
|
||||||
|
|
||||||
# Blur
|
# Blur
|
||||||
Blur.Type.Box="Box"
|
Blur.Type.Box="Box"
|
||||||
|
|
|
@ -45,20 +45,6 @@ extern "C" {
|
||||||
using namespace streamfx::encoder::ffmpeg::handler;
|
using namespace streamfx::encoder::ffmpeg::handler;
|
||||||
using namespace streamfx::encoder::codec::h264;
|
using namespace streamfx::encoder::codec::h264;
|
||||||
|
|
||||||
static std::map<profile, std::string> profiles{
|
|
||||||
{profile::BASELINE, "baseline"},
|
|
||||||
{profile::MAIN, "main"},
|
|
||||||
{profile::HIGH, "high"},
|
|
||||||
{profile::HIGH444_PREDICTIVE, "high444p"},
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::map<level, std::string> levels{
|
|
||||||
{level::L1_0, "1.0"}, {level::L1_0b, "1.0b"}, {level::L1_1, "1.1"}, {level::L1_2, "1.2"},
|
|
||||||
{level::L1_3, "1.3"}, {level::L2_0, "2.0"}, {level::L2_1, "2.1"}, {level::L2_2, "2.2"},
|
|
||||||
{level::L3_0, "3.0"}, {level::L3_1, "3.1"}, {level::L3_2, "3.2"}, {level::L4_0, "4.0"},
|
|
||||||
{level::L4_1, "4.1"}, {level::L4_2, "4.2"}, {level::L5_0, "5.0"}, {level::L5_1, "5.1"},
|
|
||||||
};
|
|
||||||
|
|
||||||
void nvenc_h264_handler::adjust_info(ffmpeg_factory* fac, const AVCodec*, std::string&, std::string& name, std::string&)
|
void nvenc_h264_handler::adjust_info(ffmpeg_factory* fac, const AVCodec*, std::string&, std::string& name, std::string&)
|
||||||
{
|
{
|
||||||
name = "NVIDIA NVENC H.264/AVC (via FFmpeg)";
|
name = "NVIDIA NVENC H.264/AVC (via FFmpeg)";
|
||||||
|
@ -108,19 +94,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) {
|
if (!context->internal) {
|
||||||
{
|
if (auto value = obs_data_get_int(settings, ST_KEY_PROFILE); value > -1) {
|
||||||
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE)));
|
av_opt_set_int(context->priv_data, "profile", value, AV_OPT_SEARCH_CHILDREN);
|
||||||
if (found != profiles.end()) {
|
|
||||||
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
if (auto value = obs_data_get_int(settings, ST_KEY_LEVEL); value > -1) {
|
||||||
auto found = levels.find(static_cast<level>(obs_data_get_int(settings, ST_KEY_LEVEL)));
|
av_opt_set_int(context->priv_data, "level", value, AV_OPT_SEARCH_CHILDREN);
|
||||||
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", AV_OPT_SEARCH_CHILDREN);
|
||||||
} else {
|
|
||||||
av_opt_set(context->priv_data, "level", "auto", 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +123,13 @@ void nvenc_h264_handler::log_options(obs_data_t* settings, const AVCodec* codec,
|
||||||
|
|
||||||
void nvenc_h264_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
void nvenc_h264_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
||||||
{
|
{
|
||||||
nvenc::get_properties_pre(props, codec);
|
AVCodecContext* context = avcodec_alloc_context3(codec);
|
||||||
|
if (!context->priv_data) {
|
||||||
|
avcodec_free_context(&context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvenc::get_properties_pre(props, codec, context);
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
|
@ -155,23 +141,27 @@ 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_INT);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(profile::UNKNOWN));
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
||||||
for (auto const kv : profiles) {
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "profile", p, S_CODEC_H264_PROFILE);
|
||||||
std::string trans = std::string(S_CODEC_H264_PROFILE) + "." + kv.second;
|
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
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_INT);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), static_cast<int64_t>(level::UNKNOWN));
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), 0);
|
||||||
for (auto const kv : levels) {
|
streamfx::ffmpeg::tools::avoption_list_add_entries_unnamed(context->priv_data, "level", p,
|
||||||
obs_property_list_add_int(p, kv.second.c_str(), static_cast<int64_t>(kv.first));
|
[](const AVOption* opt) {
|
||||||
}
|
if (opt->default_val.i64 == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nvenc::get_properties_post(props, codec);
|
nvenc::get_properties_post(props, codec, context);
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
avcodec_free_context(&context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvenc_h264_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
|
void nvenc_h264_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
|
||||||
|
|
|
@ -42,23 +42,6 @@ extern "C" {
|
||||||
using namespace streamfx::encoder::ffmpeg::handler;
|
using namespace streamfx::encoder::ffmpeg::handler;
|
||||||
using namespace streamfx::encoder::codec::hevc;
|
using namespace streamfx::encoder::codec::hevc;
|
||||||
|
|
||||||
static std::map<profile, std::string> profiles{
|
|
||||||
{profile::MAIN, "main"},
|
|
||||||
{profile::MAIN10, "main10"},
|
|
||||||
{profile::RANGE_EXTENDED, "rext"},
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::map<tier, std::string> tiers{
|
|
||||||
{tier::MAIN, "main"},
|
|
||||||
{tier::HIGH, "high"},
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::map<level, std::string> levels{
|
|
||||||
{level::L1_0, "1.0"}, {level::L2_0, "2.0"}, {level::L2_1, "2.1"}, {level::L3_0, "3.0"}, {level::L3_1, "3.1"},
|
|
||||||
{level::L4_0, "4.0"}, {level::L4_1, "4.1"}, {level::L5_0, "5.0"}, {level::L5_1, "5.1"}, {level::L5_2, "5.2"},
|
|
||||||
{level::L6_0, "6.0"}, {level::L6_1, "6.1"}, {level::L6_2, "6.2"},
|
|
||||||
};
|
|
||||||
|
|
||||||
void nvenc_hevc_handler::adjust_info(ffmpeg_factory* fac, const AVCodec*, std::string&, std::string& name, std::string&)
|
void nvenc_hevc_handler::adjust_info(ffmpeg_factory* fac, const AVCodec*, std::string&, std::string& name, std::string&)
|
||||||
{
|
{
|
||||||
name = "NVIDIA NVENC H.265/HEVC (via FFmpeg)";
|
name = "NVIDIA NVENC H.265/HEVC (via FFmpeg)";
|
||||||
|
@ -109,25 +92,16 @@ 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) {
|
||||||
{ // HEVC Options
|
if (auto v = obs_data_get_int(settings, ST_KEY_PROFILE); v > -1) {
|
||||||
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, ST_KEY_PROFILE)));
|
av_opt_set_int(context->priv_data, "profile", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
if (found != profiles.end()) {
|
|
||||||
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
if (auto v = obs_data_get_int(settings, ST_KEY_TIER); v > -1) {
|
||||||
auto found = tiers.find(static_cast<tier>(obs_data_get_int(settings, ST_KEY_TIER)));
|
av_opt_set_int(context->priv_data, "tier", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
if (found != tiers.end()) {
|
|
||||||
av_opt_set(context->priv_data, "tier", found->second.c_str(), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
if (auto v = obs_data_get_int(settings, ST_KEY_LEVEL); v > -1) {
|
||||||
auto found = levels.find(static_cast<level>(obs_data_get_int(settings, ST_KEY_LEVEL)));
|
av_opt_set_int(context->priv_data, "level", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
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", AV_OPT_SEARCH_CHILDREN);
|
||||||
} else {
|
|
||||||
av_opt_set(context->priv_data, "level", "auto", 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +126,13 @@ void nvenc_hevc_handler::log_options(obs_data_t* settings, const AVCodec* codec,
|
||||||
|
|
||||||
void nvenc_hevc_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
void nvenc_hevc_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
||||||
{
|
{
|
||||||
nvenc::get_properties_pre(props, codec);
|
AVCodecContext* context = avcodec_alloc_context3(codec);
|
||||||
|
if (!context->priv_data) {
|
||||||
|
avcodec_free_context(&context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvenc::get_properties_pre(props, codec, context);
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
|
@ -164,32 +144,33 @@ 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_INT);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(profile::UNKNOWN));
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
||||||
for (auto const kv : profiles) {
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "profile", p, S_CODEC_HEVC_PROFILE);
|
||||||
std::string trans = std::string(S_CODEC_HEVC_PROFILE) + "." + kv.second;
|
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
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_INT);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(tier::UNKNOWN));
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
||||||
for (auto const kv : tiers) {
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "tier", p, S_CODEC_HEVC_TIER);
|
||||||
std::string trans = std::string(S_CODEC_HEVC_TIER) + "." + kv.second;
|
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
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_INT);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), static_cast<int64_t>(level::UNKNOWN));
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), 0);
|
||||||
for (auto const kv : levels) {
|
streamfx::ffmpeg::tools::avoption_list_add_entries_unnamed(context->priv_data, "level", p,
|
||||||
obs_property_list_add_int(p, kv.second.c_str(), static_cast<int64_t>(kv.first));
|
[](const AVOption* opt) {
|
||||||
}
|
if (opt->default_val.i64 == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nvenc::get_properties_post(props, codec);
|
nvenc::get_properties_post(props, codec, context);
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
avcodec_free_context(&context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvenc_hevc_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
|
void nvenc_hevc_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
|
||||||
|
|
|
@ -33,12 +33,17 @@ extern "C" {
|
||||||
#define ST_I18N_PRESET "Encoder.FFmpeg.NVENC.Preset"
|
#define ST_I18N_PRESET "Encoder.FFmpeg.NVENC.Preset"
|
||||||
#define ST_I18N_PRESET_(x) ST_I18N_PRESET "." D_VSTR(x)
|
#define ST_I18N_PRESET_(x) ST_I18N_PRESET "." D_VSTR(x)
|
||||||
#define ST_KEY_PRESET "Preset"
|
#define ST_KEY_PRESET "Preset"
|
||||||
|
#define ST_I18N_TUNE "Encoder.FFmpeg.NVENC.Tune"
|
||||||
|
#define ST_I18N_TUNE_(x) ST_I18N_TUNE "." D_VSTR(x)
|
||||||
|
#define ST_KEY_TUNE "Tune"
|
||||||
#define ST_I18N_RATECONTROL "Encoder.FFmpeg.NVENC.RateControl"
|
#define ST_I18N_RATECONTROL "Encoder.FFmpeg.NVENC.RateControl"
|
||||||
#define ST_I18N_RATECONTROL_MODE ST_I18N_RATECONTROL ".Mode"
|
#define ST_I18N_RATECONTROL_MODE ST_I18N_RATECONTROL ".Mode"
|
||||||
#define ST_I18N_RATECONTROL_MODE_(x) ST_I18N_RATECONTROL_MODE "." D_VSTR(x)
|
#define ST_I18N_RATECONTROL_MODE_(x) ST_I18N_RATECONTROL_MODE "." D_VSTR(x)
|
||||||
#define ST_KEY_RATECONTROL_MODE "RateControl.Mode"
|
#define ST_KEY_RATECONTROL_MODE "RateControl.Mode"
|
||||||
#define ST_I18N_RATECONTROL_TWOPASS ST_I18N_RATECONTROL ".TwoPass"
|
#define ST_I18N_RATECONTROL_TWOPASS ST_I18N_RATECONTROL ".TwoPass"
|
||||||
#define ST_KEY_RATECONTROL_TWOPASS "RateControl.TwoPass"
|
#define ST_KEY_RATECONTROL_TWOPASS "RateControl.TwoPass"
|
||||||
|
#define ST_I18N_RATECONTROL_MULTIPASS ST_I18N_RATECONTROL ".MultiPass"
|
||||||
|
#define ST_KEY_RATECONTROL_MULTIPASS "RateControl.MultiPass"
|
||||||
#define ST_I18N_RATECONTROL_LOOKAHEAD ST_I18N_RATECONTROL ".LookAhead"
|
#define ST_I18N_RATECONTROL_LOOKAHEAD ST_I18N_RATECONTROL ".LookAhead"
|
||||||
#define ST_KEY_RATECONTROL_LOOKAHEAD "RateControl.LookAhead"
|
#define ST_KEY_RATECONTROL_LOOKAHEAD "RateControl.LookAhead"
|
||||||
#define ST_I18N_RATECONTROL_ADAPTIVEI ST_I18N_RATECONTROL ".AdaptiveI"
|
#define ST_I18N_RATECONTROL_ADAPTIVEI ST_I18N_RATECONTROL ".AdaptiveI"
|
||||||
|
@ -86,66 +91,25 @@ extern "C" {
|
||||||
#define ST_KEY_OTHER_NONREFERENCEPFRAMES "Other.NonReferencePFrames"
|
#define ST_KEY_OTHER_NONREFERENCEPFRAMES "Other.NonReferencePFrames"
|
||||||
#define ST_I18N_OTHER_REFERENCEFRAMES ST_I18N_OTHER ".ReferenceFrames"
|
#define ST_I18N_OTHER_REFERENCEFRAMES ST_I18N_OTHER ".ReferenceFrames"
|
||||||
#define ST_KEY_OTHER_REFERENCEFRAMES "Other.ReferenceFrames"
|
#define ST_KEY_OTHER_REFERENCEFRAMES "Other.ReferenceFrames"
|
||||||
|
#define ST_I18N_OTHER_LOWDELAYKEYFRAMESCALE ST_I18N_OTHER ".LowDelayKeyFrameScale"
|
||||||
|
#define ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE "Other.LowDelayKeyFrameScale"
|
||||||
|
|
||||||
using namespace streamfx::encoder::ffmpeg::handler;
|
using namespace streamfx::encoder::ffmpeg::handler;
|
||||||
|
|
||||||
std::map<nvenc::preset, std::string> nvenc::presets{
|
inline bool is_cqp(std::string_view rc)
|
||||||
{nvenc::preset::DEFAULT, ST_I18N_PRESET_(Default)},
|
{
|
||||||
{nvenc::preset::SLOW, ST_I18N_PRESET_(Slow)},
|
return std::string_view("constqp") == rc;
|
||||||
{nvenc::preset::MEDIUM, ST_I18N_PRESET_(Medium)},
|
}
|
||||||
{nvenc::preset::FAST, ST_I18N_PRESET_(Fast)},
|
|
||||||
{nvenc::preset::HIGH_PERFORMANCE, ST_I18N_PRESET_(HighPerformance)},
|
|
||||||
{nvenc::preset::HIGH_QUALITY, ST_I18N_PRESET_(HighQuality)},
|
|
||||||
{nvenc::preset::BLURAYDISC, ST_I18N_PRESET_(BluRayDisc)},
|
|
||||||
{nvenc::preset::LOW_LATENCY, ST_I18N_PRESET_(LowLatency)},
|
|
||||||
{nvenc::preset::LOW_LATENCY_HIGH_PERFORMANCE, ST_I18N_PRESET_(LowLatencyHighPerformance)},
|
|
||||||
{nvenc::preset::LOW_LATENCY_HIGH_QUALITY, ST_I18N_PRESET_(LowLatencyHighQuality)},
|
|
||||||
{nvenc::preset::LOSSLESS, ST_I18N_PRESET_(Lossless)},
|
|
||||||
{nvenc::preset::LOSSLESS_HIGH_PERFORMANCE, ST_I18N_PRESET_(LosslessHighPerformance)},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<nvenc::preset, std::string> nvenc::preset_to_opt{
|
inline bool is_cbr(std::string_view rc)
|
||||||
{nvenc::preset::DEFAULT, "default"},
|
{
|
||||||
{nvenc::preset::SLOW, "slow"},
|
return std::string_view("cbr") == rc;
|
||||||
{nvenc::preset::MEDIUM, "medium"},
|
}
|
||||||
{nvenc::preset::FAST, "fast"},
|
|
||||||
{nvenc::preset::HIGH_PERFORMANCE, "hp"},
|
|
||||||
{nvenc::preset::HIGH_QUALITY, "hq"},
|
|
||||||
{nvenc::preset::BLURAYDISC, "bd"},
|
|
||||||
{nvenc::preset::LOW_LATENCY, "ll"},
|
|
||||||
{nvenc::preset::LOW_LATENCY_HIGH_PERFORMANCE, "llhp"},
|
|
||||||
{nvenc::preset::LOW_LATENCY_HIGH_QUALITY, "llhq"},
|
|
||||||
{nvenc::preset::LOSSLESS, "lossless"},
|
|
||||||
{nvenc::preset::LOSSLESS_HIGH_PERFORMANCE, "losslesshp"},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<nvenc::ratecontrolmode, std::string> nvenc::ratecontrolmodes{
|
inline bool is_vbr(std::string_view rc)
|
||||||
{nvenc::ratecontrolmode::CQP, ST_I18N_RATECONTROL_MODE_(CQP)},
|
{
|
||||||
{nvenc::ratecontrolmode::VBR, ST_I18N_RATECONTROL_MODE_(VBR)},
|
return std::string_view("vbr") == rc;
|
||||||
{nvenc::ratecontrolmode::VBR_HQ, ST_I18N_RATECONTROL_MODE_(VBR_HQ)},
|
}
|
||||||
{nvenc::ratecontrolmode::CBR, ST_I18N_RATECONTROL_MODE_(CBR)},
|
|
||||||
{nvenc::ratecontrolmode::CBR_HQ, ST_I18N_RATECONTROL_MODE_(CBR_HQ)},
|
|
||||||
{nvenc::ratecontrolmode::CBR_LD_HQ, ST_I18N_RATECONTROL_MODE_(CBR_LD_HQ)},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<nvenc::ratecontrolmode, std::string> nvenc::ratecontrolmode_to_opt{
|
|
||||||
{nvenc::ratecontrolmode::CQP, "constqp"}, {nvenc::ratecontrolmode::VBR, "vbr"},
|
|
||||||
{nvenc::ratecontrolmode::VBR_HQ, "vbr_hq"}, {nvenc::ratecontrolmode::CBR, "cbr"},
|
|
||||||
{nvenc::ratecontrolmode::CBR_HQ, "cbr_hq"}, {nvenc::ratecontrolmode::CBR_LD_HQ, "cbr_ld_hq"},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<nvenc::b_ref_mode, std::string> nvenc::b_ref_modes{
|
|
||||||
{nvenc::b_ref_mode::INVALID, S_STATE_DEFAULT},
|
|
||||||
{nvenc::b_ref_mode::DISABLED, S_STATE_DISABLED},
|
|
||||||
{nvenc::b_ref_mode::EACH, ST_I18N_OTHER_BFRAMEREFERENCEMODE ".Each"},
|
|
||||||
{nvenc::b_ref_mode::MIDDLE, ST_I18N_OTHER_BFRAMEREFERENCEMODE ".Middle"},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<nvenc::b_ref_mode, std::string> nvenc::b_ref_mode_to_opt{
|
|
||||||
{nvenc::b_ref_mode::DISABLED, "disabled"},
|
|
||||||
{nvenc::b_ref_mode::EACH, "each"},
|
|
||||||
{nvenc::b_ref_mode::MIDDLE, "middle"},
|
|
||||||
};
|
|
||||||
|
|
||||||
bool streamfx::encoder::ffmpeg::handler::nvenc::is_available()
|
bool streamfx::encoder::ffmpeg::handler::nvenc::is_available()
|
||||||
{
|
{
|
||||||
|
@ -198,9 +162,9 @@ 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, static_cast<int64_t>(nvenc::preset::DEFAULT));
|
obs_data_set_default_int(settings, ST_KEY_PRESET, -1);
|
||||||
|
|
||||||
obs_data_set_default_int(settings, ST_KEY_RATECONTROL_MODE, static_cast<int64_t>(ratecontrolmode::CBR_HQ));
|
obs_data_set_default_int(settings, ST_KEY_RATECONTROL_MODE, -1);
|
||||||
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_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);
|
||||||
|
@ -222,11 +186,12 @@ void nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*)
|
||||||
obs_data_set_default_int(settings, ST_KEY_AQ_TEMPORAL, -1);
|
obs_data_set_default_int(settings, ST_KEY_AQ_TEMPORAL, -1);
|
||||||
|
|
||||||
obs_data_set_default_int(settings, ST_KEY_OTHER_BFRAMES, -1);
|
obs_data_set_default_int(settings, ST_KEY_OTHER_BFRAMES, -1);
|
||||||
obs_data_set_default_int(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE, static_cast<int64_t>(b_ref_mode::INVALID));
|
obs_data_set_default_int(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE, -1);
|
||||||
obs_data_set_default_int(settings, ST_KEY_OTHER_ZEROLATENCY, -1);
|
obs_data_set_default_int(settings, ST_KEY_OTHER_ZEROLATENCY, -1);
|
||||||
obs_data_set_default_int(settings, ST_KEY_OTHER_WEIGHTEDPREDICTION, -1);
|
obs_data_set_default_int(settings, ST_KEY_OTHER_WEIGHTEDPREDICTION, -1);
|
||||||
obs_data_set_default_int(settings, ST_KEY_OTHER_NONREFERENCEPFRAMES, -1);
|
obs_data_set_default_int(settings, ST_KEY_OTHER_NONREFERENCEPFRAMES, -1);
|
||||||
obs_data_set_default_int(settings, ST_KEY_OTHER_REFERENCEFRAMES, -1);
|
obs_data_set_default_int(settings, ST_KEY_OTHER_REFERENCEFRAMES, -1);
|
||||||
|
obs_data_set_default_int(settings, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE, -1);
|
||||||
|
|
||||||
// Replay Buffer
|
// Replay Buffer
|
||||||
obs_data_set_default_int(settings, "bitrate", 0);
|
obs_data_set_default_int(settings, "bitrate", 0);
|
||||||
|
@ -234,33 +199,29 @@ 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.
|
||||||
|
auto value = obs_data_get_int(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) {
|
||||||
nvenc::ratecontrolmode rc =
|
have_bitrate = true;
|
||||||
static_cast<nvenc::ratecontrolmode>(obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE));
|
} else if (value == 1) {
|
||||||
switch (rc) {
|
have_bitrate = true;
|
||||||
case nvenc::ratecontrolmode::CQP:
|
have_bitrate_range = true;
|
||||||
have_qp = true;
|
have_quality = true;
|
||||||
break;
|
have_qp_limits = true;
|
||||||
case nvenc::ratecontrolmode::INVALID:
|
have_qp = true;
|
||||||
case nvenc::ratecontrolmode::CBR:
|
} else if (value == 0) {
|
||||||
case nvenc::ratecontrolmode::CBR_HQ:
|
have_qp = true;
|
||||||
case nvenc::ratecontrolmode::CBR_LD_HQ:
|
} else {
|
||||||
have_bitrate = true;
|
|
||||||
have_qp_limits = true;
|
|
||||||
break;
|
|
||||||
case nvenc::ratecontrolmode::VBR:
|
|
||||||
case nvenc::ratecontrolmode::VBR_HQ:
|
|
||||||
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;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_I18N_RATECONTROL_LIMITS), have_bitrate || have_quality);
|
obs_property_set_visible(obs_properties_get(props, ST_I18N_RATECONTROL_LIMITS), have_bitrate || have_quality);
|
||||||
|
@ -286,16 +247,22 @@ static bool modified_aq(obs_properties_t* props, obs_property_t*, obs_data_t* se
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvenc::get_properties_pre(obs_properties_t* props, const AVCodec*)
|
void nvenc::get_properties_pre(obs_properties_t* props, const AVCodec*, const AVCodecContext* context)
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(props, ST_KEY_PRESET, D_TRANSLATE(ST_I18N_PRESET), OBS_COMBO_TYPE_LIST,
|
{
|
||||||
OBS_COMBO_FORMAT_INT);
|
auto p = obs_properties_add_list(props, ST_KEY_PRESET, D_TRANSLATE(ST_I18N_PRESET), OBS_COMBO_TYPE_LIST,
|
||||||
for (auto kv : presets) {
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(kv.second.c_str()), static_cast<int64_t>(kv.first));
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "preset", p, ST_I18N_PRESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
OBS_COMBO_FORMAT_INT);
|
||||||
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "tune", p, ST_I18N_TUNE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec)
|
void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec, const AVCodecContext* context)
|
||||||
{
|
{
|
||||||
{ // Rate Control
|
{ // Rate Control
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
|
@ -309,12 +276,23 @@ void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec)
|
||||||
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_INT);
|
||||||
obs_property_set_modified_callback(p, modified_ratecontrol);
|
obs_property_set_modified_callback(p, modified_ratecontrol);
|
||||||
for (auto kv : ratecontrolmodes) {
|
auto filter = [](const AVOption* opt) {
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(kv.second.c_str()), static_cast<int64_t>(kv.first));
|
if (opt->default_val.i64 & (1 << 23))
|
||||||
}
|
return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "rc", p, ST_I18N_RATECONTROL_MODE,
|
||||||
|
filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) {
|
||||||
|
auto p =
|
||||||
|
obs_properties_add_list(grp, ST_KEY_RATECONTROL_MULTIPASS, D_TRANSLATE(ST_I18N_RATECONTROL_MULTIPASS),
|
||||||
|
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
||||||
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "multipass", p,
|
||||||
|
ST_I18N_RATECONTROL_MULTIPASS);
|
||||||
|
} 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));
|
||||||
}
|
}
|
||||||
|
@ -347,7 +325,7 @@ void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec)
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_float_slider(grp, ST_KEY_RATECONTROL_LIMITS_QUALITY,
|
auto p = obs_properties_add_float_slider(grp, ST_KEY_RATECONTROL_LIMITS_QUALITY,
|
||||||
D_TRANSLATE(ST_I18N_RATECONTROL_LIMITS_QUALITY), 0, 100, 0.01);
|
D_TRANSLATE(ST_I18N_RATECONTROL_LIMITS_QUALITY), 0, 51, 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -442,13 +420,9 @@ void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec)
|
||||||
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_INT);
|
||||||
for (auto kv : b_ref_modes) {
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
||||||
if (kv.first == nvenc::b_ref_mode::EACH && (std::string_view("h264_nvenc") == codec->name)) {
|
streamfx::ffmpeg::tools::avoption_list_add_entries(context->priv_data, "b_ref_mode", p,
|
||||||
// H.264 does not support using all B-Frames as reference.
|
ST_I18N_OTHER_BFRAMEREFERENCEMODE);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(kv.second.c_str()), static_cast<int64_t>(kv.first));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -472,15 +446,22 @@ void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec)
|
||||||
(strcmp(codec->name, "h264_nvenc") == 0) ? 16 : 4, 1);
|
(strcmp(codec->name, "h264_nvenc") == 0) ? 16 : 4, 1);
|
||||||
obs_property_int_set_suffix(p, " frames");
|
obs_property_int_set_suffix(p, " frames");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "ldkfs")) {
|
||||||
|
auto p = obs_properties_add_int_slider(grp, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE,
|
||||||
|
D_TRANSLATE(ST_I18N_OTHER_LOWDELAYKEYFRAMESCALE), -1, 255, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvenc::get_runtime_properties(obs_properties_t* props, const AVCodec*, AVCodecContext*)
|
void nvenc::get_runtime_properties(obs_properties_t* props, const AVCodec*, AVCodecContext*)
|
||||||
{
|
{
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_PRESET), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_PRESET), false);
|
||||||
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_TUNE), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_I18N_RATECONTROL), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_I18N_RATECONTROL), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_MODE), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_MODE), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_TWOPASS), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_TWOPASS), false);
|
||||||
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_MULTIPASS), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_LOOKAHEAD), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_LOOKAHEAD), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_ADAPTIVEI), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_ADAPTIVEI), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_ADAPTIVEB), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_RATECONTROL_ADAPTIVEB), false);
|
||||||
|
@ -506,84 +487,91 @@ void nvenc::get_runtime_properties(obs_properties_t* props, const AVCodec*, AVCo
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_OTHER_WEIGHTEDPREDICTION), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_OTHER_WEIGHTEDPREDICTION), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_OTHER_NONREFERENCEPFRAMES), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_OTHER_NONREFERENCEPFRAMES), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_OTHER_REFERENCEFRAMES), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_OTHER_REFERENCEFRAMES), false);
|
||||||
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (!context->internal) {
|
||||||
preset c_preset = static_cast<preset>(obs_data_get_int(settings, ST_KEY_PRESET));
|
auto value = obs_data_get_int(settings, ST_KEY_PRESET);
|
||||||
auto found = preset_to_opt.find(c_preset);
|
if (value != -1) {
|
||||||
if (found != preset_to_opt.end()) {
|
auto name = streamfx::ffmpeg::tools::avoption_name_from_unit_value(context->priv_data, "preset", value);
|
||||||
av_opt_set(context->priv_data, "preset", found->second.c_str(), 0);
|
if (name) {
|
||||||
} else {
|
av_opt_set(context->priv_data, "preset", name, AV_OPT_SEARCH_CHILDREN);
|
||||||
av_opt_set(context->priv_data, "preset", nullptr, 0);
|
} 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 name = streamfx::ffmpeg::tools::avoption_name_from_unit_value(context->priv_data, "rc", value);
|
||||||
|
if (value != -1) {
|
||||||
|
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.
|
||||||
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 (is_cbr(name)) {
|
||||||
|
have_bitrate = true;
|
||||||
|
|
||||||
ratecontrolmode rc = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE));
|
if (!context->internal)
|
||||||
auto rcopt = ratecontrolmode_to_opt.find(rc);
|
av_opt_set_int(context->priv_data, "cbr", 1, AV_OPT_SEARCH_CHILDREN);
|
||||||
if (rcopt != ratecontrolmode_to_opt.end()) {
|
|
||||||
if (!context->internal) {
|
// Support for OBS Studio
|
||||||
av_opt_set(context->priv_data, "rc", rcopt->second.c_str(), AV_OPT_SEARCH_CHILDREN);
|
obs_data_set_string(settings, "rate_control", "CBR");
|
||||||
}
|
} else if (is_vbr(name)) {
|
||||||
|
have_bitrate = true;
|
||||||
|
have_bitrate_range = true;
|
||||||
|
have_quality = true;
|
||||||
|
have_qp_limits = true;
|
||||||
|
have_qp = true;
|
||||||
|
|
||||||
|
if (!context->internal)
|
||||||
|
av_opt_set_int(context->priv_data, "cbr", 0, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
|
||||||
|
// Support for OBS Studio
|
||||||
|
obs_data_set_string(settings, "rate_control", "VBR");
|
||||||
|
} else if (is_cqp(name)) {
|
||||||
|
have_qp = true;
|
||||||
|
|
||||||
|
if (!context->internal)
|
||||||
|
av_opt_set_int(context->priv_data, "cbr", 0, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
|
||||||
|
// Support for OBS Studio
|
||||||
|
obs_data_set_string(settings, "rate_control", "CQP");
|
||||||
} else {
|
} else {
|
||||||
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;
|
||||||
|
|
||||||
|
if (!context->internal)
|
||||||
|
av_opt_set_int(context->priv_data, "cbr", 0, AV_OPT_SEARCH_CHILDREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context->internal) {
|
if (!context->internal) {
|
||||||
av_opt_set_int(context->priv_data, "cbr", 0, AV_OPT_SEARCH_CHILDREN);
|
if (streamfx::ffmpeg::tools::avoption_exists(context->priv_data, "multipass")) {
|
||||||
}
|
// Multi-Pass
|
||||||
switch (rc) {
|
if (int tp = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_MULTIPASS)); tp > -1) {
|
||||||
case ratecontrolmode::CQP:
|
av_opt_set_int(context->priv_data, "multipass", tp, AV_OPT_SEARCH_CHILDREN);
|
||||||
have_qp = true;
|
av_opt_set_int(context->priv_data, "2pass", 0, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
}
|
||||||
{ // Support for OBS Studio
|
} else {
|
||||||
obs_data_set_string(settings, "rate_control", "CQP");
|
// Two-Pass
|
||||||
}
|
if (int tp = static_cast<int>(obs_data_get_int(settings, ST_KEY_RATECONTROL_TWOPASS)); tp > -1) {
|
||||||
break;
|
av_opt_set_int(context->priv_data, "2pass", tp ? 1 : 0, AV_OPT_SEARCH_CHILDREN);
|
||||||
case ratecontrolmode::INVALID:
|
}
|
||||||
case ratecontrolmode::CBR:
|
|
||||||
case ratecontrolmode::CBR_HQ:
|
|
||||||
case ratecontrolmode::CBR_LD_HQ:
|
|
||||||
have_bitrate = true;
|
|
||||||
have_qp_limits = true;
|
|
||||||
if (!context->internal) {
|
|
||||||
av_opt_set_int(context->priv_data, "cbr", 1, AV_OPT_SEARCH_CHILDREN);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // Support for OBS Studio
|
|
||||||
obs_data_set_string(settings, "rate_control", "CBR");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ratecontrolmode::VBR:
|
|
||||||
case ratecontrolmode::VBR_HQ:
|
|
||||||
have_bitrate_range = true;
|
|
||||||
have_bitrate = true;
|
|
||||||
have_quality = true;
|
|
||||||
have_qp = true;
|
|
||||||
have_qp_limits = true;
|
|
||||||
|
|
||||||
{ // Support for OBS Studio
|
|
||||||
obs_data_set_string(settings, "rate_control", "VBR");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context->internal) {
|
|
||||||
// Two Pass
|
|
||||||
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
|
||||||
|
@ -600,8 +588,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adaptive B-Frames
|
// Adaptive B-Frames
|
||||||
constexpr std::string_view h264_encoder_name = "h264_nvenc";
|
if (std::string_view("h264_nvenc") == 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);
|
||||||
|
@ -661,8 +648,7 @@ 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;
|
if (double_t v = obs_data_get_double(settings, ST_KEY_RATECONTROL_LIMITS_QUALITY); v > 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 {
|
||||||
|
@ -703,7 +689,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
|
|
||||||
if (!context->internal) { // 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);
|
av_opt_set_int(context, "bf", bf, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
|
||||||
if (int64_t zl = obs_data_get_int(settings, ST_KEY_OTHER_ZEROLATENCY); !streamfx::util::is_tristate_default(zl))
|
if (int64_t zl = obs_data_get_int(settings, ST_KEY_OTHER_ZEROLATENCY); !streamfx::util::is_tristate_default(zl))
|
||||||
av_opt_set_int(context->priv_data, "zerolatency", zl, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_int(context->priv_data, "zerolatency", zl, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
@ -711,7 +697,7 @@ void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* c
|
||||||
!streamfx::util::is_tristate_default(nrp))
|
!streamfx::util::is_tristate_default(nrp))
|
||||||
av_opt_set_int(context->priv_data, "nonref_p", nrp, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_int(context->priv_data, "nonref_p", nrp, AV_OPT_SEARCH_CHILDREN);
|
||||||
if (int64_t v = obs_data_get_int(settings, ST_KEY_OTHER_REFERENCEFRAMES); v > -1)
|
if (int64_t v = obs_data_get_int(settings, ST_KEY_OTHER_REFERENCEFRAMES); v > -1)
|
||||||
context->refs = v;
|
av_opt_set_int(context, "refs", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
|
||||||
int64_t wp = obs_data_get_int(settings, ST_KEY_OTHER_WEIGHTEDPREDICTION);
|
int64_t wp = obs_data_get_int(settings, ST_KEY_OTHER_WEIGHTEDPREDICTION);
|
||||||
if ((context->max_b_frames > 0) && streamfx::util::is_tristate_enabled(wp)) {
|
if ((context->max_b_frames > 0) && streamfx::util::is_tristate_enabled(wp)) {
|
||||||
|
@ -721,12 +707,12 @@ 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) {
|
||||||
auto found = b_ref_mode_to_opt.find(
|
av_opt_set_int(context->priv_data, "b_ref_mode", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
static_cast<b_ref_mode>(obs_data_get_int(settings, ST_KEY_OTHER_BFRAMEREFERENCEMODE)));
|
}
|
||||||
if (found != b_ref_mode_to_opt.end()) {
|
|
||||||
av_opt_set(context->priv_data, "b_ref_mode", found->second.c_str(), AV_OPT_SEARCH_CHILDREN);
|
if (auto v = obs_data_get_int(settings, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE); v > -1) {
|
||||||
}
|
av_opt_set_int(context->priv_data, "ldkfs", v, AV_OPT_SEARCH_CHILDREN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -741,6 +727,8 @@ void nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecContext* conte
|
||||||
tools::print_av_option_string2(context, "rc", " Rate Control",
|
tools::print_av_option_string2(context, "rc", " Rate Control",
|
||||||
[](int64_t v, std::string_view o) { return std::string(o); });
|
[](int64_t v, std::string_view o) { return std::string(o); });
|
||||||
tools::print_av_option_bool(context, "2pass", " Two Pass");
|
tools::print_av_option_bool(context, "2pass", " Two Pass");
|
||||||
|
tools::print_av_option_string2(context, "multipass", " Multi-Pass",
|
||||||
|
[](int64_t v, std::string_view o) { return std::string(o); });
|
||||||
tools::print_av_option_int(context, "rc-lookahead", " Look-Ahead", "Frames");
|
tools::print_av_option_int(context, "rc-lookahead", " Look-Ahead", "Frames");
|
||||||
tools::print_av_option_bool(context, "no-scenecut", " Adaptive I-Frames", true);
|
tools::print_av_option_bool(context, "no-scenecut", " Adaptive I-Frames", true);
|
||||||
if (strcmp(codec->name, "h264_nvenc") == 0)
|
if (strcmp(codec->name, "h264_nvenc") == 0)
|
||||||
|
@ -759,6 +747,8 @@ void nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecContext* conte
|
||||||
tools::print_av_option_int(context, "init_qpI", " I-Frame", "");
|
tools::print_av_option_int(context, "init_qpI", " I-Frame", "");
|
||||||
tools::print_av_option_int(context, "init_qpP", " P-Frame", "");
|
tools::print_av_option_int(context, "init_qpP", " P-Frame", "");
|
||||||
tools::print_av_option_int(context, "init_qpB", " B-Frame", "");
|
tools::print_av_option_int(context, "init_qpB", " B-Frame", "");
|
||||||
|
tools::print_av_option_int(context, "qp_cb_offset", " CB Offset", "");
|
||||||
|
tools::print_av_option_int(context, "qp_cr_offset", " CR Offset", "");
|
||||||
|
|
||||||
tools::print_av_option_int(context, "bf", " B-Frames", "Frames");
|
tools::print_av_option_int(context, "bf", " B-Frames", "Frames");
|
||||||
tools::print_av_option_string2(context, "b_ref_mode", " Reference Mode",
|
tools::print_av_option_string2(context, "b_ref_mode", " Reference Mode",
|
||||||
|
@ -783,9 +773,14 @@ void nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecContext* conte
|
||||||
tools::print_av_option_bool(context, "strict_gop", " Strict GOP");
|
tools::print_av_option_bool(context, "strict_gop", " Strict GOP");
|
||||||
tools::print_av_option_bool(context, "aud", " Access Unit Delimiters");
|
tools::print_av_option_bool(context, "aud", " Access Unit Delimiters");
|
||||||
tools::print_av_option_bool(context, "bluray-compat", " Bluray Compatibility");
|
tools::print_av_option_bool(context, "bluray-compat", " Bluray Compatibility");
|
||||||
if (strcmp(codec->name, "h264_nvenc") == 0)
|
tools::print_av_option_bool(context, "a53cc", " A53 Closed Captions");
|
||||||
tools::print_av_option_bool(context, "a53cc", " A53 Closed Captions");
|
|
||||||
tools::print_av_option_int(context, "dpb_size", " DPB Size", "Frames");
|
tools::print_av_option_int(context, "dpb_size", " DPB Size", "Frames");
|
||||||
|
tools::print_av_option_int(context, "ldkfs", " DPB Size", "Frames");
|
||||||
|
tools::print_av_option_bool(context, "extra_sei", " Extra SEI Data");
|
||||||
|
tools::print_av_option_bool(context, "udu_sei", " User SEI Data");
|
||||||
|
tools::print_av_option_bool(context, "intra-refresh", " Intra-Refresh");
|
||||||
|
tools::print_av_option_bool(context, "single-slice-intra-refresh", " Single Slice Intra-Refresh");
|
||||||
|
tools::print_av_option_bool(context, "constrained-encoding", " Constrained Encoding");
|
||||||
}
|
}
|
||||||
|
|
||||||
void streamfx::encoder::ffmpeg::handler::nvenc::migrate(obs_data_t* settings, uint64_t version, const AVCodec* codec,
|
void streamfx::encoder::ffmpeg::handler::nvenc::migrate(obs_data_t* settings, uint64_t version, const AVCodec* codec,
|
||||||
|
@ -814,5 +809,31 @@ void streamfx::encoder::ffmpeg::handler::nvenc::migrate(obs_data_t* settings, ui
|
||||||
obs_data_unset_user_value(settings, "Other.DecodedPictureBufferSize");
|
obs_data_unset_user_value(settings, "Other.DecodedPictureBufferSize");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version < STREAMFX_MAKE_VERSION(0, 11, 1, 0)) {
|
||||||
|
if (auto v = obs_data_get_int(settings, ST_KEY_RATECONTROL_MODE); v != -1) {
|
||||||
|
switch (v) {
|
||||||
|
case 0: // CQP
|
||||||
|
break;
|
||||||
|
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_MULTIPASS, 1);
|
||||||
|
case 1: // VBR
|
||||||
|
break;
|
||||||
|
case 5: // CBR_LD_HQ
|
||||||
|
obs_data_set_int(settings, ST_KEY_OTHER_LOWDELAYKEYFRAMESCALE, 1);
|
||||||
|
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_MULTIPASS, 1);
|
||||||
|
case 3: // CBR
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#undef COPY_UNSET
|
#undef COPY_UNSET
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,63 +42,15 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace streamfx::encoder::ffmpeg::handler::nvenc {
|
namespace streamfx::encoder::ffmpeg::handler::nvenc {
|
||||||
enum class preset : int64_t {
|
|
||||||
DEFAULT,
|
|
||||||
SLOW,
|
|
||||||
MEDIUM,
|
|
||||||
FAST,
|
|
||||||
HIGH_PERFORMANCE,
|
|
||||||
HIGH_QUALITY,
|
|
||||||
BLURAYDISC,
|
|
||||||
LOW_LATENCY,
|
|
||||||
LOW_LATENCY_HIGH_PERFORMANCE,
|
|
||||||
LOW_LATENCY_HIGH_QUALITY,
|
|
||||||
LOSSLESS,
|
|
||||||
LOSSLESS_HIGH_PERFORMANCE,
|
|
||||||
// Append things before this.
|
|
||||||
INVALID = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ratecontrolmode : int64_t {
|
|
||||||
CQP,
|
|
||||||
VBR,
|
|
||||||
VBR_HQ,
|
|
||||||
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;
|
|
||||||
|
|
||||||
extern std::map<preset, std::string> preset_to_opt;
|
|
||||||
|
|
||||||
extern std::map<ratecontrolmode, std::string> ratecontrolmodes;
|
|
||||||
|
|
||||||
extern std::map<ratecontrolmode, std::string> ratecontrolmode_to_opt;
|
|
||||||
|
|
||||||
extern std::map<b_ref_mode, std::string> b_ref_modes;
|
|
||||||
|
|
||||||
extern std::map<b_ref_mode, std::string> b_ref_mode_to_opt;
|
|
||||||
|
|
||||||
bool is_available();
|
bool is_available();
|
||||||
|
|
||||||
void override_update(ffmpeg_instance* instance, obs_data_t* settings);
|
void override_update(ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
|
||||||
void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
void get_properties_pre(obs_properties_t* props, const AVCodec* codec);
|
void get_properties_pre(obs_properties_t* props, const AVCodec* codec, const AVCodecContext* context);
|
||||||
|
|
||||||
void get_properties_post(obs_properties_t* props, const AVCodec* codec);
|
void get_properties_post(obs_properties_t* props, const AVCodec* codec, const AVCodecContext* context);
|
||||||
|
|
||||||
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
|
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue