Add CQP for older intel iGPU's
This commit is contained in:
@@ -157,14 +157,9 @@
|
|||||||
# Honestly, I have no idea what the optimal values would be.
|
# Honestly, I have no idea what the optimal values would be.
|
||||||
# Play around with this :)
|
# Play around with this :)
|
||||||
|
|
||||||
# Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still image, resulting in constant perceived quality
|
|
||||||
# Higher value means more compression, but less quality
|
|
||||||
# If crf == 0, then use QP directly instead
|
|
||||||
# crf = 0
|
|
||||||
|
|
||||||
# Quantitization Parameter
|
# Quantitization Parameter
|
||||||
|
# Some devices don't support Constant Bit Rate. For those devices, QP is used instead
|
||||||
# Higher value means more compression, but less quality
|
# Higher value means more compression, but less quality
|
||||||
# If crf != 0, then this parameter is ignored
|
|
||||||
# qp = 28
|
# qp = 28
|
||||||
|
|
||||||
# Minimum number of threads used by ffmpeg to encode the video.
|
# Minimum number of threads used by ffmpeg to encode the video.
|
||||||
|
|||||||
@@ -256,27 +256,15 @@
|
|||||||
Set the familly of ports used by Sunshine
|
Set the familly of ports used by Sunshine
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--Constant Rate Factor-->
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="crf" class="form-label">Constant Rate Factor</label>
|
|
||||||
<input type="number" min="0" max="52" class="form-control" id="crf" placeholder="0"
|
|
||||||
v-model="config.crf">
|
|
||||||
<div class="form-text">
|
|
||||||
Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still
|
|
||||||
image,
|
|
||||||
resulting in constant perceived quality<br>
|
|
||||||
Higher value means more compression, but less quality<br>
|
|
||||||
If crf == 0, then use QP directly instead
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Quantization Parameter -->
|
<!-- Quantization Parameter -->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="qp" class="form-label">Quantitization Parameter</label>
|
<label for="qp" class="form-label">Quantitization Parameter</label>
|
||||||
<input type="number" class="form-control" id="qp" placeholder="28" v-model="config.qp">
|
<input type="number" class="form-control" id="qp" placeholder="28" v-model="config.qp">
|
||||||
<div class="form-text">
|
<div class="form-text">
|
||||||
Quantitization Parameter<br>
|
Quantitization Parameter<br>
|
||||||
|
Some devices may not support Constant Bit Rate.<br>
|
||||||
|
For those devices, QP is used instead.<br>
|
||||||
Higher value means more compression, but less quality<br>
|
Higher value means more compression, but less quality<br>
|
||||||
If crf != 0, then this parameter is ignored
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Min Threads -->
|
<!-- Min Threads -->
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ int coder_from_view(const std::string_view &coder) {
|
|||||||
} // namespace amd
|
} // namespace amd
|
||||||
|
|
||||||
video_t video {
|
video_t video {
|
||||||
0, // crf
|
|
||||||
28, // qp
|
28, // qp
|
||||||
|
|
||||||
0, // hevc_mode
|
0, // hevc_mode
|
||||||
@@ -582,7 +581,6 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
|
|||||||
std::cout << "["sv << name << "] -- ["sv << val << ']' << std::endl;
|
std::cout << "["sv << name << "] -- ["sv << val << ']' << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_f(vars, "crf", video.crf);
|
|
||||||
int_f(vars, "qp", video.qp);
|
int_f(vars, "qp", video.qp);
|
||||||
int_f(vars, "min_threads", video.min_threads);
|
int_f(vars, "min_threads", video.min_threads);
|
||||||
int_between_f(vars, "hevc_mode", video.hevc_mode, { 0, 3 });
|
int_between_f(vars, "hevc_mode", video.hevc_mode, { 0, 3 });
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
namespace config {
|
namespace config {
|
||||||
struct video_t {
|
struct video_t {
|
||||||
// ffmpeg params
|
// ffmpeg params
|
||||||
int crf; // higher == more compression and less quality
|
int qp; // higher == more compression and less quality
|
||||||
int qp; // higher == more compression and less quality, ignored if crf != 0
|
|
||||||
|
|
||||||
int hevc_mode;
|
int hevc_mode;
|
||||||
|
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ struct encoder_t {
|
|||||||
REF_FRAMES_RESTRICT, // Set maximum reference frames
|
REF_FRAMES_RESTRICT, // Set maximum reference frames
|
||||||
REF_FRAMES_AUTOSELECT, // Allow encoder to select maximum reference frames (If !REF_FRAMES_RESTRICT --> REF_FRAMES_AUTOSELECT)
|
REF_FRAMES_AUTOSELECT, // Allow encoder to select maximum reference frames (If !REF_FRAMES_RESTRICT --> REF_FRAMES_AUTOSELECT)
|
||||||
SLICE, // Allow frame to be partitioned into multiple slices
|
SLICE, // Allow frame to be partitioned into multiple slices
|
||||||
|
CBR, // Some encoders don't support CBR, if not supported --> attempt constant quantatication parameter instead
|
||||||
DYNAMIC_RANGE, // hdr
|
DYNAMIC_RANGE, // hdr
|
||||||
VUI_PARAMETERS, // AMD encoder with VAAPI doesn't add VUI parameters to SPS
|
VUI_PARAMETERS, // AMD encoder with VAAPI doesn't add VUI parameters to SPS
|
||||||
NALU_PREFIX_5b, // libx264/libx265 have a 3-byte nalu prefix instead of 4-byte nalu prefix
|
NALU_PREFIX_5b, // libx264/libx265 have a 3-byte nalu prefix instead of 4-byte nalu prefix
|
||||||
@@ -265,6 +266,7 @@ struct encoder_t {
|
|||||||
_CONVERT(REF_FRAMES_RESTRICT);
|
_CONVERT(REF_FRAMES_RESTRICT);
|
||||||
_CONVERT(REF_FRAMES_AUTOSELECT);
|
_CONVERT(REF_FRAMES_AUTOSELECT);
|
||||||
_CONVERT(SLICE);
|
_CONVERT(SLICE);
|
||||||
|
_CONVERT(CBR);
|
||||||
_CONVERT(DYNAMIC_RANGE);
|
_CONVERT(DYNAMIC_RANGE);
|
||||||
_CONVERT(VUI_PARAMETERS);
|
_CONVERT(VUI_PARAMETERS);
|
||||||
_CONVERT(NALU_PREFIX_5b);
|
_CONVERT(NALU_PREFIX_5b);
|
||||||
@@ -299,7 +301,7 @@ struct encoder_t {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
std::vector<option_t> options;
|
std::vector<option_t> options;
|
||||||
std::optional<option_t> crf, qp;
|
std::optional<option_t> qp;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::bitset<MAX_FLAGS> capabilities;
|
std::bitset<MAX_FLAGS> capabilities;
|
||||||
@@ -424,7 +426,6 @@ static encoder_t nvenc {
|
|||||||
{ "rc"s, &config::video.nv.rc },
|
{ "rc"s, &config::video.nv.rc },
|
||||||
},
|
},
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
std::nullopt,
|
|
||||||
"hevc_nvenc"s,
|
"hevc_nvenc"s,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -435,7 +436,6 @@ static encoder_t nvenc {
|
|||||||
{ "rc"s, &config::video.nv.rc },
|
{ "rc"s, &config::video.nv.rc },
|
||||||
{ "coder"s, &config::video.nv.coder },
|
{ "coder"s, &config::video.nv.coder },
|
||||||
},
|
},
|
||||||
std::nullopt,
|
|
||||||
std::make_optional<encoder_t::option_t>({ "qp"s, &config::video.qp }),
|
std::make_optional<encoder_t::option_t>({ "qp"s, &config::video.qp }),
|
||||||
"h264_nvenc"s,
|
"h264_nvenc"s,
|
||||||
},
|
},
|
||||||
@@ -463,7 +463,6 @@ static encoder_t amdvce {
|
|||||||
{ "quality"s, &config::video.amd.quality },
|
{ "quality"s, &config::video.amd.quality },
|
||||||
{ "rc"s, &config::video.amd.rc },
|
{ "rc"s, &config::video.amd.rc },
|
||||||
},
|
},
|
||||||
std::nullopt,
|
|
||||||
std::make_optional<encoder_t::option_t>({ "qp"s, &config::video.qp }),
|
std::make_optional<encoder_t::option_t>({ "qp"s, &config::video.qp }),
|
||||||
"hevc_amf"s,
|
"hevc_amf"s,
|
||||||
},
|
},
|
||||||
@@ -474,7 +473,6 @@ static encoder_t amdvce {
|
|||||||
{ "rc"s, &config::video.amd.rc },
|
{ "rc"s, &config::video.amd.rc },
|
||||||
{ "log_to_dbg"s, "1"s },
|
{ "log_to_dbg"s, "1"s },
|
||||||
},
|
},
|
||||||
std::nullopt,
|
|
||||||
std::make_optional<encoder_t::option_t>({ "qp"s, &config::video.qp }),
|
std::make_optional<encoder_t::option_t>({ "qp"s, &config::video.qp }),
|
||||||
"h264_amf"s,
|
"h264_amf"s,
|
||||||
},
|
},
|
||||||
@@ -500,7 +498,6 @@ static encoder_t software {
|
|||||||
{ "preset"s, &config::video.sw.preset },
|
{ "preset"s, &config::video.sw.preset },
|
||||||
{ "tune"s, &config::video.sw.tune },
|
{ "tune"s, &config::video.sw.tune },
|
||||||
},
|
},
|
||||||
std::make_optional<encoder_t::option_t>("crf"s, &config::video.crf),
|
|
||||||
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
|
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
|
||||||
"libx265"s,
|
"libx265"s,
|
||||||
},
|
},
|
||||||
@@ -509,7 +506,6 @@ static encoder_t software {
|
|||||||
{ "preset"s, &config::video.sw.preset },
|
{ "preset"s, &config::video.sw.preset },
|
||||||
{ "tune"s, &config::video.sw.tune },
|
{ "tune"s, &config::video.sw.tune },
|
||||||
},
|
},
|
||||||
std::make_optional<encoder_t::option_t>("crf"s, &config::video.crf),
|
|
||||||
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
|
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
|
||||||
"libx264"s,
|
"libx264"s,
|
||||||
},
|
},
|
||||||
@@ -530,8 +526,7 @@ static encoder_t vaapi {
|
|||||||
{ "sei"s, 0 },
|
{ "sei"s, 0 },
|
||||||
{ "idr_interval"s, std::numeric_limits<int>::max() },
|
{ "idr_interval"s, std::numeric_limits<int>::max() },
|
||||||
},
|
},
|
||||||
std::nullopt,
|
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
|
||||||
std::nullopt,
|
|
||||||
"hevc_vaapi"s,
|
"hevc_vaapi"s,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -539,8 +534,7 @@ static encoder_t vaapi {
|
|||||||
{ "sei"s, 0 },
|
{ "sei"s, 0 },
|
||||||
{ "idr_interval"s, std::numeric_limits<int>::max() },
|
{ "idr_interval"s, std::numeric_limits<int>::max() },
|
||||||
},
|
},
|
||||||
std::nullopt,
|
std::make_optional<encoder_t::option_t>("qp"s, &config::video.qp),
|
||||||
std::nullopt,
|
|
||||||
"h264_vaapi"s,
|
"h264_vaapi"s,
|
||||||
},
|
},
|
||||||
LIMITED_GOP_SIZE | SYSTEM_MEMORY,
|
LIMITED_GOP_SIZE | SYSTEM_MEMORY,
|
||||||
@@ -921,21 +915,18 @@ std::optional<session_t> make_session(const encoder_t &encoder, const config_t &
|
|||||||
handle_option(option);
|
handle_option(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.bitrate > 500) {
|
if(video_format[encoder_t::CBR]) {
|
||||||
auto bitrate = config.bitrate * 1000;
|
auto bitrate = config.bitrate * 1000;
|
||||||
ctx->rc_max_rate = bitrate;
|
ctx->rc_max_rate = bitrate;
|
||||||
ctx->rc_buffer_size = bitrate / config.framerate;
|
ctx->rc_buffer_size = bitrate / config.framerate;
|
||||||
ctx->bit_rate = bitrate;
|
ctx->bit_rate = bitrate;
|
||||||
ctx->rc_min_rate = bitrate;
|
ctx->rc_min_rate = bitrate;
|
||||||
}
|
}
|
||||||
else if(video_format.crf && config::video.crf != 0) {
|
|
||||||
handle_option(*video_format.crf);
|
|
||||||
}
|
|
||||||
else if(video_format.qp) {
|
else if(video_format.qp) {
|
||||||
handle_option(*video_format.qp);
|
handle_option(*video_format.qp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BOOST_LOG(error) << "Couldn't set video quality: encoder "sv << encoder.name << " doesn't support either crf or qp"sv;
|
BOOST_LOG(error) << "Couldn't set video quality: encoder "sv << encoder.name << " doesn't support qp"sv;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1469,10 +1460,17 @@ bool validate_encoder(encoder_t &encoder) {
|
|||||||
config_t config_max_ref_frames { 1920, 1080, 60, 1000, 1, 1, 1, 0, 0 };
|
config_t config_max_ref_frames { 1920, 1080, 60, 1000, 1, 1, 1, 0, 0 };
|
||||||
config_t config_autoselect { 1920, 1080, 60, 1000, 1, 0, 1, 0, 0 };
|
config_t config_autoselect { 1920, 1080, 60, 1000, 1, 0, 1, 0, 0 };
|
||||||
|
|
||||||
|
retry:
|
||||||
auto max_ref_frames_h264 = validate_config(disp, encoder, config_max_ref_frames);
|
auto max_ref_frames_h264 = validate_config(disp, encoder, config_max_ref_frames);
|
||||||
auto autoselect_h264 = validate_config(disp, encoder, config_autoselect);
|
auto autoselect_h264 = validate_config(disp, encoder, config_autoselect);
|
||||||
|
|
||||||
if(max_ref_frames_h264 < 0 && autoselect_h264 < 0) {
|
if(max_ref_frames_h264 < 0 && 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1494,12 +1492,22 @@ bool validate_encoder(encoder_t &encoder) {
|
|||||||
config_max_ref_frames.videoFormat = 1;
|
config_max_ref_frames.videoFormat = 1;
|
||||||
config_autoselect.videoFormat = 1;
|
config_autoselect.videoFormat = 1;
|
||||||
|
|
||||||
|
retry_hevc:
|
||||||
auto max_ref_frames_hevc = validate_config(disp, encoder, config_max_ref_frames);
|
auto max_ref_frames_hevc = validate_config(disp, encoder, config_max_ref_frames);
|
||||||
auto autoselect_hevc = validate_config(disp, encoder, config_autoselect);
|
auto autoselect_hevc = validate_config(disp, encoder, config_autoselect);
|
||||||
|
|
||||||
// If HEVC must be supported, but it is not supported
|
// If HEVC must be supported, but it is not supported
|
||||||
if(force_hevc && max_ref_frames_hevc < 0 && autoselect_hevc < 0) {
|
if(max_ref_frames_hevc < 0 && autoselect_hevc < 0) {
|
||||||
return false;
|
if(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(force_hevc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto [validate_flag, encoder_flag] : packet_deficiencies) {
|
for(auto [validate_flag, encoder_flag] : packet_deficiencies) {
|
||||||
|
|||||||
Reference in New Issue
Block a user