From c5bddfeab8a905ce6c306ffafb079d8550f0b027 Mon Sep 17 00:00:00 2001 From: Mary Date: Thu, 14 Jul 2022 15:13:23 +0200 Subject: Remove dependency for FFmpeg.AutoGen and Update FFmpeg to 5.0.1 for Windows (#3466) * Remove dependency for FFMpeg.AutoGen Also prepare for FFMpeg 5.0 and 5.1 * Update Ryujinx.Graphics.Nvdec.Dependencies to 5.0.1-build10 * Address gdkchan's comments * Address Ack's comment * Address gdkchan's comment --- Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs | 129 ++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs (limited to 'Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs') diff --git a/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs b/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs new file mode 100644 index 00000000..4c010783 --- /dev/null +++ b/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 class FFmpegApi + { + public const string AvCodecLibraryName = "avcodec"; + public const string AvUtilLibraryName = "avutil"; + + private static readonly Dictionary _librariesWhitelist = new Dictionary + { + { 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 = minVersion; version <= maxVersion; 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); + + [DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern AVFrame* av_frame_alloc(); + + [DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void av_frame_unref(AVFrame* frame); + + [DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void av_free(AVFrame* frame); + + [DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void av_log_set_level(AVLog level); + + [DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void av_log_set_callback(av_log_set_callback_callback callback); + + [DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern AVLog av_log_get_level(); + + [DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void av_log_format_line(void* ptr, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string fmt, byte* vl, byte* line, int lineSize, int* printPrefix); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern AVCodec* avcodec_find_decoder(AVCodecID id); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern AVCodecContext* avcodec_alloc_context3(AVCodec* codec); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern int avcodec_open2(AVCodecContext* avctx, AVCodec* codec, void **options); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern int avcodec_close(AVCodecContext* avctx); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void avcodec_free_context(AVCodecContext** avctx); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern AVPacket* av_packet_alloc(); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void av_packet_unref(AVPacket* pkt); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern void av_packet_free(AVPacket** pkt); + + [DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static unsafe extern int avcodec_version(); + } +} -- cgit v1.2.3