| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 | #pragma warning disable CA1031using System;using System.Linq;using System.Runtime.InteropServices;using System.Runtime.Versioning;using Microsoft.Extensions.Logging;namespace MediaBrowser.MediaEncoding.Encoder;/// <summary>/// Helper class for Apple platform specific operations./// </summary>[SupportedOSPlatform("macos")]public static class ApplePlatformHelper{    private static readonly string[] _av1DecodeBlacklistedCpuClass = ["M1", "M2"];    private static string GetSysctlValue(ReadOnlySpan<byte> name)    {        IntPtr length = IntPtr.Zero;        // Get length of the value        int osStatus = SysctlByName(name, IntPtr.Zero, ref length, IntPtr.Zero, 0);        if (osStatus != 0)        {            throw new NotSupportedException($"Failed to get sysctl value for {System.Text.Encoding.UTF8.GetString(name)} with error {osStatus}");        }        IntPtr buffer = Marshal.AllocHGlobal(length.ToInt32());        try        {            osStatus = SysctlByName(name, buffer, ref length, IntPtr.Zero, 0);            if (osStatus != 0)            {                throw new NotSupportedException($"Failed to get sysctl value for {System.Text.Encoding.UTF8.GetString(name)} with error {osStatus}");            }            return Marshal.PtrToStringAnsi(buffer) ?? string.Empty;        }        finally        {            Marshal.FreeHGlobal(buffer);        }    }    private static int SysctlByName(ReadOnlySpan<byte> name, IntPtr oldp, ref IntPtr oldlenp, IntPtr newp, uint newlen)    {        return NativeMethods.SysctlByName(name.ToArray(), oldp, ref oldlenp, newp, newlen);    }    /// <summary>    /// Check if the current system has hardware acceleration for AV1 decoding.    /// </summary>    /// <param name="logger">The logger used for error logging.</param>    /// <returns>Boolean indicates the hwaccel support.</returns>    public static bool HasAv1HardwareAccel(ILogger logger)    {        if (!RuntimeInformation.OSArchitecture.Equals(Architecture.Arm64))        {            return false;        }        try        {            string cpuBrandString = GetSysctlValue("machdep.cpu.brand_string"u8);            return !_av1DecodeBlacklistedCpuClass.Any(blacklistedCpuClass => cpuBrandString.Contains(blacklistedCpuClass, StringComparison.OrdinalIgnoreCase));        }        catch (NotSupportedException e)        {            logger.LogError("Error getting CPU brand string: {Message}", e.Message);        }        catch (Exception e)        {            logger.LogError("Unknown error occured: {Exception}", e);        }        return false;    }    private static class NativeMethods    {        [DllImport("libc", EntryPoint = "sysctlbyname", SetLastError = true)]        [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)]        internal static extern int SysctlByName(byte[] name, IntPtr oldp, ref IntPtr oldlenp, IntPtr newp, uint newlen);    }}
 |