diff options
Diffstat (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs')
| -rw-r--r-- | MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index db86a49f6..0530e2af0 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -67,6 +67,7 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly Version _minFFmpegWorkingVtHwSurface = new Version(7, 0, 1); private readonly Version _minFFmpegDisplayRotationOption = new Version(6, 0); private readonly Version _minFFmpegAdvancedTonemapMode = new Version(7, 0, 1); + private readonly Version _minFFmpegAlteredVaVkInterop = new Version(7, 0, 1); private static readonly Regex _validationRegex = new(ValidationRegex, RegexOptions.Compiled); @@ -296,14 +297,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.VideoStream is null || !options.EnableTonemapping || GetVideoColorBitDepth(state) != 10 - || !_mediaEncoder.SupportsFilter("tonemapx") - || !(string.Equals(state.VideoStream?.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase) || string.Equals(state.VideoStream?.ColorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase))) + || !_mediaEncoder.SupportsFilter("tonemapx")) { return false; } - return state.VideoStream.VideoRange == VideoRange.HDR - && state.VideoStream.VideoRangeType is VideoRangeType.HDR10 or VideoRangeType.HLG or VideoRangeType.DOVIWithHDR10 or VideoRangeType.DOVIWithHLG; + return state.VideoStream.VideoRange == VideoRange.HDR; } private bool IsHwTonemapAvailable(EncodingJobInfo state, EncodingOptions options) @@ -3369,15 +3368,7 @@ namespace MediaBrowser.Controller.MediaEncoding algorithm = "clip"; } - tonemapArg = ":tonemapping=" + algorithm; - - if (string.Equals(mode, "max", StringComparison.OrdinalIgnoreCase) - || string.Equals(mode, "rgb", StringComparison.OrdinalIgnoreCase)) - { - tonemapArg += ":tonemapping_mode=" + mode; - } - - tonemapArg += ":peak_detect=0:color_primaries=bt709:color_trc=bt709:colorspace=bt709"; + tonemapArg = ":tonemapping=" + algorithm + ":peak_detect=0:color_primaries=bt709:color_trc=bt709:colorspace=bt709"; if (string.Equals(range, "tv", StringComparison.OrdinalIgnoreCase) || string.Equals(range, "pc", StringComparison.OrdinalIgnoreCase)) @@ -3435,6 +3426,7 @@ namespace MediaBrowser.Controller.MediaEncoding var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true); var doDeintH2645 = doDeintH264 || doDeintHevc; var doToneMap = IsSwTonemapAvailable(state, options); + var requireDoviReshaping = doToneMap && state.VideoStream.VideoRangeType == VideoRangeType.DOVI; var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream; @@ -3472,11 +3464,13 @@ namespace MediaBrowser.Controller.MediaEncoding // sw scale mainFilters.Add(swScaleFilter); - // sw tonemap <= TODO: finish dovi tone mapping - + // sw tonemap if (doToneMap) { - var tonemapArgs = $"tonemapx=tonemap={options.TonemappingAlgorithm}:desat={options.TonemappingDesat}:peak={options.TonemappingPeak}:t=bt709:m=bt709:p=bt709:format={outFormat}"; + // tonemapx requires yuv420p10 input for dovi reshaping, let ffmpeg convert the frame when necessary + var tonemapFormat = requireDoviReshaping ? "yuv420p" : outFormat; + + var tonemapArgs = $"tonemapx=tonemap={options.TonemappingAlgorithm}:desat={options.TonemappingDesat}:peak={options.TonemappingPeak}:t=bt709:m=bt709:p=bt709:format={tonemapFormat}"; if (options.TonemappingParam != 0) { @@ -4803,8 +4797,34 @@ namespace MediaBrowser.Controller.MediaEncoding if (doVkTranspose || doVkTonemap || hasSubs) { // map from vaapi to vulkan/drm via interop (Polaris/gfx8+). - mainFilters.Add("hwmap=derive_device=vulkan"); - mainFilters.Add("format=vulkan"); + if (_mediaEncoder.EncoderVersion >= _minFFmpegAlteredVaVkInterop) + { + if (doVkTranspose || !_mediaEncoder.IsVaapiDeviceSupportVulkanDrmModifier) + { + // disable the indirect va-drm-vk mapping since it's no longer reliable. + mainFilters.Add("hwmap=derive_device=drm"); + mainFilters.Add("format=drm_prime"); + mainFilters.Add("hwmap=derive_device=vulkan"); + mainFilters.Add("format=vulkan"); + + // workaround for libplacebo using the imported vulkan frame on gfx8. + if (!_mediaEncoder.IsVaapiDeviceSupportVulkanDrmModifier) + { + mainFilters.Add("scale_vulkan"); + } + } + else if (doVkTonemap || hasSubs) + { + // non ad-hoc libplacebo also accepts drm_prime direct input. + mainFilters.Add("hwmap=derive_device=drm"); + mainFilters.Add("format=drm_prime"); + } + } + else // legacy va-vk mapping that works only in jellyfin-ffmpeg6 + { + mainFilters.Add("hwmap=derive_device=vulkan"); + mainFilters.Add("format=vulkan"); + } } else { @@ -4839,6 +4859,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var libplaceboFilter = GetLibplaceboFilter(options, "bgra", doVkTonemap, swpInW, swpInH, reqW, reqH, reqMaxW, reqMaxH); mainFilters.Add(libplaceboFilter); + mainFilters.Add("format=vulkan"); } if (doVkTonemap && !hasSubs) @@ -5135,13 +5156,15 @@ namespace MediaBrowser.Controller.MediaEncoding return (null, null, null); } + // ReSharper disable once InconsistentNaming var isMacOS = OperatingSystem.IsMacOS(); var vidDecoder = GetHardwareVideoDecoder(state, options) ?? string.Empty; + var isVtDecoder = vidDecoder.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase); var isVtEncoder = vidEncoder.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase); var isVtFullSupported = isMacOS && IsVideoToolboxFullSupported(); // legacy videotoolbox pipeline (disable hw filters) - if (!isVtEncoder + if (!(isVtEncoder || isVtDecoder) || !isVtFullSupported || !_mediaEncoder.SupportsFilter("alphasrc")) { @@ -5161,12 +5184,6 @@ namespace MediaBrowser.Controller.MediaEncoding var isVtEncoder = vidEncoder.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase); var isVtDecoder = vidDecoder.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase); - if (!isVtEncoder) - { - // should not happen. - return (null, null, null); - } - var inW = state.VideoStream?.Width; var inH = state.VideoStream?.Height; var reqW = state.BaseRequest.Width; @@ -5281,6 +5298,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (usingHwSurface) { + if (!isVtEncoder) + { + mainFilters.Add("hwdownload"); + mainFilters.Add("format=nv12"); + } + return (mainFilters, subFilters, overlayFilters); } @@ -5294,6 +5317,12 @@ namespace MediaBrowser.Controller.MediaEncoding // this will pass-through automatically if in/out format matches. mainFilters.Insert(0, "hwupload"); mainFilters.Insert(0, "format=nv12|p010le|videotoolbox_vld"); + + if (!isVtEncoder) + { + mainFilters.Add("hwdownload"); + mainFilters.Add("format=nv12"); + } } return (mainFilters, subFilters, overlayFilters); |
