|
|
@ -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) |
|
|
|
{ |
|
|
|
{ |
|
|
|