fix nvidia capabilities for second-gen maxwell (#899)
This commit is contained in:
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
### Fixed
|
### Fixed
|
||||||
- Fix subtitle stream selection when subtitle language is different than audio language
|
- Fix subtitle stream selection when subtitle language is different than audio language
|
||||||
- Fix bug with unsupported AAC channel layouts
|
- Fix bug with unsupported AAC channel layouts
|
||||||
|
- Fix NVIDIA second-gen maxwell capabilities detection
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Add `640x480` resolution
|
- Add `640x480` resolution
|
||||||
|
|||||||
@@ -585,7 +585,7 @@ public class TranscodingTests
|
|||||||
public Task<IHardwareCapabilities> GetHardwareCapabilities(
|
public Task<IHardwareCapabilities> GetHardwareCapabilities(
|
||||||
string ffmpegPath,
|
string ffmpegPath,
|
||||||
HardwareAccelerationMode hardwareAccelerationMode) =>
|
HardwareAccelerationMode hardwareAccelerationMode) =>
|
||||||
Task.FromResult<IHardwareCapabilities>(new NvidiaHardwareCapabilities(61));
|
Task.FromResult<IHardwareCapabilities>(new NvidiaHardwareCapabilities(61, string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ExecutableName(string baseName) =>
|
private static string ExecutableName(string baseName) =>
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ namespace ErsatzTV.FFmpeg.Capabilities;
|
|||||||
|
|
||||||
public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
|
public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
|
||||||
{
|
{
|
||||||
private const string CacheKey = "ffmpeg.hardware.nvidia.architecture";
|
private const string ArchitectureCacheKey = "ffmpeg.hardware.nvidia.architecture";
|
||||||
|
private const string ModelCacheKey = "ffmpeg.hardware.nvidia.model";
|
||||||
private readonly ILogger<HardwareCapabilitiesFactory> _logger;
|
private readonly ILogger<HardwareCapabilitiesFactory> _logger;
|
||||||
|
|
||||||
private readonly IMemoryCache _memoryCache;
|
private readonly IMemoryCache _memoryCache;
|
||||||
@@ -31,9 +32,10 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
|
|||||||
|
|
||||||
private async Task<IHardwareCapabilities> GetNvidiaCapabilities(string ffmpegPath)
|
private async Task<IHardwareCapabilities> GetNvidiaCapabilities(string ffmpegPath)
|
||||||
{
|
{
|
||||||
if (_memoryCache.TryGetValue(CacheKey, out int cachedArchitecture))
|
if (_memoryCache.TryGetValue(ArchitectureCacheKey, out int cachedArchitecture)
|
||||||
|
&& _memoryCache.TryGetValue(ModelCacheKey, out string cachedModel))
|
||||||
{
|
{
|
||||||
return new NvidiaHardwareCapabilities(cachedArchitecture);
|
return new NvidiaHardwareCapabilities(cachedArchitecture, cachedModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] arguments =
|
string[] arguments =
|
||||||
@@ -57,13 +59,20 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
|
|||||||
Option<string> maybeLine = Optional(output.Split("\n").FirstOrDefault(x => x.Contains("GPU")));
|
Option<string> maybeLine = Optional(output.Split("\n").FirstOrDefault(x => x.Contains("GPU")));
|
||||||
foreach (string line in maybeLine)
|
foreach (string line in maybeLine)
|
||||||
{
|
{
|
||||||
const string PATTERN = @"SM\s+(\d\.\d)";
|
const string ARCHITECTURE_PATTERN = @"SM\s+(\d\.\d)";
|
||||||
Match match = Regex.Match(line, PATTERN);
|
Match match = Regex.Match(line, ARCHITECTURE_PATTERN);
|
||||||
if (match.Success && int.TryParse(match.Groups[1].Value.Replace(".", string.Empty), out int architecture))
|
if (match.Success && int.TryParse(match.Groups[1].Value.Replace(".", string.Empty), out int architecture))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Detected NVIDIA GPU architecture SM {Architecture}", architecture);
|
const string MODEL_PATTERN = @"(GTX\s+[0-9a-zA-Z]+[\sTtIi]+)";
|
||||||
_memoryCache.Set(CacheKey, architecture);
|
Match modelMatch = Regex.Match(line, MODEL_PATTERN);
|
||||||
return new NvidiaHardwareCapabilities(architecture);
|
string model = modelMatch.Success ? modelMatch.Groups[1].Value.Trim() : "unknown";
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Detected NVIDIA GPU model {Model} architecture SM {Architecture}",
|
||||||
|
model,
|
||||||
|
architecture);
|
||||||
|
_memoryCache.Set(ArchitectureCacheKey, architecture);
|
||||||
|
_memoryCache.Set(ModelCacheKey, model);
|
||||||
|
return new NvidiaHardwareCapabilities(architecture, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,14 @@ namespace ErsatzTV.FFmpeg.Capabilities;
|
|||||||
public class NvidiaHardwareCapabilities : IHardwareCapabilities
|
public class NvidiaHardwareCapabilities : IHardwareCapabilities
|
||||||
{
|
{
|
||||||
private readonly int _architecture;
|
private readonly int _architecture;
|
||||||
|
private readonly List<string> _maxwellGm206 = new() { "GTX 750", "GTX 950", "GTX 960", "GTX 965M" };
|
||||||
|
private readonly string _model;
|
||||||
|
|
||||||
public NvidiaHardwareCapabilities(int architecture) => _architecture = architecture;
|
public NvidiaHardwareCapabilities(int architecture, string model)
|
||||||
|
{
|
||||||
|
_architecture = architecture;
|
||||||
|
_model = model;
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanDecode(string videoFormat, Option<IPixelFormat> maybePixelFormat)
|
public bool CanDecode(string videoFormat, Option<IPixelFormat> maybePixelFormat)
|
||||||
{
|
{
|
||||||
@@ -14,14 +20,14 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities
|
|||||||
|
|
||||||
return videoFormat switch
|
return videoFormat switch
|
||||||
{
|
{
|
||||||
// second gen maxwell is required to decode hevc
|
// some second gen maxwell can decode hevc, otherwise pascal is required
|
||||||
VideoFormat.Hevc => _architecture >= 52,
|
VideoFormat.Hevc => _architecture == 52 && _maxwellGm206.Contains(_model) || _architecture >= 60,
|
||||||
|
|
||||||
// pascal is required to decode vp9 10-bit
|
// pascal is required to decode vp9 10-bit
|
||||||
VideoFormat.Vp9 when bitDepth == 10 => _architecture >= 60,
|
VideoFormat.Vp9 when bitDepth == 10 => _architecture >= 60,
|
||||||
|
|
||||||
// second gen maxwell is required to decode vp9
|
// some second gen maxwell can decode vp9, otherwise pascal is required
|
||||||
VideoFormat.Vp9 => _architecture >= 52,
|
VideoFormat.Vp9 => _architecture == 52 && _maxwellGm206.Contains(_model) || _architecture >= 60,
|
||||||
|
|
||||||
_ => true
|
_ => true
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user