FFmpegApi.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.Runtime.InteropServices;
  5. namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
  6. {
  7. static partial class FFmpegApi
  8. {
  9. public const string AvCodecLibraryName = "avcodec";
  10. public const string AvUtilLibraryName = "avutil";
  11. private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new Dictionary<string, (int, int)>
  12. {
  13. { AvCodecLibraryName, (58, 59) },
  14. { AvUtilLibraryName, (56, 57) }
  15. };
  16. private static string FormatLibraryNameForCurrentOs(string libraryName, int version)
  17. {
  18. if (OperatingSystem.IsWindows())
  19. {
  20. return $"{libraryName}-{version}.dll";
  21. }
  22. else if (OperatingSystem.IsLinux())
  23. {
  24. return $"lib{libraryName}.so.{version}";
  25. }
  26. else if (OperatingSystem.IsMacOS())
  27. {
  28. return $"lib{libraryName}.{version}.dylib";
  29. }
  30. else
  31. {
  32. throw new NotImplementedException($"Unsupported OS for FFmpeg: {RuntimeInformation.RuntimeIdentifier}");
  33. }
  34. }
  35. private static bool TryLoadWhitelistedLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
  36. {
  37. handle = IntPtr.Zero;
  38. if (_librariesWhitelist.TryGetValue(libraryName, out var value))
  39. {
  40. (int minVersion, int maxVersion) = value;
  41. for (int version = maxVersion; version >= minVersion; version--)
  42. {
  43. if (NativeLibrary.TryLoad(FormatLibraryNameForCurrentOs(libraryName, version), assembly, searchPath, out handle))
  44. {
  45. return true;
  46. }
  47. }
  48. }
  49. return false;
  50. }
  51. static FFmpegApi()
  52. {
  53. NativeLibrary.SetDllImportResolver(typeof(FFmpegApi).Assembly, (name, assembly, path) =>
  54. {
  55. IntPtr handle;
  56. if (name == AvUtilLibraryName && TryLoadWhitelistedLibrary(AvUtilLibraryName, assembly, path, out handle))
  57. {
  58. return handle;
  59. }
  60. else if (name == AvCodecLibraryName && TryLoadWhitelistedLibrary(AvCodecLibraryName, assembly, path, out handle))
  61. {
  62. return handle;
  63. }
  64. return IntPtr.Zero;
  65. });
  66. }
  67. public unsafe delegate void av_log_set_callback_callback(void* a0, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string a2, byte* a3);
  68. [LibraryImport(AvUtilLibraryName)]
  69. internal static unsafe partial AVFrame* av_frame_alloc();
  70. [LibraryImport(AvUtilLibraryName)]
  71. internal static unsafe partial void av_frame_unref(AVFrame* frame);
  72. [LibraryImport(AvUtilLibraryName)]
  73. internal static unsafe partial void av_free(AVFrame* frame);
  74. [LibraryImport(AvUtilLibraryName)]
  75. internal static unsafe partial void av_log_set_level(AVLog level);
  76. [LibraryImport(AvUtilLibraryName)]
  77. internal static unsafe partial void av_log_set_callback(av_log_set_callback_callback callback);
  78. [LibraryImport(AvUtilLibraryName)]
  79. internal static unsafe partial AVLog av_log_get_level();
  80. [LibraryImport(AvUtilLibraryName)]
  81. 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);
  82. [LibraryImport(AvCodecLibraryName)]
  83. internal static unsafe partial AVCodec* avcodec_find_decoder(AVCodecID id);
  84. [LibraryImport(AvCodecLibraryName)]
  85. internal static unsafe partial AVCodecContext* avcodec_alloc_context3(AVCodec* codec);
  86. [LibraryImport(AvCodecLibraryName)]
  87. internal static unsafe partial int avcodec_open2(AVCodecContext* avctx, AVCodec* codec, void **options);
  88. [LibraryImport(AvCodecLibraryName)]
  89. internal static unsafe partial int avcodec_close(AVCodecContext* avctx);
  90. [LibraryImport(AvCodecLibraryName)]
  91. internal static unsafe partial void avcodec_free_context(AVCodecContext** avctx);
  92. [LibraryImport(AvCodecLibraryName)]
  93. internal static unsafe partial AVPacket* av_packet_alloc();
  94. [LibraryImport(AvCodecLibraryName)]
  95. internal static unsafe partial void av_packet_unref(AVPacket* pkt);
  96. [LibraryImport(AvCodecLibraryName)]
  97. internal static unsafe partial void av_packet_free(AVPacket** pkt);
  98. [LibraryImport(AvCodecLibraryName)]
  99. internal static unsafe partial int avcodec_version();
  100. }
  101. }