diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs new file mode 100644 index 00000000..d173a412 --- /dev/null +++ b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native +{ + static partial class FFmpegApi + { + public const string AvCodecLibraryName = "avcodec"; + public const string AvUtilLibraryName = "avutil"; + + private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new Dictionary<string, (int, int)> + { + { AvCodecLibraryName, (58, 59) }, + { AvUtilLibraryName, (56, 57) } + }; + + private static string FormatLibraryNameForCurrentOs(string libraryName, int version) + { + if (OperatingSystem.IsWindows()) + { + return $"{libraryName}-{version}.dll"; + } + else if (OperatingSystem.IsLinux()) + { + return $"lib{libraryName}.so.{version}"; + } + else if (OperatingSystem.IsMacOS()) + { + return $"lib{libraryName}.{version}.dylib"; + } + else + { + throw new NotImplementedException($"Unsupported OS for FFmpeg: {RuntimeInformation.RuntimeIdentifier}"); + } + } + + + private static bool TryLoadWhitelistedLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle) + { + handle = IntPtr.Zero; + + if (_librariesWhitelist.TryGetValue(libraryName, out var value)) + { + (int minVersion, int maxVersion) = value; + + for (int version = maxVersion; version >= minVersion; version--) + { + if (NativeLibrary.TryLoad(FormatLibraryNameForCurrentOs(libraryName, version), assembly, searchPath, out handle)) + { + return true; + } + } + } + + return false; + } + + static FFmpegApi() + { + NativeLibrary.SetDllImportResolver(typeof(FFmpegApi).Assembly, (name, assembly, path) => + { + IntPtr handle; + + if (name == AvUtilLibraryName && TryLoadWhitelistedLibrary(AvUtilLibraryName, assembly, path, out handle)) + { + return handle; + } + else if (name == AvCodecLibraryName && TryLoadWhitelistedLibrary(AvCodecLibraryName, assembly, path, out handle)) + { + return handle; + } + + return IntPtr.Zero; + }); + } + + public unsafe delegate void av_log_set_callback_callback(void* a0, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string a2, byte* a3); + + [LibraryImport(AvUtilLibraryName)] + internal static unsafe partial AVFrame* av_frame_alloc(); + + [LibraryImport(AvUtilLibraryName)] + internal static unsafe partial void av_frame_unref(AVFrame* frame); + + [LibraryImport(AvUtilLibraryName)] + internal static unsafe partial void av_free(AVFrame* frame); + + [LibraryImport(AvUtilLibraryName)] + internal static unsafe partial void av_log_set_level(AVLog level); + + [LibraryImport(AvUtilLibraryName)] + internal static unsafe partial void av_log_set_callback(av_log_set_callback_callback callback); + + [LibraryImport(AvUtilLibraryName)] + internal static unsafe partial AVLog av_log_get_level(); + + [LibraryImport(AvUtilLibraryName)] + internal static unsafe partial void av_log_format_line(void* ptr, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string fmt, byte* vl, byte* line, int lineSize, int* printPrefix); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial AVCodec* avcodec_find_decoder(AVCodecID id); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial AVCodecContext* avcodec_alloc_context3(AVCodec* codec); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial int avcodec_open2(AVCodecContext* avctx, AVCodec* codec, void **options); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial int avcodec_close(AVCodecContext* avctx); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial void avcodec_free_context(AVCodecContext** avctx); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial AVPacket* av_packet_alloc(); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial void av_packet_unref(AVPacket* pkt); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial void av_packet_free(AVPacket** pkt); + + [LibraryImport(AvCodecLibraryName)] + internal static unsafe partial int avcodec_version(); + } +} |