Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ffmpeg static class fails to initialize on mobile. #260

Open
1 of 3 tasks
emmauss opened this issue Apr 14, 2023 · 19 comments
Open
1 of 3 tasks

ffmpeg static class fails to initialize on mobile. #260

emmauss opened this issue Apr 14, 2023 · 19 comments
Labels

Comments

@emmauss
Copy link

emmauss commented Apr 14, 2023

Note: for support questions, please use stackoverflow or special repository on [github.com](in special repository github.com). This repository's issues are reserved for feature requests and bug reports.

  • **I'm submitting a ... **

    • bug report
    • feature request
    • support request or question => Please do not submit support request or questions here, see note at the top of this template.
  • Do you want to request a feature or report a bug?
    Report a bug

  • What is the current behavior?
    ffmpeg static class fails to initialize on non desktop platforms, eg. Android. The line where it throws a PlatfromNotSupportedException is,

    throw new PlatformNotSupportedException();

  • *If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem:

  • What is the expected behavior?

  • What is the motivation / use case for changing the behavior?

  • Please tell us about your environment:

  • version: 6.0. dotnet 7 Android
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
@Ruslan-B
Copy link
Owner

I wonder what PlatformID you are getting to make it fail.
You can try to workaround by setting DynamicallyLoadedBindings.FunctionResolver = new LinuxFunctionResolver(); before calling DynamicallyLoadedBindings.Initialize().
Please, let me know upon result.

@emmauss
Copy link
Author

emmauss commented Apr 14, 2023

GetPlatformId is called here,

EAGAIN = FunctionResolverFactory.GetPlatformId() switch
, in the static constructor. I don't think it can be bypassed.

@emmauss
Copy link
Author

emmauss commented Apr 14, 2023

StackTrace

at FFmpeg.AutoGen.FunctionResolverFactory.GetPlatformId()
at FFmpeg.AutoGen.ffmpeg..cctor()

@emmauss
Copy link
Author

emmauss commented Apr 14, 2023

image
Although my projects are all Net7, the autogen nuget package is net standard 2.0.

@Ruslan-B
Copy link
Owner

Ruslan-B commented Apr 14, 2023

Right, I see. I'll do hotfix.

@emmauss
Copy link
Author

emmauss commented Apr 15, 2023

I wonder what PlatformID you are getting to make it fail. You can try to workaround by setting DynamicallyLoadedBindings.FunctionResolver = new LinuxFunctionResolver(); before calling DynamicallyLoadedBindings.Initialize(). Please, let me know upon result.

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs.
Instead it fails on dlopen, as libdl doesn't exist on android,

protected override IntPtr LoadNativeLibrary(string libraryName) => dlopen(libraryName, RTLD_NOW);

@Ruslan-B
Copy link
Owner

Well, I guess you are the first one how trying this on android.
You can create a copy of LinuxFunctionResolver with this thing private const string Libdl = "libdl.so"; - i.e. without version suffix.

@Ruslan-B
Copy link
Owner

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs. Instead it fails on dlopen, as libdl doesn't exist on android,

Question here from which set of bindings did you switched?

@emmauss
Copy link
Author

emmauss commented Apr 15, 2023

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs. Instead it fails on dlopen, as libdl doesn't exist on android,

Question here from which set of bindings did you switched?

I was using the legacy Autogen. I'm modifying an existing library to work on android, and it was made a while ago.

@Ruslan-B
Copy link
Owner

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs. Instead it fails on dlopen, as libdl doesn't exist on android,

Question here from which set of bindings did you switched?

I was using the legacy Autogen. I'm modifying an existing library to work on android, and it was made a while ago.

focus my friend and give us details, as I have no understanding how and what runs dotNET on android now.
we can do zoom session if you like too.

@emmauss
Copy link
Author

emmauss commented Apr 15, 2023

Sorry for the misunderstanding. Let me start from the beginning.
The project I'm porting is https://github.com/unosquare/ffmediaelement . It's currently outdated and uses ffmpeg 4.4 and FFMpeg.Autogen 4 nuget package. As the package, and the other Autogen packages were created using netstandard 2.0, and not multitargeting netstandard and net 5+, the exception I reported occurs because of this
image

I switched to using https://www.nuget.org/packages/FFmpeg.AutoGen.Bindings.DynamicallyLoaded, updating ffmpeg to 6.0, and setting the resolver manually. This avoids the previous crash, but the Linux resolver doesn't work on android because libdl isn't provided with the android system. This is an issue from android and not dotnet, but the sdk provides ways to dynamically load libraries packaged in your app at runtime. So I made a custom resolver that uses dotnet's NativeLibrary and that works quite well.

