Browse Source

fix qsv scaling and watermarks with new transcoder (#656)

* fix qsv scaling

* fix qsv watermarks
pull/657/head
Jason Dove 4 years ago committed by GitHub
parent
commit
040785b0d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 11
      ErsatzTV.FFmpeg/Encoder/AvailableEncoders.cs
  3. 32
      ErsatzTV.FFmpeg/Encoder/Qsv/EncoderHevcQsv.cs
  4. 3
      ErsatzTV.FFmpeg/Filter/AvailableOverlayFilters.cs
  5. 14
      ErsatzTV.FFmpeg/Filter/Qsv/OverlayQsvFilter.cs
  6. 8
      ErsatzTV.FFmpeg/Filter/Qsv/ScaleQsvFilter.cs
  7. 1
      ErsatzTV.FFmpeg/Filter/WatermarkPixelFormatFilter.cs
  8. 1
      ErsatzTV.FFmpeg/PipelineBuilder.cs

1
CHANGELOG.md

@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed
- Add improved but experimental transcoder logic, which can be toggled on and off in `Settings`
- Fix `HLS Segmenter` bug when source video packet contains no duration (`N/A`)
- Fix green line at the bottom of some content scaled using QSV acceleration
### Added
- Add configurable channel group (M3U) and categories (XMLTV)

11
ErsatzTV.FFmpeg/Encoder/AvailableEncoders.cs

@ -11,13 +11,20 @@ namespace ErsatzTV.FFmpeg.Encoder; @@ -11,13 +11,20 @@ namespace ErsatzTV.FFmpeg.Encoder;
public static class AvailableEncoders
{
public static Option<IEncoder> ForVideoFormat(FFmpegState ffmpegState, FrameState currentState, FrameState desiredState, ILogger logger) =>
public static Option<IEncoder> ForVideoFormat(
FFmpegState ffmpegState,
FrameState currentState,
FrameState desiredState,
Option<WatermarkInputFile> maybeWatermarkInputFile,
ILogger logger) =>
(ffmpegState.HardwareAccelerationMode, desiredState.VideoFormat) switch
{
(HardwareAccelerationMode.Nvenc, VideoFormat.Hevc) => new EncoderHevcNvenc(),
(HardwareAccelerationMode.Nvenc, VideoFormat.H264) => new EncoderH264Nvenc(),
(HardwareAccelerationMode.Qsv, VideoFormat.Hevc) => new EncoderHevcQsv(),
(HardwareAccelerationMode.Qsv, VideoFormat.Hevc) => new EncoderHevcQsv(
currentState,
maybeWatermarkInputFile),
(HardwareAccelerationMode.Qsv, VideoFormat.H264) => new EncoderH264Qsv(currentState),
(HardwareAccelerationMode.Vaapi, VideoFormat.Hevc) => new EncoderHevcVaapi(currentState),

32
ErsatzTV.FFmpeg/Encoder/Qsv/EncoderHevcQsv.cs

@ -1,9 +1,19 @@ @@ -1,9 +1,19 @@
using ErsatzTV.FFmpeg.Format;
using LanguageExt;
namespace ErsatzTV.FFmpeg.Encoder.Qsv;
public class EncoderHevcQsv : EncoderBase
{
private readonly FrameState _currentState;
private readonly Option<WatermarkInputFile> _maybeWatermarkInputFile;
public EncoderHevcQsv(FrameState currentState, Option<WatermarkInputFile> maybeWatermarkInputFile)
{
_currentState = currentState;
_maybeWatermarkInputFile = maybeWatermarkInputFile;
}
public override FrameState NextState(FrameState currentState) => currentState with
{
VideoFormat = VideoFormat.Hevc,
@ -12,4 +22,26 @@ public class EncoderHevcQsv : EncoderBase @@ -12,4 +22,26 @@ public class EncoderHevcQsv : EncoderBase
public override string Name => "hevc_qsv";
public override StreamKind Kind => StreamKind.Video;
// need to upload if we're still in software and a watermark is used
public override string Filter
{
get
{
// only upload to hw if we need to overlay a watermark
if (_maybeWatermarkInputFile.IsSome && _currentState.FrameDataLocation == FrameDataLocation.Software)
{
// pixel format should already be converted to a supported format by QsvHardwareAccelerationOption
foreach (IPixelFormat pixelFormat in _currentState.PixelFormat)
{
return $"format={pixelFormat.FFmpegName},hwupload=extra_hw_frames=64";
}
// default to nv12
return "format=nv12,hwupload=extra_hw_frames=64";
}
return string.Empty;
}
}
}

3
ErsatzTV.FFmpeg/Filter/AvailableOverlayFilters.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using ErsatzTV.FFmpeg.Filter.Cuda;
using ErsatzTV.FFmpeg.Filter.Qsv;
using ErsatzTV.FFmpeg.State;
namespace ErsatzTV.FFmpeg.Filter;
@ -12,7 +13,7 @@ public static class AvailableOverlayFilters @@ -12,7 +13,7 @@ public static class AvailableOverlayFilters
accelMode switch
{
HardwareAccelerationMode.Nvenc => new OverlayCudaFilter(watermarkState, resolution),
// HardwareAccelerationMode.Qsv => new DeinterlaceQsvFilter(),
HardwareAccelerationMode.Qsv => new OverlayQsvFilter(watermarkState, resolution),
// HardwareAccelerationMode.Vaapi => new DeinterlaceVaapiFilter(),
_ => new OverlayFilter(watermarkState, resolution)
};

14
ErsatzTV.FFmpeg/Filter/Qsv/OverlayQsvFilter.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
using ErsatzTV.FFmpeg.State;
namespace ErsatzTV.FFmpeg.Filter.Qsv;
public class OverlayQsvFilter : OverlayFilter
{
public OverlayQsvFilter(WatermarkState watermarkState, FrameSize resolution) : base(watermarkState, resolution)
{
}
public override FrameState NextState(FrameState currentState) => currentState;
public override string Filter => $"overlay_qsv={Position}";
}

8
ErsatzTV.FFmpeg/Filter/Qsv/ScaleQsvFilter.cs

@ -17,6 +17,8 @@ public class ScaleQsvFilter : BaseFilter @@ -17,6 +17,8 @@ public class ScaleQsvFilter : BaseFilter
{
get
{
// use vpp_qsv because scale_qsv sometimes causes green lines at the bottom
string scale = string.Empty;
if (_currentState.ScaledSize == _scaledSize)
@ -24,7 +26,7 @@ public class ScaleQsvFilter : BaseFilter @@ -24,7 +26,7 @@ public class ScaleQsvFilter : BaseFilter
foreach (IPixelFormat pixelFormat in _currentState.PixelFormat)
{
// don't need scaling, but still need pixel format
scale = $"scale_qsv=format={pixelFormat.FFmpegName}";
scale = $"vpp_qsv=format={pixelFormat.FFmpegName}";
}
}
else
@ -35,8 +37,8 @@ public class ScaleQsvFilter : BaseFilter @@ -35,8 +37,8 @@ public class ScaleQsvFilter : BaseFilter
format = $":format={pixelFormat.FFmpegName}";
}
string targetSize = $"{_scaledSize.Width}:{_scaledSize.Height}";
scale = $"scale_qsv={targetSize}{format}";
string targetSize = $"w={_scaledSize.Width}:h={_scaledSize.Height}";
scale = $"vpp_qsv={targetSize}{format}";
}
if (_currentState.FrameDataLocation == FrameDataLocation.Hardware)

1
ErsatzTV.FFmpeg/Filter/WatermarkPixelFormatFilter.cs

@ -26,6 +26,7 @@ public class WatermarkPixelFormatFilter : BaseFilter @@ -26,6 +26,7 @@ public class WatermarkPixelFormatFilter : BaseFilter
Option<string> maybeFormat = _ffmpegState.HardwareAccelerationMode switch
{
HardwareAccelerationMode.Nvenc => "yuva420p",
HardwareAccelerationMode.Qsv => "yuva420p",
_ when _watermarkState.Opacity != 100 || hasFadePoints =>
"yuva420p|yuva444p|yuva422p|rgba|abgr|bgra|gbrap|ya8",
_ => None

1
ErsatzTV.FFmpeg/PipelineBuilder.cs

@ -387,6 +387,7 @@ public class PipelineBuilder @@ -387,6 +387,7 @@ public class PipelineBuilder
ffmpegState,
currentState,
desiredState,
_watermarkInputFile,
_logger))
{
encoder = e;

Loading…
Cancel
Save