using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; namespace ADOFAIRenderer.Util.FFmpeg { [SuppressMessage("ReSharper", "InconsistentNaming")] public enum EncoderKind { Software, NVENC, AMF, QSV, VideoToolbox } [SuppressMessage("ReSharper", "InconsistentNaming")] internal sealed class VideoEncoder : IEquatable { // ReSharper disable MemberCanBePrivate.Global // ── H.264 ── public static readonly VideoEncoder H264_NVENC = new("h264_nvenc", Codec.H264, GPUVendor.NVIDIA, EncoderKind.NVENC); public static readonly VideoEncoder H264_QSV = new("h264_qsv", Codec.H264, GPUVendor.Intel, EncoderKind.QSV); public static readonly VideoEncoder H264_AMF = new("h264_amf", Codec.H264, GPUVendor.AMD, EncoderKind.AMF); public static readonly VideoEncoder H264_VideoToolbox = new("h264_videotoolbox", Codec.H264, GPUVendor.Apple, EncoderKind.VideoToolbox); public static readonly VideoEncoder Libx264 = new("libx264", Codec.H264, GPUVendor.Unknown, EncoderKind.Software); // ── H.265 (HEVC) ── public static readonly VideoEncoder HEVC_NVENC = new("hevc_nvenc", Codec.H265, GPUVendor.NVIDIA, EncoderKind.NVENC); public static readonly VideoEncoder HEVC_QSV = new("hevc_qsv", Codec.H265, GPUVendor.Intel, EncoderKind.QSV); public static readonly VideoEncoder HEVC_AMF = new("hevc_amf", Codec.H265, GPUVendor.AMD, EncoderKind.AMF); public static readonly VideoEncoder HEVC_VideoToolbox = new("hevc_videotoolbox", Codec.H265, GPUVendor.Apple, EncoderKind.VideoToolbox); public static readonly VideoEncoder Libx265 = new("libx265", Codec.H265, GPUVendor.Unknown, EncoderKind.Software); // ── VP9 ── public static readonly VideoEncoder VP9_NVENC = new("vp9_nvenc", Codec.VP9, GPUVendor.NVIDIA, EncoderKind.NVENC); public static readonly VideoEncoder VP9_QSV = new("vp9_qsv", Codec.VP9, GPUVendor.Intel, EncoderKind.QSV); public static readonly VideoEncoder LibvpxVP9 = new("libvpx-vp9", Codec.VP9, GPUVendor.Unknown, EncoderKind.Software); // ── AV1 ── public static readonly VideoEncoder AV1_NVENC = new("av1_nvenc", Codec.AV1, GPUVendor.NVIDIA, EncoderKind.NVENC); public static readonly VideoEncoder AV1_QSV = new("av1_qsv", Codec.AV1, GPUVendor.Intel, EncoderKind.QSV); public static readonly VideoEncoder AV1_AMF = new("av1_amf", Codec.AV1, GPUVendor.AMD, EncoderKind.AMF); public static readonly VideoEncoder LibSvtAv1 = new("libsvtav1", Codec.AV1, GPUVendor.Unknown, EncoderKind.Software); public static readonly VideoEncoder LibAomAv1 = new("libaom-av1", Codec.AV1, GPUVendor.Unknown, EncoderKind.Software); // ── VVC ── public static readonly VideoEncoder LibVvenc = new("libvvenc", Codec.VVC, GPUVendor.Unknown, EncoderKind.Software); // ReSharper restore MemberCanBePrivate.Global public static readonly IReadOnlyList All = new[] { H264_NVENC, H264_QSV, H264_AMF, H264_VideoToolbox, Libx264, HEVC_NVENC, HEVC_QSV, HEVC_AMF, HEVC_VideoToolbox, Libx265, VP9_NVENC, VP9_QSV, LibvpxVP9, AV1_NVENC, AV1_QSV, AV1_AMF, LibSvtAv1, LibAomAv1, LibVvenc }; private static readonly Dictionary ByName = All.ToDictionary(e => e.Name, StringComparer.OrdinalIgnoreCase); public string Name { get; } public Codec Codec { get; } public GPUVendor Vendor { get; } public EncoderKind Kind { get; } public bool IsHardware => Kind != EncoderKind.Software; private VideoEncoder(string name, Codec codec, GPUVendor vendor, EncoderKind kind) { Name = name; Codec = codec; Vendor = vendor; Kind = kind; } public static VideoEncoder? FromName(string name) { return string.IsNullOrEmpty(name) ? null : ByName.GetValueOrDefault(name); } public bool Equals(VideoEncoder other) { if (ReferenceEquals(null, other)) return false; return ReferenceEquals(this, other) || string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase); } public override bool Equals(object? obj) { return ReferenceEquals(this, obj) || obj is VideoEncoder other && Equals(other); } public override int GetHashCode() { return StringComparer.OrdinalIgnoreCase.GetHashCode(Name); } public static bool operator ==(VideoEncoder left, VideoEncoder right) { return Equals(left, right); } public static bool operator !=(VideoEncoder left, VideoEncoder right) { return !Equals(left, right); } public override string ToString() => Name; } }