fix recent nvidia regression (#2437)
* fix recent nvidia regression * update transcoding tests for graphics engine
This commit is contained in:
@@ -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) };
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
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
|
||||
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
|
||||
PlayoutItemResult playoutItemResult = await service.ForPlayoutItem(
|
||||
ExecutableName("ffmpeg"),
|
||||
ExecutableName("ffprobe"),
|
||||
false,
|
||||
true,
|
||||
channel,
|
||||
videoVersion,
|
||||
new MediaItemAudioVersion(song, songVersion),
|
||||
@@ -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
|
||||
PlayoutItemResult playoutItemResult = await service.ForPlayoutItem(
|
||||
ExecutableName("ffmpeg"),
|
||||
ExecutableName("ffprobe"),
|
||||
false,
|
||||
true,
|
||||
channel,
|
||||
v,
|
||||
new MediaItemAudioVersion(null, v),
|
||||
@@ -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
|
||||
{
|
||||
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
|
||||
{
|
||||
ImageSource = ChannelWatermarkImageSource.Custom,
|
||||
Mode = ChannelWatermarkMode.Permanent,
|
||||
Image = "ASDF",
|
||||
Opacity = 100,
|
||||
Size = WatermarkSize.Scaled,
|
||||
WidthPercent = 15
|
||||
@@ -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
|
||||
{
|
||||
ImageSource = ChannelWatermarkImageSource.Custom,
|
||||
Mode = ChannelWatermarkMode.Permanent,
|
||||
Image = "ASDF",
|
||||
Opacity = 80,
|
||||
Size = WatermarkSize.Scaled,
|
||||
WidthPercent = 15
|
||||
@@ -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
|
||||
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
|
||||
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
|
||||
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}";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user