From b205d5a03201de59240aefbce468b21199cf2b3d Mon Sep 17 00:00:00 2001 From: Chris Tam Date: Fri, 20 Aug 2021 14:22:21 -0400 Subject: Disambiguate vpx to vp8 or vp9 --- .../MediaEncoding/EncodingHelper.cs | 150 +++++++++++++-------- 1 file changed, 95 insertions(+), 55 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 8a0fae1f6..6d436bf8a 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -206,11 +206,17 @@ namespace MediaBrowser.Controller.MediaEncoding return GetH264Encoder(state, encodingOptions); } - if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(codec, "vp8", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) { return "libvpx"; } + if (string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)) + { + return "libvpx-vp9"; + } + if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase)) { return "wmv2"; @@ -442,7 +448,8 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) { - return "vpx"; + // TODO: this may not always mean VP8, as the codec ages + return "vp8"; } if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) @@ -558,12 +565,12 @@ namespace MediaBrowser.Controller.MediaEncoding { if (isOpenclTonemappingSupported && !isVppTonemappingSupported) { - arg.Append("-init_hw_device vaapi=va:") - .Append(options.VaapiDevice) - .Append(" -init_hw_device opencl=ocl@va ") - .Append("-hwaccel_device va ") - .Append("-hwaccel_output_format vaapi ") - .Append("-filter_hw_device ocl "); + arg.Append("-init_hw_device vaapi=va:") + .Append(options.VaapiDevice) + .Append(" -init_hw_device opencl=ocl@va ") + .Append("-hwaccel_device va ") + .Append("-hwaccel_output_format vaapi ") + .Append("-filter_hw_device ocl "); } else { @@ -772,49 +779,37 @@ namespace MediaBrowser.Controller.MediaEncoding public string GetVideoBitrateParam(EncodingJobInfo state, string videoCodec) { - var bitrate = state.OutputVideoBitrate; - - if (bitrate.HasValue) + if (state.OutputVideoBitrate == null) { - if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) - { - // When crf is used with vpx, b:v becomes a max rate - // https://trac.ffmpeg.org/wiki/Encode/VP9 - return string.Format( - CultureInfo.InvariantCulture, - " -maxrate:v {0} -bufsize:v {1} -b:v {0}", - bitrate.Value, - bitrate.Value * 2); - } + return string.Empty; + } - if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) - { - return string.Format( - CultureInfo.InvariantCulture, - " -b:v {0}", - bitrate.Value); - } + int bitrate = state.OutputVideoBitrate.Value; - if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) - { - // h264 - return string.Format( - CultureInfo.InvariantCulture, - " -maxrate {0} -bufsize {1}", - bitrate.Value, - bitrate.Value * 2); - } + // Currently use the same buffer size for all encoders + int bufsize = bitrate * 2; - // h264 - return string.Format( - CultureInfo.InvariantCulture, - " -b:v {0} -maxrate {0} -bufsize {1}", - bitrate.Value, - bitrate.Value * 2); + if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoCodec, "libvpx-vp9", StringComparison.OrdinalIgnoreCase)) + { + // When crf is used with vpx, b:v becomes a max rate + // https://trac.ffmpeg.org/wiki/Encode/VP8 + // https://trac.ffmpeg.org/wiki/Encode/VP9 + return FormattableString.Invariant($" -maxrate:v {bitrate} -bufsize:v {bufsize} -b:v {bitrate}"); } - return string.Empty; + if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) + { + return FormattableString.Invariant($" -b:v {bitrate}"); + } + + if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) + { + return FormattableString.Invariant($" -maxrate {bitrate} -bufsize {bufsize}"); + } + + return FormattableString.Invariant($" -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); } public static string NormalizeTranscodingLevel(EncodingJobInfo state, string level) @@ -1197,7 +1192,7 @@ namespace MediaBrowser.Controller.MediaEncoding param += " -header_insertion_mode gop -gops_per_idr 1"; } } - else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // webm + else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // vp8 { // Values 0-3, 0 being highest quality but slower var profileScore = 0; @@ -1225,6 +1220,55 @@ namespace MediaBrowser.Controller.MediaEncoding qmin, qmax); } + else if (string.Equals(videoEncoder, "libvpx-vp9", StringComparison.OrdinalIgnoreCase)) // vp9 + { + // When `-deadline` is set to `good` or `best`, `-cpu-used` ranges from 0-5. + // When `-deadline` is set to `realtime`, `-cpu-used` ranges from 0-15. + // Resources: + // * https://trac.ffmpeg.org/wiki/Encode/VP9 + // * https://superuser.com/questions/1586934 + // * https://developers.google.com/media/vp9 + param += encodingOptions.EncoderPreset switch + { + "veryslow" => " -deadline best -cpu-used 0", + "slower" => " -deadline best -cpu-used 2", + "slow" => " -deadline best -cpu-used 3", + "medium" => " -deadline good -cpu-used 0", + "fast" => " -deadline good -cpu-used 1", + "faster" => " -deadline good -cpu-used 2", + "veryfast" => " -deadline good -cpu-used 3", + "superfast" => " -deadline good -cpu-used 4", + "ultrafast" => " -deadline good -cpu-used 5", + _ => " -deadline good -cpu-used 1" + }; + + // TODO: until VP9 gets its own CRF setting, base CRF on H.265. + int h265Crf = encodingOptions.H265Crf; + int defaultVp9Crf = 31; + if (h265Crf >= 0 && h265Crf <= 51) + { + // This conversion factor is chosen to match the default CRF for H.265 to the + // recommended 1080p CRF from Google. The factor also maps the logarithmic CRF + // scale of x265 [0, 51] to that of VP9 [0, 63] relatively well. + + // Resources: + // * https://developers.google.com/media/vp9/settings/vod + const float H265ToVp9CrfConversionFactor = 1.12F; + + var vp9Crf = Convert.ToInt32(h265Crf * H265ToVp9CrfConversionFactor); + + // Encoder allows for CRF values in the range [0, 63]. + vp9Crf = Math.Clamp(vp9Crf, 0, 63); + + param += FormattableString.Invariant($" -crf {vp9Crf}"); + } + else + { + param += FormattableString.Invariant($" -crf {defaultVp9Crf}"); + } + + param += " -row-mt 1 -profile 1"; + } else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase)) { param += " -mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; @@ -3149,20 +3193,16 @@ namespace MediaBrowser.Controller.MediaEncoding #nullable enable public static int GetNumberOfThreads(EncodingJobInfo? state, EncodingOptions encodingOptions, string? outputVideoCodec) { - if (string.Equals(outputVideoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) - { - // per docs: - // -threads number of threads to use for encoding, can't be 0 [auto] with VP8 - // (recommended value : number of real cores - 1) - return Math.Max(Environment.ProcessorCount - 1, 1); - } + // VP8 and VP9 encoders must have their thread counts set. + bool mustSetThreadCount = string.Equals(outputVideoCodec, "libvpx", StringComparison.OrdinalIgnoreCase) + || string.Equals(outputVideoCodec, "libvpx-vp9", StringComparison.OrdinalIgnoreCase); var threads = state?.BaseRequest.CpuCoreLimit ?? encodingOptions.EncodingThreadCount; - // Automatic if (threads <= 0) { - return 0; + // Automatically set thread count + return mustSetThreadCount ? Math.Max(Environment.ProcessorCount - 1, 1) : 0; } else if (threads >= Environment.ProcessorCount) { -- cgit v1.2.3 From 0d16c489985da50ddd13ef228c73b3bcb0ae5f67 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 9 Sep 2021 15:59:13 +0200 Subject: Fix some warnings --- MediaBrowser.Controller/Entities/Folder.cs | 6 +++--- MediaBrowser.Controller/Entities/UserRootFolder.cs | 16 ++++++++-------- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 12 ++++++------ .../PlaybackRequests/RemoveFromPlaylistGroupRequest.cs | 1 - MediaBrowser.Model/Configuration/MetadataOptions.cs | 2 +- MediaBrowser.Model/Dlna/ResolutionNormalizer.cs | 2 +- MediaBrowser.Model/Users/UserPolicy.cs | 2 +- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 2 -- jellyfin.ruleset | 10 +++++++--- 9 files changed, 27 insertions(+), 26 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index dd08c31ed..18b4ec3c6 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1015,17 +1015,17 @@ namespace MediaBrowser.Controller.Entities if (!string.IsNullOrEmpty(query.NameStartsWithOrGreater)) { - items = items.Where(i => string.Compare(query.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1); + items = items.Where(i => string.Compare(query.NameStartsWithOrGreater, i.SortName, StringComparison.InvariantCultureIgnoreCase) < 1); } if (!string.IsNullOrEmpty(query.NameStartsWith)) { - items = items.Where(i => i.SortName.StartsWith(query.NameStartsWith, StringComparison.CurrentCultureIgnoreCase)); + items = items.Where(i => i.SortName.StartsWith(query.NameStartsWith, StringComparison.InvariantCultureIgnoreCase)); } if (!string.IsNullOrEmpty(query.NameLessThan)) { - items = items.Where(i => string.Compare(query.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1); + items = items.Where(i => string.Compare(query.NameLessThan, i.SortName, StringComparison.InvariantCultureIgnoreCase) == 1); } // This must be the last filter diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index c07fb40b3..e547db523 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -24,6 +24,14 @@ namespace MediaBrowser.Controller.Entities private readonly object _childIdsLock = new object(); private List _childrenIds = null; + /// + /// Initializes a new instance of the class. + /// + public UserRootFolder() + { + IsRoot = true; + } + [JsonIgnore] public override bool SupportsInheritedParentImages => false; @@ -44,14 +52,6 @@ namespace MediaBrowser.Controller.Entities } } - /// - /// Initializes a new instance of the class. - /// - public UserRootFolder() - { - IsRoot = true; - } - protected override List LoadChildren() { lock (_childIdsLock) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ec44150a2..bdb379332 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Controller.MediaEncoding "ConstrainedHigh" }; - private static readonly Version minVersionForCudaOverlay = new Version(4, 4); + private static readonly Version _minVersionForCudaOverlay = new Version(4, 4); public EncodingHelper( IMediaEncoder mediaEncoder, @@ -647,8 +647,8 @@ namespace MediaBrowser.Controller.MediaEncoding } if (state.IsVideoRequest - && ((string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) - && (isNvdecDecoder || isCuvidHevcDecoder || isCuvidVp9Decoder || isSwDecoder)))) + && string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) + && (isNvdecDecoder || isCuvidHevcDecoder || isCuvidVp9Decoder || isSwDecoder)) { if (!isCudaTonemappingSupported && isOpenclTonemappingSupported) { @@ -2099,7 +2099,7 @@ namespace MediaBrowser.Controller.MediaEncoding var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); var mediaEncoderVersion = _mediaEncoder.GetMediaEncoderVersion(); - var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= minVersionForCudaOverlay; + var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= _minVersionForCudaOverlay; var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilterWithOption(FilterOptionType.ScaleCudaFormat); // Tonemapping and burn-in graphical subtitles requires overlay_vaapi. @@ -2380,7 +2380,7 @@ namespace MediaBrowser.Controller.MediaEncoding var isCudaTonemappingSupported = IsCudaTonemappingSupported(state, options); var isTonemappingSupportedOnNvenc = string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase); var mediaEncoderVersion = _mediaEncoder.GetMediaEncoderVersion(); - var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= minVersionForCudaOverlay; + var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= _minVersionForCudaOverlay; var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilterWithOption(FilterOptionType.ScaleCudaFormat); var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; @@ -2683,7 +2683,7 @@ namespace MediaBrowser.Controller.MediaEncoding var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); var isCudaTonemappingSupported = IsCudaTonemappingSupported(state, options); var mediaEncoderVersion = _mediaEncoder.GetMediaEncoderVersion(); - var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= minVersionForCudaOverlay; + var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= _minVersionForCudaOverlay; var hasSubs = state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; diff --git a/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs b/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs index 856f175df..2f38d6adc 100644 --- a/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs +++ b/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs @@ -19,7 +19,6 @@ namespace MediaBrowser.Controller.SyncPlay.PlaybackRequests /// The playlist ids of the items to remove. /// Whether to clear the entire playlist. The items list will be ignored. /// Whether to remove the playing item as well. Used only when clearing the playlist. - public RemoveFromPlaylistGroupRequest(IReadOnlyList items, bool clearPlaylist = false, bool clearPlayingItem = false) { PlaylistItemIds = items ?? Array.Empty(); diff --git a/MediaBrowser.Model/Configuration/MetadataOptions.cs b/MediaBrowser.Model/Configuration/MetadataOptions.cs index 76b72bd08..384a7997f 100644 --- a/MediaBrowser.Model/Configuration/MetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/MetadataOptions.cs @@ -1,5 +1,5 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CS1591, CA1819 using System; diff --git a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs index 806877ff0..94071b419 100644 --- a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs +++ b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs @@ -5,7 +5,7 @@ using System; namespace MediaBrowser.Model.Dlna { - public class ResolutionNormalizer + public static class ResolutionNormalizer { private static readonly ResolutionConfiguration[] Configurations = new[] diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 111070d81..3634d0705 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -1,5 +1,5 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CS1591, CA1819 using System; using System.Xml.Serialization; diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 3d866cdc2..52611c427 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -29,8 +29,6 @@ net5.0 false true - true - AllEnabledByDefault ../jellyfin.ruleset disable diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 68fb9064e..dfb991170 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -1,9 +1,6 @@ - - - @@ -57,12 +54,19 @@ + + + + + + +