Browse Source

fix recent nvidia regression (#2437)

* fix recent nvidia regression

* update transcoding tests for graphics engine
pull/2438/head
Jason Dove 4 months ago committed by GitHub
parent
commit
aa5ba5a78e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 15
      ErsatzTV.FFmpeg/OutputOption/PixelFormatOutputOption.cs
  2. 30
      ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs
  3. 44
      ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs

15
ErsatzTV.FFmpeg/OutputOption/PixelFormatOutputOption.cs

@ -2,14 +2,17 @@ @@ -2,14 +2,17 @@
namespace ErsatzTV.FFmpeg.OutputOption;
public class PixelFormatOutputOption : OutputOption
public class PixelFormatOutputOption(
IPixelFormat pixelFormat,
HardwareAccelerationMode encoderMode = HardwareAccelerationMode.None)
: OutputOption
{
private readonly IPixelFormat _pixelFormat;
public PixelFormatOutputOption(IPixelFormat pixelFormat) => _pixelFormat = pixelFormat;
public override string[] OutputOptions => ["-pix_fmt", _pixelFormat.Name];
public override string[] OutputOptions =>
[
"-pix_fmt", encoderMode is HardwareAccelerationMode.Nvenc ? pixelFormat.FFmpegName : pixelFormat.Name
];
public override FrameState NextState(FrameState currentState) =>
currentState with { PixelFormat = Some(_pixelFormat) };
currentState with { PixelFormat = Some(pixelFormat) };
}

30
ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs

@ -181,6 +181,19 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -181,6 +181,19 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
true);
currentState = filter.NextState(currentState);
videoInputFile.FilterSteps.Add(filter);
if (desiredState.BitDepth == 8)
{
var filter2 = new ScaleCudaFilter(
currentState with { PixelFormat = new PixelFormatYuv420P() },
videoStream.FrameSize,
videoStream.FrameSize,
Option<FrameSize>.None,
false,
false);
currentState = filter2.NextState(currentState);
videoInputFile.FilterSteps.Add(filter2);
}
}
}
@ -214,7 +227,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -214,7 +227,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
{
Option<IPixelFormat> desiredPixelFormat = Some((IPixelFormat)new PixelFormatYuv420P());
if (desiredPixelFormat != currentState.PixelFormat)
if (desiredPixelFormat.Map(pf => pf.FFmpegName) != currentState.PixelFormat.Map(pf => pf.FFmpegName))
{
if (currentState.FrameDataLocation == FrameDataLocation.Software)
{
@ -244,8 +257,8 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -244,8 +257,8 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
}
// need to upload for any sort of overlay
if (currentState.FrameDataLocation == FrameDataLocation.Software &&
currentState.BitDepth == 8 && !context.HasSubtitleText
if (currentState is { FrameDataLocation: FrameDataLocation.Software, BitDepth: 8 }
&& !context.HasSubtitleText
&& (context.HasSubtitleOverlay || context.HasWatermark || context.HasGraphicsEngine))
{
var hardwareUpload = new HardwareUploadCudaFilter(currentState);
@ -263,10 +276,9 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -263,10 +276,9 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
fontsFolder,
subtitleOverlayFilterSteps);
// need to use software overlay for watermark with fade points
// because `-loop 1` seems to cause a green line at the bottom of the resulting video with overlay_cuda
if (context.HasWatermark && watermarkInputFile
.Map(wm => wm.DesiredState.MaybeFadePoints.Map(fp => fp.Count > 0).IfNone(false)).IfNone(false))
// need to use software overlay with 10 bit primary content and graphics engine
if (currentState.FrameDataLocation is FrameDataLocation.Hardware && context.HasGraphicsEngine &&
currentState.BitDepth == 10)
{
var hardwareDownload = new CudaHardwareDownloadFilter(currentState.PixelFormat, None);
currentState = hardwareDownload.NextState(currentState);
@ -434,12 +446,12 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -434,12 +446,12 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
}
else
{
pipelineSteps.Add(new PixelFormatOutputOption(format));
pipelineSteps.Add(new PixelFormatOutputOption(format, ffmpegState.EncoderHardwareAccelerationMode));
}
}
else
{
pipelineSteps.Add(new PixelFormatOutputOption(format));
pipelineSteps.Add(new PixelFormatOutputOption(format, ffmpegState.EncoderHardwareAccelerationMode));
}
}

44
ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs

@ -113,16 +113,16 @@ public class TranscodingTests @@ -113,16 +113,16 @@ public class TranscodingTests
[
Watermark.None,
Watermark.PermanentOpaqueScaled,
Watermark.PermanentOpaqueActualSize,
Watermark.PermanentTransparentScaled,
Watermark.PermanentTransparentActualSize
// Watermark.PermanentOpaqueActualSize,
// Watermark.PermanentTransparentScaled,
// Watermark.PermanentTransparentActualSize
];
public static Subtitle[] Subtitles =
[
Subtitle.None,
Subtitle.Picture,
Subtitle.Text
// Subtitle.Text
];
public static Padding[] Paddings =
@ -253,6 +253,13 @@ public class TranscodingTests @@ -253,6 +253,13 @@ public class TranscodingTests
Arg.Any<Option<int>>())
.Returns(Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "song_album_cover_512.png"));
var graphicsElementLoader = Substitute.For<IGraphicsElementLoader>();
graphicsElementLoader.LoadAll(
Arg.Any<GraphicsEngineContext>(),
Arg.Any<List<PlayoutItemGraphicsElement>>(),
Arg.Any<CancellationToken>())
.Returns(callInfo => Task.FromResult(callInfo.Arg<GraphicsEngineContext>()));
var oldService = new FFmpegProcessService(
new FakeStreamSelector(),
tempFilePool,
@ -272,7 +279,7 @@ public class TranscodingTests @@ -272,7 +279,7 @@ public class TranscodingTests
LoggerFactory.CreateLogger<HardwareCapabilitiesFactory>()),
LoggerFactory.CreateLogger<PipelineBuilderFactory>()),
Substitute.For<IConfigElementRepository>(),
Substitute.For<IGraphicsElementLoader>(),
graphicsElementLoader,
LoggerFactory.CreateLogger<FFmpegLibraryProcessService>());
var songVideoGenerator = new SongVideoGenerator(tempFilePool, mockImageCache, service);
@ -362,7 +369,7 @@ public class TranscodingTests @@ -362,7 +369,7 @@ public class TranscodingTests
PlayoutItemResult playoutItemResult = await service.ForPlayoutItem(
ExecutableName("ffmpeg"),
ExecutableName("ffprobe"),
false,
true,
channel,
videoVersion,
new MediaItemAudioVersion(song, songVersion),
@ -617,7 +624,11 @@ public class TranscodingTests @@ -617,7 +624,11 @@ public class TranscodingTests
hasSubtitleFilters.ShouldBe(subtitle != Subtitle.None);
bool hasWatermarkFilters = filterChain.WatermarkOverlayFilterSteps.Any(s =>
s is OverlayWatermarkFilter or OverlayWatermarkCudaFilter or OverlayWatermarkQsvFilter);
s is OverlayWatermarkFilter or OverlayWatermarkCudaFilter
or OverlayWatermarkQsvFilter) ||
filterChain.GraphicsEngineOverlayFilterSteps.Any(s =>
s is OverlayGraphicsEngineFilter or OverlayGraphicsEngineCudaFilter
or OverlayGraphicsEngineVaapiFilter);
hasWatermarkFilters.ShouldBe(watermark != Watermark.None);
}
@ -668,7 +679,7 @@ public class TranscodingTests @@ -668,7 +679,7 @@ public class TranscodingTests
PlayoutItemResult playoutItemResult = await service.ForPlayoutItem(
ExecutableName("ffmpeg"),
ExecutableName("ffprobe"),
false,
true,
channel,
v,
new MediaItemAudioVersion(null, v),
@ -725,6 +736,7 @@ public class TranscodingTests @@ -725,6 +736,7 @@ public class TranscodingTests
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Intermittent,
Image = "ASDF",
// TODO: how do we make sure this actually appears
FrequencyMinutes = 1,
DurationSeconds = 2,
@ -735,6 +747,7 @@ public class TranscodingTests @@ -735,6 +747,7 @@ public class TranscodingTests
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Intermittent,
Image = "ASDF",
// TODO: how do we make sure this actually appears
FrequencyMinutes = 1,
DurationSeconds = 2,
@ -745,6 +758,7 @@ public class TranscodingTests @@ -745,6 +758,7 @@ public class TranscodingTests
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Image = "ASDF",
Opacity = 100,
Size = WatermarkSize.Scaled,
WidthPercent = 15
@ -754,6 +768,7 @@ public class TranscodingTests @@ -754,6 +768,7 @@ public class TranscodingTests
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Image = "ASDF",
Opacity = 100,
Size = WatermarkSize.ActualSize
};
@ -762,6 +777,7 @@ public class TranscodingTests @@ -762,6 +777,7 @@ public class TranscodingTests
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Image = "ASDF",
Opacity = 80,
Size = WatermarkSize.Scaled,
WidthPercent = 15
@ -771,6 +787,7 @@ public class TranscodingTests @@ -771,6 +787,7 @@ public class TranscodingTests
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Image = "ASDF",
Opacity = 80,
Size = WatermarkSize.ActualSize
};
@ -930,6 +947,13 @@ public class TranscodingTests @@ -930,6 +947,13 @@ public class TranscodingTests
Arg.Any<Option<int>>())
.Returns(Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "song_album_cover_512.png"));
var graphicsElementLoader = Substitute.For<IGraphicsElementLoader>();
graphicsElementLoader.LoadAll(
Arg.Any<GraphicsEngineContext>(),
Arg.Any<List<PlayoutItemGraphicsElement>>(),
Arg.Any<CancellationToken>())
.Returns(callInfo => Task.FromResult(callInfo.Arg<GraphicsEngineContext>()));
var oldService = new FFmpegProcessService(
new FakeStreamSelector(),
Substitute.For<ITempFilePool>(),
@ -949,7 +973,7 @@ public class TranscodingTests @@ -949,7 +973,7 @@ public class TranscodingTests
LoggerFactory.CreateLogger<HardwareCapabilitiesFactory>()),
LoggerFactory.CreateLogger<PipelineBuilderFactory>()),
Substitute.For<IConfigElementRepository>(),
Substitute.For<IGraphicsElementLoader>(),
graphicsElementLoader,
LoggerFactory.CreateLogger<FFmpegLibraryProcessService>());
return service;
@ -1125,5 +1149,5 @@ public class TranscodingTests @@ -1125,5 +1149,5 @@ public class TranscodingTests
private static string ExecutableName(string baseName) =>
OperatingSystem.IsWindows()
? $"{baseName}.exe"
: $"/home/jason/Downloads/ffmpeg/ffmpeg-n7.1.1-56-gc2184b65d2-linux64-gpl-7.1/bin/{baseName}";
: $"{baseName}";
}

Loading…
Cancel
Save