|
|
@ -41,6 +41,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
|
|
private readonly Version _maxKerneli915Hang = new Version(6, 1, 3);
|
|
|
|
private readonly Version _maxKerneli915Hang = new Version(6, 1, 3);
|
|
|
|
private readonly Version _minFixedKernel60i915Hang = new Version(6, 0, 18);
|
|
|
|
private readonly Version _minFixedKernel60i915Hang = new Version(6, 0, 18);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Version _minFFmpegImplictHwaccel = new Version(6, 0);
|
|
|
|
|
|
|
|
private readonly Version _minFFmpegHwaUnsafeOutput = new Version(6, 0);
|
|
|
|
|
|
|
|
|
|
|
|
private static readonly string[] _videoProfilesH264 = new[]
|
|
|
|
private static readonly string[] _videoProfilesH264 = new[]
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"ConstrainedBaseline",
|
|
|
|
"ConstrainedBaseline",
|
|
|
@ -2397,6 +2400,30 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
|
|
return args;
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Gets the negative map args by filters.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="state">The state.</param>
|
|
|
|
|
|
|
|
/// <param name="videoProcessFilters">The videoProcessFilters.</param>
|
|
|
|
|
|
|
|
/// <returns>System.String.</returns>
|
|
|
|
|
|
|
|
public string GetNegativeMapArgsByFilters(EncodingJobInfo state, string videoProcessFilters)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
string args = string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// http://ffmpeg.org/ffmpeg-all.html#toc-Complex-filtergraphs-1
|
|
|
|
|
|
|
|
if (state.VideoStream != null && videoProcessFilters.Contains("-filter_complex", StringComparison.Ordinal))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int videoStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.VideoStream);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
args += string.Format(
|
|
|
|
|
|
|
|
CultureInfo.InvariantCulture,
|
|
|
|
|
|
|
|
"-map -0:{0} ",
|
|
|
|
|
|
|
|
videoStreamIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return args;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Determines which stream will be used for playback.
|
|
|
|
/// Determines which stream will be used for playback.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
@ -4538,13 +4565,19 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
|
|
var isVideotoolboxSupported = isMacOS && _mediaEncoder.SupportsHwaccel("videotoolbox");
|
|
|
|
var isVideotoolboxSupported = isMacOS && _mediaEncoder.SupportsHwaccel("videotoolbox");
|
|
|
|
var isCodecAvailable = options.HardwareDecodingCodecs.Contains(videoCodec, StringComparison.OrdinalIgnoreCase);
|
|
|
|
var isCodecAvailable = options.HardwareDecodingCodecs.Contains(videoCodec, StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var ffmpegVersion = _mediaEncoder.EncoderVersion;
|
|
|
|
|
|
|
|
|
|
|
|
// Set the av1 codec explicitly to trigger hw accelerator, otherwise libdav1d will be used.
|
|
|
|
// Set the av1 codec explicitly to trigger hw accelerator, otherwise libdav1d will be used.
|
|
|
|
var isAv1 = string.Equals(videoCodec, "av1", StringComparison.OrdinalIgnoreCase);
|
|
|
|
var isAv1 = ffmpegVersion < _minFFmpegImplictHwaccel
|
|
|
|
|
|
|
|
&& string.Equals(videoCodec, "av1", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
|
|
// Allow profile mismatch if decoding H.264 baseline with d3d11va and vaapi hwaccels.
|
|
|
|
// Allow profile mismatch if decoding H.264 baseline with d3d11va and vaapi hwaccels.
|
|
|
|
var profileMismatch = string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)
|
|
|
|
var profileMismatch = string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)
|
|
|
|
&& string.Equals(state.VideoStream?.Profile, "baseline", StringComparison.OrdinalIgnoreCase);
|
|
|
|
&& string.Equals(state.VideoStream?.Profile, "baseline", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Disable the extra internal copy in nvdec. We already handle it in filter chain.
|
|
|
|
|
|
|
|
var nvdecNoInternalCopy = ffmpegVersion >= _minFFmpegHwaUnsafeOutput;
|
|
|
|
|
|
|
|
|
|
|
|
if (bitDepth == 10 && isCodecAvailable)
|
|
|
|
if (bitDepth == 10 && isCodecAvailable)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (string.Equals(videoCodec, "hevc", StringComparison.OrdinalIgnoreCase)
|
|
|
|
if (string.Equals(videoCodec, "hevc", StringComparison.OrdinalIgnoreCase)
|
|
|
@ -4598,7 +4631,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
|
|
if (options.EnableEnhancedNvdecDecoder)
|
|
|
|
if (options.EnableEnhancedNvdecDecoder)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// set -threads 1 to nvdec decoder explicitly since it doesn't implement threading support.
|
|
|
|
// set -threads 1 to nvdec decoder explicitly since it doesn't implement threading support.
|
|
|
|
return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty) + " -threads 1" + (isAv1 ? " -c:v av1" : string.Empty);
|
|
|
|
return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty)
|
|
|
|
|
|
|
|
+ (nvdecNoInternalCopy ? " -hwaccel_flags +unsafe_output" : string.Empty) + " -threads 1" + (isAv1 ? " -c:v av1" : string.Empty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -5428,7 +5462,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
|
|
// video processing filters.
|
|
|
|
// video processing filters.
|
|
|
|
var videoProcessParam = GetVideoProcessingFilterParam(state, encodingOptions, videoCodec);
|
|
|
|
var videoProcessParam = GetVideoProcessingFilterParam(state, encodingOptions, videoCodec);
|
|
|
|
|
|
|
|
|
|
|
|
args += videoProcessParam;
|
|
|
|
var negativeMapArgs = GetNegativeMapArgsByFilters(state, videoProcessParam);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
args = negativeMapArgs + args + videoProcessParam;
|
|
|
|
|
|
|
|
|
|
|
|
hasCopyTs = videoProcessParam.Contains("copyts", StringComparison.OrdinalIgnoreCase);
|
|
|
|
hasCopyTs = videoProcessParam.Contains("copyts", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
|
|