diff options
| author | Joshua M. Boniface <joshua@boniface.me> | 2025-08-03 17:27:17 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-03 17:27:17 -0400 |
| commit | 4b6fb6c4bb2478badad068ce18aabe0c2955db48 (patch) | |
| tree | 15f986ee62327cceb8f5c8f009bcf08d10cfaa66 /MediaBrowser.MediaEncoding/Encoder/ApplePlatformHelper.cs | |
| parent | e7bc86ebb8496615e0b3f73eb4f13ab4c0913dc8 (diff) | |
| parent | db7465e83d9cc07134a0bffad7ed17b1c7b873da (diff) | |
Merge branch 'master' into master
Diffstat (limited to 'MediaBrowser.MediaEncoding/Encoder/ApplePlatformHelper.cs')
| -rw-r--r-- | MediaBrowser.MediaEncoding/Encoder/ApplePlatformHelper.cs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/MediaBrowser.MediaEncoding/Encoder/ApplePlatformHelper.cs b/MediaBrowser.MediaEncoding/Encoder/ApplePlatformHelper.cs new file mode 100644 index 000000000..a8ff58b09 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Encoder/ApplePlatformHelper.cs @@ -0,0 +1,87 @@ +#pragma warning disable CA1031 + +using 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); + } +} |
