From f21ab50a81dec27a14f7f985917eca7ea55176b2 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Thu, 9 Mar 2023 19:38:15 -0500 Subject: Backport pull request #9422 from jellyfin/release-10.8.z Fix stream map when using filter_complex with unlabeled output Original-merge: 6821a2ab358761282a0030c42c837b39bad089e1 Merged-by: Bond-009 Backported-by: crobibero --- .../MediaEncoding/EncodingHelper.cs | 42 ++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 0f3912e28..afe5a686e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -43,6 +43,9 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly Version _maxKerneli915Hang = new Version(6, 1, 3); 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[] { "ConstrainedBaseline", @@ -2455,6 +2458,30 @@ namespace MediaBrowser.Controller.MediaEncoding return args; } + /// + /// Gets the negative map args by filters. + /// + /// The state. + /// The videoProcessFilters. + /// System.String. + 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; + } + /// /// Determines which stream will be used for playback. /// @@ -4906,13 +4933,19 @@ namespace MediaBrowser.Controller.MediaEncoding var isVideotoolboxSupported = isMacOS && _mediaEncoder.SupportsHwaccel("videotoolbox"); 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. - 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. var profileMismatch = string.Equals(videoCodec, "h264", 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 (string.Equals(videoCodec, "hevc", StringComparison.OrdinalIgnoreCase) @@ -4966,7 +4999,8 @@ namespace MediaBrowser.Controller.MediaEncoding if (options.EnableEnhancedNvdecDecoder) { // 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 { @@ -5799,7 +5833,9 @@ namespace MediaBrowser.Controller.MediaEncoding // video processing filters. var videoProcessParam = GetVideoProcessingFilterParam(state, encodingOptions, videoCodec); - args += videoProcessParam; + var negativeMapArgs = GetNegativeMapArgsByFilters(state, videoProcessParam); + + args = negativeMapArgs + args + videoProcessParam; hasCopyTs = videoProcessParam.Contains("copyts", StringComparison.OrdinalIgnoreCase); -- cgit v1.2.3