enhance platform check and 10bit detect

This commit is contained in:
Nyanmisaka 2020-07-17 19:32:15 +08:00 committed by GitHub
parent e1ba1fcebe
commit 77f9417d84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
@ -449,60 +450,66 @@ namespace MediaBrowser.Controller.MediaEncoding
var arg = new StringBuilder(); var arg = new StringBuilder();
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty; var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty;
var outputVideoCodec = GetVideoEncoder(state, encodingOptions) ?? string.Empty; var outputVideoCodec = GetVideoEncoder(state, encodingOptions) ?? string.Empty;
bool isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
bool isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
bool isQsvDecoder = videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; var isQsvDecoder = videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
bool isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
if (state.IsVideoRequest if (!IsCopyCodec(outputVideoCodec))
&& string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
{ {
if (isVaapiDecoder) if (state.IsVideoRequest
&& IsVaapiSupported(state)
&& string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
{ {
arg.Append("-hwaccel_output_format vaapi ") if (isVaapiDecoder)
.Append("-vaapi_device ")
.Append(encodingOptions.VaapiDevice)
.Append(" ");
}
else if (!isVaapiDecoder && isVaapiEncoder)
{
arg.Append("-vaapi_device ")
.Append(encodingOptions.VaapiDevice)
.Append(" ");
}
}
if (state.IsVideoRequest
&& string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
var isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
if (isQsvEncoder)
{
if (isQsvDecoder)
{ {
if (!isWindows) arg.Append("-hwaccel_output_format vaapi ")
.Append("-vaapi_device ")
.Append(encodingOptions.VaapiDevice)
.Append(" ");
}
else if (!isVaapiDecoder && isVaapiEncoder)
{
arg.Append("-vaapi_device ")
.Append(encodingOptions.VaapiDevice)
.Append(" ");
}
}
if (state.IsVideoRequest
&& string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
if (isQsvEncoder)
{
if (isQsvDecoder)
{ {
if (hasGraphicalSubs) if (isLinux)
{ {
arg.Append("-init_hw_device qsv=hw -filter_hw_device hw "); if (hasGraphicalSubs)
{
arg.Append("-init_hw_device qsv=hw -filter_hw_device hw ");
}
else
{
arg.Append("-hwaccel qsv -init_hw_device qsv=hw ");
}
} }
else
if (isWindows)
{ {
arg.Append("-hwaccel qsv -init_hw_device qsv=hw "); arg.Append("-hwaccel qsv -init_hw_device qsv=hw ");
} }
} }
// While using SW decoder
else else
{ {
arg.Append("-hwaccel qsv -init_hw_device qsv=hw "); arg.Append("-init_hw_device qsv=hw -filter_hw_device hw ");
} }
} }
// While using SW decoder
else
{
arg.Append("-init_hw_device qsv=hw -filter_hw_device hw ");
}
} }
} }
@ -1625,7 +1632,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var videoSizeParam = string.Empty; var videoSizeParam = string.Empty;
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty; var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty;
var isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
// Setup subtitle scaling // Setup subtitle scaling
if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue) if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue)
@ -1646,7 +1653,7 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
// For QSV, feed it into hardware encoder now // For QSV, feed it into hardware encoder now
if (!isWindows && string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) if (isLinux && string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
{ {
videoSizeParam += ",hwupload=extra_hw_frames=64"; videoSizeParam += ",hwupload=extra_hw_frames=64";
} }
@ -1696,7 +1703,7 @@ namespace MediaBrowser.Controller.MediaEncoding
with fixed frame size. with fixed frame size.
Currently only supports linux. Currently only supports linux.
*/ */
if (!isWindows) if (isLinux)
{ {
retStr = !string.IsNullOrEmpty(outputSizeParam) ? retStr = !string.IsNullOrEmpty(outputSizeParam) ?
" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_qsv\"" : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_qsv\"" :
@ -2043,14 +2050,11 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first // If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
else if (videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1 else if (IsVaapiSupported(state) && videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1
&& string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) && string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
{ {
var codec = videoStream.Codec.ToLowerInvariant(); var codec = videoStream.Codec.ToLowerInvariant();
var isColorDepth10 = !string.IsNullOrEmpty(videoStream.Profile) var isColorDepth10 = IsColorDepth10(state);
&& (videoStream.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase)
|| videoStream.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase)
|| videoStream.Profile.Contains("Profile 2", StringComparison.OrdinalIgnoreCase));
// Assert 10-bit hardware VAAPI decodable // Assert 10-bit hardware VAAPI decodable
if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)
@ -2318,7 +2322,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
inputModifier += " " + videoDecoder; inputModifier += " " + videoDecoder;
if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1) if (!IsCopyCodec(state.OutputVideoCodec)
&& (videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1)
{ {
var videoStream = state.VideoStream; var videoStream = state.VideoStream;
var inputWidth = videoStream?.Width; var inputWidth = videoStream?.Width;
@ -2589,10 +2594,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(videoStream.Codec) && !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType)) if (!string.IsNullOrEmpty(videoStream.Codec) && !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType))
{ {
var isColorDepth10 = !string.IsNullOrEmpty(videoStream.Profile) var isColorDepth10 = IsColorDepth10(state);
&& (videoStream.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase)
|| videoStream.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase)
|| videoStream.Profile.Contains("Profile 2", StringComparison.OrdinalIgnoreCase));
// Only hevc and vp9 formats have 10-bit hardware decoder support now. // Only hevc and vp9 formats have 10-bit hardware decoder support now.
if (isColorDepth10 && !(string.Equals(videoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase) if (isColorDepth10 && !(string.Equals(videoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase)
@ -2669,13 +2671,6 @@ namespace MediaBrowser.Controller.MediaEncoding
case "h264": case "h264":
if (_mediaEncoder.SupportsDecoder("h264_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase)) if (_mediaEncoder.SupportsDecoder("h264_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
{ {
// cuvid decoder does not support 10-bit input.
if ((videoStream.BitDepth ?? 8) > 8)
{
encodingOptions.HardwareDecodingCodecs = Array.Empty<string>();
return null;
}
return "-c:v h264_cuvid"; return "-c:v h264_cuvid";
} }
@ -2942,21 +2937,24 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary> /// </summary>
public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec) public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec)
{ {
var isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
var isWindows8orLater = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1); var isWindows8orLater = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1);
var isDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va"); var isDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va");
if ((isDxvaSupported || IsVaapiSupported(state)) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase)) if ((isDxvaSupported || IsVaapiSupported(state)) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase))
{ {
if (!isWindows) if (isLinux)
{ {
return "-hwaccel vaapi"; return "-hwaccel vaapi";
} }
else if (isWindows8orLater)
if (isWindows && isWindows8orLater)
{ {
return "-hwaccel d3d11va"; return "-hwaccel d3d11va";
} }
else
if (isWindows && !isWindows8orLater)
{ {
return "-hwaccel dxva2"; return "-hwaccel dxva2";
} }
@ -3225,5 +3223,42 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
return string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase); return string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase);
} }
public static bool IsColorDepth10(EncodingJobInfo state)
{
var result = false;
var videoStream = state.VideoStream;
if (videoStream != null)
{
if (!string.IsNullOrEmpty(videoStream.PixelFormat))
{
result = videoStream.PixelFormat.Contains("p10", StringComparison.OrdinalIgnoreCase);
if (result)
{
return true;
}
}
if (!string.IsNullOrEmpty(videoStream.Profile))
{
result = videoStream.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase)
|| videoStream.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase)
|| videoStream.Profile.Contains("Profile 2", StringComparison.OrdinalIgnoreCase);
if (result)
{
return true;
}
}
result = (videoStream.BitDepth ?? 8) == 10;
if (result)
{
return true;
}
}
return result;
}
} }
} }