Browse Source

fix case when cuda hw decode falls back to sw

pull/2718/head
Jason Dove 8 months ago
parent
commit
920eb95e59
No known key found for this signature in database
  1. 1
      CHANGELOG.md
  2. 9
      ErsatzTV.FFmpeg/Filter/HardwareUploadCudaFilter.cs
  3. 2
      ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/CudaHardwareAccelerationOption.cs
  4. 21
      ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs

1
CHANGELOG.md

@ -53,6 +53,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Automatically kill playback troubleshooting ffmpeg process if it hasn't completed after two minutes - Automatically kill playback troubleshooting ffmpeg process if it hasn't completed after two minutes
- Fix playback of certain BT.2020 content - Fix playback of certain BT.2020 content
- Use playlist item count when using a playlist as filler (instead of a fixed count of 1 for each playlist item) - Use playlist item count when using a playlist as filler (instead of a fixed count of 1 for each playlist item)
- NVIDIA: fix stream failure with certain content that should decode in hardware but falls back to software
### Changed ### Changed
- No longer round framerate to nearest integer when normalizing framerate - No longer round framerate to nearest integer when normalizing framerate

9
ErsatzTV.FFmpeg/Filter/HardwareUploadCudaFilter.cs

@ -1,14 +1,11 @@
namespace ErsatzTV.FFmpeg.Filter; namespace ErsatzTV.FFmpeg.Filter;
public class HardwareUploadCudaFilter : BaseFilter public class HardwareUploadCudaFilter(FrameDataLocation frameDataLocation) : BaseFilter
{ {
private readonly FrameState _currentState; public override string Filter => frameDataLocation switch
public HardwareUploadCudaFilter(FrameState currentState) => _currentState = currentState;
public override string Filter => _currentState.FrameDataLocation switch
{ {
FrameDataLocation.Hardware => string.Empty, FrameDataLocation.Hardware => string.Empty,
FrameDataLocation.Unknown => "hwupload",
_ => "hwupload_cuda" _ => "hwupload_cuda"
}; };

2
ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/CudaHardwareAccelerationOption.cs

@ -11,7 +11,7 @@ public class CudaHardwareAccelerationOption(bool isVulkanHdr) : GlobalOption
return ["-init_hw_device", "cuda=nv", "-init_hw_device", "vulkan=vk@nv", "-hwaccel", "vulkan"]; return ["-init_hw_device", "cuda=nv", "-init_hw_device", "vulkan=vk@nv", "-hwaccel", "vulkan"];
} }
return ["-hwaccel", "cuda"]; return ["-init_hw_device", "cuda", "-hwaccel", "cuda"];
} }
} }
} }

21
ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs

@ -134,6 +134,12 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
foreach (IDecoder decoder in maybeDecoder) foreach (IDecoder decoder in maybeDecoder)
{ {
videoInputFile.AddOption(decoder); videoInputFile.AddOption(decoder);
if (ffmpegState.DecoderHardwareAccelerationMode is HardwareAccelerationMode.Nvenc)
{
videoInputFile.FilterSteps.Add(new HardwareUploadCudaFilter(FrameDataLocation.Unknown));
}
return Some(decoder); return Some(decoder);
} }
@ -266,7 +272,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
&& !context.HasSubtitleText && !context.HasSubtitleText
&& (context.HasSubtitleOverlay || context.HasWatermark || context.HasGraphicsEngine)) && (context.HasSubtitleOverlay || context.HasWatermark || context.HasGraphicsEngine))
{ {
var hardwareUpload = new HardwareUploadCudaFilter(currentState); var hardwareUpload = new HardwareUploadCudaFilter(currentState.FrameDataLocation);
currentState = hardwareUpload.NextState(currentState); currentState = hardwareUpload.NextState(currentState);
videoInputFile.FilterSteps.Add(hardwareUpload); videoInputFile.FilterSteps.Add(hardwareUpload);
} }
@ -562,7 +568,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
else else
{ {
watermark.FilterSteps.Add( watermark.FilterSteps.Add(
new HardwareUploadCudaFilter(currentState with { FrameDataLocation = FrameDataLocation.Software })); new HardwareUploadCudaFilter(FrameDataLocation.Software));
var watermarkFilter = new OverlayWatermarkCudaFilter( var watermarkFilter = new OverlayWatermarkCudaFilter(
watermark.DesiredState, watermark.DesiredState,
@ -612,7 +618,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
if (context.HasWatermark || context.HasGraphicsEngine) if (context.HasWatermark || context.HasGraphicsEngine)
{ {
var subtitleHardwareUpload = new HardwareUploadCudaFilter(currentState); var subtitleHardwareUpload = new HardwareUploadCudaFilter(currentState.FrameDataLocation);
currentState = subtitleHardwareUpload.NextState(currentState); currentState = subtitleHardwareUpload.NextState(currentState);
videoInputFile.FilterSteps.Add(subtitleHardwareUpload); videoInputFile.FilterSteps.Add(subtitleHardwareUpload);
} }
@ -626,8 +632,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
{ {
if (_ffmpegCapabilities.HasFilter(FFmpegKnownFilter.ScaleNpp)) if (_ffmpegCapabilities.HasFilter(FFmpegKnownFilter.ScaleNpp))
{ {
var subtitleHardwareUpload = new HardwareUploadCudaFilter( var subtitleHardwareUpload = new HardwareUploadCudaFilter(FrameDataLocation.Software);
currentState with { FrameDataLocation = FrameDataLocation.Software });
subtitle.FilterSteps.Add(subtitleHardwareUpload); subtitle.FilterSteps.Add(subtitleHardwareUpload);
// only scale if scaling or padding was used for main video stream // only scale if scaling or padding was used for main video stream
@ -648,8 +653,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
subtitle.FilterSteps.Add(scaleFilter); subtitle.FilterSteps.Add(scaleFilter);
} }
var subtitleHardwareUpload = new HardwareUploadCudaFilter( var subtitleHardwareUpload = new HardwareUploadCudaFilter(FrameDataLocation.Software);
currentState with { FrameDataLocation = FrameDataLocation.Software });
subtitle.FilterSteps.Add(subtitleHardwareUpload); subtitle.FilterSteps.Add(subtitleHardwareUpload);
} }
@ -700,8 +704,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
{ {
graphicsEngine.FilterSteps.Add(new PixelFormatFilter(new PixelFormatYuva420P())); graphicsEngine.FilterSteps.Add(new PixelFormatFilter(new PixelFormatYuva420P()));
graphicsEngine.FilterSteps.Add( graphicsEngine.FilterSteps.Add(new HardwareUploadCudaFilter(FrameDataLocation.Software));
new HardwareUploadCudaFilter(currentState with { FrameDataLocation = FrameDataLocation.Software }));
var graphicsEngineFilter = new OverlayGraphicsEngineCudaFilter(); var graphicsEngineFilter = new OverlayGraphicsEngineCudaFilter();
graphicsEngineOverlayFilterSteps.Add(graphicsEngineFilter); graphicsEngineOverlayFilterSteps.Add(graphicsEngineFilter);

Loading…
Cancel
Save