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 @@
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
{ {
get get
{ {
string[] initDevices = OperatingSystem.IsWindows() string[] initDevices = ["-init_hw_device", "qsv=hw", "-filter_hw_device", "hw"];
? new[] { "-init_hw_device", "d3d11va=hw:,vendor=0x8086", "-filter_hw_device", "hw" }
: new[] { "-init_hw_device", "qsv=hw", "-filter_hw_device", "hw" };
var result = new List<string> var result = new List<string>
{ {

2
ErsatzTV.FFmpeg/InputOption/StreamSeekInputOption.cs

@ -15,7 +15,7 @@ public class StreamSeekInputOption : IInputOption
public string[] OutputOptions => Array.Empty<string>(); public string[] OutputOptions => Array.Empty<string>();
public FrameState NextState(FrameState currentState) => currentState; 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 // don't seek into a still image
public bool AppliesTo(VideoInputFile videoInputFile) => videoInputFile.VideoStreams.All(s => !s.StillImage); 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;
using ErsatzTV.FFmpeg.Decoder.Qsv; using ErsatzTV.FFmpeg.Decoder.Qsv;
using ErsatzTV.FFmpeg.Encoder; using ErsatzTV.FFmpeg.Encoder;
using ErsatzTV.FFmpeg.Encoder.Qsv; using ErsatzTV.FFmpeg.Encoder.Qsv;
using ErsatzTV.FFmpeg.Environment;
using ErsatzTV.FFmpeg.Filter; using ErsatzTV.FFmpeg.Filter;
using ErsatzTV.FFmpeg.Filter.Qsv; using ErsatzTV.FFmpeg.Filter.Qsv;
using ErsatzTV.FFmpeg.Format; using ErsatzTV.FFmpeg.Format;
@ -75,7 +76,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
} }
bool isHevcOrH264 = videoStream.Codec is /*VideoFormat.Hevc or*/ VideoFormat.H264; 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 // 10-bit hevc/h264 qsv decoders have issues, so use software
if (decodeCapability == FFmpegCapability.Hardware && isHevcOrH264 && is10Bit) if (decodeCapability == FFmpegCapability.Hardware && isHevcOrH264 && is10Bit)
@ -89,6 +90,9 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
decodeCapability = FFmpegCapability.Software; 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)); pipelineSteps.Add(new QsvHardwareAccelerationOption(ffmpegState.VaapiDevice, decodeCapability));
// disable hw accel if decoder/encoder isn't supported // disable hw accel if decoder/encoder isn't supported
@ -279,8 +283,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
IPixelFormat formatForDownload = pixelFormat; IPixelFormat formatForDownload = pixelFormat;
bool usesVppQsv = bool usesVppQsv =
videoInputFile.FilterSteps.Any(f => videoInputFile.FilterSteps.Any(f => f is QsvFormatFilter or ScaleQsvFilter or DeinterlaceQsvFilter or TonemapQsvFilter);
f is QsvFormatFilter or ScaleQsvFilter or DeinterlaceQsvFilter or TonemapQsvFilter);
// if we have no filters, check whether we need to convert pixel format // 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 // since qsv doesn't seem to like doing that at the encoder
@ -336,17 +339,20 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
// force p010/nv12 if we're still in hardware // force p010/nv12 if we're still in hardware
if (currentState.FrameDataLocation == FrameDataLocation.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(); formatForDownload = new PixelFormatYuv420P10Le();
currentState = currentState with { PixelFormat = Some(formatForDownload) }; 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); formatForDownload = new PixelFormatNv12(formatForDownload.Name);
currentState = currentState with { PixelFormat = Some(formatForDownload) }; 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 // vpp_qsv seems to strip color info, so if we use that at all, force overriding input color info
var colorspace = new ColorspaceFilter( var colorspace = new ColorspaceFilter(
@ -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 // auto_scale filter seems to muck up 10-bit software decode => hardware scale, so use software scale in that case
useSoftwareFilter = useSoftwareFilter || useSoftwareFilter = useSoftwareFilter ||
ffmpegState is { DecoderHardwareAccelerationMode: HardwareAccelerationMode.None } && (ffmpegState is { DecoderHardwareAccelerationMode: HardwareAccelerationMode.None } &&
OperatingSystem.IsWindows() && currentState.BitDepth == 10; OperatingSystem.IsWindows() && currentState.BitDepth == 10);
if (currentState.ScaledSize != desiredState.ScaledSize && useSoftwareFilter) if (currentState.ScaledSize != desiredState.ScaledSize && useSoftwareFilter)
{ {

Loading…
Cancel
Save