|
@@ -127,6 +127,25 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
&& videoStream.VideoRange.Contains("HDR", StringComparison.OrdinalIgnoreCase);
|
|
&& videoStream.VideoRange.Contains("HDR", StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private bool IsVppTonemappingSupported(EncodingJobInfo state, EncodingOptions options)
|
|
|
|
+ {
|
|
|
|
+ var videoStream = state.VideoStream;
|
|
|
|
+ var codec = videoStream.Codec;
|
|
|
|
+ if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
|
|
|
|
+ {
|
|
|
|
+ // Limited to HEVC for now since the filter doesn't accept master data from VP9.
|
|
|
|
+ return IsColorDepth10(state)
|
|
|
|
+ && string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)
|
|
|
|
+ && _mediaEncoder.SupportsHwaccel("vaapi")
|
|
|
|
+ && options.EnableVppTonemapping
|
|
|
|
+ && !string.IsNullOrEmpty(videoStream.ColorTransfer)
|
|
|
|
+ && videoStream.ColorTransfer.Equals("smpte2084", StringComparison.OrdinalIgnoreCase);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Vpp tonemapping may come to QSV in the future.
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Gets the name of the output video codec.
|
|
/// Gets the name of the output video codec.
|
|
/// </summary>
|
|
/// </summary>
|
|
@@ -469,6 +488,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
|
|
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
|
|
var isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
|
var isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, encodingOptions);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, encodingOptions);
|
|
|
|
+ var isVppTonemappingSupported = IsVppTonemappingSupported(state, encodingOptions);
|
|
|
|
|
|
if (!IsCopyCodec(outputVideoCodec))
|
|
if (!IsCopyCodec(outputVideoCodec))
|
|
{
|
|
{
|
|
@@ -478,7 +498,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
{
|
|
{
|
|
if (isVaapiDecoder)
|
|
if (isVaapiDecoder)
|
|
{
|
|
{
|
|
- if (isTonemappingSupported)
|
|
|
|
|
|
+ if (isTonemappingSupported && !isVppTonemappingSupported)
|
|
{
|
|
{
|
|
arg.Append("-init_hw_device vaapi=va:")
|
|
arg.Append("-init_hw_device vaapi=va:")
|
|
.Append(encodingOptions.VaapiDevice)
|
|
.Append(encodingOptions.VaapiDevice)
|
|
@@ -938,7 +958,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
var videoStream = state.VideoStream;
|
|
var videoStream = state.VideoStream;
|
|
var isColorDepth10 = IsColorDepth10(state);
|
|
var isColorDepth10 = IsColorDepth10(state);
|
|
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty;
|
|
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty;
|
|
- var isNvdecDecoder = videoDecoder.IndexOf("cuda", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
|
|
+ var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
if (!isNvdecDecoder)
|
|
if (!isNvdecDecoder)
|
|
{
|
|
{
|
|
@@ -1932,14 +1952,15 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isVaapiH264Encoder = outputVideoCodec.IndexOf("h264_vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isVaapiH264Encoder = outputVideoCodec.IndexOf("h264_vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isVaapiHevcEncoder = outputVideoCodec.IndexOf("hevc_vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isVaapiHevcEncoder = outputVideoCodec.IndexOf("hevc_vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
- var isNvdecDecoder = videoDecoder.IndexOf("cuda", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
- var isNvencEncoder = outputVideoCodec.IndexOf("nvenc", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
|
|
+ var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase);
|
|
|
|
+ var isNvencEncoder = outputVideoCodec.Contains("nvenc", StringComparison.OrdinalIgnoreCase);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, options);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, options);
|
|
|
|
+ var isVppTonemappingSupported = IsVppTonemappingSupported(state, options);
|
|
var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder);
|
|
var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder);
|
|
|
|
|
|
// Tonemapping and burn-in graphical subtitles requires overlay_vaapi.
|
|
// Tonemapping and burn-in graphical subtitles requires overlay_vaapi.
|
|
// But it's still in ffmpeg mailing list. Disable it for now.
|
|
// But it's still in ffmpeg mailing list. Disable it for now.
|
|
- if (isTonemappingSupported && isTonemappingSupportedOnVaapi)
|
|
|
|
|
|
+ if (isTonemappingSupported && isTonemappingSupportedOnVaapi && !isVppTonemappingSupported)
|
|
{
|
|
{
|
|
return GetOutputSizeParam(state, options, outputVideoCodec);
|
|
return GetOutputSizeParam(state, options, outputVideoCodec);
|
|
}
|
|
}
|
|
@@ -2123,17 +2144,24 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
|| state.DeInterlace("h265", true)
|
|
|| state.DeInterlace("h265", true)
|
|
|| state.DeInterlace("hevc", true);
|
|
|| state.DeInterlace("hevc", true);
|
|
|
|
|
|
|
|
+ var isVaapiDecoder = videoDecoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase);
|
|
|
|
+ var isVaapiH264Encoder = videoEncoder.Contains("h264_vaapi", StringComparison.OrdinalIgnoreCase);
|
|
|
|
+ var isVaapiHevcEncoder = videoEncoder.Contains("hevc_vaapi", StringComparison.OrdinalIgnoreCase);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, options);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, options);
|
|
- var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && !qsv_or_vaapi;
|
|
|
|
|
|
+ var isVppTonemappingSupported = IsVppTonemappingSupported(state, options);
|
|
|
|
+ var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder);
|
|
|
|
|
|
- var outputPixFmt = string.Empty;
|
|
|
|
- if (isTonemappingSupported && isTonemappingSupportedOnVaapi)
|
|
|
|
- {
|
|
|
|
- outputPixFmt = "format=p010:out_range=limited";
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
|
|
+ var outputPixFmt = "format=nv12";
|
|
|
|
+ if (isTonemappingSupportedOnVaapi)
|
|
{
|
|
{
|
|
- outputPixFmt = "format=nv12";
|
|
|
|
|
|
+ if (isVppTonemappingSupported)
|
|
|
|
+ {
|
|
|
|
+ outputPixFmt = "format=p010";
|
|
|
|
+ }
|
|
|
|
+ else if (isTonemappingSupported)
|
|
|
|
+ {
|
|
|
|
+ outputPixFmt = "format=p010:out_range=limited";
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (!videoWidth.HasValue
|
|
if (!videoWidth.HasValue
|
|
@@ -2164,7 +2192,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
(qsv_or_vaapi && isDeintEnabled) ? ":deinterlace=1" : string.Empty));
|
|
(qsv_or_vaapi && isDeintEnabled) ? ":deinterlace=1" : string.Empty));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- else if ((videoDecoder ?? string.Empty).IndexOf("cuda", StringComparison.OrdinalIgnoreCase) != -1
|
|
|
|
|
|
+ else if ((videoDecoder ?? string.Empty).Contains("cuda", StringComparison.OrdinalIgnoreCase)
|
|
&& width.HasValue
|
|
&& width.HasValue
|
|
&& height.HasValue)
|
|
&& height.HasValue)
|
|
{
|
|
{
|
|
@@ -2418,15 +2446,16 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
var isVaapiHevcEncoder = outputVideoCodec.IndexOf("hevc_vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isVaapiHevcEncoder = outputVideoCodec.IndexOf("hevc_vaapi", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isQsvH264Encoder = outputVideoCodec.IndexOf("h264_qsv", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isQsvH264Encoder = outputVideoCodec.IndexOf("h264_qsv", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isQsvHevcEncoder = outputVideoCodec.IndexOf("hevc_qsv", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isQsvHevcEncoder = outputVideoCodec.IndexOf("hevc_qsv", StringComparison.OrdinalIgnoreCase) != -1;
|
|
- var isNvdecDecoder = videoDecoder.IndexOf("cuda", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
- var isNvencEncoder = outputVideoCodec.IndexOf("nvenc", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
- var isCuvidH264Decoder = videoDecoder.IndexOf("h264_cuvid", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
- var isCuvidHevcDecoder = videoDecoder.IndexOf("hevc_cuvid", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
|
|
+ var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase);
|
|
|
|
+ var isNvencEncoder = outputVideoCodec.Contains("nvenc", StringComparison.OrdinalIgnoreCase);
|
|
|
|
+ var isCuvidH264Decoder = videoDecoder.Contains("h264_cuvid", StringComparison.OrdinalIgnoreCase);
|
|
|
|
+ var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase);
|
|
var isLibX264Encoder = outputVideoCodec.IndexOf("libx264", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isLibX264Encoder = outputVideoCodec.IndexOf("libx264", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isLibX265Encoder = outputVideoCodec.IndexOf("libx265", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isLibX265Encoder = outputVideoCodec.IndexOf("libx265", StringComparison.OrdinalIgnoreCase) != -1;
|
|
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
|
|
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
|
|
var isColorDepth10 = IsColorDepth10(state);
|
|
var isColorDepth10 = IsColorDepth10(state);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, options);
|
|
var isTonemappingSupported = IsTonemappingSupported(state, options);
|
|
|
|
+ var isVppTonemappingSupported = IsVppTonemappingSupported(state, options);
|
|
var isTonemappingSupportedOnNvenc = string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder);
|
|
var isTonemappingSupportedOnNvenc = string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder);
|
|
var isTonemappingSupportedOnAmf = string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) && (isD3d11vaDecoder || isSwDecoder);
|
|
var isTonemappingSupportedOnAmf = string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) && (isD3d11vaDecoder || isSwDecoder);
|
|
var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder);
|
|
var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder);
|
|
@@ -2444,7 +2473,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
var isDeinterlaceH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
|
var isDeinterlaceH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
|
|
var isDeinterlaceHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
|
var isDeinterlaceHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
|
|
|
|
|
|
- if (isTonemappingSupportedOnNvenc || isTonemappingSupportedOnAmf || isTonemappingSupportedOnVaapi)
|
|
|
|
|
|
+ // Add OpenCL tonemapping filter for NVENC/AMF/VAAPI.
|
|
|
|
+ if (isTonemappingSupportedOnNvenc || isTonemappingSupportedOnAmf || (isTonemappingSupportedOnVaapi && !isVppTonemappingSupported))
|
|
{
|
|
{
|
|
// Currently only with the use of NVENC decoder can we get a decent performance.
|
|
// Currently only with the use of NVENC decoder can we get a decent performance.
|
|
// Currently only the HEVC/H265 format is supported with NVDEC decoder.
|
|
// Currently only the HEVC/H265 format is supported with NVDEC decoder.
|
|
@@ -2490,7 +2520,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
filters.Add(
|
|
filters.Add(
|
|
string.Format(
|
|
string.Format(
|
|
CultureInfo.InvariantCulture,
|
|
CultureInfo.InvariantCulture,
|
|
- "yadif={0}:-1:0",
|
|
|
|
|
|
+ "yadif_cuda={0}:-1:0",
|
|
doubleRateDeinterlace ? "1" : "0"));
|
|
doubleRateDeinterlace ? "1" : "0"));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2563,7 +2593,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
}
|
|
}
|
|
|
|
|
|
// When the input may or may not be hardware VAAPI decodable.
|
|
// When the input may or may not be hardware VAAPI decodable.
|
|
- if ((isVaapiH264Encoder || isVaapiHevcEncoder) && !isTonemappingSupported && !isTonemappingSupportedOnVaapi)
|
|
|
|
|
|
+ if ((isVaapiH264Encoder || isVaapiHevcEncoder)
|
|
|
|
+ && !isTonemappingSupported
|
|
|
|
+ && !isVppTonemappingSupported
|
|
|
|
+ && !isTonemappingSupportedOnVaapi)
|
|
{
|
|
{
|
|
filters.Add("format=nv12|vaapi");
|
|
filters.Add("format=nv12|vaapi");
|
|
filters.Add("hwupload");
|
|
filters.Add("hwupload");
|
|
@@ -2668,21 +2701,28 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
request.MaxHeight));
|
|
request.MaxHeight));
|
|
}
|
|
}
|
|
|
|
|
|
- // Another case is using Nvenc decoder.
|
|
|
|
|
|
+ // Add Vpp tonemapping filter for VAAPI.
|
|
|
|
+ // Full hardware based video post processing, faster than OpenCL but lacks fine tuning options.
|
|
|
|
+ if (isTonemappingSupportedOnVaapi && isVppTonemappingSupported)
|
|
|
|
+ {
|
|
|
|
+ filters.Add("tonemap_vaapi=format=nv12:transfer=bt709:matrix=bt709:primaries=bt709");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Another case is when using Nvenc decoder.
|
|
if (isNvdecDecoder && !isTonemappingSupported)
|
|
if (isNvdecDecoder && !isTonemappingSupported)
|
|
{
|
|
{
|
|
- var codec = videoStream.Codec.ToLowerInvariant();
|
|
|
|
|
|
+ var codec = videoStream.Codec;
|
|
|
|
|
|
// Assert 10-bit hardware decodable
|
|
// Assert 10-bit hardware decodable
|
|
if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)
|
|
if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)))
|
|
|| string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
{
|
|
- // Download data from GPU to CPU as p010le format.
|
|
|
|
|
|
+ // Download data from GPU to CPU as p010 format.
|
|
filters.Add("hwdownload");
|
|
filters.Add("hwdownload");
|
|
filters.Add("format=p010");
|
|
filters.Add("format=p010");
|
|
|
|
|
|
- // cuda lacks of a pixel format converter.
|
|
|
|
|
|
+ // Cuda lacks of a pixel format converter.
|
|
if (isNvencEncoder)
|
|
if (isNvencEncoder)
|
|
{
|
|
{
|
|
isHwuploadCudaRequired = true;
|
|
isHwuploadCudaRequired = true;
|
|
@@ -2710,7 +2750,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
{
|
|
{
|
|
// Convert hw context from ocl to va.
|
|
// Convert hw context from ocl to va.
|
|
// For tonemapping and text subs burn-in.
|
|
// For tonemapping and text subs burn-in.
|
|
- if (isTonemappingSupported && isTonemappingSupportedOnVaapi)
|
|
|
|
|
|
+ if (isTonemappingSupported && isTonemappingSupportedOnVaapi && !isVppTonemappingSupported)
|
|
{
|
|
{
|
|
filters.Add("scale_vaapi");
|
|
filters.Add("scale_vaapi");
|
|
}
|
|
}
|