mirror of https://github.com/ErsatzTV/ErsatzTV.git
5 changed files with 154 additions and 4 deletions
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
using ErsatzTV.FFmpeg.Format; |
||||
|
||||
namespace ErsatzTV.FFmpeg.Capabilities; |
||||
|
||||
public class AmfHardwareCapabilities : IHardwareCapabilities |
||||
{ |
||||
public bool CanDecode(string videoFormat, Option<IPixelFormat> maybePixelFormat) => false; |
||||
|
||||
public bool CanEncode(string videoFormat, Option<IPixelFormat> maybePixelFormat) |
||||
{ |
||||
int bitDepth = maybePixelFormat.Map(pf => pf.BitDepth).IfNone(8); |
||||
|
||||
return (videoFormat, bitDepth) switch |
||||
{ |
||||
// 10-bit hevc encoding is not yet supported by ffmpeg
|
||||
(VideoFormat.Hevc, 10) => false, |
||||
|
||||
// 10-bit h264 encoding is not support by any hardware
|
||||
(VideoFormat.H264, 10) => false, |
||||
|
||||
_ => true |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,108 @@
@@ -0,0 +1,108 @@
|
||||
using ErsatzTV.FFmpeg.Capabilities; |
||||
using ErsatzTV.FFmpeg.Encoder; |
||||
using ErsatzTV.FFmpeg.Encoder.Amf; |
||||
using ErsatzTV.FFmpeg.Filter; |
||||
using ErsatzTV.FFmpeg.Format; |
||||
using ErsatzTV.FFmpeg.Option; |
||||
using ErsatzTV.FFmpeg.Option.HardwareAcceleration; |
||||
using Microsoft.Extensions.Logging; |
||||
|
||||
namespace ErsatzTV.FFmpeg.Pipeline; |
||||
|
||||
public class AmfPipelineBuilder : SoftwarePipelineBuilder |
||||
{ |
||||
private readonly IHardwareCapabilities _hardwareCapabilities; |
||||
private readonly ILogger _logger; |
||||
|
||||
public AmfPipelineBuilder( |
||||
IHardwareCapabilities hardwareCapabilities, |
||||
HardwareAccelerationMode hardwareAccelerationMode, |
||||
Option<VideoInputFile> videoInputFile, |
||||
Option<AudioInputFile> audioInputFile, |
||||
Option<WatermarkInputFile> watermarkInputFile, |
||||
Option<SubtitleInputFile> subtitleInputFile, |
||||
string reportsFolder, |
||||
string fontsFolder, |
||||
ILogger logger) : base( |
||||
hardwareAccelerationMode, |
||||
videoInputFile, |
||||
audioInputFile, |
||||
watermarkInputFile, |
||||
subtitleInputFile, |
||||
reportsFolder, |
||||
fontsFolder, |
||||
logger) |
||||
{ |
||||
_hardwareCapabilities = hardwareCapabilities; |
||||
_logger = logger; |
||||
} |
||||
|
||||
protected override FFmpegState SetAccelState( |
||||
VideoStream videoStream, |
||||
FFmpegState ffmpegState, |
||||
FrameState desiredState, |
||||
PipelineContext context, |
||||
ICollection<IPipelineStep> pipelineSteps) |
||||
{ |
||||
bool canDecode = _hardwareCapabilities.CanDecode(videoStream.Codec, videoStream.PixelFormat); |
||||
bool canEncode = _hardwareCapabilities.CanEncode(desiredState.VideoFormat, desiredState.PixelFormat); |
||||
|
||||
pipelineSteps.Add(new AmfHardwareAccelerationOption()); |
||||
|
||||
// disable hw accel if decoder/encoder isn't supported
|
||||
return ffmpegState with |
||||
{ |
||||
DecoderHardwareAccelerationMode = canDecode |
||||
? HardwareAccelerationMode.Amf |
||||
: HardwareAccelerationMode.None, |
||||
EncoderHardwareAccelerationMode = canEncode |
||||
? HardwareAccelerationMode.Amf |
||||
: HardwareAccelerationMode.None |
||||
}; |
||||
} |
||||
|
||||
protected override Option<IEncoder> GetEncoder(FFmpegState ffmpegState, FrameState currentState, FrameState desiredState) |
||||
{ |
||||
return (ffmpegState.EncoderHardwareAccelerationMode, desiredState.VideoFormat) switch |
||||
{ |
||||
(HardwareAccelerationMode.Amf, VideoFormat.Hevc) => |
||||
new EncoderHevcAmf(), |
||||
(HardwareAccelerationMode.Amf, VideoFormat.H264) => |
||||
new EncoderH264Amf(), |
||||
|
||||
_ => GetSoftwareEncoder(currentState, desiredState) |
||||
}; |
||||
} |
||||
|
||||
protected override List<IPipelineFilterStep> SetPixelFormat( |
||||
VideoStream videoStream, |
||||
Option<IPixelFormat> desiredPixelFormat, |
||||
FrameState currentState, |
||||
ICollection<IPipelineStep> pipelineSteps) |
||||
{ |
||||
var result = new List<IPipelineFilterStep>(); |
||||
|
||||
foreach (IPixelFormat pixelFormat in desiredPixelFormat) |
||||
{ |
||||
if (!videoStream.ColorParams.IsBt709) |
||||
{ |
||||
_logger.LogDebug("Adding colorspace filter"); |
||||
var colorspace = new ColorspaceFilter(videoStream, pixelFormat); |
||||
currentState = colorspace.NextState(currentState); |
||||
result.Add(colorspace); |
||||
} |
||||
|
||||
if (currentState.PixelFormat.Map(f => f.FFmpegName) != pixelFormat.FFmpegName) |
||||
{ |
||||
_logger.LogDebug( |
||||
"Format {A} doesn't equal {B}", |
||||
currentState.PixelFormat.Map(f => f.FFmpegName), |
||||
pixelFormat.FFmpegName); |
||||
} |
||||
|
||||
pipelineSteps.Add(new PixelFormatOutputOption(pixelFormat)); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
} |
Loading…
Reference in new issue