From 1b65c019288380239fcbbc0a0b9da073acbea93a Mon Sep 17 00:00:00 2001 From: knackebrot Date: Tue, 4 Apr 2023 19:30:18 +0200 Subject: [PATCH] Add advanced options for Intel QSV encoders --- .../MediaEncoding/EncodingHelper.cs | 90 +++++++++++++++++-- .../Configuration/EncodingOptions.cs | 72 +++++++++++++++ 2 files changed, 156 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index f7ee3c1732..275c8c7b2b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -896,6 +896,16 @@ namespace MediaBrowser.Controller.MediaEncoding } args.Append(GetQsvDeviceArgs(QsvAlias)); + + if (string.Equals(vidEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && options.EnableIntelLookAheadH264) + { + args.Append(" -extra_hw_frames=" + options.IntelLookAheadDepthH264); + } + else if (string.Equals(vidEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase) && options.EnableIntelLookAheadHevc) + { + args.Append(" -extra_hw_frames=" + options.IntelLookAheadDepthHevc); + } + var filterDevArgs = GetFilterHwDeviceArgs(QsvAlias); // child device used by qsv. if (_mediaEncoder.SupportsHwaccel("vaapi") || _mediaEncoder.SupportsHwaccel("d3d11va")) @@ -1543,7 +1553,61 @@ namespace MediaBrowser.Controller.MediaEncoding // Only h264_qsv has look_ahead option if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { - param += " -look_ahead 0"; + if (encodingOptions.EnableIntelLookAheadH264) + { + param += $" -look_ahead 1 -look_ahead_depth {encodingOptions.IntelLookAheadDepthH264}"; + } + else + { + param += " -look_ahead 0"; + } + + if (encodingOptions.EnableIntelExtBrcH264) + { + param += " -extbrc 1"; + } + + if (encodingOptions.EnableIntelBPyramidH264) + { + param += " -b_strategy 1"; + } + + if (encodingOptions.EnableIntelAdaptiveIBFramesH264) + { + param += " -adaptive_i 1 -adaptive_b 1"; + } + + if (encodingOptions.EnableIntelTrellisH264) + { + param += " -trellis 1"; + } + } + else if (string.Equals(videoEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) + { + if (encodingOptions.EnableIntelLookAheadHevc) + { + param += $" -look_ahead_depth {encodingOptions.IntelLookAheadDepthHevc}"; + } + + if (encodingOptions.EnableIntelExtBrcHevc) + { + param += " -extbrc 1"; + } + + if (encodingOptions.EnableIntelBPyramidHevc) + { + param += " -b_strategy 1"; + } + + if (encodingOptions.EnableIntelAdaptiveIBFramesHevc) + { + param += " -adaptive_i 1 -adaptive_b 1"; + } + + if (encodingOptions.EnableIntelTrellisHevc) + { + param += " -trellis 1"; + } } } else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc) @@ -3698,7 +3762,7 @@ namespace MediaBrowser.Controller.MediaEncoding // qsv requires a fixed pool size. // default to 64 otherwise it will fail on certain iGPU. - subFilters.Add("hwupload=derive_device=qsv:extra_hw_frames=64"); + subFilters.Add($"hwupload=derive_device=qsv:extra_hw_frames={GetIntelExtraHwFrames(vidEncoder, options, 64)}"); var (overlayW, overlayH) = GetFixedOutputSize(inW, inH, reqW, reqH, reqMaxW, reqMaxH); var overlaySize = (overlayW.HasValue && overlayH.HasValue) @@ -3805,7 +3869,7 @@ namespace MediaBrowser.Controller.MediaEncoding // allocate extra pool sizes for vaapi vpp if (!string.IsNullOrEmpty(hwScaleFilter) && isVaapiDecoder) { - hwScaleFilter += ":extra_hw_frames=24"; + hwScaleFilter += $":extra_hw_frames={GetIntelExtraHwFrames(vidEncoder, options, 24)}"; } // hw scale @@ -3881,7 +3945,7 @@ namespace MediaBrowser.Controller.MediaEncoding // OUTPUT qsv(nv12) surface(vram) // reverse-mapping via qsv(vaapi)-opencl interop. // add extra pool size to avoid the 'cannot allocate memory' error on hevc_qsv. - mainFilters.Add("hwmap=derive_device=qsv:reverse=1:extra_hw_frames=16"); + mainFilters.Add($"hwmap=derive_device=qsv:reverse=1:extra_hw_frames={GetIntelExtraHwFrames(vidEncoder, options, 16)}"); mainFilters.Add("format=qsv"); } else if (isVaapiDecoder) @@ -3914,7 +3978,7 @@ namespace MediaBrowser.Controller.MediaEncoding // qsv requires a fixed pool size. // default to 64 otherwise it will fail on certain iGPU. - subFilters.Add("hwupload=derive_device=qsv:extra_hw_frames=64"); + subFilters.Add($"hwupload=derive_device=qsv:extra_hw_frames={GetIntelExtraHwFrames(vidEncoder, options, 64)}"); var (overlayW, overlayH) = GetFixedOutputSize(inW, inH, reqW, reqH, reqMaxW, reqMaxH); var overlaySize = (overlayW.HasValue && overlayH.HasValue) @@ -4087,7 +4151,7 @@ namespace MediaBrowser.Controller.MediaEncoding // allocate extra pool sizes for vaapi vpp if (!string.IsNullOrEmpty(hwScaleFilter)) { - hwScaleFilter += ":extra_hw_frames=24"; + hwScaleFilter += $":extra_hw_frames={GetIntelExtraHwFrames(vidEncoder, options, 24)}"; } // hw scale @@ -6106,5 +6170,19 @@ namespace MediaBrowser.Controller.MediaEncoding { return string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase); } + + public int GetIntelExtraHwFrames(string vidEncoder, EncodingOptions options, int initialExtraHwFrames) + { + if (string.Equals(vidEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && options.EnableIntelLookAheadH264) + { + initialExtraHwFrames += options.IntelLookAheadDepthH264; + } + else if (string.Equals(vidEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase) && options.EnableIntelLookAheadHevc) + { + initialExtraHwFrames += options.IntelLookAheadDepthHevc; + } + + return initialExtraHwFrames; + } } } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index f9f63f751a..d7517ae342 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -44,7 +44,19 @@ public class EncodingOptions EnableEnhancedNvdecDecoder = true; PreferSystemNativeHwDecoder = true; EnableIntelLowPowerH264HwEncoder = false; + EnableIntelLookAheadH264 = false; + IntelLookAheadDepthH264 = 60; + EnableIntelExtBrcH264 = false; + EnableIntelBPyramidH264 = false; + EnableIntelAdaptiveIBFramesH264 = false; + EnableIntelTrellisH264 = false; EnableIntelLowPowerHevcHwEncoder = false; + EnableIntelLookAheadHevc = false; + IntelLookAheadDepthHevc = 60; + EnableIntelExtBrcHevc = false; + EnableIntelBPyramidHevc = false; + EnableIntelAdaptiveIBFramesHevc = false; + EnableIntelTrellisHevc = false; EnableHardwareEncoding = true; AllowHevcEncoding = false; EnableSubtitleExtraction = true; @@ -222,11 +234,71 @@ public class EncodingOptions /// public bool EnableIntelLowPowerH264HwEncoder { get; set; } + /// + /// Gets or sets a value indicating whether LookAhead should be used for Intel H264 encoder. + /// + public bool EnableIntelLookAheadH264 { get; set; } + + /// + /// Gets or sets a value indicating the number of frames that should be used for LookAhead with Intel H264 encoder. + /// + public int IntelLookAheadDepthH264 { get; set; } + + /// + /// Gets or sets a value indicating whether ExtBrc should be used for Intel H264 encoder. + /// + public bool EnableIntelExtBrcH264 { get; set; } + + /// + /// Gets or sets a value indicating whether B-Pyramid should be used for Intel H264 encoder. + /// + public bool EnableIntelBPyramidH264 { get; set; } + + /// + /// Gets or sets a value indicating whether Adaptive I/B frames should be used for Intel H264 encoder. + /// + public bool EnableIntelAdaptiveIBFramesH264 { get; set; } + + /// + /// Gets or sets a value indicating whether Trellis quantization should be used for Intel H264 encoder. + /// + public bool EnableIntelTrellisH264 { get; set; } + /// /// Gets or sets a value indicating whether the Intel HEVC low-power hardware encoder should be used. /// public bool EnableIntelLowPowerHevcHwEncoder { get; set; } + /// + /// Gets or sets a value indicating whether LookAhead should be used for Intel HEVC encoder. + /// + public bool EnableIntelLookAheadHevc { get; set; } + + /// + /// Gets or sets a value indicating the number of frames that should be used for LookAhead with Intel HEVC encoder. + /// + public int IntelLookAheadDepthHevc { get; set; } + + /// + /// Gets or sets a value indicating whether ExtBrc should be used for Intel HEVC encoder. + /// + public bool EnableIntelExtBrcHevc { get; set; } + + /// + /// Gets or sets a value indicating whether B-Pyramid should be used for Intel HEVC encoder. + /// + public bool EnableIntelBPyramidHevc { get; set; } + + /// + /// Gets or sets a value indicating whether Adaptive I/B frames should be used for Intel HEVC encoder. + /// + public bool EnableIntelAdaptiveIBFramesHevc { get; set; } + + /// + /// Gets or sets a value indicating whether Trellis quantization should be used for Intel HEVC encoder. + /// + public bool EnableIntelTrellisHevc { get; set; } + /// /// Gets or sets a value indicating whether hardware encoding is enabled. ///