Browse Source

fix nvidia watermark (#660)

* add watermark transcoding tests

* nvidia fixes

* update changelog
pull/661/head
Jason Dove 4 years ago committed by GitHub
parent
commit
6b0ced6be9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 6
      ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
  3. 78
      ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs
  4. BIN
      ErsatzTV.Core.Tests/Resources/ErsatzTV.png
  5. 9
      ErsatzTV.FFmpeg/Decoder/AvailableDecoders.cs
  6. 10
      ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderMpeg2Cuvid.cs
  7. 5
      ErsatzTV.FFmpeg/PipelineBuilder.cs

2
CHANGELOG.md

@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Fix song sorting with `Chronological` and `Shuffle In Order` playback orders
- Fix watermark on scaled and/or padded video with NVIDIA acceleration
- Fix playback of interlaced mpeg2video content with NVIDIA acceleration
## [0.4.2-alpha] - 2022-02-26
### Fixed

6
ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj

@ -29,4 +29,10 @@ @@ -29,4 +29,10 @@
<ProjectReference Include="..\ErsatzTV.Core\ErsatzTV.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="Resources\ErsatzTV.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

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

@ -47,8 +47,25 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -47,8 +47,25 @@ namespace ErsatzTV.Core.Tests.FFmpeg
WithPadding
}
public enum Watermark
{
None,
PermanentOpaque,
PermanentTransparent,
IntermittentOpaque,
IntermittentTransparent
// TODO: animated vs static
}
private class TestData
{
public static Watermark[] Watermarks =
{
Watermark.None,
Watermark.PermanentOpaque,
Watermark.PermanentTransparent
};
public static Padding[] Paddings =
{
Padding.NoPadding,
@ -160,6 +177,8 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -160,6 +177,8 @@ namespace ErsatzTV.Core.Tests.FFmpeg
Padding padding,
[ValueSource(typeof(TestData), nameof(TestData.VideoScanKinds))]
VideoScanKind videoScanKind,
[ValueSource(typeof(TestData), nameof(TestData.Watermarks))]
Watermark watermark,
// [ValueSource(typeof(TestData), nameof(TestData.SoftwareCodecs))] string profileCodec,
// [ValueSource(typeof(TestData), nameof(TestData.NoAcceleration))] HardwareAccelerationKind profileAcceleration)
[ValueSource(typeof(TestData), nameof(TestData.NvidiaCodecs))] string profileCodec,
@ -209,10 +228,20 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -209,10 +228,20 @@ namespace ErsatzTV.Core.Tests.FFmpeg
p1.ExitCode.Should().Be(0);
}
var imageCache = new Mock<IImageCache>();
// always return the static watermark resource
imageCache.Setup(
ic => ic.GetPathForImage(
It.IsAny<string>(),
It.Is<ArtworkKind>(x => x == ArtworkKind.Watermark),
It.IsAny<Option<int>>()))
.Returns(Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "ErsatzTV.png"));
var oldService = new FFmpegProcessService(
new FFmpegPlaybackSettingsCalculator(),
new FakeStreamSelector(),
new Mock<IImageCache>().Object,
imageCache.Object,
new Mock<ITempFilePool>().Object,
new Mock<ILogger<FFmpegProcessService>>().Object);
@ -262,6 +291,51 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -262,6 +291,51 @@ namespace ErsatzTV.Core.Tests.FFmpeg
DateTimeOffset now = DateTimeOffset.Now;
Option<ChannelWatermark> channelWatermark = Option<ChannelWatermark>.None;
switch (watermark)
{
case Watermark.None:
break;
case Watermark.IntermittentOpaque:
channelWatermark = new ChannelWatermark
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Intermittent,
// TODO: how do we make sure this actually appears
FrequencyMinutes = 1,
DurationSeconds = 2,
Opacity = 100
};
break;
case Watermark.IntermittentTransparent:
channelWatermark = new ChannelWatermark
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Intermittent,
// TODO: how do we make sure this actually appears
FrequencyMinutes = 1,
DurationSeconds = 2,
Opacity = 80
};
break;
case Watermark.PermanentOpaque:
channelWatermark = new ChannelWatermark
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Opacity = 100
};
break;
case Watermark.PermanentTransparent:
channelWatermark = new ChannelWatermark
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Opacity = 80
};
break;
}
Process process = await service.ForPlayoutItem(
"ffmpeg",
false,
@ -283,7 +357,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg @@ -283,7 +357,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg
now,
now + TimeSpan.FromSeconds(5),
now,
None,
channelWatermark,
VaapiDriver.Default,
"/dev/dri/renderD128",
false,

BIN
ErsatzTV.Core.Tests/Resources/ErsatzTV.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

9
ErsatzTV.FFmpeg/Decoder/AvailableDecoders.cs

@ -8,7 +8,11 @@ namespace ErsatzTV.FFmpeg.Decoder; @@ -8,7 +8,11 @@ namespace ErsatzTV.FFmpeg.Decoder;
public static class AvailableDecoders
{
public static Option<IDecoder> ForVideoFormat(FFmpegState ffmpegState, FrameState currentState, ILogger logger)
public static Option<IDecoder> ForVideoFormat(
FFmpegState ffmpegState,
FrameState currentState,
FrameState desiredState,
ILogger logger)
{
return (ffmpegState.HardwareAccelerationMode, currentState.VideoFormat,
currentState.PixelFormat.Match(pf => pf.Name, () => string.Empty)) switch
@ -20,7 +24,8 @@ public static class AvailableDecoders @@ -20,7 +24,8 @@ public static class AvailableDecoders
=> new DecoderH264(),
(HardwareAccelerationMode.Nvenc, VideoFormat.H264, _) => new DecoderH264Cuvid(),
(HardwareAccelerationMode.Nvenc, VideoFormat.Mpeg2Video, _) => new DecoderMpeg2Cuvid(),
(HardwareAccelerationMode.Nvenc, VideoFormat.Mpeg2Video, _) => new DecoderMpeg2Cuvid(
desiredState.Deinterlaced),
(HardwareAccelerationMode.Nvenc, VideoFormat.Vc1, _) => new DecoderVc1Cuvid(),
(HardwareAccelerationMode.Nvenc, VideoFormat.Vp9, _) => new DecoderVp9Cuvid(),
(HardwareAccelerationMode.Nvenc, VideoFormat.Mpeg4, _) => new DecoderMpeg4Cuvid(),

10
ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderMpeg2Cuvid.cs

@ -2,6 +2,13 @@ @@ -2,6 +2,13 @@
public class DecoderMpeg2Cuvid : DecoderBase
{
private readonly bool _contentIsInterlaced;
public DecoderMpeg2Cuvid(bool contentIsInterlaced)
{
_contentIsInterlaced = contentIsInterlaced;
}
public override string Name => "mpeg2_cuvid";
public override IList<string> InputOptions(InputFile inputFile)
{
@ -13,5 +20,6 @@ public class DecoderMpeg2Cuvid : DecoderBase @@ -13,5 +20,6 @@ public class DecoderMpeg2Cuvid : DecoderBase
return result;
}
protected override FrameDataLocation OutputFrameDataLocation => FrameDataLocation.Hardware;
protected override FrameDataLocation OutputFrameDataLocation =>
_contentIsInterlaced ? FrameDataLocation.Software : FrameDataLocation.Hardware;
}

5
ErsatzTV.FFmpeg/PipelineBuilder.cs

@ -180,7 +180,7 @@ public class PipelineBuilder @@ -180,7 +180,7 @@ public class PipelineBuilder
_pipelineSteps.Add(step);
}
foreach (IDecoder decoder in AvailableDecoders.ForVideoFormat(ffmpegState, currentState, _logger))
foreach (IDecoder decoder in AvailableDecoders.ForVideoFormat(ffmpegState, currentState, desiredState, _logger))
{
foreach (VideoInputFile videoInputFile in _videoInputFile)
{
@ -327,7 +327,8 @@ public class PipelineBuilder @@ -327,7 +327,8 @@ public class PipelineBuilder
currentState = sarStep.NextState(currentState);
_videoInputFile.Iter(f => f.FilterSteps.Add(sarStep));
}
else if (_watermarkInputFile.IsSome && currentState.PixelFormat != desiredState.PixelFormat)
if (_watermarkInputFile.IsSome && currentState.PixelFormat != desiredState.PixelFormat)
{
// this should only happen with nvenc?
// use scale filter to fix pixel format

Loading…
Cancel
Save