add nvidia av1 encoder (#2469)
This commit is contained in:
@@ -60,6 +60,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Allow HEVC playback in channel preview
|
||||
- This is restricted to compatible browsers
|
||||
- Preview button will be red when preview is disabled due to browser incompatibility
|
||||
- Add AV1 encoding support with NVIDIA acceleration
|
||||
- This also requires `HLS Segmenter (fmp4)`
|
||||
|
||||
### Fixed
|
||||
- Fix green output when libplacebo tonemapping is used with NVIDIA acceleration and 10-bit output in FFmpeg Profile
|
||||
|
||||
@@ -57,6 +57,12 @@ public class
|
||||
? FFmpegProfileBitDepth.EightBit
|
||||
: update.BitDepth;
|
||||
|
||||
if (p.HardwareAcceleration is not HardwareAccelerationKind.Nvenc &&
|
||||
p.VideoFormat is FFmpegProfileVideoFormat.Av1)
|
||||
{
|
||||
p.VideoFormat = FFmpegProfileVideoFormat.Hevc;
|
||||
}
|
||||
|
||||
p.VideoBitrate = update.VideoBitrate;
|
||||
p.VideoBufferSize = update.VideoBufferSize;
|
||||
p.TonemapAlgorithm = update.TonemapAlgorithm;
|
||||
|
||||
@@ -587,7 +587,7 @@ public class HlsSessionWorker : IHlsSessionWorker
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error transcoding channel {Channel}", _channelNumber);
|
||||
_logger.LogError(ex, "Error transcoding channel {Channel} - {Message}", _channelNumber, ex.Message);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ public enum FFmpegProfileVideoFormat
|
||||
H264 = 1,
|
||||
Hevc = 2,
|
||||
Mpeg2Video = 3,
|
||||
Av1 = 4,
|
||||
|
||||
Copy = 99
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ public static class FFmpegLibraryHelper
|
||||
{
|
||||
FFmpegProfileVideoFormat.H264 => VideoFormat.H264,
|
||||
FFmpegProfileVideoFormat.Hevc => VideoFormat.Hevc,
|
||||
FFmpegProfileVideoFormat.Av1 => VideoFormat.Av1,
|
||||
_ => VideoFormat.Mpeg2Video
|
||||
};
|
||||
|
||||
|
||||
@@ -1100,6 +1100,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
|
||||
private static string GetVideoFormat(FFmpegPlaybackSettings playbackSettings) =>
|
||||
playbackSettings.VideoFormat switch
|
||||
{
|
||||
FFmpegProfileVideoFormat.Av1 => VideoFormat.Av1,
|
||||
FFmpegProfileVideoFormat.Hevc => VideoFormat.Hevc,
|
||||
FFmpegProfileVideoFormat.H264 => VideoFormat.H264,
|
||||
FFmpegProfileVideoFormat.Mpeg2Video => VideoFormat.Mpeg2Video,
|
||||
|
||||
@@ -12,10 +12,14 @@ internal static class CudaHelper
|
||||
private static bool _initialized;
|
||||
private static readonly Lock Lock = new();
|
||||
|
||||
public static Guid Av1CodecGuid = Guid.Parse("0A352289-0AA7-4759-862D-5D15CD16D254");
|
||||
public static Guid Av1ProfileGuid = Guid.Parse("5f2a39f5-f14e-4f95-9a9e-b76d568fcf97");
|
||||
|
||||
private static readonly Dictionary<string, Guid> AllEncoders = new()
|
||||
{
|
||||
[VideoFormat.H264] = NvEncCodecGuids.H264,
|
||||
[VideoFormat.Hevc] = NvEncCodecGuids.Hevc
|
||||
[VideoFormat.Hevc] = NvEncCodecGuids.Hevc,
|
||||
[VideoFormat.Av1] = Av1CodecGuid
|
||||
};
|
||||
|
||||
private sealed record Decoder(CuVideoChromaFormat ChromaFormat, CuVideoCodec VideoCodec, int BitDepth);
|
||||
|
||||
@@ -105,6 +105,8 @@ public class NvidiaHardwareCapabilities(CudaDevice cudaDevice, IFFmpegCapabiliti
|
||||
// high10 is for libx264, nvenc needs high444
|
||||
(VideoFormat.H264, VideoProfile.High10, _) => NvEncProfileGuids.H264High444,
|
||||
|
||||
(VideoFormat.Av1, _, _) => CudaHelper.Av1ProfileGuid,
|
||||
|
||||
_ => NvEncProfileGuids.H264Main
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using ErsatzTV.FFmpeg.Format;
|
||||
|
||||
namespace ErsatzTV.FFmpeg.Encoder.Nvenc;
|
||||
|
||||
public class EncoderAv1Nvenc : EncoderBase
|
||||
{
|
||||
public override string Name => "av1_nvenc";
|
||||
public override StreamKind Kind => StreamKind.Video;
|
||||
|
||||
public override FrameState NextState(FrameState currentState) => currentState with
|
||||
{
|
||||
VideoFormat = VideoFormat.Av1
|
||||
};
|
||||
}
|
||||
@@ -74,6 +74,11 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
|
||||
encodeCapability = FFmpegCapability.Software;
|
||||
}
|
||||
|
||||
if (desiredState.VideoFormat is VideoFormat.Av1 && ffmpegState.OutputFormat is not OutputFormatKind.HlsMp4)
|
||||
{
|
||||
throw new NotSupportedException("AV1 output is only supported with HLS Segmenter (fmp4)");
|
||||
}
|
||||
|
||||
// mpeg2_cuvid seems to have issues when yadif_cuda is used, so just use software decoding
|
||||
if (context.ShouldDeinterlace && videoStream.Codec == VideoFormat.Mpeg2Video)
|
||||
{
|
||||
@@ -311,6 +316,9 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
|
||||
(HardwareAccelerationMode.Nvenc, VideoFormat.H264) =>
|
||||
new EncoderH264Nvenc(desiredState.VideoProfile, desiredState.VideoPreset),
|
||||
|
||||
(HardwareAccelerationMode.Nvenc, VideoFormat.Av1) => new EncoderAv1Nvenc(),
|
||||
(HardwareAccelerationMode.None, VideoFormat.Av1) => throw new NotSupportedException("AV1 software encoding is not supported"),
|
||||
|
||||
// don't pass NVENC profile down to libx264
|
||||
(_, _) => GetSoftwareEncoder(ffmpegState, currentState, desiredState with { VideoProfile = Option<string>.None })
|
||||
};
|
||||
|
||||
@@ -209,6 +209,7 @@
|
||||
{
|
||||
string videoCodec = profile.VideoFormat switch
|
||||
{
|
||||
FFmpegProfileVideoFormat.Av1 => "av01.0.01M.08",
|
||||
FFmpegProfileVideoFormat.Hevc => "hvc1.1.6.L93.B0",
|
||||
FFmpegProfileVideoFormat.H264 => "avc1.4D4028",
|
||||
_ => string.Empty
|
||||
|
||||
@@ -67,6 +67,10 @@
|
||||
<MudSelectItem Value="@FFmpegProfileVideoFormat.H264">h264</MudSelectItem>
|
||||
<MudSelectItem Value="@FFmpegProfileVideoFormat.Hevc">hevc</MudSelectItem>
|
||||
<MudSelectItem Value="@FFmpegProfileVideoFormat.Mpeg2Video">mpeg-2</MudSelectItem>
|
||||
@if (_model.HardwareAcceleration is HardwareAccelerationKind.Nvenc)
|
||||
{
|
||||
<MudSelectItem Value="@FFmpegProfileVideoFormat.Av1">av1</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
|
||||
@@ -18,7 +18,8 @@ public class FFmpegProfileEditViewModelValidator : AbstractValidator<FFmpegProfi
|
||||
private static readonly List<FFmpegProfileVideoFormat> NvencFormats =
|
||||
[
|
||||
FFmpegProfileVideoFormat.H264,
|
||||
FFmpegProfileVideoFormat.Hevc
|
||||
FFmpegProfileVideoFormat.Hevc,
|
||||
FFmpegProfileVideoFormat.Av1
|
||||
];
|
||||
|
||||
private static readonly List<FFmpegProfileVideoFormat> VaapiFormats =
|
||||
@@ -77,7 +78,7 @@ public class FFmpegProfileEditViewModelValidator : AbstractValidator<FFmpegProfi
|
||||
() =>
|
||||
{
|
||||
RuleFor(x => x.VideoFormat).Must(c => NvencFormats.Contains(c))
|
||||
.WithMessage("NVENC supports formats (h264, hevc)");
|
||||
.WithMessage("NVENC supports formats (h264, hevc, av1)");
|
||||
});
|
||||
|
||||
When(
|
||||
|
||||
Reference in New Issue
Block a user