Browse Source

fix nvidia in docker; minimize nvenc sessions (#2460)

pull/2461/head
Jason Dove 8 months ago committed by GitHub
parent
commit
8b4b7cf16a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      ErsatzTV.FFmpeg/Capabilities/Nvidia/CudaDevice.cs
  2. 55
      ErsatzTV.FFmpeg/Capabilities/Nvidia/CudaHelper.cs
  3. 6
      ErsatzTV.FFmpeg/Capabilities/Nvidia/NvEncSharpRedirector.cs
  4. 49
      ErsatzTV.FFmpeg/Capabilities/NvidiaHardwareCapabilities.cs

4
ErsatzTV.FFmpeg/Capabilities/Nvidia/CudaDevice.cs

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
namespace ErsatzTV.FFmpeg.Capabilities.Nvidia;
public record CudaDevice(int Handle, string Model, Version Version);
public record CudaDevice(int Handle, string Model, Version Version, IReadOnlyList<CudaCodec> Codecs);
public record CudaCodec(string Name, Guid CodecGuid, IReadOnlyList<Guid> ProfileGuids, IReadOnlyList<int> BitDepths);

55
ErsatzTV.FFmpeg/Capabilities/Nvidia/CudaHelper.cs

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
using System.Collections.Immutable;
using System.Globalization;
using System.Text;
using ErsatzTV.FFmpeg.Format;
@ -61,6 +62,8 @@ internal static class CudaHelper @@ -61,6 +62,8 @@ internal static class CudaHelper
}
foreach (var description in CuDevice.GetDescriptions())
{
try
{
var device = description.Device;
@ -74,20 +77,7 @@ internal static class CudaHelper @@ -74,20 +77,7 @@ internal static class CudaHelper
int major = device.GetAttribute(CuDeviceAttribute.ComputeCapabilityMajor);
int minor = device.GetAttribute(CuDeviceAttribute.ComputeCapabilityMinor);
result.Add(new CudaDevice(device.Handle, name, new Version(major, minor)));
}
return result;
}
internal static string GetDeviceDetails(CudaDevice device)
{
var sb = new StringBuilder();
try
{
var dev = CuDevice.GetDevice(device.Handle);
using var context = dev.CreateContext();
using var context = device.CreateContext();
var sessionParams = new NvEncOpenEncodeSessionExParams
{
Version = LibNvEnc.NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER,
@ -96,24 +86,34 @@ internal static class CudaHelper @@ -96,24 +86,34 @@ internal static class CudaHelper
DeviceType = NvEncDeviceType.Cuda
};
var codecs = new List<CudaCodec>();
var encoder = LibNvEnc.OpenEncoder(ref sessionParams);
try
{
sb.AppendLine(" Encoding:");
IReadOnlyList<Guid> codecGuids = encoder.GetEncodeGuids();
foreach ((string codecName, Guid codecGuid) in AllCodecs)
{
if (codecGuids.Contains(codecGuid))
{
sb.AppendLine(CultureInfo.InvariantCulture, $" - Supports {codecName} 8-bit");
IReadOnlyList<Guid> codecProfileGuids = encoder.GetEncodeProfileGuids(codecGuid);
var bitDepths = new List<int> { 8 };
var cap = new NvEncCapsParam { CapsToQuery = NvEncCaps.Support10bitEncode };
var capsVal = 0;
encoder.GetEncodeCaps(codecGuid, ref cap, ref capsVal);
if (capsVal > 0)
{
sb.AppendLine(CultureInfo.InvariantCulture, $" - Supports {codecName} 10-bit");
bitDepths.Add(10);
}
var cudaCodec = new CudaCodec(
codecName,
codecGuid,
codecProfileGuids,
bitDepths.ToImmutableList());
codecs.Add(cudaCodec);
}
}
}
@ -121,11 +121,32 @@ internal static class CudaHelper @@ -121,11 +121,32 @@ internal static class CudaHelper
{
encoder.DestroyEncoder();
}
result.Add(new CudaDevice(device.Handle, name, new Version(major, minor), codecs));
}
catch (Exception)
{
// do nothing
}
}
return result;
}
internal static string GetDeviceDetails(CudaDevice device)
{
var sb = new StringBuilder();
sb.AppendLine(" Encoding:");
foreach (CudaCodec cudaCodec in device.Codecs)
{
sb.AppendLine(CultureInfo.InvariantCulture, $" - Supports {cudaCodec.Name} 8-bit");
if (cudaCodec.BitDepths.Contains(10))
{
sb.AppendLine(CultureInfo.InvariantCulture, $" - Supports {cudaCodec.Name} 10-bit");
}
}
return sb.ToString();
}

6
ErsatzTV.FFmpeg/Capabilities/Nvidia/NvEncSharpRedirector.cs

