diff --git a/ErsatzTV.FFmpeg/OutputOption/AmdCropMetadataWorkaroundFilter.cs b/ErsatzTV.FFmpeg/OutputOption/AmdCropMetadataWorkaroundFilter.cs new file mode 100644 index 000000000..96de6b5f6 --- /dev/null +++ b/ErsatzTV.FFmpeg/OutputOption/AmdCropMetadataWorkaroundFilter.cs @@ -0,0 +1,34 @@ +using ErsatzTV.FFmpeg.Format; + +namespace ErsatzTV.FFmpeg.OutputOption; + +public class AmdCropMetadataWorkaroundFilter(string videoFormat, FrameSize frameSize) : OutputOption +{ + public override string[] OutputOptions + { + get + { + if (videoFormat is not VideoFormat.Hevc) + { + return []; + } + + int cropPixels = frameSize.Height switch + { + 1080 => 8, + _ => 0 + }; + + if (cropPixels == 0) + { + return []; + } + + return + [ + "-bsf:v", + $"{videoFormat}_metadata=crop_bottom={cropPixels}" + ]; + } + } +} diff --git a/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs b/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs index 562240754..0d76611c0 100644 --- a/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs @@ -283,6 +283,14 @@ public class VaapiPipelineBuilder : SoftwarePipelineBuilder currentState, pipelineSteps); + if (ffmpegState.VaapiDriver == "radeonsi") + { + pipelineSteps.Add( + new AmdCropMetadataWorkaroundFilter( + desiredState.VideoFormat, + desiredState.CroppedSize.IfNone(desiredState.PaddedSize))); + } + return new FilterChain( videoInputFile.FilterSteps, watermarkInputFile.Map(wm => wm.FilterSteps).IfNone([]),