Stream custom live channels using your own media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.8 KiB

using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using ErsatzTV.FFmpeg.Capabilities.VideoToolbox;
using ErsatzTV.FFmpeg.Format;
using Microsoft.Extensions.Logging;
namespace ErsatzTV.FFmpeg.Capabilities;
public class VideoToolboxHardwareCapabilities : IHardwareCapabilities
{
private static readonly ConcurrentDictionary<string, bool> Encoders = new ();
private static readonly ConcurrentDictionary<string, bool> Decoders = new ();
private readonly IFFmpegCapabilities _ffmpegCapabilities;
private readonly ILogger _logger;
public VideoToolboxHardwareCapabilities(IFFmpegCapabilities ffmpegCapabilities, ILogger logger)
{
_ffmpegCapabilities = ffmpegCapabilities;
_logger = logger;
}
public FFmpegCapability CanDecode(string videoFormat, Option<string> videoProfile, Option<IPixelFormat> maybePixelFormat, bool isHdr)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && Decoders.IsEmpty)
{
if (VideoToolboxUtil.IsHardwareDecoderSupported(FourCC.H264, _logger))
{
Decoders.AddOrUpdate(VideoFormat.H264, true, (_, _) => true);
}
if (VideoToolboxUtil.IsHardwareDecoderSupported(FourCC.Hevc, _logger))
{
Decoders.AddOrUpdate(VideoFormat.Hevc, true, (_, _) => true);
}
if (VideoToolboxUtil.IsHardwareDecoderSupported(FourCC.Vp9, _logger))
{
Decoders.AddOrUpdate(VideoFormat.Vp9, true, (_, _) => true);
}
}
int bitDepth = maybePixelFormat.Map(pf => pf.BitDepth).IfNone(8);
return (videoFormat, bitDepth) switch
{
// 10-bit h264 decoding is likely not support by any hardware
(VideoFormat.H264, 10) => FFmpegCapability.Software,
_ => Decoders.ContainsKey(videoFormat) ? FFmpegCapability.Hardware : FFmpegCapability.Software
};
}
public FFmpegCapability CanEncode(string videoFormat, Option<string> videoProfile, Option<IPixelFormat> maybePixelFormat)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && Encoders.IsEmpty)
{
var encoderList = VideoToolboxUtil.GetAvailableEncoders(_logger);
_logger.LogDebug("VideoToolbox reports {Count} encoders", encoderList.Count);
// we only really care about h264 and hevc hardware encoders
foreach (var encoder in encoderList)
{
if (encoder.Contains("HEVC (HW)", StringComparison.OrdinalIgnoreCase))
{
Encoders.AddOrUpdate(VideoFormat.Hevc, true, (_, _) => true);
}
if (encoder.Contains("H.264 (HW)", StringComparison.OrdinalIgnoreCase))
{
Encoders.AddOrUpdate(VideoFormat.H264, true, (_, _) => true);
}
}
}
int bitDepth = maybePixelFormat.Map(pf => pf.BitDepth).IfNone(8);
return (videoFormat, bitDepth) switch
{
// 10-bit h264 encoding is not support by any hardware
(VideoFormat.H264, 10) => FFmpegCapability.Software,
(VideoFormat.H264, 8) =>
_ffmpegCapabilities.HasEncoder(FFmpegKnownEncoder.H264VideoToolbox) && Encoders.ContainsKey(videoFormat)
? FFmpegCapability.Hardware
: FFmpegCapability.Software,
(VideoFormat.Hevc, _) =>
_ffmpegCapabilities.HasEncoder(FFmpegKnownEncoder.HevcVideoToolbox) && Encoders.ContainsKey(videoFormat)
? FFmpegCapability.Hardware
: FFmpegCapability.Software,
_ => FFmpegCapability.Software
};
}
public Option<RateControlMode> GetRateControlMode(string videoFormat, Option<IPixelFormat> maybePixelFormat) =>
Option<RateControlMode>.None;
}