using ErsatzTV.FFmpeg.Decoder; using ErsatzTV.FFmpeg.Format; namespace ErsatzTV.FFmpeg.Capabilities; public class FFmpegCapabilities( string ffmpegVersion, IReadOnlySet ffmpegHardwareAccelerations, IReadOnlySet ffmpegDecoders, IReadOnlySet ffmpegFilters, IReadOnlySet ffmpegEncoders, IReadOnlySet ffmpegOptions, IReadOnlySet ffmpegDemuxFormats) : IFFmpegCapabilities { public string Version => ffmpegVersion; public bool HasHardwareAcceleration(HardwareAccelerationMode hardwareAccelerationMode) { // AMF isn't a "hwaccel" in ffmpeg, so check for presence of encoders if (hardwareAccelerationMode is HardwareAccelerationMode.Amf) { return ffmpegEncoders.Any(e => e.EndsWith( $"_{FFmpegKnownHardwareAcceleration.Amf.Name}", StringComparison.OrdinalIgnoreCase)); } // V4l2m2m isn't a "hwaccel" in ffmpeg, so check for presence of encoders if (hardwareAccelerationMode is HardwareAccelerationMode.V4l2m2m) { return ffmpegEncoders.Any(e => e.EndsWith( $"_{FFmpegKnownHardwareAcceleration.V4l2m2m.Name}", StringComparison.OrdinalIgnoreCase)); } Option maybeAccelToCheck = hardwareAccelerationMode switch { HardwareAccelerationMode.Nvenc => FFmpegKnownHardwareAcceleration.Cuda, HardwareAccelerationMode.Qsv => FFmpegKnownHardwareAcceleration.Qsv, HardwareAccelerationMode.Vaapi => FFmpegKnownHardwareAcceleration.Vaapi, HardwareAccelerationMode.VideoToolbox => FFmpegKnownHardwareAcceleration.VideoToolbox, HardwareAccelerationMode.OpenCL => FFmpegKnownHardwareAcceleration.OpenCL, HardwareAccelerationMode.Vulkan => FFmpegKnownHardwareAcceleration.Vulkan, HardwareAccelerationMode.Rkmpp => FFmpegKnownHardwareAcceleration.Rkmpp, _ => Option.None }; foreach (FFmpegKnownHardwareAcceleration accelToCheck in maybeAccelToCheck) { return ffmpegHardwareAccelerations.Contains(accelToCheck.Name); } return false; } public bool HasDecoder(FFmpegKnownDecoder decoder) => ffmpegDecoders.Contains(decoder.Name); public bool HasEncoder(FFmpegKnownEncoder encoder) => ffmpegEncoders.Contains(encoder.Name); public bool HasFilter(FFmpegKnownFilter filter) => ffmpegFilters.Contains(filter.Name); public bool HasOption(FFmpegKnownOption ffmpegOption) => ffmpegOptions.Contains(ffmpegOption.Name); public bool HasDemuxFormat(FFmpegKnownFormat format) => ffmpegDemuxFormats.Contains(format.Name); public Option SoftwareDecoderForVideoFormat(string videoFormat) => videoFormat switch { VideoFormat.Hevc => new DecoderHevc(), VideoFormat.H264 => new DecoderH264(), VideoFormat.Mpeg1Video => new DecoderMpeg1Video(), VideoFormat.Mpeg2Video => new DecoderMpeg2Video(), VideoFormat.Vc1 => new DecoderVc1(), VideoFormat.MsMpeg4V2 => new DecoderMsMpeg4V2(), VideoFormat.MsMpeg4V3 => new DecoderMsMpeg4V3(), VideoFormat.Mpeg4 => new DecoderMpeg4(), VideoFormat.Vp9 => new DecoderVp9(), VideoFormat.Av1 => new DecoderAv1(ffmpegDecoders), VideoFormat.Raw or VideoFormat.RawVideo => new DecoderRawVideo(), VideoFormat.Undetermined => new DecoderImplicit(), VideoFormat.Copy => new DecoderImplicit(), VideoFormat.GeneratedImage => new DecoderImplicit(), _ => Option.None }; }