diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index b9ef189e98..db1d866985 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -40,8 +40,8 @@ namespace Jellyfin.Api.Controllers;
[Authorize]
public class DynamicHlsController : BaseJellyfinApiController
{
- private const string DefaultVodEncoderPreset = "veryfast";
- private const string DefaultEventEncoderPreset = "superfast";
+ private const EncoderPreset DefaultVodEncoderPreset = EncoderPreset.veryfast;
+ private const EncoderPreset DefaultEventEncoderPreset = EncoderPreset.superfast;
private const TranscodingJobType TranscodingJobType = MediaBrowser.Controller.MediaEncoding.TranscodingJobType.Hls;
private readonly Version _minFFmpegFlacInMp4 = new Version(6, 0);
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index effe7b021b..8348fd937d 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -482,7 +482,7 @@ public class VideosController : BaseJellyfinApiController
// Need to start ffmpeg (because media can't be returned directly)
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
- var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, "superfast");
+ var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, EncoderPreset.superfast);
return await FileStreamResponseHelpers.GetTranscodedFile(
state,
isHeadRequest,
diff --git a/Jellyfin.Server/Migrations/MigrationRunner.cs b/Jellyfin.Server/Migrations/MigrationRunner.cs
index 8682f28e04..9d4441ac39 100644
--- a/Jellyfin.Server/Migrations/MigrationRunner.cs
+++ b/Jellyfin.Server/Migrations/MigrationRunner.cs
@@ -23,7 +23,8 @@ namespace Jellyfin.Server.Migrations
{
typeof(PreStartupRoutines.CreateNetworkConfiguration),
typeof(PreStartupRoutines.MigrateMusicBrainzTimeout),
- typeof(PreStartupRoutines.MigrateNetworkConfiguration)
+ typeof(PreStartupRoutines.MigrateNetworkConfiguration),
+ typeof(PreStartupRoutines.MigrateEncodingOptions)
};
///
diff --git a/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs b/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs
index 139a6ec640..8462d0a8c9 100644
--- a/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs
+++ b/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs
@@ -132,5 +132,4 @@ public class CreateNetworkConfiguration : IMigrationRoutine
public string[] KnownProxies { get; set; } = Array.Empty();
}
-#pragma warning restore
}
diff --git a/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateEncodingOptions.cs b/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateEncodingOptions.cs
new file mode 100644
index 0000000000..61f5620dc0
--- /dev/null
+++ b/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateEncodingOptions.cs
@@ -0,0 +1,245 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Serialization;
+using Emby.Server.Implementations;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Entities;
+using Microsoft.Extensions.Logging;
+
+namespace Jellyfin.Server.Migrations.PreStartupRoutines;
+
+///
+public class MigrateEncodingOptions : IMigrationRoutine
+{
+ private readonly ServerApplicationPaths _applicationPaths;
+ private readonly ILogger _logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An instance of .
+ /// An instance of the interface.
+ public MigrateEncodingOptions(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory)
+ {
+ _applicationPaths = applicationPaths;
+ _logger = loggerFactory.CreateLogger();
+ }
+
+ ///
+ public Guid Id => Guid.Parse("A8E61960-7726-4450-8F3D-82C12DAABBCB");
+
+ ///
+ public string Name => nameof(MigrateEncodingOptions);
+
+ ///
+ public bool PerformOnNewInstall => false;
+
+ ///
+ public void Perform()
+ {
+ string path = Path.Combine(_applicationPaths.ConfigurationDirectoryPath, "encoding.xml");
+ var oldSerializer = new XmlSerializer(typeof(OldEncodingOptions), new XmlRootAttribute("EncodingOptions"));
+ OldEncodingOptions? oldConfig = null;
+
+ try
+ {
+ using var xmlReader = XmlReader.Create(path);
+ oldConfig = (OldEncodingOptions?)oldSerializer.Deserialize(xmlReader);
+ }
+ catch (InvalidOperationException ex)
+ {
+ _logger.LogError(ex, "Migrate EncodingOptions deserialize Invalid Operation error");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Migrate EncodingOptions deserialize error");
+ }
+
+ if (oldConfig is null)
+ {
+ return;
+ }
+
+ var hardwareAccelerationType = HardwareAccelerationType.none;
+ if (Enum.TryParse(oldConfig.HardwareAccelerationType, true, out var parsedHardwareAccelerationType))
+ {
+ hardwareAccelerationType = parsedHardwareAccelerationType;
+ }
+
+ var tonemappingAlgorithm = TonemappingAlgorithm.none;
+ if (Enum.TryParse(oldConfig.TonemappingAlgorithm, true, out var parsedTonemappingAlgorithm))
+ {
+ tonemappingAlgorithm = parsedTonemappingAlgorithm;
+ }
+
+ var tonemappingMode = TonemappingMode.auto;
+ if (Enum.TryParse(oldConfig.TonemappingMode, true, out var parsedTonemappingMode))
+ {
+ tonemappingMode = parsedTonemappingMode;
+ }
+
+ var tonemappingRange = TonemappingRange.auto;
+ if (Enum.TryParse(oldConfig.TonemappingRange, true, out var parsedTonemappingRange))
+ {
+ tonemappingRange = parsedTonemappingRange;
+ }
+
+ var encoderPreset = EncoderPreset.superfast;
+ if (Enum.TryParse(oldConfig.TonemappingRange, true, out var parsedEncoderPreset))
+ {
+ encoderPreset = parsedEncoderPreset;
+ }
+
+ var deinterlaceMethod = DeinterlaceMethod.yadif;
+ if (Enum.TryParse(oldConfig.TonemappingRange, true, out var parsedDeinterlaceMethod))
+ {
+ deinterlaceMethod = parsedDeinterlaceMethod;
+ }
+
+ var encodingOptions = new EncodingOptions()
+ {
+ EncodingThreadCount = oldConfig.EncodingThreadCount,
+ TranscodingTempPath = oldConfig.TranscodingTempPath,
+ FallbackFontPath = oldConfig.FallbackFontPath,
+ EnableFallbackFont = oldConfig.EnableFallbackFont,
+ EnableAudioVbr = oldConfig.EnableAudioVbr,
+ DownMixAudioBoost = oldConfig.DownMixAudioBoost,
+ DownMixStereoAlgorithm = oldConfig.DownMixStereoAlgorithm,
+ MaxMuxingQueueSize = oldConfig.MaxMuxingQueueSize,
+ EnableThrottling = oldConfig.EnableThrottling,
+ ThrottleDelaySeconds = oldConfig.ThrottleDelaySeconds,
+ EnableSegmentDeletion = oldConfig.EnableSegmentDeletion,
+ SegmentKeepSeconds = oldConfig.SegmentKeepSeconds,
+ HardwareAccelerationType = hardwareAccelerationType,
+ EncoderAppPath = oldConfig.EncoderAppPath,
+ EncoderAppPathDisplay = oldConfig.EncoderAppPathDisplay,
+ VaapiDevice = oldConfig.VaapiDevice,
+ EnableTonemapping = oldConfig.EnableTonemapping,
+ EnableVppTonemapping = oldConfig.EnableVppTonemapping,
+ EnableVideoToolboxTonemapping = oldConfig.EnableVideoToolboxTonemapping,
+ TonemappingAlgorithm = tonemappingAlgorithm,
+ TonemappingMode = tonemappingMode,
+ TonemappingRange = tonemappingRange,
+ TonemappingDesat = oldConfig.TonemappingDesat,
+ TonemappingPeak = oldConfig.TonemappingPeak,
+ TonemappingParam = oldConfig.TonemappingParam,
+ VppTonemappingBrightness = oldConfig.VppTonemappingBrightness,
+ VppTonemappingContrast = oldConfig.VppTonemappingContrast,
+ H264Crf = oldConfig.H264Crf,
+ H265Crf = oldConfig.H265Crf,
+ EncoderPreset = encoderPreset,
+ DeinterlaceDoubleRate = oldConfig.DeinterlaceDoubleRate,
+ DeinterlaceMethod = deinterlaceMethod,
+ EnableDecodingColorDepth10Hevc = oldConfig.EnableDecodingColorDepth10Hevc,
+ EnableDecodingColorDepth10Vp9 = oldConfig.EnableDecodingColorDepth10Vp9,
+ EnableEnhancedNvdecDecoder = oldConfig.EnableEnhancedNvdecDecoder,
+ PreferSystemNativeHwDecoder = oldConfig.PreferSystemNativeHwDecoder,
+ EnableIntelLowPowerH264HwEncoder = oldConfig.EnableIntelLowPowerH264HwEncoder,
+ EnableIntelLowPowerHevcHwEncoder = oldConfig.EnableIntelLowPowerHevcHwEncoder,
+ EnableHardwareEncoding = oldConfig.EnableHardwareEncoding,
+ AllowHevcEncoding = oldConfig.AllowHevcEncoding,
+ AllowAv1Encoding = oldConfig.AllowAv1Encoding,
+ EnableSubtitleExtraction = oldConfig.EnableSubtitleExtraction,
+ HardwareDecodingCodecs = oldConfig.HardwareDecodingCodecs,
+ AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = oldConfig.AllowOnDemandMetadataBasedKeyframeExtractionForExtensions
+ };
+
+ var newSerializer = new XmlSerializer(typeof(EncodingOptions));
+ var xmlWriterSettings = new XmlWriterSettings { Indent = true };
+ using var xmlWriter = XmlWriter.Create(path, xmlWriterSettings);
+ newSerializer.Serialize(xmlWriter, encodingOptions);
+ }
+
+#pragma warning disable
+ public sealed class OldEncodingOptions
+ {
+ public int EncodingThreadCount { get; set; }
+
+ public string TranscodingTempPath { get; set; }
+
+ public string FallbackFontPath { get; set; }
+
+ public bool EnableFallbackFont { get; set; }
+
+ public bool EnableAudioVbr { get; set; }
+
+ public double DownMixAudioBoost { get; set; }
+
+ public DownMixStereoAlgorithms DownMixStereoAlgorithm { get; set; }
+
+ public int MaxMuxingQueueSize { get; set; }
+
+ public bool EnableThrottling { get; set; }
+
+ public int ThrottleDelaySeconds { get; set; }
+
+ public bool EnableSegmentDeletion { get; set; }
+
+ public int SegmentKeepSeconds { get; set; }
+
+ public string HardwareAccelerationType { get; set; }
+
+ public string EncoderAppPath { get; set; }
+
+ public string EncoderAppPathDisplay { get; set; }
+
+ public string VaapiDevice { get; set; }
+
+ public bool EnableTonemapping { get; set; }
+
+ public bool EnableVppTonemapping { get; set; }
+
+ public bool EnableVideoToolboxTonemapping { get; set; }
+
+ public string TonemappingAlgorithm { get; set; }
+
+ public string TonemappingMode { get; set; }
+
+ public string TonemappingRange { get; set; }
+
+ public double TonemappingDesat { get; set; }
+
+ public double TonemappingPeak { get; set; }
+
+ public double TonemappingParam { get; set; }
+
+ public double VppTonemappingBrightness { get; set; }
+
+ public double VppTonemappingContrast { get; set; }
+
+ public int H264Crf { get; set; }
+
+ public int H265Crf { get; set; }
+
+ public string EncoderPreset { get; set; }
+
+ public bool DeinterlaceDoubleRate { get; set; }
+
+ public string DeinterlaceMethod { get; set; }
+
+ public bool EnableDecodingColorDepth10Hevc { get; set; }
+
+ public bool EnableDecodingColorDepth10Vp9 { get; set; }
+
+ public bool EnableEnhancedNvdecDecoder { get; set; }
+
+ public bool PreferSystemNativeHwDecoder { get; set; }
+
+ public bool EnableIntelLowPowerH264HwEncoder { get; set; }
+
+ public bool EnableIntelLowPowerHevcHwEncoder { get; set; }
+
+ public bool EnableHardwareEncoding { get; set; }
+
+ public bool AllowHevcEncoding { get; set; }
+
+ public bool AllowAv1Encoding { get; set; }
+
+ public bool EnableSubtitleExtraction { get; set; }
+
+ public string[] HardwareDecodingCodecs { get; set; }
+
+ public string[] AllowOnDemandMetadataBasedKeyframeExtractionForExtensions { get; set; }
+ }
+}
diff --git a/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateMusicBrainzTimeout.cs b/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateMusicBrainzTimeout.cs
index 0544fe561a..580282a5f5 100644
--- a/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateMusicBrainzTimeout.cs
+++ b/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateMusicBrainzTimeout.cs
@@ -48,9 +48,11 @@ public class MigrateMusicBrainzTimeout : IMigrationRoutine
if (oldPluginConfiguration is not null)
{
- var newPluginConfiguration = new PluginConfiguration();
- newPluginConfiguration.Server = oldPluginConfiguration.Server;
- newPluginConfiguration.ReplaceArtistName = oldPluginConfiguration.ReplaceArtistName;
+ var newPluginConfiguration = new PluginConfiguration
+ {
+ Server = oldPluginConfiguration.Server,
+ ReplaceArtistName = oldPluginConfiguration.ReplaceArtistName
+ };
var newRateLimit = oldPluginConfiguration.RateLimit / 1000.0;
newPluginConfiguration.RateLimit = newRateLimit < 1.0 ? 1.0 : newRateLimit;
WriteNew(path, newPluginConfiguration);
@@ -93,6 +95,4 @@ public class MigrateMusicBrainzTimeout : IMigrationRoutine
public bool ReplaceArtistName { get; set; }
}
-#pragma warning restore
-
}
diff --git a/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateNetworkConfiguration.cs b/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateNetworkConfiguration.cs
index d92c00991b..49960f4305 100644
--- a/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateNetworkConfiguration.cs
+++ b/Jellyfin.Server/Migrations/PreStartupRoutines/MigrateNetworkConfiguration.cs
@@ -55,49 +55,53 @@ public class MigrateNetworkConfiguration : IMigrationRoutine
_logger.LogError(ex, "Migrate NetworkConfiguration deserialize error");
}
- if (oldNetworkConfiguration is not null)
+ if (oldNetworkConfiguration is null)
{
- // Migrate network config values to new config schema
- var networkConfiguration = new NetworkConfiguration();
- networkConfiguration.AutoDiscovery = oldNetworkConfiguration.AutoDiscovery;
- networkConfiguration.BaseUrl = oldNetworkConfiguration.BaseUrl;
- networkConfiguration.CertificatePassword = oldNetworkConfiguration.CertificatePassword;
- networkConfiguration.CertificatePath = oldNetworkConfiguration.CertificatePath;
- networkConfiguration.EnableHttps = oldNetworkConfiguration.EnableHttps;
- networkConfiguration.EnableIPv4 = oldNetworkConfiguration.EnableIPV4;
- networkConfiguration.EnableIPv6 = oldNetworkConfiguration.EnableIPV6;
- networkConfiguration.EnablePublishedServerUriByRequest = oldNetworkConfiguration.EnablePublishedServerUriByRequest;
- networkConfiguration.EnableRemoteAccess = oldNetworkConfiguration.EnableRemoteAccess;
- networkConfiguration.EnableUPnP = oldNetworkConfiguration.EnableUPnP;
- networkConfiguration.IgnoreVirtualInterfaces = oldNetworkConfiguration.IgnoreVirtualInterfaces;
- networkConfiguration.InternalHttpPort = oldNetworkConfiguration.HttpServerPortNumber;
- networkConfiguration.InternalHttpsPort = oldNetworkConfiguration.HttpsPortNumber;
- networkConfiguration.IsRemoteIPFilterBlacklist = oldNetworkConfiguration.IsRemoteIPFilterBlacklist;
- networkConfiguration.KnownProxies = oldNetworkConfiguration.KnownProxies;
- networkConfiguration.LocalNetworkAddresses = oldNetworkConfiguration.LocalNetworkAddresses;
- networkConfiguration.LocalNetworkSubnets = oldNetworkConfiguration.LocalNetworkSubnets;
- networkConfiguration.PublicHttpPort = oldNetworkConfiguration.PublicPort;
- networkConfiguration.PublicHttpsPort = oldNetworkConfiguration.PublicHttpsPort;
- networkConfiguration.PublishedServerUriBySubnet = oldNetworkConfiguration.PublishedServerUriBySubnet;
- networkConfiguration.RemoteIPFilter = oldNetworkConfiguration.RemoteIPFilter;
- networkConfiguration.RequireHttps = oldNetworkConfiguration.RequireHttps;
-
- // Migrate old virtual interface name schema
- var oldVirtualInterfaceNames = oldNetworkConfiguration.VirtualInterfaceNames;
- if (oldVirtualInterfaceNames.Equals("vEthernet*", StringComparison.OrdinalIgnoreCase))
- {
- networkConfiguration.VirtualInterfaceNames = new string[] { "veth" };
- }
- else
- {
- networkConfiguration.VirtualInterfaceNames = oldVirtualInterfaceNames.Replace("*", string.Empty, StringComparison.OrdinalIgnoreCase).Split(',');
- }
-
- var networkConfigSerializer = new XmlSerializer(typeof(NetworkConfiguration));
- var xmlWriterSettings = new XmlWriterSettings { Indent = true };
- using var xmlWriter = XmlWriter.Create(path, xmlWriterSettings);
- networkConfigSerializer.Serialize(xmlWriter, networkConfiguration);
+ return;
}
+
+ // Migrate network config values to new config schema
+ var networkConfiguration = new NetworkConfiguration
+ {
+ AutoDiscovery = oldNetworkConfiguration.AutoDiscovery,
+ BaseUrl = oldNetworkConfiguration.BaseUrl,
+ CertificatePassword = oldNetworkConfiguration.CertificatePassword,
+ CertificatePath = oldNetworkConfiguration.CertificatePath,
+ EnableHttps = oldNetworkConfiguration.EnableHttps,
+ EnableIPv4 = oldNetworkConfiguration.EnableIPV4,
+ EnableIPv6 = oldNetworkConfiguration.EnableIPV6,
+ EnablePublishedServerUriByRequest = oldNetworkConfiguration.EnablePublishedServerUriByRequest,
+ EnableRemoteAccess = oldNetworkConfiguration.EnableRemoteAccess,
+ EnableUPnP = oldNetworkConfiguration.EnableUPnP,
+ IgnoreVirtualInterfaces = oldNetworkConfiguration.IgnoreVirtualInterfaces,
+ InternalHttpPort = oldNetworkConfiguration.HttpServerPortNumber,
+ InternalHttpsPort = oldNetworkConfiguration.HttpsPortNumber,
+ IsRemoteIPFilterBlacklist = oldNetworkConfiguration.IsRemoteIPFilterBlacklist,
+ KnownProxies = oldNetworkConfiguration.KnownProxies,
+ LocalNetworkAddresses = oldNetworkConfiguration.LocalNetworkAddresses,
+ LocalNetworkSubnets = oldNetworkConfiguration.LocalNetworkSubnets,
+ PublicHttpPort = oldNetworkConfiguration.PublicPort,
+ PublicHttpsPort = oldNetworkConfiguration.PublicHttpsPort,
+ PublishedServerUriBySubnet = oldNetworkConfiguration.PublishedServerUriBySubnet,
+ RemoteIPFilter = oldNetworkConfiguration.RemoteIPFilter,
+ RequireHttps = oldNetworkConfiguration.RequireHttps
+ };
+
+ // Migrate old virtual interface name schema
+ var oldVirtualInterfaceNames = oldNetworkConfiguration.VirtualInterfaceNames;
+ if (oldVirtualInterfaceNames.Equals("vEthernet*", StringComparison.OrdinalIgnoreCase))
+ {
+ networkConfiguration.VirtualInterfaceNames = new string[] { "veth" };
+ }
+ else
+ {
+ networkConfiguration.VirtualInterfaceNames = oldVirtualInterfaceNames.Replace("*", string.Empty, StringComparison.OrdinalIgnoreCase).Split(',');
+ }
+
+ var networkConfigSerializer = new XmlSerializer(typeof(NetworkConfiguration));
+ var xmlWriterSettings = new XmlWriterSettings { Indent = true };
+ using var xmlWriter = XmlWriter.Create(path, xmlWriterSettings);
+ networkConfigSerializer.Serialize(xmlWriter, networkConfiguration);
}
#pragma warning disable
@@ -204,5 +208,4 @@ public class MigrateNetworkConfiguration : IMigrationRoutine
public bool EnablePublishedServerUriByRequest { get; set; } = false;
}
-#pragma warning restore
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index d6ad7e2b35..fdc56652ae 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -37,6 +37,8 @@ namespace MediaBrowser.Controller.MediaEncoding
///
public const string ValidationRegex = @"^[a-zA-Z0-9\-\._,|]{0,40}$";
+ private const string _defaultMjpegEncoder = "mjpeg";
+
private const string QsvAlias = "qs";
private const string VaapiAlias = "va";
private const string D3d11vaAlias = "dx11";
@@ -72,8 +74,8 @@ namespace MediaBrowser.Controller.MediaEncoding
private static readonly Regex _validationRegex = new(ValidationRegex, RegexOptions.Compiled);
- private static readonly string[] _videoProfilesH264 = new[]
- {
+ private static readonly string[] _videoProfilesH264 =
+ [
"ConstrainedBaseline",
"Baseline",
"Extended",
@@ -82,20 +84,20 @@ namespace MediaBrowser.Controller.MediaEncoding
"ProgressiveHigh",
"ConstrainedHigh",
"High10"
- };
+ ];
- private static readonly string[] _videoProfilesH265 = new[]
- {
+ private static readonly string[] _videoProfilesH265 =
+ [
"Main",
"Main10"
- };
+ ];
- private static readonly string[] _videoProfilesAv1 = new[]
- {
+ private static readonly string[] _videoProfilesAv1 =
+ [
"Main",
"High",
"Professional",
- };
+ ];
private static readonly HashSet _mp4ContainerNames = new(StringComparer.OrdinalIgnoreCase)
{
@@ -107,8 +109,8 @@ namespace MediaBrowser.Controller.MediaEncoding
"m4v",
};
- private static readonly string[] _legacyTonemapModes = new[] { "max", "rgb" };
- private static readonly string[] _advancedTonemapModes = new[] { "lum", "itp" };
+ private static readonly TonemappingMode[] _legacyTonemapModes = [TonemappingMode.max, TonemappingMode.rgb];
+ private static readonly TonemappingMode[] _advancedTonemapModes = [TonemappingMode.lum, TonemappingMode.itp];
// Set max transcoding channels for encoders that can't handle more than a set amount of channels
// AAC, FLAC, ALAC, libopus, libvorbis encoders all support at least 8 channels
@@ -123,23 +125,22 @@ namespace MediaBrowser.Controller.MediaEncoding
{ "truehd", 6 },
};
- private static readonly string _defaultMjpegEncoder = "mjpeg";
- private static readonly Dictionary _mjpegCodecMap = new(StringComparer.OrdinalIgnoreCase)
+ private static readonly Dictionary _mjpegCodecMap = new()
{
- { "vaapi", _defaultMjpegEncoder + "_vaapi" },
- { "qsv", _defaultMjpegEncoder + "_qsv" },
- { "videotoolbox", _defaultMjpegEncoder + "_videotoolbox" }
+ { HardwareAccelerationType.vaapi, _defaultMjpegEncoder + "_vaapi" },
+ { HardwareAccelerationType.qsv, _defaultMjpegEncoder + "_qsv" },
+ { HardwareAccelerationType.videotoolbox, _defaultMjpegEncoder + "_videotoolbox" }
};
- public static readonly string[] LosslessAudioCodecs = new string[]
- {
+ public static readonly string[] LosslessAudioCodecs =
+ [
"alac",
"ape",
"flac",
"mlp",
"truehd",
"wavpack"
- };
+ ];
public EncodingHelper(
IApplicationPaths appPaths,
@@ -176,18 +177,18 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var hwType = encodingOptions.HardwareAccelerationType;
- var codecMap = new Dictionary(StringComparer.OrdinalIgnoreCase)
+ var codecMap = new Dictionary()
{
- { "amf", hwEncoder + "_amf" },
- { "nvenc", hwEncoder + "_nvenc" },
- { "qsv", hwEncoder + "_qsv" },
- { "vaapi", hwEncoder + "_vaapi" },
- { "videotoolbox", hwEncoder + "_videotoolbox" },
- { "v4l2m2m", hwEncoder + "_v4l2m2m" },
- { "rkmpp", hwEncoder + "_rkmpp" },
+ { HardwareAccelerationType.amf, hwEncoder + "_amf" },
+ { HardwareAccelerationType.nvenc, hwEncoder + "_nvenc" },
+ { HardwareAccelerationType.qsv, hwEncoder + "_qsv" },
+ { HardwareAccelerationType.vaapi, hwEncoder + "_vaapi" },
+ { HardwareAccelerationType.videotoolbox, hwEncoder + "_videotoolbox" },
+ { HardwareAccelerationType.v4l2m2m, hwEncoder + "_v4l2m2m" },
+ { HardwareAccelerationType.rkmpp, hwEncoder + "_rkmpp" },
};
- if (!string.IsNullOrEmpty(hwType)
+ if (hwType != HardwareAccelerationType.none
&& encodingOptions.EnableHardwareEncoding
&& codecMap.TryGetValue(hwType, out var preferredEncoder)
&& _mediaEncoder.SupportsEncoder(preferredEncoder))
@@ -205,7 +206,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var hwType = encodingOptions.HardwareAccelerationType;
- if (!string.IsNullOrEmpty(hwType)
+ if (hwType != HardwareAccelerationType.none
&& encodingOptions.EnableHardwareEncoding
&& _mjpegCodecMap.TryGetValue(hwType, out var preferredEncoder)
&& _mediaEncoder.SupportsEncoder(preferredEncoder))
@@ -360,7 +361,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// prefer 'tonemap_vaapi' over 'vpp_qsv' on Linux for supporting Gen9/KBLx.
// 'vpp_qsv' requires VPL, which is only supported on Gen12/TGLx and newer.
if (OperatingSystem.IsWindows()
- && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)
+ && options.HardwareAccelerationType == HardwareAccelerationType.qsv
&& _mediaEncoder.EncoderVersion < _minFFmpegQsvVppTonemapOption)
{
return false;
@@ -970,7 +971,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var vidDecoder = GetHardwareVideoDecoder(state, options) ?? string.Empty;
var isHwTonemapAvailable = IsHwTonemapAvailable(state, options);
- if (string.Equals(optHwaccelType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ if (optHwaccelType == HardwareAccelerationType.vaapi)
{
if (!isLinux || !_mediaEncoder.SupportsHwaccel("vaapi"))
{
@@ -1044,7 +1045,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args.Append(filterDevArgs);
}
- else if (string.Equals(optHwaccelType, "qsv", StringComparison.OrdinalIgnoreCase))
+ else if (optHwaccelType == HardwareAccelerationType.qsv)
{
if ((!isLinux && !isWindows) || !_mediaEncoder.SupportsHwaccel("qsv"))
{
@@ -1079,7 +1080,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args.Append(filterDevArgs);
}
- else if (string.Equals(optHwaccelType, "nvenc", StringComparison.OrdinalIgnoreCase))
+ else if (optHwaccelType == HardwareAccelerationType.nvenc)
{
if ((!isLinux && !isWindows) || !IsCudaFullSupported())
{
@@ -1098,7 +1099,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args.Append(GetCudaDeviceArgs(0, CudaAlias))
.Append(GetFilterHwDeviceArgs(CudaAlias));
}
- else if (string.Equals(optHwaccelType, "amf", StringComparison.OrdinalIgnoreCase))
+ else if (optHwaccelType == HardwareAccelerationType.amf)
{
if (!isWindows || !_mediaEncoder.SupportsHwaccel("d3d11va"))
{
@@ -1123,7 +1124,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args.Append(filterDevArgs);
}
- else if (string.Equals(optHwaccelType, "videotoolbox", StringComparison.OrdinalIgnoreCase))
+ else if (optHwaccelType == HardwareAccelerationType.videotoolbox)
{
if (!isMacOS || !_mediaEncoder.SupportsHwaccel("videotoolbox"))
{
@@ -1140,7 +1141,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// videotoolbox hw filter does not require device selection
args.Append(GetVideoToolboxDeviceArgs(VideotoolboxAlias));
}
- else if (string.Equals(optHwaccelType, "rkmpp", StringComparison.OrdinalIgnoreCase))
+ else if (optHwaccelType == HardwareAccelerationType.rkmpp)
{
if (!isLinux || !_mediaEncoder.SupportsHwaccel("rkmpp"))
{
@@ -1413,6 +1414,149 @@ namespace MediaBrowser.Controller.MediaEncoding
return FormattableString.Invariant($" -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
}
+ private string GetEncoderParam(EncoderPreset? preset, EncoderPreset defaultPreset, EncodingOptions encodingOptions, string videoEncoder, bool isLibX265)
+ {
+ var param = string.Empty;
+ var encoderPreset = preset ?? defaultPreset;
+ if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase) || isLibX265)
+ {
+ param += " -preset " + encoderPreset.ToString().ToLowerInvariant();
+
+ int encodeCrf = encodingOptions.H264Crf;
+ if (isLibX265)
+ {
+ encodeCrf = encodingOptions.H265Crf;
+ }
+
+ if (encodeCrf >= 0 && encodeCrf <= 51)
+ {
+ param += " -crf " + encodeCrf.ToString(CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ string defaultCrf = "23";
+ if (isLibX265)
+ {
+ defaultCrf = "28";
+ }
+
+ param += " -crf " + defaultCrf;
+ }
+ }
+ else if (string.Equals(videoEncoder, "libsvtav1", StringComparison.OrdinalIgnoreCase))
+ {
+ // Default to use the recommended preset 10.
+ // Omit presets < 5, which are too slow for on the fly encoding.
+ // https://gitlab.com/AOMediaCodec/SVT-AV1/-/blob/master/Docs/Ffmpeg.md
+ param += encoderPreset switch
+ {
+ EncoderPreset.veryslow => " -preset 5",
+ EncoderPreset.slower => " -preset 6",
+ EncoderPreset.slow => " -preset 7",
+ EncoderPreset.medium => " -preset 8",
+ EncoderPreset.fast => " -preset 9",
+ EncoderPreset.faster => " -preset 10",
+ EncoderPreset.veryfast => " -preset 11",
+ EncoderPreset.superfast => " -preset 12",
+ EncoderPreset.ultrafast => " -preset 13",
+ _ => " -preset 10"
+ };
+ }
+ else if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(videoEncoder, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(videoEncoder, "av1_vaapi", StringComparison.OrdinalIgnoreCase))
+ {
+ // -compression_level is not reliable on AMD.
+ if (_mediaEncoder.IsVaapiDeviceInteliHD)
+ {
+ param += encoderPreset switch
+ {
+ EncoderPreset.veryslow => " -compression_level 1",
+ EncoderPreset.slower => " -compression_level 2",
+ EncoderPreset.slow => " -compression_level 3",
+ EncoderPreset.medium => " -compression_level 4",
+ EncoderPreset.fast => " -compression_level 5",
+ EncoderPreset.faster => " -compression_level 6",
+ EncoderPreset.veryfast => " -compression_level 7",
+ EncoderPreset.superfast => " -compression_level 7",
+ EncoderPreset.ultrafast => " -compression_level 7",
+ _ => string.Empty
+ };
+ }
+ }
+ else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) // h264 (h264_qsv)
+ || string.Equals(videoEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase) // hevc (hevc_qsv)
+ || string.Equals(videoEncoder, "av1_qsv", StringComparison.OrdinalIgnoreCase)) // av1 (av1_qsv)
+ {
+ EncoderPreset[] valid_presets = [EncoderPreset.veryslow, EncoderPreset.slower, EncoderPreset.slow, EncoderPreset.medium, EncoderPreset.fast, EncoderPreset.faster, EncoderPreset.veryfast];
+
+ if (valid_presets.Contains(encoderPreset))
+ {
+ param += " -preset " + encodingOptions.EncoderPreset;
+ }
+ else
+ {
+ param += " -preset " + EncoderPreset.veryfast.ToString().ToLowerInvariant();
+ }
+ }
+ else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
+ || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase) // hevc (hevc_nvenc)
+ || string.Equals(videoEncoder, "av1_nvenc", StringComparison.OrdinalIgnoreCase) // av1 (av1_nvenc)
+ )
+ {
+ param += encoderPreset switch
+ {
+ EncoderPreset.veryslow => " -preset p7",
+ EncoderPreset.slower => " -preset p6",
+ EncoderPreset.slow => " -preset p5",
+ EncoderPreset.medium => " -preset p4",
+ EncoderPreset.fast => " -preset p3",
+ EncoderPreset.faster => " -preset p2",
+ _ => " -preset p1"
+ };
+ }
+ else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase) // h264 (h264_amf)
+ || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase) // hevc (hevc_amf)
+ || string.Equals(videoEncoder, "av1_amf", StringComparison.OrdinalIgnoreCase) // av1 (av1_amf)
+ )
+ {
+ param += encoderPreset switch
+ {
+ EncoderPreset.veryslow => " -quality quality",
+ EncoderPreset.slower => " -quality quality",
+ EncoderPreset.slow => " -quality quality",
+ EncoderPreset.medium => " -quality balanced",
+ _ => " -quality speed"
+ };
+
+ if (string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(videoEncoder, "av1_amf", StringComparison.OrdinalIgnoreCase))
+ {
+ param += " -header_insertion_mode gop";
+ }
+
+ if (string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase))
+ {
+ param += " -gops_per_idr 1";
+ }
+ }
+ else if (string.Equals(videoEncoder, "h264_videotoolbox", StringComparison.OrdinalIgnoreCase) // h264 (h264_videotoolbox)
+ || string.Equals(videoEncoder, "hevc_videotoolbox", StringComparison.OrdinalIgnoreCase) // hevc (hevc_videotoolbox)
+ )
+ {
+ param += encoderPreset switch
+ {
+ EncoderPreset.veryslow => " -prio_speed 0",
+ EncoderPreset.slower => " -prio_speed 0",
+ EncoderPreset.slow => " -prio_speed 0",
+ EncoderPreset.medium => " -prio_speed 0",
+ _ => " -prio_speed 1"
+ };
+ }
+
+ return param;
+ }
+
public static string NormalizeTranscodingLevel(EncodingJobInfo state, string level)
{
if (double.TryParse(level, CultureInfo.InvariantCulture, out double requestLevel))
@@ -1625,7 +1769,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// Encoding options.
/// Default present to use for encoding.
/// Video bitrate.
- public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, string defaultPreset)
+ public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, EncoderPreset defaultPreset)
{
var param = string.Empty;
@@ -1640,7 +1784,9 @@ namespace MediaBrowser.Controller.MediaEncoding
// https://github.com/intel/media-driver/issues/1456
var enableWaFori915Hang = false;
- if (string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ var hardwareAccelerationType = encodingOptions.HardwareAccelerationType;
+
+ if (hardwareAccelerationType == HardwareAccelerationType.vaapi)
{
var isIntelVaapiDriver = _mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965;
@@ -1653,7 +1799,7 @@ namespace MediaBrowser.Controller.MediaEncoding
intelLowPowerHwEncoding = encodingOptions.EnableIntelLowPowerHevcHwEncoder && isIntelVaapiDriver;
}
}
- else if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
+ else if (hardwareAccelerationType == HardwareAccelerationType.qsv)
{
if (OperatingSystem.IsLinux())
{
@@ -1700,204 +1846,10 @@ namespace MediaBrowser.Controller.MediaEncoding
param += " -async_depth 1";
}
- var isVc1 = string.Equals(state.VideoStream?.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
var isLibX265 = string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase);
+ var encodingPreset = encodingOptions.EncoderPreset;
- if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase) || isLibX265)
- {
- if (!string.IsNullOrEmpty(encodingOptions.EncoderPreset))
- {
- param += " -preset " + encodingOptions.EncoderPreset;
- }
- else
- {
- param += " -preset " + defaultPreset;
- }
-
- int encodeCrf = encodingOptions.H264Crf;
- if (isLibX265)
- {
- encodeCrf = encodingOptions.H265Crf;
- }
-
- if (encodeCrf >= 0 && encodeCrf <= 51)
- {
- param += " -crf " + encodeCrf.ToString(CultureInfo.InvariantCulture);
- }
- else
- {
- string defaultCrf = "23";
- if (isLibX265)
- {
- defaultCrf = "28";
- }
-
- param += " -crf " + defaultCrf;
- }
- }
- else if (string.Equals(videoEncoder, "libsvtav1", StringComparison.OrdinalIgnoreCase))
- {
- // Default to use the recommended preset 10.
- // Omit presets < 5, which are too slow for on the fly encoding.
- // https://gitlab.com/AOMediaCodec/SVT-AV1/-/blob/master/Docs/Ffmpeg.md
- param += encodingOptions.EncoderPreset switch
- {
- "veryslow" => " -preset 5",
- "slower" => " -preset 6",
- "slow" => " -preset 7",
- "medium" => " -preset 8",
- "fast" => " -preset 9",
- "faster" => " -preset 10",
- "veryfast" => " -preset 11",
- "superfast" => " -preset 12",
- "ultrafast" => " -preset 13",
- _ => " -preset 10"
- };
- }
- else if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
- || string.Equals(videoEncoder, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)
- || string.Equals(videoEncoder, "av1_vaapi", StringComparison.OrdinalIgnoreCase))
- {
- // -compression_level is not reliable on AMD.
- if (_mediaEncoder.IsVaapiDeviceInteliHD)
- {
- param += encodingOptions.EncoderPreset switch
- {
- "veryslow" => " -compression_level 1",
- "slower" => " -compression_level 2",
- "slow" => " -compression_level 3",
- "medium" => " -compression_level 4",
- "fast" => " -compression_level 5",
- "faster" => " -compression_level 6",
- "veryfast" => " -compression_level 7",
- "superfast" => " -compression_level 7",
- "ultrafast" => " -compression_level 7",
- _ => string.Empty
- };
- }
- }
- else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) // h264 (h264_qsv)
- || string.Equals(videoEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase) // hevc (hevc_qsv)
- || string.Equals(videoEncoder, "av1_qsv", StringComparison.OrdinalIgnoreCase)) // av1 (av1_qsv)
- {
- string[] valid_presets = { "veryslow", "slower", "slow", "medium", "fast", "faster", "veryfast" };
-
- if (valid_presets.Contains(encodingOptions.EncoderPreset, StringComparison.OrdinalIgnoreCase))
- {
- param += " -preset " + encodingOptions.EncoderPreset;
- }
- else
- {
- param += " -preset veryfast";
- }
- }
- else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
- || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase) // hevc (hevc_nvenc)
- || string.Equals(videoEncoder, "av1_nvenc", StringComparison.OrdinalIgnoreCase)) // av1 (av1_nvenc)
- {
- switch (encodingOptions.EncoderPreset)
- {
- case "veryslow":
- param += " -preset p7";
- break;
-
- case "slower":
- param += " -preset p6";
- break;
-
- case "slow":
- param += " -preset p5";
- break;
-
- case "medium":
- param += " -preset p4";
- break;
-
- case "fast":
- param += " -preset p3";
- break;
-
- case "faster":
- param += " -preset p2";
- break;
-
- case "veryfast":
- case "superfast":
- case "ultrafast":
- param += " -preset p1";
- break;
-
- default:
- param += " -preset p1";
- break;
- }
- }
- else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase) // h264 (h264_amf)
- || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase) // hevc (hevc_amf)
- || string.Equals(videoEncoder, "av1_amf", StringComparison.OrdinalIgnoreCase)) // av1 (av1_amf)
- {
- switch (encodingOptions.EncoderPreset)
- {
- case "veryslow":
- case "slower":
- case "slow":
- param += " -quality quality";
- break;
-
- case "medium":
- param += " -quality balanced";
- break;
-
- case "fast":
- case "faster":
- case "veryfast":
- case "superfast":
- case "ultrafast":
- param += " -quality speed";
- break;
-
- default:
- param += " -quality speed";
- break;
- }
-
- if (string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)
- || string.Equals(videoEncoder, "av1_amf", StringComparison.OrdinalIgnoreCase))
- {
- param += " -header_insertion_mode gop";
- }
-
- if (string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase))
- {
- param += " -gops_per_idr 1";
- }
- }
- else if (string.Equals(videoEncoder, "h264_videotoolbox", StringComparison.OrdinalIgnoreCase) // h264 (h264_videotoolbox)
- || string.Equals(videoEncoder, "hevc_videotoolbox", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_videotoolbox)
- {
- switch (encodingOptions.EncoderPreset)
- {
- case "veryslow":
- case "slower":
- case "slow":
- case "medium":
- param += " -prio_speed 0";
- break;
-
- case "fast":
- case "faster":
- case "veryfast":
- case "superfast":
- case "ultrafast":
- param += " -prio_speed 1";
- break;
-
- default:
- param += " -prio_speed 1";
- break;
- }
- }
-
+ param += GetEncoderParam(encodingPreset, defaultPreset, encodingOptions, videoEncoder, isLibX265);
param += GetVideoBitrateParam(state, videoEncoder);
var framerate = GetFramerateParam(state);
@@ -3256,7 +3208,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
"{0}={1}:-1:0",
- string.Equals(options.DeinterlaceMethod, "bwdif", StringComparison.OrdinalIgnoreCase) ? "bwdif" : "yadif",
+ options.DeinterlaceMethod.ToString().ToLowerInvariant(),
doubleRateDeint ? "1" : "0");
}
@@ -3265,8 +3217,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doubleRateDeint = options.DeinterlaceDoubleRate && (state.VideoStream?.ReferenceFrameRate ?? 60) <= 30;
if (hwDeintSuffix.Contains("cuda", StringComparison.OrdinalIgnoreCase))
{
- var useBwdif = string.Equals(options.DeinterlaceMethod, "bwdif", StringComparison.OrdinalIgnoreCase)
- && _mediaEncoder.SupportsFilter("bwdif_cuda");
+ var useBwdif = options.DeinterlaceMethod == DeinterlaceMethod.bwdif && _mediaEncoder.SupportsFilter("bwdif_cuda");
return string.Format(
CultureInfo.InvariantCulture,
@@ -3307,7 +3258,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var args = string.Empty;
- var algorithm = options.TonemappingAlgorithm;
+ var algorithm = options.TonemappingAlgorithm.ToString().ToLowerInvariant();
+ var mode = options.TonemappingMode.ToString().ToLowerInvariant();
+ var range = options.TonemappingRange;
+ var rangeString = range.ToString().ToLowerInvariant();
if (string.Equals(hwTonemapSuffix, "vaapi", StringComparison.OrdinalIgnoreCase))
{
@@ -3342,10 +3296,10 @@ namespace MediaBrowser.Controller.MediaEncoding
args = "tonemap_{0}=format={1}:p=bt709:t=bt709:m=bt709:tonemap={2}:peak={3}:desat={4}";
var useLegacyTonemapModes = _mediaEncoder.EncoderVersion >= _minFFmpegOclCuTonemapMode
- && _legacyTonemapModes.Contains(options.TonemappingMode, StringComparison.OrdinalIgnoreCase);
+ && _legacyTonemapModes.Contains(options.TonemappingMode);
var useAdvancedTonemapModes = _mediaEncoder.EncoderVersion >= _minFFmpegAdvancedTonemapMode
- && _advancedTonemapModes.Contains(options.TonemappingMode, StringComparison.OrdinalIgnoreCase);
+ && _advancedTonemapModes.Contains(options.TonemappingMode);
if (useLegacyTonemapModes || useAdvancedTonemapModes)
{
@@ -3357,8 +3311,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args += ":param={6}";
}
- if (string.Equals(options.TonemappingRange, "tv", StringComparison.OrdinalIgnoreCase)
- || string.Equals(options.TonemappingRange, "pc", StringComparison.OrdinalIgnoreCase))
+ if (range == TonemappingRange.tv || range == TonemappingRange.pc)
{
args += ":range={7}";
}
@@ -3372,9 +3325,9 @@ namespace MediaBrowser.Controller.MediaEncoding
algorithm,
options.TonemappingPeak,
options.TonemappingDesat,
- options.TonemappingMode,
+ mode,
options.TonemappingParam,
- options.TonemappingRange);
+ rangeString);
}
public string GetLibplaceboFilter(
@@ -3409,24 +3362,24 @@ namespace MediaBrowser.Controller.MediaEncoding
if (doTonemap)
{
var algorithm = options.TonemappingAlgorithm;
+ var algorithmString = "clip";
var mode = options.TonemappingMode;
var range = options.TonemappingRange;
- if (string.Equals(algorithm, "bt2390", StringComparison.OrdinalIgnoreCase))
+ if (algorithm == TonemappingAlgorithm.bt2390)
{
- algorithm = "bt.2390";
+ algorithmString = "bt.2390";
}
- else if (string.Equals(algorithm, "none", StringComparison.OrdinalIgnoreCase))
+ else if (algorithm != TonemappingAlgorithm.none)
{
- algorithm = "clip";
+ algorithmString = algorithm.ToString().ToLowerInvariant();
}
tonemapArg = ":tonemapping=" + algorithm + ":peak_detect=0:color_primaries=bt709:color_trc=bt709:colorspace=bt709";
- if (string.Equals(range, "tv", StringComparison.OrdinalIgnoreCase)
- || string.Equals(range, "pc", StringComparison.OrdinalIgnoreCase))
+ if (range == TonemappingRange.tv || range == TonemappingRange.pc)
{
- tonemapArg += ":range=" + range;
+ tonemapArg += ":range=" + range.ToString().ToLowerInvariant();
}
}
@@ -3530,8 +3483,8 @@ namespace MediaBrowser.Controller.MediaEncoding
tonemapArgs += $":param={options.TonemappingParam}";
}
- if (string.Equals(options.TonemappingRange, "tv", StringComparison.OrdinalIgnoreCase)
- || string.Equals(options.TonemappingRange, "pc", StringComparison.OrdinalIgnoreCase))
+ var range = options.TonemappingRange;
+ if (range == TonemappingRange.tv || range == TonemappingRange.pc)
{
tonemapArgs += $":range={options.TonemappingRange}";
}
@@ -3575,7 +3528,7 @@ namespace MediaBrowser.Controller.MediaEncoding
EncodingOptions options,
string vidEncoder)
{
- if (!string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase))
+ if (options.HardwareAccelerationType != HardwareAccelerationType.nvenc)
{
return (null, null, null);
}
@@ -3777,7 +3730,7 @@ namespace MediaBrowser.Controller.MediaEncoding
EncodingOptions options,
string vidEncoder)
{
- if (!string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase))
+ if (options.HardwareAccelerationType != HardwareAccelerationType.amf)
{
return (null, null, null);
}
@@ -3993,7 +3946,7 @@ namespace MediaBrowser.Controller.MediaEncoding
EncodingOptions options,
string vidEncoder)
{
- if (!string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
+ if (options.HardwareAccelerationType != HardwareAccelerationType.qsv)
{
return (null, null, null);
}
@@ -4543,7 +4496,7 @@ namespace MediaBrowser.Controller.MediaEncoding
EncodingOptions options,
string vidEncoder)
{
- if (!string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ if (options.HardwareAccelerationType != HardwareAccelerationType.vaapi)
{
return (null, null, null);
}
@@ -5247,7 +5200,7 @@ namespace MediaBrowser.Controller.MediaEncoding
EncodingOptions options,
string vidEncoder)
{
- if (!string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase))
+ if (options.HardwareAccelerationType != HardwareAccelerationType.videotoolbox)
{
return (null, null, null);
}
@@ -5436,7 +5389,7 @@ namespace MediaBrowser.Controller.MediaEncoding
EncodingOptions options,
string vidEncoder)
{
- if (!string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
+ if (options.HardwareAccelerationType != HardwareAccelerationType.rkmpp)
{
return (null, null, null);
}
@@ -5696,38 +5649,20 @@ namespace MediaBrowser.Controller.MediaEncoding
List subFilters;
List overlayFilters;
- if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ (mainFilters, subFilters, overlayFilters) = options.HardwareAccelerationType switch
{
- (mainFilters, subFilters, overlayFilters) = GetVaapiVidFilterChain(state, options, outputVideoCodec);
- }
- else if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
- {
- (mainFilters, subFilters, overlayFilters) = GetIntelVidFilterChain(state, options, outputVideoCodec);
- }
- else if (string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase))
- {
- (mainFilters, subFilters, overlayFilters) = GetNvidiaVidFilterChain(state, options, outputVideoCodec);
- }
- else if (string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase))
- {
- (mainFilters, subFilters, overlayFilters) = GetAmdVidFilterChain(state, options, outputVideoCodec);
- }
- else if (string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase))
- {
- (mainFilters, subFilters, overlayFilters) = GetAppleVidFilterChain(state, options, outputVideoCodec);
- }
- else if (string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
- {
- (mainFilters, subFilters, overlayFilters) = GetRkmppVidFilterChain(state, options, outputVideoCodec);
- }
- else
- {
- (mainFilters, subFilters, overlayFilters) = GetSwVidFilterChain(state, options, outputVideoCodec);
- }
+ HardwareAccelerationType.vaapi => GetVaapiVidFilterChain(state, options, outputVideoCodec),
+ HardwareAccelerationType.amf => GetAmdVidFilterChain(state, options, outputVideoCodec),
+ HardwareAccelerationType.qsv => GetIntelVidFilterChain(state, options, outputVideoCodec),
+ HardwareAccelerationType.nvenc => GetNvidiaVidFilterChain(state, options, outputVideoCodec),
+ HardwareAccelerationType.videotoolbox => GetAppleVidFilterChain(state, options, outputVideoCodec),
+ HardwareAccelerationType.rkmpp => GetRkmppVidFilterChain(state, options, outputVideoCodec),
+ _ => GetSwVidFilterChain(state, options, outputVideoCodec),
+ };
- mainFilters?.RemoveAll(filter => string.IsNullOrEmpty(filter));
- subFilters?.RemoveAll(filter => string.IsNullOrEmpty(filter));
- overlayFilters?.RemoveAll(filter => string.IsNullOrEmpty(filter));
+ mainFilters?.RemoveAll(string.IsNullOrEmpty);
+ subFilters?.RemoveAll(string.IsNullOrEmpty);
+ overlayFilters?.RemoveAll(string.IsNullOrEmpty);
var framerate = GetFramerateParam(state);
if (framerate.HasValue)
@@ -5907,7 +5842,9 @@ namespace MediaBrowser.Controller.MediaEncoding
return null;
}
- if (!string.IsNullOrEmpty(videoStream.Codec) && !string.IsNullOrEmpty(options.HardwareAccelerationType))
+ var hardwareAccelerationType = options.HardwareAccelerationType;
+
+ if (!string.IsNullOrEmpty(videoStream.Codec) && hardwareAccelerationType != HardwareAccelerationType.none)
{
var bitDepth = GetVideoColorBitDepth(state);
@@ -5919,10 +5856,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|| string.Equals(videoStream.Codec, "av1", StringComparison.OrdinalIgnoreCase)))
{
// RKMPP has H.264 Hi10P decoder
- bool hasHardwareHi10P = string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase);
+ bool hasHardwareHi10P = hardwareAccelerationType == HardwareAccelerationType.rkmpp;
// VideoToolbox on Apple Silicon has H.264 Hi10P mode enabled after macOS 14.6
- if (string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase))
+ if (hardwareAccelerationType == HardwareAccelerationType.videotoolbox)
{
var ver = Environment.OSVersion.Version;
var arch = RuntimeInformation.OSArchitecture;
@@ -5939,34 +5876,20 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
+ var decoder = hardwareAccelerationType switch
{
- return GetQsvHwVidDecoder(state, options, videoStream, bitDepth);
- }
+ HardwareAccelerationType.vaapi => GetVaapiVidDecoder(state, options, videoStream, bitDepth),
+ HardwareAccelerationType.amf => GetAmfVidDecoder(state, options, videoStream, bitDepth),
+ HardwareAccelerationType.qsv => GetQsvHwVidDecoder(state, options, videoStream, bitDepth),
+ HardwareAccelerationType.nvenc => GetNvdecVidDecoder(state, options, videoStream, bitDepth),
+ HardwareAccelerationType.videotoolbox => GetVideotoolboxVidDecoder(state, options, videoStream, bitDepth),
+ HardwareAccelerationType.rkmpp => GetRkmppVidDecoder(state, options, videoStream, bitDepth),
+ _ => string.Empty
+ };
- if (string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase))
+ if (!string.IsNullOrEmpty(decoder))
{
- return GetNvdecVidDecoder(state, options, videoStream, bitDepth);
- }
-
- if (string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase))
- {
- return GetAmfVidDecoder(state, options, videoStream, bitDepth);
- }
-
- if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
- {
- return GetVaapiVidDecoder(state, options, videoStream, bitDepth);
- }
-
- if (string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase))
- {
- return GetVideotoolboxVidDecoder(state, options, videoStream, bitDepth);
- }
-
- if (string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
- {
- return GetRkmppVidDecoder(state, options, videoStream, bitDepth);
+ return decoder;
}
}
@@ -5981,7 +5904,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Avoid a second attempt if no hardware acceleration is being used
- options.HardwareDecodingCodecs = Array.FindAll(options.HardwareDecodingCodecs, val => !string.Equals(val, whichCodec, StringComparison.OrdinalIgnoreCase));
+ options.HardwareDecodingCodecs = options.HardwareDecodingCodecs.Where(c => !string.Equals(c, whichCodec, StringComparison.OrdinalIgnoreCase)).ToArray();
// leave blank so ffmpeg will decide
return null;
@@ -6062,6 +5985,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var isVideotoolboxSupported = isMacOS && _mediaEncoder.SupportsHwaccel("videotoolbox");
var isRkmppSupported = isLinux && IsRkmppFullSupported();
var isCodecAvailable = options.HardwareDecodingCodecs.Contains(videoCodec, StringComparison.OrdinalIgnoreCase);
+ var hardwareAccelerationType = options.HardwareAccelerationType;
var ffmpegVersion = _mediaEncoder.EncoderVersion;
@@ -6099,7 +6023,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Intel qsv/d3d11va/vaapi
- if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
+ if (hardwareAccelerationType == HardwareAccelerationType.qsv)
{
if (options.PreferSystemNativeHwDecoder)
{
@@ -6125,7 +6049,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Nvidia cuda
- if (string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase))
+ if (hardwareAccelerationType == HardwareAccelerationType.nvenc)
{
if (isCudaSupported && isCodecAvailable)
{
@@ -6142,7 +6066,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Amd d3d11va
- if (string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase))
+ if (hardwareAccelerationType == HardwareAccelerationType.amf)
{
if (isD3d11Supported && isCodecAvailable)
{
@@ -6152,7 +6076,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Vaapi
- if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)
+ if (hardwareAccelerationType == HardwareAccelerationType.vaapi
&& isVaapiSupported
&& isCodecAvailable)
{
@@ -6161,7 +6085,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Apple videotoolbox
- if (string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase)
+ if (hardwareAccelerationType == HardwareAccelerationType.videotoolbox
&& isVideotoolboxSupported
&& isCodecAvailable)
{
@@ -6169,7 +6093,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Rockchip rkmpp
- if (string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase)
+ if (hardwareAccelerationType == HardwareAccelerationType.rkmpp
&& isRkmppSupported
&& isCodecAvailable)
{
@@ -6185,7 +6109,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var isLinux = OperatingSystem.IsLinux();
if ((!isWindows && !isLinux)
- || !string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
+ || options.HardwareAccelerationType != HardwareAccelerationType.qsv)
{
return null;
}
@@ -6254,7 +6178,7 @@ namespace MediaBrowser.Controller.MediaEncoding
public string GetNvdecVidDecoder(EncodingJobInfo state, EncodingOptions options, MediaStream videoStream, int bitDepth)
{
if ((!OperatingSystem.IsWindows() && !OperatingSystem.IsLinux())
- || !string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase))
+ || options.HardwareAccelerationType != HardwareAccelerationType.nvenc)
{
return null;
}
@@ -6319,7 +6243,7 @@ namespace MediaBrowser.Controller.MediaEncoding
public string GetAmfVidDecoder(EncodingJobInfo state, EncodingOptions options, MediaStream videoStream, int bitDepth)
{
if (!OperatingSystem.IsWindows()
- || !string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase))
+ || options.HardwareAccelerationType != HardwareAccelerationType.amf)
{
return null;
}
@@ -6375,7 +6299,7 @@ namespace MediaBrowser.Controller.MediaEncoding
public string GetVaapiVidDecoder(EncodingJobInfo state, EncodingOptions options, MediaStream videoStream, int bitDepth)
{
if (!OperatingSystem.IsLinux()
- || !string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ || options.HardwareAccelerationType != HardwareAccelerationType.vaapi)
{
return null;
}
@@ -6437,7 +6361,7 @@ namespace MediaBrowser.Controller.MediaEncoding
public string GetVideotoolboxVidDecoder(EncodingJobInfo state, EncodingOptions options, MediaStream videoStream, int bitDepth)
{
if (!OperatingSystem.IsMacOS()
- || !string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase))
+ || options.HardwareAccelerationType != HardwareAccelerationType.videotoolbox)
{
return null;
}
@@ -6485,7 +6409,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var isLinux = OperatingSystem.IsLinux();
if (!isLinux
- || !string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
+ || options.HardwareAccelerationType != HardwareAccelerationType.rkmpp)
{
return null;
}
@@ -6749,7 +6673,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.IsVideoRequest)
{
- if (!string.IsNullOrEmpty(state.InputContainer) && state.VideoType == VideoType.VideoFile && string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType))
+ if (!string.IsNullOrEmpty(state.InputContainer) && state.VideoType == VideoType.VideoFile && encodingOptions.HardwareAccelerationType != HardwareAccelerationType.none)
{
var inputFormat = GetInputFormat(state.InputContainer);
if (!string.IsNullOrEmpty(inputFormat))
@@ -6865,7 +6789,7 @@ namespace MediaBrowser.Controller.MediaEncoding
state.SupportedAudioCodecs = supportedAudioCodecsList.ToArray();
- request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(i => _mediaEncoder.CanEncodeToAudioCodec(i))
+ request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(_mediaEncoder.CanEncodeToAudioCodec)
?? state.SupportedAudioCodecs.FirstOrDefault();
}
@@ -6991,7 +6915,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return " -codec:s:0 " + codec + " -disposition:s:0 default";
}
- public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string defaultPreset)
+ public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, EncoderPreset defaultPreset)
{
// Get the output codec name
var videoCodec = GetVideoEncoder(state, encodingOptions);
@@ -7042,7 +6966,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Empty;
}
- public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, string defaultPreset)
+ public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, EncoderPreset defaultPreset)
{
var args = "-codec:v:0 " + videoCodec;
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index a6a443f3dd..caa9cb499d 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -224,7 +224,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (OperatingSystem.IsLinux()
&& SupportsHwaccel("vaapi")
&& !string.IsNullOrEmpty(options.VaapiDevice)
- && string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ && options.HardwareAccelerationType == HardwareAccelerationType.vaapi)
{
_isVaapiDeviceAmd = validator.CheckVaapiDeviceByDriverName("Mesa Gallium driver", options.VaapiDevice);
_isVaapiDeviceInteliHD = validator.CheckVaapiDeviceByDriverName("Intel iHD driver", options.VaapiDevice);
@@ -799,11 +799,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (allowHwAccel && enableKeyFrameOnlyExtraction)
{
- var supportsKeyFrameOnly = (string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && options.EnableEnhancedNvdecDecoder)
- || (string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) && OperatingSystem.IsWindows())
- || (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) && options.PreferSystemNativeHwDecoder)
- || string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)
- || string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase);
+ var hardwareAccelerationType = options.HardwareAccelerationType;
+ var supportsKeyFrameOnly = (hardwareAccelerationType == HardwareAccelerationType.nvenc && options.EnableEnhancedNvdecDecoder)
+ || (hardwareAccelerationType == HardwareAccelerationType.amf && OperatingSystem.IsWindows())
+ || (hardwareAccelerationType == HardwareAccelerationType.qsv && options.PreferSystemNativeHwDecoder)
+ || hardwareAccelerationType == HardwareAccelerationType.vaapi
+ || hardwareAccelerationType == HardwareAccelerationType.videotoolbox;
if (!supportsKeyFrameOnly)
{
// Disable hardware acceleration when the hardware decoder does not support keyframe only mode.
@@ -817,7 +818,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (!allowHwAccel)
{
options.EnableHardwareEncoding = false;
- options.HardwareAccelerationType = string.Empty;
+ options.HardwareAccelerationType = HardwareAccelerationType.none;
options.EnableTonemapping = false;
}
@@ -861,7 +862,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
inputArg = "-threads " + threads + " " + inputArg; // HW accel args set a different input thread count, only set if disabled
}
- if (options.HardwareAccelerationType.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase) && _isLowPriorityHwDecodeSupported)
+ if (options.HardwareAccelerationType == HardwareAccelerationType.videotoolbox && _isLowPriorityHwDecodeSupported)
{
// VideoToolbox supports low priority decoding, which is useful for trickplay
inputArg = "-hwaccel_flags +low_priority " + inputArg;
diff --git a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs
index 42f355b052..57557d55ca 100644
--- a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs
+++ b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs
@@ -352,12 +352,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable
{
var audioCodec = state.ActualOutputAudioCodec;
var videoCodec = state.ActualOutputVideoCodec;
- var hardwareAccelerationTypeString = _serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType;
- HardwareEncodingType? hardwareAccelerationType = null;
- if (Enum.TryParse(hardwareAccelerationTypeString, out var parsedHardwareAccelerationType))
- {
- hardwareAccelerationType = parsedHardwareAccelerationType;
- }
+ var hardwareAccelerationType = _serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType;
_sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo
{
diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs
index 4c5213d4e2..d67a2479fb 100644
--- a/MediaBrowser.Model/Configuration/EncodingOptions.cs
+++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CA1819 // XML serialization handles collections improperly, so we need to use arrays
+
#nullable disable
using MediaBrowser.Model.Entities;
@@ -30,9 +32,9 @@ public class EncodingOptions
EnableTonemapping = false;
EnableVppTonemapping = false;
EnableVideoToolboxTonemapping = false;
- TonemappingAlgorithm = "bt2390";
- TonemappingMode = "auto";
- TonemappingRange = "auto";
+ TonemappingAlgorithm = TonemappingAlgorithm.bt2390;
+ TonemappingMode = TonemappingMode.auto;
+ TonemappingRange = TonemappingRange.auto;
TonemappingDesat = 0;
TonemappingPeak = 100;
TonemappingParam = 0;
@@ -41,7 +43,7 @@ public class EncodingOptions
H264Crf = 23;
H265Crf = 28;
DeinterlaceDoubleRate = false;
- DeinterlaceMethod = "yadif";
+ DeinterlaceMethod = DeinterlaceMethod.yadif;
EnableDecodingColorDepth10Hevc = true;
EnableDecodingColorDepth10Vp9 = true;
// Enhanced Nvdec or system native decoder is required for DoVi to SDR tone-mapping.
@@ -53,8 +55,8 @@ public class EncodingOptions
AllowHevcEncoding = false;
AllowAv1Encoding = false;
EnableSubtitleExtraction = true;
- AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = new[] { "mkv" };
- HardwareDecodingCodecs = new string[] { "h264", "vc1" };
+ AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = ["mkv"];
+ HardwareDecodingCodecs = ["h264", "vc1"];
}
///
@@ -120,7 +122,7 @@ public class EncodingOptions
///
/// Gets or sets the hardware acceleration type.
///
- public string HardwareAccelerationType { get; set; }
+ public HardwareAccelerationType HardwareAccelerationType { get; set; }
///
/// Gets or sets the FFmpeg path as set by the user via the UI.
@@ -160,17 +162,17 @@ public class EncodingOptions
///
/// Gets or sets the tone-mapping algorithm.
///
- public string TonemappingAlgorithm { get; set; }
+ public TonemappingAlgorithm TonemappingAlgorithm { get; set; }
///
/// Gets or sets the tone-mapping mode.
///
- public string TonemappingMode { get; set; }
+ public TonemappingMode TonemappingMode { get; set; }
///
/// Gets or sets the tone-mapping range.
///
- public string TonemappingRange { get; set; }
+ public TonemappingRange TonemappingRange { get; set; }
///
/// Gets or sets the tone-mapping desaturation.
@@ -210,7 +212,7 @@ public class EncodingOptions
///
/// Gets or sets the encoder preset.
///
- public string EncoderPreset { get; set; }
+ public EncoderPreset? EncoderPreset { get; set; }
///
/// Gets or sets a value indicating whether the framerate is doubled when deinterlacing.
@@ -220,7 +222,7 @@ public class EncodingOptions
///
/// Gets or sets the deinterlace method.
///
- public string DeinterlaceMethod { get; set; }
+ public DeinterlaceMethod DeinterlaceMethod { get; set; }
///
/// Gets or sets a value indicating whether 10bit HEVC decoding is enabled.
diff --git a/MediaBrowser.Model/Entities/DeinterlaceMethod.cs b/MediaBrowser.Model/Entities/DeinterlaceMethod.cs
new file mode 100644
index 0000000000..d05aac4339
--- /dev/null
+++ b/MediaBrowser.Model/Entities/DeinterlaceMethod.cs
@@ -0,0 +1,19 @@
+#pragma warning disable SA1300 // Lowercase required for backwards compat.
+
+namespace MediaBrowser.Model.Entities;
+
+///
+/// Enum containing deinterlace methods.
+///
+public enum DeinterlaceMethod
+{
+ ///
+ /// YADIF.
+ ///
+ yadif = 0,
+
+ ///
+ /// BWDIF.
+ ///
+ bwdif = 1
+}
diff --git a/MediaBrowser.Model/Entities/EncoderPreset.cs b/MediaBrowser.Model/Entities/EncoderPreset.cs
new file mode 100644
index 0000000000..74c0714334
--- /dev/null
+++ b/MediaBrowser.Model/Entities/EncoderPreset.cs
@@ -0,0 +1,64 @@
+#pragma warning disable SA1300 // Lowercase required for backwards compat.
+
+namespace MediaBrowser.Model.Entities;
+
+///
+/// Enum containing encoder presets.
+///
+public enum EncoderPreset
+{
+ ///
+ /// Auto preset.
+ ///
+ auto = 0,
+
+ ///
+ /// Placebo preset.
+ ///
+ placebo = 1,
+
+ ///
+ /// Veryslow preset.
+ ///
+ veryslow = 2,
+
+ ///
+ /// Slower preset.
+ ///
+ slower = 3,
+
+ ///
+ /// Slow preset.
+ ///
+ slow = 4,
+
+ ///
+ /// Medium preset.
+ ///
+ medium = 5,
+
+ ///
+ /// Fast preset.
+ ///
+ fast = 6,
+
+ ///
+ /// Faster preset.
+ ///
+ faster = 7,
+
+ ///
+ /// Veryfast preset.
+ ///
+ veryfast = 8,
+
+ ///
+ /// Superfast preset.
+ ///
+ superfast = 9,
+
+ ///
+ /// Ultrafast preset.
+ ///
+ ultrafast = 10
+}
diff --git a/MediaBrowser.Model/Entities/HardwareAccelerationType.cs b/MediaBrowser.Model/Entities/HardwareAccelerationType.cs
new file mode 100644
index 0000000000..198a2e00f6
--- /dev/null
+++ b/MediaBrowser.Model/Entities/HardwareAccelerationType.cs
@@ -0,0 +1,49 @@
+#pragma warning disable SA1300 // Lowercase required for backwards compat.
+
+namespace MediaBrowser.Model.Entities;
+
+///
+/// Enum containing hardware acceleration types.
+///
+public enum HardwareAccelerationType
+{
+ ///
+ /// Software accelleration.
+ ///
+ none = 0,
+
+ ///
+ /// AMD AMF.
+ ///
+ amf = 1,
+
+ ///
+ /// Intel Quick Sync Video.
+ ///
+ qsv = 2,
+
+ ///
+ /// NVIDIA NVENC.
+ ///
+ nvenc = 3,
+
+ ///
+ /// Video4Linux2 V4L2M2M.
+ ///
+ v4l2m2m = 4,
+
+ ///
+ /// Video Acceleration API (VAAPI).
+ ///
+ vaapi = 5,
+
+ ///
+ /// Video ToolBox.
+ ///
+ videotoolbox = 6,
+
+ ///
+ /// Rockchip Media Process Platform (RKMPP).
+ ///
+ rkmpp = 7
+}
diff --git a/MediaBrowser.Model/Entities/TonemappingAlgorithm.cs b/MediaBrowser.Model/Entities/TonemappingAlgorithm.cs
new file mode 100644
index 0000000000..488006e0bc
--- /dev/null
+++ b/MediaBrowser.Model/Entities/TonemappingAlgorithm.cs
@@ -0,0 +1,49 @@
+#pragma warning disable SA1300 // Lowercase required for backwards compat.
+
+namespace MediaBrowser.Model.Entities;
+
+///
+/// Enum containing tonemapping algorithms.
+///
+public enum TonemappingAlgorithm
+{
+ ///
+ /// None.
+ ///
+ none = 0,
+
+ ///
+ /// Clip.
+ ///
+ clip = 1,
+
+ ///
+ /// Linear.
+ ///
+ linear = 2,
+
+ ///
+ /// Gamma.
+ ///
+ gamma = 3,
+
+ ///
+ /// Reinhard.
+ ///
+ reinhard = 4,
+
+ ///
+ /// Hable.
+ ///
+ hable = 5,
+
+ ///
+ /// Mobius.
+ ///
+ mobius = 6,
+
+ ///
+ /// BT2390.
+ ///
+ bt2390 = 7
+}
diff --git a/MediaBrowser.Model/Entities/TonemappingMode.cs b/MediaBrowser.Model/Entities/TonemappingMode.cs
new file mode 100644
index 0000000000..e10a0b4ad1
--- /dev/null
+++ b/MediaBrowser.Model/Entities/TonemappingMode.cs
@@ -0,0 +1,34 @@
+#pragma warning disable SA1300 // Lowercase required for backwards compat.
+
+namespace MediaBrowser.Model.Entities;
+
+///
+/// Enum containing tonemapping modes.
+///
+public enum TonemappingMode
+{
+ ///
+ /// Auto.
+ ///
+ auto = 0,
+
+ ///
+ /// Max.
+ ///
+ max = 1,
+
+ ///
+ /// RGB.
+ ///
+ rgb = 2,
+
+ ///
+ /// Lum.
+ ///
+ lum = 3,
+
+ ///
+ /// ITP.
+ ///
+ itp = 4
+}
diff --git a/MediaBrowser.Model/Entities/TonemappingRange.cs b/MediaBrowser.Model/Entities/TonemappingRange.cs
new file mode 100644
index 0000000000..b1446b81c6
--- /dev/null
+++ b/MediaBrowser.Model/Entities/TonemappingRange.cs
@@ -0,0 +1,24 @@
+#pragma warning disable SA1300 // Lowercase required for backwards compat.
+
+namespace MediaBrowser.Model.Entities;
+
+///
+/// Enum containing tonemapping ranges.
+///
+public enum TonemappingRange
+{
+ ///
+ /// Auto.
+ ///
+ auto = 0,
+
+ ///
+ /// TV.
+ ///
+ tv = 1,
+
+ ///
+ /// PC.
+ ///
+ pc = 2
+}
diff --git a/MediaBrowser.Model/Session/HardwareEncodingType.cs b/MediaBrowser.Model/Session/HardwareEncodingType.cs
deleted file mode 100644
index cf424fef53..0000000000
--- a/MediaBrowser.Model/Session/HardwareEncodingType.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-namespace MediaBrowser.Model.Session
-{
- ///
- /// Enum HardwareEncodingType.
- ///
- public enum HardwareEncodingType
- {
- ///
- /// AMD AMF.
- ///
- AMF = 0,
-
- ///
- /// Intel Quick Sync Video.
- ///
- QSV = 1,
-
- ///
- /// NVIDIA NVENC.
- ///
- NVENC = 2,
-
- ///
- /// Video4Linux2 V4L2.
- ///
- V4L2M2M = 3,
-
- ///
- /// Video Acceleration API (VAAPI).
- ///
- VAAPI = 4,
-
- ///
- /// Video ToolBox.
- ///
- VideoToolBox = 5,
-
- ///
- /// Rockchip Media Process Platform (RKMPP).
- ///
- RKMPP = 6
- }
-}
diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs
index 000cbd4c54..ae25267aca 100644
--- a/MediaBrowser.Model/Session/TranscodingInfo.cs
+++ b/MediaBrowser.Model/Session/TranscodingInfo.cs
@@ -1,34 +1,76 @@
#nullable disable
-#pragma warning disable CS1591
-namespace MediaBrowser.Model.Session
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Session;
+
+///
+/// Class holding information on a runnning transcode.
+///
+public class TranscodingInfo
{
- public class TranscodingInfo
- {
- public string AudioCodec { get; set; }
+ ///
+ /// Gets or sets the thread count used for encoding.
+ ///
+ public string AudioCodec { get; set; }
- public string VideoCodec { get; set; }
+ ///
+ /// Gets or sets the thread count used for encoding.
+ ///
+ public string VideoCodec { get; set; }
- public string Container { get; set; }
+ ///
+ /// Gets or sets the thread count used for encoding.
+ ///
+ public string Container { get; set; }
- public bool IsVideoDirect { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the video is passed through.
+ ///
+ public bool IsVideoDirect { get; set; }
- public bool IsAudioDirect { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the audio is passed through.
+ ///
+ public bool IsAudioDirect { get; set; }
- public int? Bitrate { get; set; }
+ ///
+ /// Gets or sets the bitrate.
+ ///
+ public int? Bitrate { get; set; }
- public float? Framerate { get; set; }
+ ///
+ /// Gets or sets the framerate.
+ ///
+ public float? Framerate { get; set; }
- public double? CompletionPercentage { get; set; }
+ ///
+ /// Gets or sets the completion percentage.
+ ///
+ public double? CompletionPercentage { get; set; }
- public int? Width { get; set; }
+ ///
+ /// Gets or sets the video width.
+ ///
+ public int? Width { get; set; }
- public int? Height { get; set; }
+ ///
+ /// Gets or sets the video height.
+ ///
+ public int? Height { get; set; }
- public int? AudioChannels { get; set; }
+ ///
+ /// Gets or sets the audio channels.
+ ///
+ public int? AudioChannels { get; set; }
- public HardwareEncodingType? HardwareAccelerationType { get; set; }
+ ///
+ /// Gets or sets the hardware acceleration type.
+ ///
+ public HardwareAccelerationType? HardwareAccelerationType { get; set; }
- public TranscodeReason TranscodeReasons { get; set; }
- }
+ ///
+ /// Gets or sets the transcode reasons.
+ ///
+ public TranscodeReason TranscodeReasons { get; set; }
}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs b/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
index 9a023d7ed9..1846ba26bf 100644
--- a/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
+++ b/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
@@ -128,7 +128,7 @@ public class DynamicHlsPlaylistGenerator : IDynamicHlsPlaylistGenerator
return false;
}
- internal static bool IsExtractionAllowedForFile(ReadOnlySpan filePath, string[] allowedExtensions)
+ internal static bool IsExtractionAllowedForFile(ReadOnlySpan filePath, IReadOnlyList allowedExtensions)
{
var extension = Path.GetExtension(filePath);
if (extension.IsEmpty)
@@ -138,7 +138,7 @@ public class DynamicHlsPlaylistGenerator : IDynamicHlsPlaylistGenerator
// Remove the leading dot
var extensionWithoutDot = extension[1..];
- for (var i = 0; i < allowedExtensions.Length; i++)
+ for (var i = 0; i < allowedExtensions.Count; i++)
{
var allowedExtension = allowedExtensions[i].AsSpan().TrimStart('.');
if (extensionWithoutDot.Equals(allowedExtension, StringComparison.OrdinalIgnoreCase))