internal class AndroidFunctionResolver : FunctionResolverBase
    {
        protected override nint GetFunctionPointer(nint nativeLibraryHandle, string functionName)
        {
            var func = NativeLibrary.GetExport(nativeLibraryHandle, functionName);

            return func;
        }
        protected override string GetNativeLibraryName(string libraryName, int version) => $"lib{libraryName}.so";

        protected override nint LoadNativeLibrary(string libraryName)
        {
            var lib = NativeLibrary.Load(libraryName);

            return lib;
        }
    }

The original project was ported to a cross platform toolkit, so it doesn't rely on wpf. the port isn't public at this moment so I can't share much.

@Ruslan-B
Copy link
Owner

Well great if you manage to solve the issue, I guess we can close this topic - however would be nice if you share what is behind NativeLibrary call, if some one will try android once again.

@emmauss
Copy link
Author

emmauss commented Apr 19, 2023

Well great if you manage to solve the issue, I guess we can close this topic - however would be nice if you share what is behind NativeLibrary call, if some one will try android once again.

NativeLibrary is dotnets loader. https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.nativelibrary?source=recommendations&view=net-7.0

@Ruslan-B
Copy link
Owner

I'll try to address this in upcoming update. Wrt to 7.0 we have another issue #254 - I'll look into it when earlier issues will be solved.

@Ruslan-B Ruslan-B added the bug label Nov 15, 2023
@zero16832
Copy link

Sorry for the misunderstanding. Let me start from the beginning. The project I'm porting is https://github.com/unosquare/ffmediaelement . It's currently outdated and uses ffmpeg 4.4 and FFMpeg.Autogen 4 nuget package. As the package, and the other Autogen packages were created using netstandard 2.0, and not multitargeting netstandard and net 5+, the exception I reported occurs because of this image

I switched to using https://www.nuget.org/packages/FFmpeg.AutoGen.Bindings.DynamicallyLoaded, updating ffmpeg to 6.0, and setting the resolver manually. This avoids the previous crash, but the Linux resolver doesn't work on android because libdl isn't provided with the android system. This is an issue from android and not dotnet, but the sdk provides ways to dynamically load libraries packaged in your app at runtime. So I made a custom resolver that uses dotnet's NativeLibrary and that works quite well.

internal class AndroidFunctionResolver : FunctionResolverBase
    {
        protected override nint GetFunctionPointer(nint nativeLibraryHandle, string functionName)
        {
            var func = NativeLibrary.GetExport(nativeLibraryHandle, functionName);

            return func;
        }
        protected override string GetNativeLibraryName(string libraryName, int version) => $"lib{libraryName}.so";

        protected override nint LoadNativeLibrary(string libraryName)
        {
            var lib = NativeLibrary.Load(libraryName);

            return lib;
        }
    }

The original project was ported to a cross platform toolkit, so it doesn't rely on wpf. the port isn't public at this moment so I can't share much.

how to setup the rootpath?

@juanmalm
Copy link

Trying to use it on Android here. I followed the approach to create the AndroidFunctionResolver and set it on DynamicallyLoadedBindings.FunctionResolver but I still getting the platform not supported exception on

EAGAIN = FunctionResolverFactory.GetPlatformId() switch

@zero16832
Copy link

Trying to use it on Android here. I followed the approach to create the AndroidFunctionResolver and set it on DynamicallyLoadedBindings.FunctionResolver but I still getting the platform not supported exception on

EAGAIN = FunctionResolverFactory.GetPlatformId() switch

dose you use it in unity?

@juanmalm
Copy link

Trying to use it on Android here. I followed the approach to create the AndroidFunctionResolver and set it on DynamicallyLoadedBindings.FunctionResolver but I still getting the platform not supported exception on

EAGAIN = FunctionResolverFactory.GetPlatformId() switch

dose you use it in unity?

Nope. Using it on MAUI. I just realized I must move from FFmpeg.AutoGen package to FFmpeg.AutoGen.Abstractions and FFmpeg.AutoGen.Bindings.DynamicallyLoaded.

@Ruslan-B
Copy link
Owner

Ruslan-B commented Mar 26, 2024

I'll make possible to do a platform loader override within few days. However, I see you have a workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants