Files
ersatztv/ErsatzTV/Validators/FFmpegProfileEditViewModelValidator.cs
T
Jason DoveandGitHub 0489741123 add videotoolbox capabilities (#2239)
* implement videotoolbox hardware capabilities

* add videotoolbox troubleshooting info

* update changelog
2025-08-02 17:16:24 +00:00

129 lines
4.5 KiB
C#

using ErsatzTV.Core.Domain;
using ErsatzTV.FFmpeg.Format;
using ErsatzTV.ViewModels;
using FluentValidation;
using FluentValidation.Results;
namespace ErsatzTV.Validators;
public class FFmpegProfileEditViewModelValidator : AbstractValidator<FFmpegProfileEditViewModel>
{
private static readonly List<FFmpegProfileVideoFormat> QsvFormats =
[
FFmpegProfileVideoFormat.H264,
FFmpegProfileVideoFormat.Hevc,
FFmpegProfileVideoFormat.Mpeg2Video
];
private static readonly List<FFmpegProfileVideoFormat> NvencFormats =
[
FFmpegProfileVideoFormat.H264,
FFmpegProfileVideoFormat.Hevc
];
private static readonly List<FFmpegProfileVideoFormat> VaapiFormats =
[
FFmpegProfileVideoFormat.H264,
FFmpegProfileVideoFormat.Hevc,
FFmpegProfileVideoFormat.Mpeg2Video
];
private static readonly List<FFmpegProfileVideoFormat> VideoToolboxFormats =
[
FFmpegProfileVideoFormat.H264,
FFmpegProfileVideoFormat.Hevc
];
private static readonly List<FFmpegProfileVideoFormat> AmfFormats =
[
FFmpegProfileVideoFormat.H264,
FFmpegProfileVideoFormat.Hevc
];
public FFmpegProfileEditViewModelValidator()
{
RuleFor(x => x.Name).NotEmpty();
RuleFor(x => x.ThreadCount).GreaterThanOrEqualTo(0);
RuleFor(x => x.VideoFormat).NotEqual(FFmpegProfileVideoFormat.None);
RuleFor(x => x.VideoBitrate).GreaterThan(0);
RuleFor(x => x.VideoBufferSize).GreaterThan(0);
RuleFor(x => x.AudioFormat).NotEqual(FFmpegProfileAudioFormat.None);
RuleFor(x => x.AudioBitrate).GreaterThan(0);
RuleFor(x => x.AudioChannels).GreaterThan(0);
When(
x => x.HardwareAcceleration == HardwareAccelerationKind.Qsv,
() =>
{
RuleFor(x => x.VideoFormat).Must(c => QsvFormats.Contains(c))
.WithMessage("QSV supports formats (h264, hevc, mpeg2video)");
});
When(
x => x.HardwareAcceleration == HardwareAccelerationKind.Nvenc,
() =>
{
RuleFor(x => x.VideoFormat).Must(c => NvencFormats.Contains(c))
.WithMessage("NVENC supports formats (h264, hevc)");
});
When(
x => x.HardwareAcceleration == HardwareAccelerationKind.Vaapi,
() =>
{
RuleFor(x => x.VideoFormat).Must(c => VaapiFormats.Contains(c))
.WithMessage("VAAPI supports formats (h264, hevc, mpeg2video)");
});
When(
x => x.HardwareAcceleration == HardwareAccelerationKind.VideoToolbox,
() =>
{
RuleFor(x => x.VideoFormat).Must(c => VideoToolboxFormats.Contains(c))
.WithMessage("VideoToolbox supports formats (h264, hevc)");
});
When(
x => x.HardwareAcceleration == HardwareAccelerationKind.Amf,
() =>
{
RuleFor(x => x.VideoFormat).Must(c => AmfFormats.Contains(c))
.WithMessage("Amf supports formats (h264, hevc)");
});
When(
x => x.VideoFormat == FFmpegProfileVideoFormat.Mpeg2Video,
() => RuleFor(x => x.BitDepth)
.Must(bd => bd is FFmpegProfileBitDepth.EightBit)
.WithMessage("Mpeg2Video does not support 10-bit content"));
When(
x => x.VideoFormat == FFmpegProfileVideoFormat.H264 && x.BitDepth == FFmpegProfileBitDepth.TenBit,
() => RuleFor(x => x.VideoProfile)
.Must(vp => vp == VideoProfile.High10)
.WithMessage("VideoProfile must be high10 with 10-bit h264"));
When(
x => x.VideoFormat == FFmpegProfileVideoFormat.H264 && x.BitDepth == FFmpegProfileBitDepth.EightBit,
() => RuleFor(x => x.VideoProfile)
.Must(vp => vp != VideoProfile.High10)
.WithMessage("VideoProfile cannot be high10 with 8-bit h264"));
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
ValidationResult result = await ValidateAsync(
ValidationContext<FFmpegProfileEditViewModel>.CreateWithOptions(
(FFmpegProfileEditViewModel)model,
x => x.IncludeProperties(propertyName)));
if (result.IsValid)
{
return [];
}
return result.Errors.Select(e => e.ErrorMessage);
};
}