work around nvidia green line (#2447)

This commit is contained in:
Jason Dove
2025-09-20 16:12:08 +00:00
committed by GitHub
parent 788a1ecdc4
commit 07a160fcc6
3 changed files with 48 additions and 1 deletions
+2 -1
View File
@@ -46,7 +46,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Text that already fits with the configured style will not be adjusted
- Block schedules: add **experimental** `Break Content` to decos
- Break content is similar to filler from classic schedules
- Break content is currently limited to placement `Break Start` (play before anything else in the block)
- Break content is currently limited to placement `Block Start` (play before anything else in the block)
- Future work will add other placement options
- Break content is currently limited to playlists (which do *not* pad - they simply play through the playlist one time)
- Future work will add other collection options which will pad to the full block duration
@@ -64,6 +64,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix deco dead air fallback selection and duration on mirror channels
- Fix fallback filler duration on mirror channels
- Fix slow startup caused by check for overlapping playout items
- Fix green line in *most* cases when overlaying content using NVIDIA acceleration
### Changed
- Filler presets: use separate text fields for `hours`, `minutes` and `seconds` duration
@@ -0,0 +1,35 @@
using ErsatzTV.FFmpeg.Format;
namespace ErsatzTV.FFmpeg.OutputOption;
public class NvidiaGreenLineWorkaroundFilter(string videoFormat, FrameSize frameSize) : OutputOption
{
public override string[] OutputOptions
{
get
{
if (videoFormat is not (VideoFormat.Hevc or VideoFormat.H264))
{
return [];
}
int cropPixels = frameSize.Height switch
{
1080 => 8,
720 => 16,
_ => 0
};
if (cropPixels == 0)
{
return [];
}
return
[
"-bsf:v",
$"{videoFormat}_metadata=crop_bottom={cropPixels}"
];
}
}
}
@@ -329,6 +329,17 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
context,
pipelineSteps);
if (ffmpegState.DecoderHardwareAccelerationMode is HardwareAccelerationMode.Nvenc &&
ffmpegState.EncoderHardwareAccelerationMode is HardwareAccelerationMode.Nvenc &&
(videoStream.FrameSize == desiredState.ScaledSize || (context is { HasSubtitleOverlay: true, HasGraphicsEngine: true } && desiredState.PaddedSize == desiredState.ScaledSize)) &&
(context.HasSubtitleOverlay || context.HasGraphicsEngine || context.HasWatermark))
{
pipelineSteps.Add(
new NvidiaGreenLineWorkaroundFilter(
desiredState.VideoFormat,
desiredState.CroppedSize.IfNone(desiredState.PaddedSize)));
}
return new FilterChain(
videoInputFile.FilterSteps,
watermarkInputFile.Map(wm => wm.FilterSteps).IfNone([]),