Skip to content

Commit

Permalink
Eliminate the QP fallback code that was only required for VAAPI
Browse files Browse the repository at this point in the history
  • Loading branch information
cgutman committed Nov 1, 2024
1 parent 2dd5027 commit c9c6095
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 92 deletions.
7 changes: 6 additions & 1 deletion src/platform/linux/vaapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,14 @@ namespace va {
av_dict_set(options, "rc_mode", "CBR", 0);

Check warning on line 287 in src/platform/linux/vaapi.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/vaapi.cpp#L287

Added line #L287 was not covered by tests
}
else {
BOOST_LOG(info) << "Using default rate control with single frame VBV size"sv;
BOOST_LOG(warning) << "Using CQP with single frame VBV size"sv;
av_dict_set_int(options, "qp", config::video.qp, 0);

Check warning on line 291 in src/platform/linux/vaapi.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/vaapi.cpp#L291

Added line #L291 was not covered by tests
}
}
else if (!(rc_attr.value & (VA_RC_CBR | VA_RC_VBR))) {
BOOST_LOG(warning) << "Using CQP rate control"sv;
av_dict_set_int(options, "qp", config::video.qp, 0);

Check warning on line 296 in src/platform/linux/vaapi.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/vaapi.cpp#L296

Added line #L296 was not covered by tests
}
else {
BOOST_LOG(info) << "Using default rate control"sv;
}
Expand Down
113 changes: 29 additions & 84 deletions src/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"av1_nvenc"s,
},
{
Expand All @@ -472,7 +471,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"hevc_nvenc"s,
},
{
Expand All @@ -482,7 +480,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"h264_nvenc"s,
},
PARALLEL_ENCODING | REF_FRAMES_INVALIDATION | YUV444_SUPPORT // flags
Expand Down Expand Up @@ -525,7 +522,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"av1_nvenc"s,
},
{
Expand All @@ -552,7 +548,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"hevc_nvenc"s,
},
{
Expand All @@ -576,7 +571,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"h264_nvenc"s,
},
PARALLEL_ENCODING
Expand Down Expand Up @@ -618,7 +612,6 @@ namespace video {
{ "profile"s, (int) qsv::profile_av1_e::high },
},
{}, // Fallback options
std::nullopt, // QP rate control fallback
"av1_qsv"s,
},
{
Expand Down Expand Up @@ -652,7 +645,6 @@ namespace video {
// Fallback options
{ "low_power"s, []() { return config::video.qsv.qsv_slow_hevc ? 0 : 1; } },
},
std::nullopt, // QP rate control fallback
"hevc_qsv"s,
},
{
Expand Down Expand Up @@ -683,7 +675,6 @@ namespace video {
// Fallback options
{ "low_power"s, 0 }, // Some old/low-end Intel GPUs don't support low power encoding
},
std::nullopt, // QP rate control fallback
"h264_qsv"s,
},
PARALLEL_ENCODING | CBR_WITH_VBR | RELAXED_COMPLIANCE | NO_RC_BUF_LIMIT | YUV444_SUPPORT
Expand Down Expand Up @@ -716,7 +707,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"av1_amf"s,
},
{
Expand All @@ -741,7 +731,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"hevc_amf"s,
},
{
Expand All @@ -767,7 +756,6 @@ namespace video {
// Fallback options
{ "usage"s, 2 /* AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY */ }, // Workaround for https://github.com/GPUOpen-LibrariesAndSDKs/AMF/issues/410
},
std::nullopt, // QP rate control fallback
"h264_amf"s,
},
PARALLEL_ENCODING
Expand Down Expand Up @@ -797,13 +785,10 @@ namespace video {
{}, // YUV444 HDR-specific options
{}, // Fallback options

// QP rate control fallback
std::nullopt,

#ifdef ENABLE_BROKEN_AV1_ENCODER
// Due to bugs preventing on-demand IDR frames from working and very poor
// real-time encoding performance, we do not enable libsvtav1 by default.
// It is only suitable for testing AV1 until the IDR frame issue is fixed.
// Due to bugs preventing on-demand IDR frames from working and very poor
// real-time encoding performance, we do not enable libsvtav1 by default.
// It is only suitable for testing AV1 until the IDR frame issue is fixed.
"libsvtav1"s,
#else
{},
Expand All @@ -825,7 +810,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"libx265"s,
},
{
Expand All @@ -839,7 +823,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt, // QP rate control fallback
"libx264"s,
},
H264_ONLY | PARALLEL_ENCODING | ALWAYS_REPROBE | YUV444_SUPPORT
Expand All @@ -865,7 +848,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
"av1_vaapi"s,
},
{
Expand All @@ -880,7 +862,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
"hevc_vaapi"s,
},
{
Expand All @@ -895,7 +876,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
"h264_vaapi"s,
},
// RC buffer size will be set in platform code if supported
Expand Down Expand Up @@ -926,7 +906,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt,
"av1_videotoolbox"s,
},
{
Expand All @@ -943,7 +922,6 @@ namespace video {
{}, // YUV444 SDR-specific options
{}, // YUV444 HDR-specific options
{}, // Fallback options
std::nullopt,
"hevc_videotoolbox"s,
},
{
Expand All @@ -963,7 +941,6 @@ namespace video {
// Fallback options
{ "flags"s, "-low_delay" },
},
std::nullopt,
"h264_videotoolbox"s,
},
DEFAULT
Expand Down Expand Up @@ -1639,49 +1616,40 @@ namespace video {
}
}

