Use strict QSV CPB size for less powerful H.264 decoder (#16743)

* Fix int32 overflow in QSV rate-control parameter computation (#16376)

Fix int32 overflow in QSV rate-control parameter computation

* Use strict QSV CPB size for less powerful H.264 decoder

Signed-off-by: nyanmisaka <nst799610810@gmail.com>

---------

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
Co-authored-by: scheilch <christian.scheil@icloud.com>
This commit is contained in:
Bond-009
2026-05-03 12:21:33 +02:00
committed by GitHub

View File

@@ -1578,14 +1578,15 @@ namespace MediaBrowser.Controller.MediaEncoding
int bitrate = state.OutputVideoBitrate.Value;
// Bit rate under 1000k is not allowed in h264_qsv
// Bit rate under 1000k is not allowed in h264_qsv.
if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
{
bitrate = Math.Max(bitrate, 1000);
}
// Currently use the same buffer size for all encoders
int bufsize = bitrate * 2;
// Currently use the same buffer size for all non-QSV encoders.
// Use long arithmetic to prevent int32 overflow for very high bitrate values.
int bufsize = (int)Math.Min((long)bitrate * 2, int.MaxValue);
if (string.Equals(videoCodec, "libsvtav1", StringComparison.OrdinalIgnoreCase))
{
@@ -1613,9 +1614,27 @@ namespace MediaBrowser.Controller.MediaEncoding
mbbrcOpt = " -mbbrc 1";
}
// Some less powerful H.264 HW decoders require strict CPB size
// So bufsize optimizations should not be applied to them
int factor = 2;
var codec = state.ActualOutputVideoCodec;
var level = state.GetRequestedLevel(codec);
if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)
&& double.TryParse(level, CultureInfo.InvariantCulture, out double requestedLevel)
&& requestedLevel < 51)
{
factor = 1;
}
// Set (maxrate == bitrate + 1) to trigger VBR for better bitrate allocation
// Set (rc_init_occupancy == 2 * bitrate) and (bufsize == 4 * bitrate) to deal with drastic scene changes
return FormattableString.Invariant($"{mbbrcOpt} -b:v {bitrate} -maxrate {bitrate + 1} -rc_init_occupancy {bitrate * 2} -bufsize {bitrate * 4}");
// Use long arithmetic and clamp to int.MaxValue to prevent int32 overflow
// (e.g. bitrate * 4 wraps to a negative value for bitrates above ~537 million)
int qsvMaxrate = (int)Math.Min((long)bitrate + 1, int.MaxValue);
int qsvInitOcc = (int)Math.Min((long)bitrate * 1 * factor, int.MaxValue);
int qsvBufsize = (int)Math.Min((long)bitrate * 2 * factor, int.MaxValue);
return FormattableString.Invariant($"{mbbrcOpt} -b:v {bitrate} -maxrate {qsvMaxrate} -rc_init_occupancy {qsvInitOcc} -bufsize {qsvBufsize}");
}
if (string.Equals(videoCodec, "h264_amf", StringComparison.OrdinalIgnoreCase)