Browse Source

change how qsv is initialized on windows (#2183)

pull/2186/head
Jason Dove 4 weeks ago committed by GitHub
parent
commit
74d6b32828
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 11
      ErsatzTV.FFmpeg/Environment/CudaVisibleDevicesVariable.cs
  2. 4
      ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOption.cs
  3. 2
      ErsatzTV.FFmpeg/InputOption/StreamSeekInputOption.cs
  4. 20
      ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs

11
ErsatzTV.FFmpeg/Environment/CudaVisibleDevicesVariable.cs

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
namespace ErsatzTV.FFmpeg.Environment;
public class CudaVisibleDevicesVariable(string visibleDevices) : IPipelineStep
{
public EnvironmentVariable[] EnvironmentVariables => [ new("CUDA_VISIBLE_DEVICES", visibleDevices) ];
public string[] GlobalOptions => [];
public string[] InputOptions(InputFile inputFile) => [];
public string[] FilterOptions => [];
public string[] OutputOptions => [];
public FrameState NextState(FrameState currentState) => currentState;
}

4
ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOption.cs

@ -16,9 +16,7 @@ public class QsvHardwareAccelerationOption(Option<string> device, FFmpegCapabili @@ -16,9 +16,7 @@ public class QsvHardwareAccelerationOption(Option<string> device, FFmpegCapabili
{
get
{
string[] initDevices = OperatingSystem.IsWindows()
? new[] { "-init_hw_device", "d3d11va=hw:,vendor=0x8086", "-filter_hw_device", "hw" }
: new[] { "-init_hw_device", "qsv=hw", "-filter_hw_device", "hw" };
string[] initDevices = ["-init_hw_device", "qsv=hw", "-filter_hw_device", "hw"];
var result = new List<string>
{

2
ErsatzTV.FFmpeg/InputOption/StreamSeekInputOption.cs

@ -15,7 +15,7 @@ public class StreamSeekInputOption : IInputOption @@ -15,7 +15,7 @@ public class StreamSeekInputOption : IInputOption
public string[] OutputOptions => Array.Empty<string>();
public FrameState NextState(FrameState currentState) => currentState;
public bool AppliesTo(AudioInputFile audioInputFile) => true;
public bool AppliesTo(AudioInputFile audioInputFile) => audioInputFile is not NullAudioInputFile;
// don't seek into a still image
public bool AppliesTo(VideoInputFile videoInputFile) => videoInputFile.VideoStreams.All(s => !s.StillImage);

20
ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs

@ -3,6 +3,7 @@ using ErsatzTV.FFmpeg.Decoder; @@ -3,6 +3,7 @@ using ErsatzTV.FFmpeg.Decoder;
using ErsatzTV.FFmpeg.Decoder.Qsv;
using ErsatzTV.FFmpeg.Encoder;
using ErsatzTV.FFmpeg.Encoder.Qsv;
using ErsatzTV.FFmpeg.Environment;
using ErsatzTV.FFmpeg.Filter;
using ErsatzTV.FFmpeg.Filter.Qsv;
using ErsatzTV.FFmpeg.Format;
@ -75,7 +76,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -75,7 +76,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
}
bool isHevcOrH264 = videoStream.Codec is /*VideoFormat.Hevc or*/ VideoFormat.H264;
bool is10Bit = videoStream.BitDepth == 10;
bool is10Bit = videoStream.PixelFormat.Map(pf => pf.BitDepth).IfNone(8) == 10;
// 10-bit hevc/h264 qsv decoders have issues, so use software
if (decodeCapability == FFmpegCapability.Hardware && isHevcOrH264 && is10Bit)
@ -89,6 +90,9 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -89,6 +90,9 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
decodeCapability = FFmpegCapability.Software;
}
// give a bogus value so no cuda devices are visible to ffmpeg
pipelineSteps.Add(new CudaVisibleDevicesVariable("999"));
pipelineSteps.Add(new QsvHardwareAccelerationOption(ffmpegState.VaapiDevice, decodeCapability));
// disable hw accel if decoder/encoder isn't supported
@ -279,8 +283,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -279,8 +283,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
IPixelFormat formatForDownload = pixelFormat;
bool usesVppQsv =
videoInputFile.FilterSteps.Any(f =>
f is QsvFormatFilter or ScaleQsvFilter or DeinterlaceQsvFilter or TonemapQsvFilter);
videoInputFile.FilterSteps.Any(f => f is QsvFormatFilter or ScaleQsvFilter or DeinterlaceQsvFilter or TonemapQsvFilter);
// if we have no filters, check whether we need to convert pixel format
// since qsv doesn't seem to like doing that at the encoder
@ -336,17 +339,20 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -336,17 +339,20 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
// force p010/nv12 if we're still in hardware
if (currentState.FrameDataLocation == FrameDataLocation.Hardware)
{
if (currentState.BitDepth is 10 && formatForDownload is not PixelFormatYuv420P10Le)
foreach (int bitDepth in currentState.PixelFormat.Map(pf => pf.BitDepth))
{
if (bitDepth is 10 && formatForDownload is not PixelFormatYuv420P10Le)
{
formatForDownload = new PixelFormatYuv420P10Le();
currentState = currentState with { PixelFormat = Some(formatForDownload) };
}
else if (currentState.BitDepth is 8 && formatForDownload is not PixelFormatNv12)
else if (bitDepth is 8 && formatForDownload is not PixelFormatNv12)
{
formatForDownload = new PixelFormatNv12(formatForDownload.Name);
currentState = currentState with { PixelFormat = Some(formatForDownload) };
}
}
}
// vpp_qsv seems to strip color info, so if we use that at all, force overriding input color info
var colorspace = new ColorspaceFilter(
@ -586,8 +592,8 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -586,8 +592,8 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
// auto_scale filter seems to muck up 10-bit software decode => hardware scale, so use software scale in that case
useSoftwareFilter = useSoftwareFilter ||
ffmpegState is { DecoderHardwareAccelerationMode: HardwareAccelerationMode.None } &&
OperatingSystem.IsWindows() && currentState.BitDepth == 10;
(ffmpegState is { DecoderHardwareAccelerationMode: HardwareAccelerationMode.None } &&
OperatingSystem.IsWindows() && currentState.BitDepth == 10);
if (currentState.ScaledSize != desiredState.ScaledSize && useSoftwareFilter)
{

Loading…
Cancel
Save