using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.FFmpeg; using ErsatzTV.FFmpeg.Capabilities; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.FFmpegProfiles; public class GetSupportedHardwareAccelerationKindsHandler : IRequestHandler> { private readonly IDbContextFactory _dbContextFactory; private readonly IHardwareCapabilitiesFactory _hardwareCapabilitiesFactory; public GetSupportedHardwareAccelerationKindsHandler( IDbContextFactory dbContextFactory, IHardwareCapabilitiesFactory hardwareCapabilitiesFactory) { _dbContextFactory = dbContextFactory; _hardwareCapabilitiesFactory = hardwareCapabilitiesFactory; } public async Task> Handle( GetSupportedHardwareAccelerationKinds request, CancellationToken cancellationToken) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext); return await validation.Match( GetHardwareAccelerationKinds, _ => Task.FromResult(new List { HardwareAccelerationKind.None })); } private async Task> GetHardwareAccelerationKinds(string ffmpegPath) { var result = new List { HardwareAccelerationKind.None }; IFFmpegCapabilities ffmpegCapabilities = await _hardwareCapabilitiesFactory.GetFFmpegCapabilities(ffmpegPath); if (ffmpegCapabilities.HasHardwareAcceleration(HardwareAccelerationMode.Nvenc)) { result.Add(HardwareAccelerationKind.Nvenc); } if (ffmpegCapabilities.HasHardwareAcceleration(HardwareAccelerationMode.Qsv)) { result.Add(HardwareAccelerationKind.Qsv); } if (ffmpegCapabilities.HasHardwareAcceleration(HardwareAccelerationMode.Vaapi)) { result.Add(HardwareAccelerationKind.Vaapi); } if (ffmpegCapabilities.HasHardwareAcceleration(HardwareAccelerationMode.VideoToolbox)) { result.Add(HardwareAccelerationKind.VideoToolbox); } if (ffmpegCapabilities.HasHardwareAcceleration(HardwareAccelerationMode.Amf)) { result.Add(HardwareAccelerationKind.Amf); } return result; } private static async Task> Validate(TvContext dbContext) => await FFmpegPathMustExist(dbContext); private static Task> FFmpegPathMustExist(TvContext dbContext) => dbContext.ConfigElements.GetValue(ConfigElementKey.FFmpegPath) .FilterT(File.Exists) .Map(maybePath => maybePath.ToValidation("FFmpeg path does not exist on filesystem")); }