@ -15,7 +15,7 @@ public static class NvEncSharpRedirector @@ -15,7 +15,7 @@ public static class NvEncSharpRedirector
if (libraryName.Equals("nvEncodeAPI64.dll", StringComparison.OrdinalIgnoreCase))
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return NativeLibrary.Load("libnvidia-encode.so", assembly, searchPath);
return NativeLibrary.Load("libnvidia-encode.so.1", assembly, searchPath);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return NativeLibrary.Load("nvEncodeAPI64.dll", assembly, searchPath);
}
@ -23,7 +23,7 @@ public static class NvEncSharpRedirector @@ -23,7 +23,7 @@ public static class NvEncSharpRedirector
if (libraryName.Equals("nvEncodeAPI.dll", StringComparison.OrdinalIgnoreCase))
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return NativeLibrary.Load("libnvidia-encode.so", assembly, searchPath);
return NativeLibrary.Load("libnvidia-encode.so.1", assembly, searchPath);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return NativeLibrary.Load("nvEncodeAPI.dll", assembly, searchPath);
}
@ -31,7 +31,7 @@ public static class NvEncSharpRedirector @@ -31,7 +31,7 @@ public static class NvEncSharpRedirector
if (libraryName.Equals("nvcuda.dll", StringComparison.OrdinalIgnoreCase))
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return NativeLibrary.Load("libcuda.so", assembly, searchPath);
return NativeLibrary.Load("libcuda.so.1", assembly, searchPath);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return NativeLibrary.Load("nvcuda.dll", assembly, searchPath);
}

49
ErsatzTV.FFmpeg/Capabilities/NvidiaHardwareCapabilities.cs

@ -95,35 +95,17 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities @@ -95,35 +95,17 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities
{
int bitDepth = maybePixelFormat.Map(pf => pf.BitDepth).IfNone(8);
try
{
var dev = CuDevice.GetDevice(0);
using var context = dev.CreateContext();
var sessionParams = new NvEncOpenEncodeSessionExParams
{
Version = LibNvEnc.NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER,
ApiVersion = LibNvEnc.NVENCAPI_VERSION,
Device = context.Handle,
DeviceType = NvEncDeviceType.Cuda
};
var encoder = LibNvEnc.OpenEncoder(ref sessionParams);
try
{
_logger.LogDebug(
"Checking NvEnc {Format} / {Profile} / {BitDepth}-bit",
videoFormat,
videoProfile,
bitDepth);
var codecGuid = videoFormat switch
{
VideoFormat.Hevc => NvEncCodecGuids.Hevc,
_ => NvEncCodecGuids.H264
};
var codec = _cudaDevice.Codecs.FirstOrDefault(c => c.Name.Equals(
videoFormat,
StringComparison.OrdinalIgnoreCase));
IReadOnlyList<Guid> codecGuids = encoder.GetEncodeGuids();
if (!codecGuids.Contains(codecGuid))
if (codec == null)
{
_logger.LogWarning("NvEnc {Format} is not supported; will use software encode", videoFormat);
return FFmpegCapability.Software;
@ -142,8 +124,7 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities @@ -142,8 +124,7 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities
_ => NvEncProfileGuids.H264Main
};
IReadOnlyList<Guid> profileGuids = encoder.GetEncodeProfileGuids(codecGuid);
if (!profileGuids.Contains(profileGuid))
if (!codec.ProfileGuids.Contains(profileGuid))
{
_logger.LogWarning(
"NvEnc {Format} / {Profile} is not supported; will use software encode",
@ -152,12 +133,7 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities @@ -152,12 +133,7 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities
return FFmpegCapability.Software;
}
if (bitDepth == 10)
{
var cap = new NvEncCapsParam { CapsToQuery = NvEncCaps.Support10bitEncode };
var capsVal = 0;
encoder.GetEncodeCaps(codecGuid, ref cap, ref capsVal);
if (capsVal == 0)
if (!codec.BitDepths.Contains(bitDepth))
{
_logger.LogWarning(
"NvEnc {Format} / {Profile} / {BitDepth}-bit is not supported; will use software encode",
@ -166,22 +142,9 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities @@ -166,22 +142,9 @@ public class NvidiaHardwareCapabilities : IHardwareCapabilities
bitDepth);
return FFmpegCapability.Software;
}
}
return FFmpegCapability.Hardware;
}
finally
{
encoder.DestroyEncoder();
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Unexpected error checking NvEnc capabilities; falling back to software");
}
return FFmpegCapability.Software;
}
public Option<RateControlMode> GetRateControlMode(string videoFormat, Option<IPixelFormat> maybePixelFormat) =>
Option<RateControlMode>.None;

Loading…
Cancel
Save