if (video_format[encoder_t::CBR]) {
auto bitrate = config.bitrate * 1000;
ctx->rc_max_rate = bitrate;
ctx->bit_rate = bitrate;
auto bitrate = config.bitrate * 1000;
ctx->rc_max_rate = bitrate;
ctx->bit_rate = bitrate;

if (encoder.flags & CBR_WITH_VBR) {
// Ensure rc_max_bitrate != bit_rate to force VBR mode
ctx->bit_rate--;
}
else {
ctx->rc_min_rate = bitrate;
}
if (encoder.flags & CBR_WITH_VBR) {
// Ensure rc_max_bitrate != bit_rate to force VBR mode
ctx->bit_rate--;
}
else {
ctx->rc_min_rate = bitrate;
}

if (encoder.flags & RELAXED_COMPLIANCE) {
ctx->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
}
if (encoder.flags & RELAXED_COMPLIANCE) {
ctx->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
}

if (!(encoder.flags & NO_RC_BUF_LIMIT)) {
if (!hardware && (ctx->slices > 1 || config.videoFormat == 1)) {
// Use a larger rc_buffer_size for software encoding when slices are enabled,
// because libx264 can severely degrade quality if the buffer is too small.
// libx265 encounters this issue more frequently, so always scale the
// buffer by 1.5x for software HEVC encoding.
ctx->rc_buffer_size = bitrate / ((config.framerate * 10) / 15);
}
else {
ctx->rc_buffer_size = bitrate / config.framerate;
if (!(encoder.flags & NO_RC_BUF_LIMIT)) {
if (!hardware && (ctx->slices > 1 || config.videoFormat == 1)) {
// Use a larger rc_buffer_size for software encoding when slices are enabled,
// because libx264 can severely degrade quality if the buffer is too small.
// libx265 encounters this issue more frequently, so always scale the
// buffer by 1.5x for software HEVC encoding.
ctx->rc_buffer_size = bitrate / ((config.framerate * 10) / 15);
}
else {
ctx->rc_buffer_size = bitrate / config.framerate;

#ifndef __APPLE__
if (encoder.name == "nvenc" && config::video.nv_legacy.vbv_percentage_increase > 0) {
ctx->rc_buffer_size += ctx->rc_buffer_size * config::video.nv_legacy.vbv_percentage_increase / 100;
}
#endif
if (encoder.name == "nvenc" && config::video.nv_legacy.vbv_percentage_increase > 0) {
ctx->rc_buffer_size += ctx->rc_buffer_size * config::video.nv_legacy.vbv_percentage_increase / 100;

Check warning on line 1648 in src/video.cpp

View check run for this annotation

Codecov / codecov/patch

src/video.cpp#L1648

Added line #L1648 was not covered by tests
}
#endif
}
}
else if (video_format.qp) {
handle_option(*video_format.qp);
}
else {
BOOST_LOG(error) << "Couldn't set video quality: encoder "sv << encoder.name << " doesn't support qp"sv;
return nullptr;
}

// Allow the encoding device a final opportunity to set/unset or override any options
encode_device->init_codec_options(ctx.get(), &options);
Expand Down Expand Up @@ -2407,18 +2375,11 @@ namespace video {
return false;
}

retry:
// If we're expecting failure, use the autoselect ref config first since that will always succeed
// if the encoder is available.
auto max_ref_frames_h264 = expect_failure ? -1 : validate_config(disp, encoder, config_max_ref_frames);
auto autoselect_h264 = max_ref_frames_h264 >= 0 ? max_ref_frames_h264 : validate_config(disp, encoder, config_autoselect);
if (autoselect_h264 < 0) {
if (encoder.h264.qp && encoder.h264[encoder_t::CBR]) {
// It's possible the encoder isn't accepting Constant Bit Rate. Turn off CBR and make another attempt
encoder.h264.capabilities.set();
encoder.h264[encoder_t::CBR] = false;
goto retry;
}
return false;
}
else if (expect_failure) {
Expand All @@ -2442,7 +2403,6 @@ namespace video {
config_autoselect.videoFormat = 1;

if (disp->is_codec_supported(encoder.hevc.name, config_autoselect)) {
retry_hevc:
auto max_ref_frames_hevc = validate_config(disp, encoder, config_max_ref_frames);

// If H.264 succeeded with max ref frames specified, assume that we can count on
Expand All @@ -2451,13 +2411,6 @@ namespace video {
max_ref_frames_hevc :
validate_config(disp, encoder, config_autoselect);

if (autoselect_hevc < 0 && encoder.hevc.qp && encoder.hevc[encoder_t::CBR]) {
// It's possible the encoder isn't accepting Constant Bit Rate. Turn off CBR and make another attempt
encoder.hevc.capabilities.set();
encoder.hevc[encoder_t::CBR] = false;
goto retry_hevc;
}

for (auto [validate_flag, encoder_flag] : packet_deficiencies) {
encoder.hevc[encoder_flag] = (max_ref_frames_hevc & validate_flag && autoselect_hevc & validate_flag);
}
Expand All @@ -2480,7 +2433,6 @@ namespace video {
config_autoselect.videoFormat = 2;

if (disp->is_codec_supported(encoder.av1.name, config_autoselect)) {
retry_av1:
auto max_ref_frames_av1 = validate_config(disp, encoder, config_max_ref_frames);

// If H.264 succeeded with max ref frames specified, assume that we can count on
Expand All @@ -2489,13 +2441,6 @@ namespace video {
max_ref_frames_av1 :
validate_config(disp, encoder, config_autoselect);

if (autoselect_av1 < 0 && encoder.av1.qp && encoder.av1[encoder_t::CBR]) {
// It's possible the encoder isn't accepting Constant Bit Rate. Turn off CBR and make another attempt
encoder.av1.capabilities.set();
encoder.av1[encoder_t::CBR] = false;
goto retry_av1;
}

for (auto [validate_flag, encoder_flag] : packet_deficiencies) {
encoder.av1[encoder_flag] = (max_ref_frames_av1 & validate_flag && autoselect_av1 & validate_flag);
}
Expand Down
7 changes: 0 additions & 7 deletions src/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ namespace video {
enum flag_e {
PASSED, ///< Indicates the encoder is supported.
REF_FRAMES_RESTRICT, ///< Set maximum reference frames.
CBR, ///< Some encoders don't support CBR, if not supported attempt constant quantization parameter instead.
DYNAMIC_RANGE, ///< HDR support.
YUV444, ///< YUV 4:4:4 support.
VUI_PARAMETERS, ///< AMD encoder with VAAPI doesn't add VUI parameters to SPS.
Expand All @@ -135,7 +134,6 @@ namespace video {
switch (flag) {
_CONVERT(PASSED);
_CONVERT(REF_FRAMES_RESTRICT);
_CONVERT(CBR);
_CONVERT(DYNAMIC_RANGE);
_CONVERT(YUV444);
_CONVERT(VUI_PARAMETERS);
Expand Down Expand Up @@ -167,11 +165,6 @@ namespace video {
std::vector<option_t> hdr444_options;
std::vector<option_t> fallback_options;

// QP option to set in the case that CBR/VBR is not supported
// by the encoder. If CBR/VBR is guaranteed to be supported,
// don't specify this option to avoid wasteful encoder probing.
std::optional<option_t> qp;

std::string name;
std::bitset<MAX_FLAGS> capabilities;

Expand Down

0 comments on commit c9c6095

Please sign in to comment.