A Beginner’s Guide to FFmpeg.AutoGen
Introduction
FFmpeg.AutoGen is an auto-generated unsafe bindings for C#/.NET and Mono. It can be used in C#/.NET to invoke ffmpeg’s C/C++ libraries.
The usage is the same as C/C++ API so you can refer to ffmpeg official documents. However, in C#/.NET, we need to load the libraries first, which confused me for a long time.
Here I concluded the some useful information for beginners to start using ffmpeg.AutoGen.
This guide addresses the following questions:
- which nuget package should I use?
- how to configure the libraries root path?
- how to load libraries from system default path?
- how to solve
System.NotSupportedException?
which nuget package should I use? - ffmpeg.AutoGen packages
packages list
FFmpeg.AutoGen has the following packages on NuGet:
- FFmpeg.AutoGen
- FFmpeg.AutoGen.Abstractions
- FFmpeg.AutoGen.Bindings.DynamicallyLoaded
- FFmpeg.AutoGen.Bindings.DynamicallyLinked
- FFmpeg.AutoGen.Bindings.StaticallyLinked
Introduct to each packages
FFmpeg.AutoGen.Bindings.DynamicallyLinked
FFmpeg.AutoGen.Bindings.DynamicallyLinked uses DllImport to load libraries.
It loads libraries from the default path.
But the file name passed to DllImport is hard-coded in Windows file naming convention, such as something like “avutil-59”. That means you can not use this package directly on other platforms. But you can implement a custom resolver to adapt the filename convention from windows to others platforms by using the code below:
| |
And using thos codes to configure DllImport use custom resolver:
| |
FFmpeg.AutoGen.Bindings.DynamicallyLoaded
FFmpeg.AutoGen.Bindings.DynamicallyLoaded use LoadLibrary method in Kernel32 library on Windows, use dlopen method in Libdl on Linux and MacOS.
FFmpeg.AutoGen.Bindings.StaticallyLinked
This package use DllImport("__Internal") to import libraries, it required you build the library into assembly.
FFmpeg.AutoGen.Abstractions
This package contains definitions about structs and functions. But you can’t invoke functions define in this package, because it’s only have definitions but no body, you need install others Bindings package and use DynamicallyLinkedBindings.Initialize(); or DynamicallyLoadedBindings.Initialize(); method to initialize.
FFmpeg.AutoGen
This package looks like a combine of FFmpeg.AutoGen.Abstractions and FFmpeg.AutoGen.Bindings.DynamicallyLoaded with a few properties changed.
The offical example use ``FFmpeg.AutoGen.Bindings.DynamicallyLoadedBindingsinstead ofFFmpeg.AutoGen, but the README use ffmpeg.RootPath = to set libraries path which is defined inFFmpeg.AutoGen`.
conclusion of which package should I choose
If you’re using ffmpeg in Mono, choose
FFmpeg.AutoGen.Bindings.StaticallyLinkedandFFmpeg.AutoGen.Abstractions.If your app only run on Windows, choose
FFmpeg.AutoGen.Bindings.DynamicallyLinkedandFFmpeg.AutoGen.Abstractions.If your app running on mult-platform, choose
FFmpeg.AutoGen.Bindings.DynamicallyLoadedandFFmpeg.AutoGen.AbstractionsorFFmpeg.AutoGen.Bindings.DynamicallyLinkedwith custom resolver. UseFFmpeg.AutoGenis also a good choice.
how to configure the libraries root path? - use prop in DynamicallyLoaded or FFmpeg.AutoGen
DynamicallyLinked can’t specify a custom root path for libraries.
If you want to use the library files which are not in the default search path, use DynamicallyLoaded and set the path to property DynamicallyLoadedBindings.LibrariesPath.
ffmpeg.RootPath from package FFmpeg.AutoGen is the same as DynamicallyLoadedBindings.LibrariesPath.
By the way, the libraries root should contains libs like avutil-59.dll on Windows, and libavutil.59.so on Linux.
hot to load libraries from system default path - just do nothing
In the previous section, I explained the libraries load function of each packages. According to Microsoft Docs and Linux manual page we can find the search order.
Search order on Windows and Linux
On windows, the main search order are:
- Application directory;
- System directory;
- Windows directory;
- Current work directory;
- Directories in the
PATHenvironment variable;
For more information, see reference:
On Linux, the main search order are:
- Directories in the
LD_LIBRARY_PATHenvironment variable; /etc/ld.so.cachedirectory;/liband/usr/libdirectories.
For more information, see reference:
- dlopen(3) - Linux manual page
- ld.so(8) - Linux manual page
- FFmpeg.AutoGen/FFmpeg.AutoGen.Bindings.DynamicallyLoaded/Native at master · Ruslan-B/FFmpeg.AutoGen
I have no computer with MacOS, so I haven’t figured out the search order on MacOS, but I guess it maybe very like the order on Linux.
If you want to use DynamicallyLoaded with default path, just do not modify DynamicallyLoadedBindings.LibrariesPath or ensure its value are string.Empty. This prop will be added to the front of library name and version. Keep it empty and the package will deliver pure library file name to the method which load the library to memory, that will lead the load method use default search path.
hot to solve System.NotSupportException? - a few debug tips
If you invoke a ffmpeg.* function and throw this exception, it is often because you didn’t load the libraries successfully.
First, make sure you install the FFmpeg.AutoGen.Bindings or FFmpeg.AutoGen and called the Initialize().
Second, make sure your libraries files are in correct path with correct file name. If you use the custom root path, just open it and have a look, If you use system default path, try using the system tools to ensure it can be found, such as ldconfig -p -N | grep lib<name>.<version>.
Third, make sure all libraries are fine. You can set DynamicallyLoadedBindings.ThrowErrorIfFunctionNotFound to true, then the exception will sent during libraries loading. I suggess you print all libriaries version to ensure they are all loaded with the code below:
| |
You can also just add the project source code as a dependency of your project and debug in file FunctionResolverBase.cs or files under Native folder.