mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-12-16 14:03:03 +03:00
add support for cuda tonemap and overlay
This commit is contained in:
@@ -89,6 +89,24 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
"hevc_videotoolbox"
|
||||
};
|
||||
|
||||
private static readonly string[] _requiredFilters = new[]
|
||||
{
|
||||
"scale_cuda",
|
||||
"yadif_cuda",
|
||||
"hwupload_cuda",
|
||||
"overlay_cuda",
|
||||
"tonemap_cuda",
|
||||
"tonemap_opencl",
|
||||
"tonemap_vaapi",
|
||||
};
|
||||
|
||||
private static readonly IReadOnlyDictionary<int, string[]> _filterOptionsDict = new Dictionary<int, string[]>
|
||||
{
|
||||
{ 0, new string[] { "scale_cuda", "Output format (default \"same\")" } },
|
||||
{ 1, new string[] { "tonemap_cuda", "GPU accelerated HDR to SDR tonemapping" } },
|
||||
{ 2, new string[] { "tonemap_opencl", "bt2390" } }
|
||||
};
|
||||
|
||||
// These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below
|
||||
private static readonly IReadOnlyDictionary<string, Version> _ffmpegMinimumLibraryVersions = new Dictionary<string, Version>
|
||||
{
|
||||
@@ -156,7 +174,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
}
|
||||
|
||||
// Work out what the version under test is
|
||||
var version = GetFFmpegVersion(versionOutput);
|
||||
var version = GetFFmpegVersionInternal(versionOutput);
|
||||
|
||||
_logger.LogInformation("Found ffmpeg version {Version}", version != null ? version.ToString() : "unknown");
|
||||
|
||||
@@ -200,6 +218,34 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
|
||||
public IEnumerable<string> GetHwaccels() => GetHwaccelTypes();
|
||||
|
||||
public IEnumerable<string> GetFilters() => GetFFmpegFilters();
|
||||
|
||||
public IDictionary<int, bool> GetFiltersWithOption() => GetFFmpegFiltersWithOption();
|
||||
|
||||
public Version? GetFFmpegVersion()
|
||||
{
|
||||
string output;
|
||||
try
|
||||
{
|
||||
output = GetProcessOutput(_encoderPath, "-version");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error validating encoder");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
_logger.LogError("FFmpeg validation: The process returned no result");
|
||||
return null;
|
||||
}
|
||||
|
||||
_logger.LogDebug("ffmpeg output: {Output}", output);
|
||||
|
||||
return GetFFmpegVersionInternal(output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Using the output from "ffmpeg -version" work out the FFmpeg version.
|
||||
/// For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy
|
||||
@@ -208,7 +254,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
/// </summary>
|
||||
/// <param name="output">The output from "ffmpeg -version".</param>
|
||||
/// <returns>The FFmpeg version.</returns>
|
||||
internal Version? GetFFmpegVersion(string output)
|
||||
internal Version? GetFFmpegVersionInternal(string output)
|
||||
{
|
||||
// For pre-built binaries the FFmpeg version should be mentioned at the very start of the output
|
||||
var match = Regex.Match(output, @"^ffmpeg version n?((?:[0-9]+\.?)+)");
|
||||
@@ -297,9 +343,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
return found;
|
||||
}
|
||||
|
||||
public bool CheckFilter(string filter, string option)
|
||||
public bool CheckFilterWithOption(string filter, string option)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filter))
|
||||
if (string.IsNullOrEmpty(filter) || string.IsNullOrEmpty(option))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -317,11 +363,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
|
||||
if (output.Contains("Filter " + filter, StringComparison.Ordinal))
|
||||
{
|
||||
if (string.IsNullOrEmpty(option))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return output.Contains(option, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
@@ -362,6 +403,49 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
return found;
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetFFmpegFilters()
|
||||
{
|
||||
string output;
|
||||
try
|
||||
{
|
||||
output = GetProcessOutput(_encoderPath, "-filters");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error detecting available filters");
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
var found = Regex
|
||||
.Matches(output, @"^\s\S{3}\s(?<filter>[\w|-]+)\s+.+$", RegexOptions.Multiline)
|
||||
.Cast<Match>()
|
||||
.Select(x => x.Groups["filter"].Value)
|
||||
.Where(x => _requiredFilters.Contains(x));
|
||||
|
||||
_logger.LogInformation("Available filters: {Filters}", found);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private IDictionary<int, bool> GetFFmpegFiltersWithOption()
|
||||
{
|
||||
IDictionary<int, bool> dict = new Dictionary<int, bool>();
|
||||
for (int i = 0; i < _filterOptionsDict.Count; i++)
|
||||
{
|
||||
if (_filterOptionsDict.TryGetValue(i, out var val) && val.Length == 2)
|
||||
{
|
||||
dict.Add(i, CheckFilterWithOption(val[0], val[1]));
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
private string GetProcessOutput(string path, string arguments)
|
||||
{
|
||||
using (var process = new Process()
|
||||
|
||||
Reference in New Issue
Block a user