mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
Add native VPP tonemap for QSV on Windows (#12592)
This commit is contained in:
parent
1451cbc39e
commit
48b2941cfe
@ -68,6 +68,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
private readonly Version _minFFmpegDisplayRotationOption = new Version(6, 0);
|
private readonly Version _minFFmpegDisplayRotationOption = new Version(6, 0);
|
||||||
private readonly Version _minFFmpegAdvancedTonemapMode = new Version(7, 0, 1);
|
private readonly Version _minFFmpegAdvancedTonemapMode = new Version(7, 0, 1);
|
||||||
private readonly Version _minFFmpegAlteredVaVkInterop = new Version(7, 0, 1);
|
private readonly Version _minFFmpegAlteredVaVkInterop = new Version(7, 0, 1);
|
||||||
|
private readonly Version _minFFmpegQsvVppTonemapOption = new Version(7, 0, 1);
|
||||||
|
|
||||||
private static readonly Regex _validationRegex = new(ValidationRegex, RegexOptions.Compiled);
|
private static readonly Regex _validationRegex = new(ValidationRegex, RegexOptions.Compiled);
|
||||||
|
|
||||||
@ -348,7 +349,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
&& GetVideoColorBitDepth(state) == 10;
|
&& GetVideoColorBitDepth(state) == 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsVaapiVppTonemapAvailable(EncodingJobInfo state, EncodingOptions options)
|
private bool IsIntelVppTonemapAvailable(EncodingJobInfo state, EncodingOptions options)
|
||||||
{
|
{
|
||||||
if (state.VideoStream is null
|
if (state.VideoStream is null
|
||||||
|| !options.EnableVppTonemapping
|
|| !options.EnableVppTonemapping
|
||||||
@ -357,7 +358,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Native VPP tonemapping may come to QSV in the future.
|
// prefer 'tonemap_vaapi' over 'vpp_qsv' on Linux for supporting Gen9/KBLx.
|
||||||
|
// 'vpp_qsv' requires VPL, which is only supported on Gen12/TGLx and newer.
|
||||||
|
if (OperatingSystem.IsWindows()
|
||||||
|
&& string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& _mediaEncoder.EncoderVersion < _minFFmpegQsvVppTonemapOption)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return state.VideoStream.VideoRange == VideoRange.HDR
|
return state.VideoStream.VideoRange == VideoRange.HDR
|
||||||
&& (state.VideoStream.VideoRangeType == VideoRangeType.HDR10
|
&& (state.VideoStream.VideoRangeType == VideoRangeType.HDR10
|
||||||
@ -1662,7 +1670,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
var doOclTonemap = _mediaEncoder.SupportsHwaccel("qsv")
|
var doOclTonemap = _mediaEncoder.SupportsHwaccel("qsv")
|
||||||
&& IsVaapiSupported(state)
|
&& IsVaapiSupported(state)
|
||||||
&& IsOpenclFullSupported()
|
&& IsOpenclFullSupported()
|
||||||
&& !IsVaapiVppTonemapAvailable(state, encodingOptions)
|
&& !IsIntelVppTonemapAvailable(state, encodingOptions)
|
||||||
&& IsHwTonemapAvailable(state, encodingOptions);
|
&& IsHwTonemapAvailable(state, encodingOptions);
|
||||||
|
|
||||||
enableWaFori915Hang = isIntelDecoder && doOclTonemap;
|
enableWaFori915Hang = isIntelDecoder && doOclTonemap;
|
||||||
@ -3281,14 +3289,31 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
|
|
||||||
if (string.Equals(hwTonemapSuffix, "vaapi", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(hwTonemapSuffix, "vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
args = "procamp_vaapi=b={1}:c={2},tonemap_vaapi=format={0}:p=bt709:t=bt709:m=bt709:extra_hw_frames=32";
|
var doVaVppProcamp = false;
|
||||||
|
var procampParams = string.Empty;
|
||||||
|
if (options.VppTonemappingBrightness != 0
|
||||||
|
&& options.VppTonemappingBrightness >= -100
|
||||||
|
&& options.VppTonemappingBrightness <= 100)
|
||||||
|
{
|
||||||
|
procampParams += $"=b={options.VppTonemappingBrightness}";
|
||||||
|
doVaVppProcamp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.VppTonemappingContrast > 1
|
||||||
|
&& options.VppTonemappingContrast <= 10)
|
||||||
|
{
|
||||||
|
procampParams += doVaVppProcamp ? ":" : "=";
|
||||||
|
procampParams += $"c={options.VppTonemappingContrast}";
|
||||||
|
doVaVppProcamp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
args = "{0}tonemap_vaapi=format={1}:p=bt709:t=bt709:m=bt709:extra_hw_frames=32";
|
||||||
|
|
||||||
return string.Format(
|
return string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
args,
|
args,
|
||||||
videoFormat ?? "nv12",
|
doVaVppProcamp ? $"procamp_vaapi{procampParams}," : string.Empty,
|
||||||
options.VppTonemappingBrightness,
|
videoFormat ?? "nv12");
|
||||||
options.VppTonemappingContrast);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4012,7 +4037,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
||||||
var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
||||||
var doDeintH2645 = doDeintH264 || doDeintHevc;
|
var doDeintH2645 = doDeintH264 || doDeintHevc;
|
||||||
var doOclTonemap = IsHwTonemapAvailable(state, options);
|
var doVppTonemap = IsIntelVppTonemapAvailable(state, options);
|
||||||
|
var doOclTonemap = !doVppTonemap && IsHwTonemapAvailable(state, options);
|
||||||
|
var doTonemap = doVppTonemap || doOclTonemap;
|
||||||
|
|
||||||
var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||||
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
|
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
|
||||||
@ -4031,7 +4058,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
/* Make main filters for video stream */
|
/* Make main filters for video stream */
|
||||||
var mainFilters = new List<string>();
|
var mainFilters = new List<string>();
|
||||||
|
|
||||||
mainFilters.Add(GetOverwriteColorPropertiesParam(state, doOclTonemap));
|
mainFilters.Add(GetOverwriteColorPropertiesParam(state, doTonemap));
|
||||||
|
|
||||||
if (isSwDecoder)
|
if (isSwDecoder)
|
||||||
{
|
{
|
||||||
@ -4059,9 +4086,33 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
}
|
}
|
||||||
else if (isD3d11vaDecoder || isQsvDecoder)
|
else if (isD3d11vaDecoder || isQsvDecoder)
|
||||||
{
|
{
|
||||||
|
var doVppProcamp = false;
|
||||||
|
var procampParams = string.Empty;
|
||||||
|
if (doVppTonemap)
|
||||||
|
{
|
||||||
|
if (options.VppTonemappingBrightness != 0
|
||||||
|
&& options.VppTonemappingBrightness >= -100
|
||||||
|
&& options.VppTonemappingBrightness <= 100)
|
||||||
|
{
|
||||||
|
procampParams += $":brightness={options.VppTonemappingBrightness}";
|
||||||
|
doVppProcamp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.VppTonemappingContrast > 1
|
||||||
|
&& options.VppTonemappingContrast <= 10)
|
||||||
|
{
|
||||||
|
procampParams += $":contrast={options.VppTonemappingContrast}";
|
||||||
|
doVppProcamp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
procampParams += doVppProcamp ? ":procamp=1:async_depth=2" : string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
var outFormat = doOclTonemap ? (doVppTranspose ? "p010" : string.Empty) : "nv12";
|
var outFormat = doOclTonemap ? (doVppTranspose ? "p010" : string.Empty) : "nv12";
|
||||||
|
outFormat = (doVppTonemap && doVppProcamp) ? "p010" : outFormat;
|
||||||
|
|
||||||
var swapOutputWandH = doVppTranspose && swapWAndH;
|
var swapOutputWandH = doVppTranspose && swapWAndH;
|
||||||
var hwScalePrefix = doVppTranspose ? "vpp" : "scale";
|
var hwScalePrefix = (doVppTranspose || doVppTonemap) ? "vpp" : "scale";
|
||||||
var hwScaleFilter = GetHwScaleFilter(hwScalePrefix, "qsv", outFormat, swapOutputWandH, swpInW, swpInH, reqW, reqH, reqMaxW, reqMaxH);
|
var hwScaleFilter = GetHwScaleFilter(hwScalePrefix, "qsv", outFormat, swapOutputWandH, swpInW, swpInH, reqW, reqH, reqMaxW, reqMaxH);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(hwScaleFilter) && doVppTranspose)
|
if (!string.IsNullOrEmpty(hwScaleFilter) && doVppTranspose)
|
||||||
@ -4069,6 +4120,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
hwScaleFilter += $":transpose={tranposeDir}";
|
hwScaleFilter += $":transpose={tranposeDir}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(hwScaleFilter) && doVppTonemap)
|
||||||
|
{
|
||||||
|
hwScaleFilter += doVppProcamp ? procampParams : ":tonemap=1";
|
||||||
|
}
|
||||||
|
|
||||||
if (isD3d11vaDecoder)
|
if (isD3d11vaDecoder)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(hwScaleFilter) || doDeintH2645)
|
if (!string.IsNullOrEmpty(hwScaleFilter) || doDeintH2645)
|
||||||
@ -4086,8 +4142,20 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
mainFilters.Add(deintFilter);
|
mainFilters.Add(deintFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hw transpose & scale
|
// hw transpose & scale & tonemap(w/o procamp)
|
||||||
mainFilters.Add(hwScaleFilter);
|
mainFilters.Add(hwScaleFilter);
|
||||||
|
|
||||||
|
// hw tonemap(w/ procamp)
|
||||||
|
if (doVppTonemap && doVppProcamp)
|
||||||
|
{
|
||||||
|
mainFilters.Add("vpp_qsv=tonemap=1:format=nv12:async_depth=2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// force bt709 just in case vpp tonemap is not triggered or using MSDK instead of VPL.
|
||||||
|
if (doVppTonemap)
|
||||||
|
{
|
||||||
|
mainFilters.Add(GetOverwriteColorPropertiesParam(state, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doOclTonemap && isHwDecoder)
|
if (doOclTonemap && isHwDecoder)
|
||||||
@ -4220,7 +4288,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
|
|
||||||
var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
||||||
var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
||||||
var doVaVppTonemap = IsVaapiVppTonemapAvailable(state, options);
|
var doVaVppTonemap = IsIntelVppTonemapAvailable(state, options);
|
||||||
var doOclTonemap = !doVaVppTonemap && IsHwTonemapAvailable(state, options);
|
var doOclTonemap = !doVaVppTonemap && IsHwTonemapAvailable(state, options);
|
||||||
var doTonemap = doVaVppTonemap || doOclTonemap;
|
var doTonemap = doVaVppTonemap || doOclTonemap;
|
||||||
var doDeintH2645 = doDeintH264 || doDeintHevc;
|
var doDeintH2645 = doDeintH264 || doDeintHevc;
|
||||||
@ -4531,7 +4599,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
|
|
||||||
var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
||||||
var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
||||||
var doVaVppTonemap = isVaapiDecoder && IsVaapiVppTonemapAvailable(state, options);
|
var doVaVppTonemap = isVaapiDecoder && IsIntelVppTonemapAvailable(state, options);
|
||||||
var doOclTonemap = !doVaVppTonemap && IsHwTonemapAvailable(state, options);
|
var doOclTonemap = !doVaVppTonemap && IsHwTonemapAvailable(state, options);
|
||||||
var doTonemap = doVaVppTonemap || doOclTonemap;
|
var doTonemap = doVaVppTonemap || doOclTonemap;
|
||||||
var doDeintH2645 = doDeintH264 || doDeintHevc;
|
var doDeintH2645 = doDeintH264 || doDeintHevc;
|
||||||
|
Loading…
Reference in New Issue
Block a user