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 of
FFmpeg.AutoGen, but the README use
ffmpeg.RootPath = to set libraries path which is defined in
FFmpeg.AutoGen`.
conclusion of which package should I choose
If you’re using ffmpeg in Mono, choose
FFmpeg.AutoGen.Bindings.StaticallyLinked
andFFmpeg.AutoGen.Abstractions
.If your app only run on Windows, choose
FFmpeg.AutoGen.Bindings.DynamicallyLinked
andFFmpeg.AutoGen.Abstractions
.If your app running on mult-platform, choose
FFmpeg.AutoGen.Bindings.DynamicallyLoaded
andFFmpeg.AutoGen.Abstractions
orFFmpeg.AutoGen.Bindings.DynamicallyLinked
with custom resolver. UseFFmpeg.AutoGen
is 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
PATH
environment variable;
For more information, see reference:
On Linux, the main search order are:
- Directories in the
LD_LIBRARY_PATH
environment variable; /etc/ld.so.cache
directory;/lib
and/usr/lib
directories.
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.