Last active
March 24, 2026 18:44
-
-
Save nidbCN/03e99ad55d40a146a789253233d43eba to your computer and use it in GitHub Desktop.
FFmpeg.Autogen configure ffmpeg libraries and initialize
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Reflection; | |
| using System.Runtime.InteropServices; | |
| using System.Text; | |
| using CameraCaptureBot.Core.Configs; | |
| using FFmpeg.AutoGen.Abstractions; | |
| using FFmpeg.AutoGen.Bindings.DynamicallyLinked; | |
| using FFmpeg.AutoGen.Bindings.DynamicallyLoaded; | |
| using Microsoft.Extensions.Options; | |
| namespace CameraCaptureBot.Core; | |
| public class FfMpegConfigure | |
| { | |
| private readonly ILogger logger; // you have a logger. | |
| // feel free to make it static if you don't use something like logger and not use .NET generic host | |
| private void ConfigureFfMpegLibrary(string? searchPath = null) | |
| { | |
| // use linked | |
| if (searchPath is null) | |
| { | |
| logger.LogInformation("ffmpeg library path not set, use {bind}.", nameof(FFmpeg.AutoGen.Bindings.DynamicallyLinked)); | |
| if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | |
| { | |
| var bindingAssembly = typeof(DynamicallyLinkedBindings).Assembly; | |
| if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) | |
| || RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD)) | |
| { | |
| logger.LogInformation("Linux/FreeBSD platform, use resolver {name} for assembly `{asm}`.", nameof(LinuxFfMpegDllImportResolver), bindingAssembly.GetName()); | |
| NativeLibrary.SetDllImportResolver(bindingAssembly, LinuxFfMpegDllImportResolver); | |
| } | |
| else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | |
| { | |
| logger.LogInformation("OSX platform, use resolver {name} for assembly `{asm}`.", nameof(LinuxFfMpegDllImportResolver), bindingAssembly.GetName()); | |
| NativeLibrary.SetDllImportResolver(bindingAssembly, MacOsFfMpegDllImportResolver); | |
| } | |
| else | |
| { | |
| throw new PlatformNotSupportedException(); | |
| } | |
| } | |
| DynamicallyLinkedBindings.Initialize(); | |
| } | |
| else | |
| { | |
| DynamicallyLoadedBindings.LibrariesPath = options.Value.FfMpegLibrariesPath; | |
| if (searchPath == string.Empty) | |
| { | |
| logger.LogInformation("ffmpeg library path set to system default search path, use {bind}.", | |
| nameof(FFmpeg.AutoGen.Bindings.DynamicallyLoaded)); | |
| } | |
| else | |
| { | |
| logger.LogInformation("ffmpeg library path set to `{path}`, use {bind}.", | |
| DynamicallyLoadedBindings.LibrariesPath = searchPath, | |
| nameof(FFmpeg.AutoGen.Bindings.DynamicallyLoaded)); | |
| } | |
| DynamicallyLoadedBindings.ThrowErrorIfFunctionNotFound = true; | |
| DynamicallyLoadedBindings.Initialize(); | |
| } | |
| } | |
| // feel free to make it static too | |
| public void TestFfMpegLoad() | |
| { | |
| // test ffmpeg load | |
| try | |
| { | |
| var version = ffmpeg.av_version_info(); | |
| var libraryVersion = new StringBuilder(48 * DynamicallyLoadedBindings.LibraryVersionMap.Count); | |
| foreach (var (library, requiredVersion) in DynamicallyLoadedBindings.LibraryVersionMap) | |
| { | |
| var versionFunc = typeof(ffmpeg).GetMethod($"{library}_version"); | |
| var versionInfo = new FfMpegVersionStruct((uint)(versionFunc?.Invoke(null, null) ?? 0u)); | |
| libraryVersion.AppendLine($"\tLibrary: {library}, require `{requiredVersion}`, load `{versionInfo}`"); | |
| } | |
| libraryVersion.Remove(libraryVersion.Length - 1, 1); // remove '\n' | |
| logger.LogInformation("Load ffmpeg, version `{v}`", version); | |
| logger.LogInformation("Load ffmpeg, libraries:\n{libInfo}", libraryVersion); | |
| } | |
| catch (NotSupportedException e) | |
| { | |
| logger.LogCritical(e, "Failed to load ffmpeg, exit."); | |
| } | |
| } | |
| public static IntPtr LinuxFfMpegDllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) | |
| => FfMpegDllImportResolverCore(libraryName, assembly, searchPath, "so"); | |
| public static IntPtr MacOsFfMpegDllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) | |
| => FfMpegDllImportResolverCore(libraryName, assembly, searchPath, "dylib"); | |
| public static IntPtr FfMpegDllImportResolverCore(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, string extension) | |
| { | |
| var libraryNameSpan = libraryName.AsSpan(); | |
| var partedIndex = libraryNameSpan.IndexOf('-'); | |
| if (libraryNameSpan.LastIndexOf('-') != partedIndex) | |
| { | |
| // format not ffmpeg library | |
| return NativeLibrary.Load(libraryName, assembly, searchPath); | |
| } | |
| var pureName = libraryNameSpan[..partedIndex]; | |
| if (!DynamicallyLoadedBindings.LibraryVersionMap.ContainsKey(pureName.ToString())) | |
| { | |
| // not ffmpeg library | |
| return NativeLibrary.Load(libraryName, assembly, searchPath); | |
| } | |
| var versionName = libraryNameSpan[(partedIndex + 1)..]; | |
| var styledName = $"{pureName}.{extension}.{versionName}"; | |
| return NativeLibrary.Load(styledName, assembly, searchPath); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment