Browse Source

nvidia transcoding improvements (#412)

* nvidia transcoding fixes

* use yadif_cuda to deinterlace
pull/413/head
Jason Dove 5 years ago committed by GitHub
parent
commit
6ba9404752
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      CHANGELOG.md
  2. 27
      ErsatzTV.Core.Tests/FFmpeg/FFmpegComplexFilterBuilderTests.cs
  3. 7
      ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs
  4. 8
      ErsatzTV.Core/FFmpeg/FFmpegComplexFilterBuilder.cs
  5. 11
      ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs
  6. 2
      ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs
  7. 2
      docker/nvidia/ffmpeg.Dockerfile

6
CHANGELOG.md

@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Added
- Include more cuda (nvidia) filters in docker image
- Enable deinterlacing with nvidia using new `yadif_cuda` filter
### Fixed
- Fix some transcoding edge cases with nvidia and pixel format `yuv420p10le`
## [0.1.1-alpha] - 2021-10-10
### Added

27
ErsatzTV.Core.Tests/FFmpeg/FFmpegComplexFilterBuilderTests.cs

@ -341,43 +341,24 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -341,43 +341,24 @@ namespace ErsatzTV.Core.Tests.FFmpeg
}
[Test]
// TODO: get yadif_cuda working in docker
// [TestCase(true, false, false, "[0:V]yadif_cuda[v]", "[v]")]
// [TestCase(
// true,
// true,
// false,
// "[0:V]yadif_cuda,scale_npp=1920:1000:format=yuv420p,hwdownload,setsar=1,hwupload[v]",
// "[v]")]
// [TestCase(
// true,
// false,
// true,
// "[0:V]yadif_cuda,hwdownload,setsar=1,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,hwupload[v]",
// "[v]")]
// [TestCase(
// true,
// true,
// true,
// "[0:V]yadif_cuda,scale_npp=1920:1000:format=yuv420p,hwdownload,setsar=1,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,hwupload[v]",
// "[v]")]
[TestCase(true, false, false, "[0:0]yadif_cuda[v]", "[v]")]
[TestCase(
true,
true,
false,
"[0:0]scale_npp=1920:1000,hwdownload,format=nv12,setsar=1,hwupload[v]",
"[0:0]yadif_cuda,scale_npp=1920:1000,hwdownload,format=nv12,setsar=1,hwupload[v]",
"[v]")]
[TestCase(
true,
false,
true,
"[0:0]hwdownload,format=nv12,setsar=1,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,hwupload[v]",
"[0:0]yadif_cuda,hwdownload,format=nv12,setsar=1,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,hwupload[v]",
"[v]")]
[TestCase(
true,
true,
true,
"[0:0]scale_npp=1920:1000,hwdownload,format=nv12,setsar=1,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,hwupload[v]",
"[0:0]yadif_cuda,scale_npp=1920:1000,hwdownload,format=nv12,setsar=1,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,hwupload[v]",
"[v]")]
[TestCase(
false,

7
ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs

@ -205,9 +205,9 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -205,9 +205,9 @@ namespace ErsatzTV.Core.Tests.FFmpeg
if (profileAcceleration != HardwareAccelerationKind.None && unsupportedMessages.Any(error.Contains))
{
IEnumerable<string> quotedArgs = process.StartInfo.ArgumentList.Map(a => $"\'{a}\'");
var quotedArgs = process.StartInfo.ArgumentList.Map(a => $"\'{a}\'").ToList();
process.ExitCode.Should().Be(1, $"Error message with successful exit code? {string.Join(" ", quotedArgs)}");
Assert.Warn("Unsupported on this hardware");
Assert.Warn($"Unsupported on this hardware: ffmpeg {string.Join(" ", quotedArgs)}");
}
else if (error.Contains("Impossible to convert between"))
{
@ -216,7 +216,8 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -216,7 +216,8 @@ namespace ErsatzTV.Core.Tests.FFmpeg
}
else
{
process.ExitCode.Should().Be(0, error);
IEnumerable<string> quotedArgs = process.StartInfo.ArgumentList.Map(a => $"\'{a}\'");
process.ExitCode.Should().Be(0, error + Environment.NewLine + string.Join(" ", quotedArgs));
}
}

8
ErsatzTV.Core/FFmpeg/FFmpegComplexFilterBuilder.cs

@ -125,7 +125,7 @@ namespace ErsatzTV.Core.FFmpeg @@ -125,7 +125,7 @@ namespace ErsatzTV.Core.FFmpeg
string filter = acceleration switch
{
HardwareAccelerationKind.Qsv => "deinterlace_qsv",
HardwareAccelerationKind.Nvenc => "", // TODO: yadif_cuda support in docker
HardwareAccelerationKind.Nvenc => "yadif_cuda",
HardwareAccelerationKind.Vaapi => "deinterlace_vaapi",
_ => "yadif=1"
};
@ -156,8 +156,8 @@ namespace ErsatzTV.Core.FFmpeg @@ -156,8 +156,8 @@ namespace ErsatzTV.Core.FFmpeg
string filter = acceleration switch
{
HardwareAccelerationKind.Qsv => $"scale_qsv=w={size.Width}:h={size.Height}",
HardwareAccelerationKind.Nvenc when _pixelFormat == "yuv420p10le" =>
$"hwdownload,format=p010le,format=nv12,hwupload,scale_npp={size.Width}:{size.Height}",
HardwareAccelerationKind.Nvenc when _pixelFormat is "yuv420p10le" =>
$"hwupload_cuda,scale_cuda={size.Width}:{size.Height}",
HardwareAccelerationKind.Nvenc => $"scale_npp={size.Width}:{size.Height}",
HardwareAccelerationKind.Vaapi => $"scale_vaapi=format=nv12:w={size.Width}:h={size.Height}",
_ => $"scale={size.Width}:{size.Height}:flags=fast_bilinear"
@ -180,7 +180,7 @@ namespace ErsatzTV.Core.FFmpeg @@ -180,7 +180,7 @@ namespace ErsatzTV.Core.FFmpeg
string format = acceleration switch
{
HardwareAccelerationKind.Vaapi => "format=nv12|vaapi",
HardwareAccelerationKind.Nvenc when _scaleToSize.IsNone && _pixelFormat == "yuv420p10le" =>
HardwareAccelerationKind.Nvenc when _pixelFormat == "yuv420p10le" =>
"format=p010le,format=nv12",
_ => "format=nv12"
};

11
ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs

@ -72,7 +72,7 @@ namespace ErsatzTV.Core.FFmpeg @@ -72,7 +72,7 @@ namespace ErsatzTV.Core.FFmpeg
return this;
}
public FFmpegProcessBuilder WithHardwareAcceleration(HardwareAccelerationKind hwAccel)
public FFmpegProcessBuilder WithHardwareAcceleration(HardwareAccelerationKind hwAccel, string pixelFormat)
{
_hwAccel = hwAccel;
@ -85,10 +85,17 @@ namespace ErsatzTV.Core.FFmpeg @@ -85,10 +85,17 @@ namespace ErsatzTV.Core.FFmpeg
_arguments.Add("qsv=qsv:MFX_IMPL_hw_any");
break;
case HardwareAccelerationKind.Nvenc:
string outputFormat = pixelFormat switch
{
"yuv420p10le" => "p010le",
// "yuv444p10le" => "p016le",
_ => "cuda"
};
_arguments.Add("-hwaccel");
_arguments.Add("cuda");
_arguments.Add("-hwaccel_output_format");
_arguments.Add("cuda");
_arguments.Add(outputFormat);
break;
case HardwareAccelerationKind.Vaapi:
_arguments.Add("-hwaccel");

2
ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs

@ -64,7 +64,7 @@ namespace ErsatzTV.Core.FFmpeg @@ -64,7 +64,7 @@ namespace ErsatzTV.Core.FFmpeg
FFmpegProcessBuilder builder = new FFmpegProcessBuilder(ffmpegPath, saveReports, _logger)
.WithThreads(playbackSettings.ThreadCount)
.WithHardwareAcceleration(playbackSettings.HardwareAcceleration)
.WithHardwareAcceleration(playbackSettings.HardwareAcceleration, videoStream.PixelFormat)
.WithVaapiDriver(maybeVaapiDriver)
.WithQuiet()
.WithFormatFlags(playbackSettings.FormatFlags)

2
docker/nvidia/ffmpeg.Dockerfile

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
FROM mcr.microsoft.com/dotnet/aspnet:5.0-focal-amd64 AS dotnet-runtime
FROM jrottenberg/ffmpeg:4.3-nvidia2004 AS runtime-base
FROM jasongdove/ffmpeg-base:4.3-nvidia2004 AS runtime-base
COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet
RUN apt-get update \
&& DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata \

Loading…
Cancel
Save